Skip to content

Discord 0.61.5 #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions Libraries/CameraRoll/RCTImagePickerManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@

#import <MobileCoreServices/UTCoreTypes.h>
#import <UIKit/UIKit.h>
#import <Photos/Photos.h>

#import <React/RCTConvert.h>
#import <React/RCTImageStoreManager.h>
#import <React/RCTRootView.h>
#import <React/RCTUtils.h>

@import Photos;

@interface RCTImagePickerController : UIImagePickerController

@property (nonatomic, assign) BOOL unmirrorFrontFacingCamera;
Expand Down Expand Up @@ -96,7 +99,7 @@ - (dispatch_queue_t)methodQueue
imagePicker.unmirrorFrontFacingCamera = [RCTConvert BOOL:config[@"unmirrorFrontFacingCamera"]];

if ([RCTConvert BOOL:config[@"videoMode"]]) {
imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;
imagePicker.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie];
}

[self _presentPicker:imagePicker
Expand All @@ -116,6 +119,11 @@ - (dispatch_queue_t)methodQueue
UIImagePickerController *imagePicker = [UIImagePickerController new];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

// Don't compress the video
if (@available(iOS 11.0, *)) {
imagePicker.videoExportPreset = AVAssetExportPresetPassthrough;
}

NSMutableArray<NSString *> *allowedTypes = [NSMutableArray new];
if ([RCTConvert BOOL:config[@"showImages"]]) {
Expand Down Expand Up @@ -155,15 +163,24 @@ - (void)imagePickerController:(UIImagePickerController *)picker
{
NSString *mediaType = info[UIImagePickerControllerMediaType];
BOOL isMovie = [mediaType isEqualToString:(NSString *)kUTTypeMovie];
NSString *key = isMovie ? UIImagePickerControllerMediaURL : UIImagePickerControllerReferenceURL;
NSURL *imageURL = info[key];
NSURL *imageURL = info[UIImagePickerControllerReferenceURL] ?: info[UIImagePickerControllerMediaURL];
UIImage *image = info[UIImagePickerControllerOriginalImage];
NSNumber *width = 0;
NSNumber *height = 0;
if (image) {
height = @(image.size.height);
width = @(image.size.width);
} else if (isMovie && info[UIImagePickerControllerReferenceURL]) {
// these are movies picked from the image picker. videos taken from the camera roll are not saved yet and
// cannot be loaded with a width or height
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithALAssetURLs:@[[info valueForKey:UIImagePickerControllerReferenceURL]] options:nil];
if (assets.count > 0) {
PHAsset *videoAsset = assets.firstObject;
height = @(videoAsset.pixelHeight);
width = @(videoAsset.pixelWidth);
}
}

if (imageURL) {
NSString *imageURLString = imageURL.absoluteString;
// In iOS 13, video URLs are only valid while info dictionary is retained
Expand All @@ -181,10 +198,18 @@ - (void)imagePickerController:(UIImagePickerController *)picker
// We need to save it to the image store first.
UIImage *originalImage = info[UIImagePickerControllerOriginalImage];

// WARNING: Using ImageStoreManager may cause a memory leak because the
// image isn't automatically removed from store once we're done using it.
[_bridge.imageStoreManager storeImage:originalImage withBlock:^(NSString *tempImageTag) {
[self _dismissPicker:picker args:tempImageTag ? @[tempImageTag, RCTNullIfNil(height), RCTNullIfNil(width)] : nil];
__block PHObjectPlaceholder *placeholderAsset = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *assetChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:originalImage];
placeholderAsset = assetChangeRequest.placeholderForCreatedAsset;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
// probably a bit hacky...
NSString *id = [placeholderAsset.localIdentifier substringToIndex:36];
NSString *assetUrlString = [NSString stringWithFormat:@"assets-library://asset/asset.JPG?id=%@&ext=JPG", id];

[self _dismissPicker:picker args:@[assetUrlString, height, width]];
}
}];
}

Expand Down Expand Up @@ -228,7 +253,9 @@ - (void)_dismissPicker:(UIImagePickerController *)picker args:(NSArray *)args
[_pickerCancelCallbacks removeObjectAtIndex:index];

UIViewController *rootViewController = RCTPresentedViewController();
[rootViewController dismissViewControllerAnimated:YES completion:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[rootViewController dismissViewControllerAnimated:YES completion:nil];
});

if (args) {
successCallback(args);
Expand Down
14 changes: 7 additions & 7 deletions Libraries/Performance/Systrace.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ const Systrace = {
},
};

if (__DEV__) {
// This is needed, because require callis in polyfills are not processed as
// other files. Therefore, calls to `require('moduleId')` are not replaced
// with numeric IDs
// TODO(davidaurelio) Scan polyfills for dependencies, too (t9759686)
(require: any).Systrace = Systrace;
}
// if (__DEV__) {
// // This is needed, because require callis in polyfills are not processed as
// // other files. Therefore, calls to `require('moduleId')` are not replaced
// // with numeric IDs
// // TODO(davidaurelio) Scan polyfills for dependencies, too (t9759686)
// (require: any).Systrace = Systrace;
// }

module.exports = Systrace;
2 changes: 1 addition & 1 deletion Libraries/WebSocket/RCTSRWebSocket.m
Original file line number Diff line number Diff line change
Expand Up @@ -1388,7 +1388,7 @@ - (void)safeHandleEvent:(NSStreamEvent)eventCode stream:(NSStream *)aStream
// If we get closed in this state it's probably not clean because we should be sending this when we send messages
[self _performDelegateBlock:^{
if ([self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) {
[self.delegate webSocket:self didCloseWithCode:RCTSRStatusCodeGoingAway reason:@"Stream end encountered" wasClean:NO];
[self.delegate webSocket:self didCloseWithCode:self->_closeCode reason:self->_closeReason wasClean:NO];
}
}];
}
Expand Down
2 changes: 0 additions & 2 deletions Libraries/WebSocket/RCTWebSocketModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ - (void)webSocket:(RCTSRWebSocket *)webSocket didFailWithError:(NSError *)error
{
NSNumber *socketID = [webSocket reactTag];
_contentHandlers[socketID] = nil;
_sockets[socketID] = nil;
[self sendEventWithName:@"websocketFailed" body:@{
@"message": error.localizedDescription,
@"id": socketID
Expand All @@ -178,7 +177,6 @@ - (void)webSocket:(RCTSRWebSocket *)webSocket
{
NSNumber *socketID = [webSocket reactTag];
_contentHandlers[socketID] = nil;
_sockets[socketID] = nil;
[self sendEventWithName:@"websocketClosed" body:@{
@"code": @(code),
@"reason": RCTNullIfNil(reason),
Expand Down
61 changes: 61 additions & 0 deletions React/Base/DCDDisplayLink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// RCTDisplayLink.h
// React
//
// Created by Stanislav Vishnevskiy on 6/8/15.
// Copyright (c) 2015 Facebook. All rights reserved.
//

#import <QuartzCore/CABase.h>
#import <Foundation/NSObject.h>

@class NSString, NSRunLoop;

@interface DCDDisplayLink : NSObject

/* Create a new display link object for the main display. It will
* invoke the method called 'sel' on 'target', the method has the
* signature '(void)selector:(CADisplayLink *)sender'. */

+ (DCDDisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel;

/* Adds the receiver to the given run-loop and mode. Unless paused, it
* will fire every vsync until removed. Each object may only be added
* to a single run-loop, but it may be added in multiple modes at once.
* While added to a run-loop it will implicitly be retained. */

- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;

/* Removes the receiver from the given mode of the runloop. This will
* implicitly release it when removed from the last mode it has been
* registered for. */

- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;

/* Removes the object from all runloop modes (releasing the receiver if
* it has been implicitly retained) and releases the 'target' object. */

- (void)invalidate;

/* The current time, and duration of the display frame associated with
* the most recent target invocation. Time is represented using the
* normal Core Animation conventions, i.e. Mach host time converted to
* seconds. */

@property(readonly, nonatomic) CFTimeInterval timestamp;
@property(readonly, nonatomic) CFTimeInterval duration;

/* When true the object is prevented from firing. Initial state is
* false. */

@property(getter=isPaused, nonatomic) BOOL paused;

/* Defines how many display frames must pass between each time the
* display link fires. Default value is one, which means the display
* link will fire for every display frame. Setting the interval to two
* will cause the display link to fire every other display frame, and
* so on. The behavior when using values less than one is undefined. */

@property(nonatomic) NSInteger frameInterval;

@end
159 changes: 159 additions & 0 deletions React/Base/DCDDisplayLink.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//
// RCTDisplayLink.m
// React
//
// Created by Stanislav Vishnevskiy on 6/8/15.
// Copyright (c) 2015 Facebook. All rights reserved.
//

#import "DCDDisplayLink.h"
#import <UIKit/UIKit.h>

@interface DCDDisplayLink ()

@property(nonatomic) NSRunLoop *runloop;
@property(nonatomic) NSString *mode;
@property(nonatomic) id target;
@property(nonatomic) SEL selector;
@property(nonatomic) NSTimer *timer;
@property(nonatomic) CADisplayLink *displayLink;

// CADisplayLink is not thread safe.
// Add a flag to avoid the crash of removing invalidated CADisplayLink from the run loop.
@property(nonatomic) BOOL resourcesLoaded;

@end

@implementation DCDDisplayLink

+ (DCDDisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel {
return [[self alloc] initWithTarget:target selector:sel];
}

- (instancetype)initWithTarget:(id)target selector:(SEL)sel {
if (self = [super init]) {
_target = target;
_selector = sel;
_displayLink = [CADisplayLink displayLinkWithTarget:target selector:sel];
_resourcesLoaded = YES;

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(switchToTimer)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(switchToDisplayLink)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
return self;
}

- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)switchToDisplayLink {
if (_timer) {
[_timer invalidate];
_timer = nil;
[self setPaused:_paused];
if (_runloop) {
[_displayLink addToRunLoop:_runloop forMode:_mode];
}
}
}

- (void)switchToTimer {
if (!_timer) {
[self maybeResetTimer];
[self setPaused:_paused];
if (_runloop && _resourcesLoaded) {
[_displayLink removeFromRunLoop:_runloop forMode:_mode];
[_runloop addTimer:_timer forMode:_mode];
}
}
}

- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode {
_runloop = runloop;
_mode = mode;
if (_timer) {
[self maybeResetTimer];
[runloop addTimer:_timer forMode:mode];
}
else {
[_displayLink addToRunLoop:runloop forMode:mode];
}
}

- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode {
_runloop = nil;
_mode = nil;
if (_timer) {
[_timer invalidate];
}
else {
[_displayLink removeFromRunLoop:runloop forMode:mode];
}
}

- (void)invalidate {
_resourcesLoaded = NO;
if (_timer) {
[_timer invalidate];
}
else {
[_displayLink invalidate];
}
}

- (void)setPaused:(BOOL)paused {
_paused = paused;
if (_timer) {
if (paused) {
[_timer invalidate];
}
else {
[self maybeResetTimer];
if (_runloop) {
[_runloop addTimer:_timer forMode:_mode];
}
}
}
else {
_displayLink.paused = paused;
}
}

- (CFTimeInterval)timestamp {
if (_timer) {
// TODO: Does React Native actually need this?
return 0;
}
return _displayLink.timestamp;
}

- (CFTimeInterval)duration {
if (_timer) {
// TODO: Does React Native actually need this?
return 0;
}
return _displayLink.duration;
}

- (void)maybeResetTimer {
if (!_timer || ![_timer isValid]) {
_timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(timerLoop) userInfo:nil repeats:YES];
}
}

- (void)timerLoop {
if (_target) {
IMP imp = [_target methodForSelector:_selector];
void (*func)(id, SEL, DCDDisplayLink *) = (void *)imp;
func(_target, _selector, self);
}
}

@end
Loading