mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Video avatar fixes
This commit is contained in:
@@ -39,11 +39,13 @@
|
||||
#import "TGPhotoToolsController.h"
|
||||
#import "TGPhotoPaintController.h"
|
||||
#import "TGPhotoQualityController.h"
|
||||
#import "TGPhotoAvatarCropController.h"
|
||||
#import "TGPhotoAvatarPreviewController.h"
|
||||
|
||||
#import "TGPhotoAvatarCropView.h"
|
||||
|
||||
#import "TGMessageImageViewOverlayView.h"
|
||||
#import "TGMediaPickerGalleryVideoScrubber.h"
|
||||
#import "TGMediaPickerGalleryVideoScrubberThumbnailView.h"
|
||||
|
||||
#import "TGMenuSheetController.h"
|
||||
|
||||
@@ -107,11 +109,13 @@
|
||||
|
||||
bool _wasPlaying;
|
||||
bool _initializedScrubber;
|
||||
NSArray *_cachedThumbnails;
|
||||
TGMediaPickerGalleryVideoScrubber *_scrubberView;
|
||||
|
||||
bool _resetDotPosition;
|
||||
NSTimeInterval _dotPosition;
|
||||
UIImageView *_dotMarkerView;
|
||||
UIImageView *_dotImageView;
|
||||
TGMediaPickerGalleryVideoScrubberThumbnailView *_dotImageView;
|
||||
UIView *_dotImageSnapshotView;
|
||||
|
||||
bool _requestingThumbnails;
|
||||
@@ -154,6 +158,7 @@
|
||||
_photoEditor = [[PGPhotoEditor alloc] initWithOriginalSize:_item.originalSize adjustments:adjustments forVideo:item.isVideo enableStickers:(intent & TGPhotoEditorControllerSignupAvatarIntent) == 0];
|
||||
if ([self presentedForAvatarCreation])
|
||||
{
|
||||
_photoEditor.cropOnLast = true;
|
||||
CGFloat shortSide = MIN(_item.originalSize.width, _item.originalSize.height);
|
||||
_photoEditor.cropRect = CGRectMake((_item.originalSize.width - shortSide) / 2, (_item.originalSize.height - shortSide) / 2, shortSide, shortSide);
|
||||
}
|
||||
@@ -209,6 +214,10 @@
|
||||
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
[_wrapperView addSubview:_containerView];
|
||||
|
||||
_progressView = [[TGMessageImageViewOverlayView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 60.0f, 60.0f)];
|
||||
[_progressView setRadius:60.0];
|
||||
_progressView.userInteractionEnabled = false;
|
||||
|
||||
__weak TGPhotoEditorController *weakSelf = self;
|
||||
|
||||
void(^toolbarCancelPressed)(void) = ^
|
||||
@@ -247,7 +256,7 @@
|
||||
switch (tab)
|
||||
{
|
||||
default:
|
||||
[strongSelf presentEditorTab:tab];
|
||||
[strongSelf presentTab:tab];
|
||||
break;
|
||||
|
||||
case TGPhotoEditorToolsTab:
|
||||
@@ -257,7 +266,7 @@
|
||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoToolsController class]])
|
||||
[strongSelf->_currentTabController handleTabAction:tab];
|
||||
else
|
||||
[strongSelf presentEditorTab:TGPhotoEditorToolsTab];
|
||||
[strongSelf presentTab:TGPhotoEditorToolsTab];
|
||||
break;
|
||||
|
||||
case TGPhotoEditorPaintTab:
|
||||
@@ -265,7 +274,7 @@
|
||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoPaintController class]])
|
||||
[strongSelf->_currentTabController handleTabAction:tab];
|
||||
else
|
||||
[strongSelf presentEditorTab:TGPhotoEditorPaintTab];
|
||||
[strongSelf presentTab:TGPhotoEditorPaintTab];
|
||||
break;
|
||||
|
||||
case TGPhotoEditorStickerTab:
|
||||
@@ -276,7 +285,7 @@
|
||||
case TGPhotoEditorRotateTab:
|
||||
case TGPhotoEditorMirrorTab:
|
||||
case TGPhotoEditorAspectRatioTab:
|
||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoCropController class]] || [strongSelf->_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoCropController class]] || [strongSelf->_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]])
|
||||
[strongSelf->_currentTabController handleTabAction:tab];
|
||||
break;
|
||||
}
|
||||
@@ -322,9 +331,15 @@
|
||||
[_scrubberView addSubview:_dotMarkerView];
|
||||
_dotMarkerView.center = CGPointMake(30.0, -20.0);
|
||||
|
||||
_dotImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 160.0, 160.0)];
|
||||
_dotImageView = [[TGMediaPickerGalleryVideoScrubberThumbnailView alloc] initWithImage:nil originalSize:_item.originalSize cropRect:CGRectZero cropOrientation:UIImageOrientationUp cropMirrored:false];
|
||||
_dotImageView.frame = CGRectMake(0.0, 0.0, 160.0, 160.0);
|
||||
_dotImageView.userInteractionEnabled = true;
|
||||
|
||||
CAShapeLayer* maskLayer = [CAShapeLayer new];
|
||||
maskLayer.frame = _dotImageView.bounds;
|
||||
maskLayer.path = [UIBezierPath bezierPathWithOvalInRect:_dotImageView.bounds].CGPath;
|
||||
_dotImageView.layer.mask = maskLayer;
|
||||
|
||||
UITapGestureRecognizer *dotTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDotTap)];
|
||||
[_dotImageView addGestureRecognizer:dotTapRecognizer];
|
||||
|
||||
@@ -337,7 +352,7 @@
|
||||
|
||||
[self detectFaces];
|
||||
|
||||
[self presentEditorTab:_currentTab];
|
||||
[self presentTab:_currentTab];
|
||||
}
|
||||
|
||||
- (void)handleDotTap {
|
||||
@@ -495,12 +510,7 @@
|
||||
|
||||
TGDispatchOnMainThread(^
|
||||
{
|
||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
||||
[(TGPhotoAvatarCropController *)strongSelf->_currentTabController setPlayer:strongSelf->_player];
|
||||
|
||||
[strongSelf->_previewView performTransitionInWithCompletion:^
|
||||
{
|
||||
}];
|
||||
[strongSelf->_previewView performTransitionInWithCompletion:^{}];
|
||||
|
||||
if (strongSelf->_scheduledVideoPlayback) {
|
||||
strongSelf->_scheduledVideoPlayback = false;
|
||||
@@ -519,12 +529,14 @@
|
||||
if (strongSelf->_dismissed)
|
||||
return;
|
||||
|
||||
if (progressVisible)
|
||||
strongSelf->_hadProgress = true;
|
||||
[strongSelf setProgressVisible:progressVisible value:progress animated:true];
|
||||
[strongSelf updateDoneButtonEnabled:doneEnabled animated:true];
|
||||
if (progressVisible)
|
||||
strongSelf->_hadProgress = true;
|
||||
|
||||
if (strongSelf->_hadProgress) {
|
||||
if (strongSelf->_hadProgress && !progressVisible) {
|
||||
[strongSelf->_progressView setPlay];
|
||||
|
||||
[strongSelf->_scrubberView reloadThumbnails];
|
||||
}
|
||||
});
|
||||
@@ -566,8 +578,8 @@
|
||||
- (void)_setupPlaybackStartedObserver
|
||||
{
|
||||
CMTime startTime = CMTimeMake(10, 100);
|
||||
if (_photoEditor.trimStartValue > DBL_EPSILON)
|
||||
startTime = CMTimeMakeWithSeconds(_photoEditor.trimStartValue + 0.1, NSEC_PER_SEC);
|
||||
if (_scrubberView.trimStartValue > DBL_EPSILON)
|
||||
startTime = CMTimeMakeWithSeconds(_scrubberView.trimStartValue + 0.1, NSEC_PER_SEC);
|
||||
|
||||
__weak TGPhotoEditorController *weakSelf = self;
|
||||
_playerStartedObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:startTime]] queue:NULL usingBlock:^
|
||||
@@ -589,14 +601,13 @@
|
||||
if (_playerReachedEndObserver != nil)
|
||||
[_player removeTimeObserver:_playerReachedEndObserver];
|
||||
|
||||
PGPhotoEditor *photoEditor = _photoEditor;
|
||||
CMTime endTime = CMTimeSubtract(_player.currentItem.duration, CMTimeMake(10, 100));
|
||||
if (photoEditor.trimEndValue > DBL_EPSILON && photoEditor.trimEndValue < CMTimeGetSeconds(_player.currentItem.duration))
|
||||
endTime = CMTimeMakeWithSeconds(photoEditor.trimEndValue - 0.1, NSEC_PER_SEC);
|
||||
if (_scrubberView.trimEndValue > DBL_EPSILON && _scrubberView.trimEndValue < CMTimeGetSeconds(_player.currentItem.duration))
|
||||
endTime = CMTimeMakeWithSeconds(_scrubberView.trimEndValue - 0.1, NSEC_PER_SEC);
|
||||
|
||||
CMTime startTime = CMTimeMake(5, 100);
|
||||
if (photoEditor.trimStartValue > DBL_EPSILON)
|
||||
startTime = CMTimeMakeWithSeconds(photoEditor.trimStartValue + 0.05, NSEC_PER_SEC);
|
||||
if (_scrubberView.trimStartValue > DBL_EPSILON)
|
||||
startTime = CMTimeMakeWithSeconds(_scrubberView.trimStartValue + 0.05, NSEC_PER_SEC);
|
||||
|
||||
__weak TGPhotoEditorController *weakSelf = self;
|
||||
_playerReachedEndObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:endTime]] queue:NULL usingBlock:^
|
||||
@@ -604,7 +615,7 @@
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && !strongSelf->_dismissed) {
|
||||
[strongSelf->_player seekToTime:startTime];
|
||||
[strongSelf->_scrubberView setValue:strongSelf->_photoEditor.trimEndValue resetPosition:true];
|
||||
[strongSelf->_scrubberView setValue:strongSelf->_scrubberView.trimStartValue resetPosition:true];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -617,8 +628,8 @@
|
||||
|
||||
if (reset) {
|
||||
NSTimeInterval startPosition = 0.0f;
|
||||
if (_photoEditor.trimStartValue > DBL_EPSILON)
|
||||
startPosition = _photoEditor.trimStartValue;
|
||||
if (_scrubberView.trimStartValue > DBL_EPSILON)
|
||||
startPosition = _scrubberView.trimStartValue;
|
||||
|
||||
CMTime targetTime = CMTimeMakeWithSeconds(startPosition, NSEC_PER_SEC);
|
||||
[_player.currentItem seekToTime:targetTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
|
||||
@@ -650,6 +661,8 @@
|
||||
[_player removeObserver:self forKeyPath:@"rate" context:nil];
|
||||
_registeredKeypathObserver = false;
|
||||
}
|
||||
|
||||
[_scrubberView setIsPlaying:false];
|
||||
}
|
||||
|
||||
_isPlaying = false;
|
||||
@@ -1064,7 +1077,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)presentEditorTab:(TGPhotoEditorTab)tab
|
||||
- (void)presentTab:(TGPhotoEditorTab)tab
|
||||
{
|
||||
if (_switchingTab || (tab == _currentTab && _currentTabController != nil))
|
||||
return;
|
||||
@@ -1087,7 +1100,7 @@
|
||||
|
||||
transitionReferenceFrame = [currentController transitionOutReferenceFrame];
|
||||
transitionReferenceView = [currentController transitionOutReferenceView];
|
||||
transitionNoTransitionView = [currentController isKindOfClass:[TGPhotoAvatarCropController class]];
|
||||
transitionNoTransitionView = [currentController isKindOfClass:[TGPhotoAvatarPreviewController class]];
|
||||
|
||||
currentController.switchingToTab = tab;
|
||||
[currentController transitionOutSwitching:true completion:^
|
||||
@@ -1142,59 +1155,15 @@
|
||||
TGPhotoEditorTabController *controller = nil;
|
||||
switch (tab)
|
||||
{
|
||||
case TGPhotoEditorPaintTab:
|
||||
{
|
||||
TGPhotoPaintController *paintController = [[TGPhotoPaintController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
||||
paintController.stickersContext = _stickersContext;
|
||||
paintController.toolbarLandscapeSize = TGPhotoEditorToolbarSize;
|
||||
paintController.controlVideoPlayback = ^(bool play) {
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
if (play) {
|
||||
[strongSelf startVideoPlayback:false];
|
||||
} else {
|
||||
[strongSelf stopVideoPlayback:false];
|
||||
}
|
||||
};
|
||||
paintController.beginTransitionIn = ^UIView *(CGRect *referenceFrame, UIView **parentView, bool *noTransitionView)
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return nil;
|
||||
|
||||
*referenceFrame = transitionReferenceFrame;
|
||||
*parentView = transitionParentView;
|
||||
*noTransitionView = transitionNoTransitionView;
|
||||
|
||||
return transitionReferenceView;
|
||||
};
|
||||
paintController.finishedTransitionIn = ^
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if (isInitialAppearance && strongSelf.finishedTransitionIn != nil)
|
||||
strongSelf.finishedTransitionIn();
|
||||
|
||||
strongSelf->_switchingTab = false;
|
||||
[strongSelf startVideoPlayback:true];
|
||||
};
|
||||
|
||||
controller = paintController;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGPhotoEditorCropTab:
|
||||
{
|
||||
__block UIView *initialBackgroundView = nil;
|
||||
|
||||
if ([self presentedForAvatarCreation])
|
||||
{
|
||||
TGPhotoAvatarCropController *cropController = [[TGPhotoAvatarCropController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
||||
|
||||
bool skipInitialTransition = (![self presentedFromCamera] && self.navigationController != nil) || self.skipInitialTransition;
|
||||
|
||||
TGPhotoAvatarPreviewController *cropController = [[TGPhotoAvatarPreviewController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView scrubberView:_scrubberView dotImageView:_dotImageView];
|
||||
cropController.fromCamera = [self presentedFromCamera];
|
||||
cropController.skipTransitionIn = skipInitialTransition;
|
||||
if (snapshotView != nil)
|
||||
@@ -1212,13 +1181,37 @@
|
||||
[strongSelf stopVideoPlayback:false];
|
||||
}
|
||||
};
|
||||
cropController.togglePlayback = ^{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil || !strongSelf->_item.isVideo)
|
||||
return;
|
||||
|
||||
if (strongSelf->_isPlaying) {
|
||||
[strongSelf stopVideoPlayback:false];
|
||||
[strongSelf setPlayButtonHidden:false animated:true];
|
||||
} else {
|
||||
[strongSelf startVideoPlayback:true];
|
||||
[strongSelf setPlayButtonHidden:true animated:true];
|
||||
}
|
||||
};
|
||||
cropController.croppingChanged = ^{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
[strongSelf->_scrubberView updateThumbnails];
|
||||
|
||||
strongSelf->_dotImageView.cropRect = strongSelf->_photoEditor.cropRect;
|
||||
strongSelf->_dotImageView.cropOrientation = strongSelf->_photoEditor.cropOrientation;
|
||||
strongSelf->_dotImageView.cropMirrored = strongSelf->_photoEditor.cropMirrored;
|
||||
[strongSelf->_dotImageView updateCropping:true];
|
||||
}
|
||||
};
|
||||
cropController.beginTransitionIn = ^UIView *(CGRect *referenceFrame, UIView **parentView, bool *noTransitionView)
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
*referenceFrame = transitionReferenceFrame;
|
||||
*noTransitionView = transitionNoTransitionView;
|
||||
*parentView = transitionParentView;
|
||||
|
||||
|
||||
if (strongSelf != nil)
|
||||
{
|
||||
UIView *backgroundView = nil;
|
||||
@@ -1240,7 +1233,7 @@
|
||||
}
|
||||
|
||||
[UIView animateWithDuration:0.3f animations:^
|
||||
{
|
||||
{
|
||||
backgroundView.alpha = 1.0f;
|
||||
}];
|
||||
}
|
||||
@@ -1304,19 +1297,15 @@
|
||||
{
|
||||
if (cropController.dismissing && !cropController.switching)
|
||||
return;
|
||||
|
||||
|
||||
[self updateDoneButtonEnabled:!image.degraded animated:true];
|
||||
if (image.degraded)
|
||||
{
|
||||
if (image.degraded) {
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
self.fullSizeImage = image;
|
||||
[cropController setImage:image];
|
||||
}
|
||||
}];
|
||||
|
||||
controller = cropController;
|
||||
}
|
||||
else
|
||||
@@ -1415,6 +1404,50 @@
|
||||
}
|
||||
break;
|
||||
|
||||
case TGPhotoEditorPaintTab:
|
||||
{
|
||||
TGPhotoPaintController *paintController = [[TGPhotoPaintController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
||||
paintController.stickersContext = _stickersContext;
|
||||
paintController.toolbarLandscapeSize = TGPhotoEditorToolbarSize;
|
||||
paintController.controlVideoPlayback = ^(bool play) {
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
if (play) {
|
||||
[strongSelf startVideoPlayback:false];
|
||||
} else {
|
||||
[strongSelf stopVideoPlayback:false];
|
||||
}
|
||||
};
|
||||
paintController.beginTransitionIn = ^UIView *(CGRect *referenceFrame, UIView **parentView, bool *noTransitionView)
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return nil;
|
||||
|
||||
*referenceFrame = transitionReferenceFrame;
|
||||
*parentView = transitionParentView;
|
||||
*noTransitionView = transitionNoTransitionView;
|
||||
|
||||
return transitionReferenceView;
|
||||
};
|
||||
paintController.finishedTransitionIn = ^
|
||||
{
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if (isInitialAppearance && strongSelf.finishedTransitionIn != nil)
|
||||
strongSelf.finishedTransitionIn();
|
||||
|
||||
strongSelf->_switchingTab = false;
|
||||
[strongSelf startVideoPlayback:true];
|
||||
};
|
||||
|
||||
controller = paintController;
|
||||
}
|
||||
break;
|
||||
|
||||
case TGPhotoEditorToolsTab:
|
||||
{
|
||||
TGPhotoToolsController *toolsController = [[TGPhotoToolsController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
||||
@@ -1495,14 +1528,7 @@
|
||||
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf != nil) {
|
||||
if ([currentController isKindOfClass:[TGPhotoAvatarCropController class]]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[strongSelf stopVideoPlayback:false];
|
||||
[strongSelf seekVideo:0];
|
||||
});
|
||||
} else {
|
||||
[strongSelf startVideoPlayback:true];
|
||||
}
|
||||
[strongSelf startVideoPlayback:true];
|
||||
}
|
||||
|
||||
return transitionReferenceView;
|
||||
@@ -1516,10 +1542,6 @@
|
||||
if (isInitialAppearance && strongSelf.finishedTransitionIn != nil)
|
||||
strongSelf.finishedTransitionIn();
|
||||
|
||||
if ([currentController isKindOfClass:[TGPhotoAvatarCropController class]]) {
|
||||
[strongSelf startVideoPlayback:false];
|
||||
}
|
||||
|
||||
strongSelf->_switchingTab = false;
|
||||
};
|
||||
previewController.controlVideoPlayback = ^(bool play) {
|
||||
@@ -1684,8 +1706,8 @@
|
||||
|
||||
- (void)dismissEditor
|
||||
{
|
||||
if ((![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]] && ![_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]]) && [self presentedForAvatarCreation]) {
|
||||
[self presentEditorTab:TGPhotoEditorPreviewTab];
|
||||
if (![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]] && [self presentedForAvatarCreation]) {
|
||||
[self presentTab:TGPhotoEditorPreviewTab];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1778,7 +1800,7 @@
|
||||
- (void)doneButtonPressed
|
||||
{
|
||||
if ([self presentedForAvatarCreation] && ![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]]) {
|
||||
[self presentEditorTab:TGPhotoEditorPreviewTab];
|
||||
[self presentTab:TGPhotoEditorPreviewTab];
|
||||
} else {
|
||||
[self applyEditor];
|
||||
}
|
||||
@@ -1876,9 +1898,12 @@
|
||||
fullImage = TGPhotoEditorVideoCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, CGSizeMake(640, 640), item.originalSize, true, false);
|
||||
}
|
||||
|
||||
NSTimeInterval duration = trimEndValue - trimStartValue;
|
||||
TGMediaVideoConversionPreset preset = duration < 4.0 ? TGMediaVideoConversionPresetProfileHigh : TGMediaVideoConversionPresetProfile;
|
||||
|
||||
TGDispatchOnMainThread(^{
|
||||
if (self.didFinishEditingVideo != nil)
|
||||
self.didFinishEditingVideo(asset.URL, [adjustments editAdjustmentsWithPreset:TGMediaVideoConversionPresetProfile videoStartValue:videoStartValue trimStartValue:trimStartValue trimEndValue:trimEndValue], fullImage, nil, true);
|
||||
self.didFinishEditingVideo(asset.URL, [adjustments editAdjustmentsWithPreset:preset videoStartValue:videoStartValue trimStartValue:trimStartValue trimEndValue:trimEndValue], fullImage, nil, true);
|
||||
|
||||
[self dismissAnimated:true];
|
||||
});
|
||||
@@ -2234,7 +2259,7 @@
|
||||
_portraitToolbarView.frame = CGRectMake(screenEdges.left, portraitToolbarViewBottomEdge - TGPhotoEditorToolbarSize - safeAreaInset.bottom, referenceSize.width, TGPhotoEditorToolbarSize + safeAreaInset.bottom);
|
||||
|
||||
_scrubberView.frame = CGRectMake(0.0, 0.0, _portraitToolbarView.frame.size.width, _scrubberView.frame.size.height);
|
||||
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (!_initializedScrubber) {
|
||||
[_scrubberView layoutSubviews];
|
||||
@@ -2250,15 +2275,15 @@
|
||||
- (void)_setScreenImage:(UIImage *)screenImage
|
||||
{
|
||||
_screenImage = screenImage;
|
||||
if ([_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
||||
[(TGPhotoAvatarCropController *)_currentTabController setSnapshotImage:screenImage];
|
||||
if ([_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]])
|
||||
[(TGPhotoAvatarPreviewController *)_currentTabController setSnapshotImage:screenImage];
|
||||
}
|
||||
|
||||
- (void)_finishedTransitionIn
|
||||
{
|
||||
_switchingTab = false;
|
||||
if ([_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
||||
[(TGPhotoAvatarCropController *)_currentTabController _finishedTransitionIn];
|
||||
if ([_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]])
|
||||
[(TGPhotoAvatarPreviewController *)_currentTabController _finishedTransitionIn];
|
||||
}
|
||||
|
||||
- (CGFloat)toolbarLandscapeSize
|
||||
@@ -2271,25 +2296,23 @@
|
||||
return _transitionWrapperView;
|
||||
}
|
||||
|
||||
- (void)layoutProgressView {
|
||||
if (_progressView.superview == nil)
|
||||
[_containerView addSubview:_progressView];
|
||||
|
||||
CGSize referenceSize = [self referenceViewSize];
|
||||
CGRect containerFrame = [TGPhotoEditorTabController photoContainerFrameForParentViewFrame:CGRectMake(0, 0, referenceSize.width, referenceSize.height) toolbarLandscapeSize:self.toolbarLandscapeSize orientation:self.effectiveOrientation panelSize:0.0 hasOnScreenNavigation:self.hasOnScreenNavigation];
|
||||
|
||||
_progressView.frame = (CGRect){{CGFloor(CGRectGetMidX(containerFrame) - _progressView.frame.size.width / 2.0f), CGFloor(CGRectGetMidY(containerFrame) - _progressView.frame.size.height / 2.0f)}, _progressView.frame.size};
|
||||
}
|
||||
|
||||
- (void)setProgressVisible:(bool)progressVisible value:(CGFloat)value animated:(bool)animated
|
||||
{
|
||||
_progressVisible = progressVisible;
|
||||
|
||||
if (progressVisible && _progressView == nil)
|
||||
{
|
||||
_progressView = [[TGMessageImageViewOverlayView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 50.0f, 50.0f)];
|
||||
_progressView.userInteractionEnabled = false;
|
||||
|
||||
CGSize referenceSize = [self referenceViewSize];
|
||||
CGRect containerFrame = [TGPhotoEditorTabController photoContainerFrameForParentViewFrame:CGRectMake(0, 0, referenceSize.width, referenceSize.height) toolbarLandscapeSize:self.toolbarLandscapeSize orientation:self.effectiveOrientation panelSize:0.0 hasOnScreenNavigation:self.hasOnScreenNavigation];
|
||||
|
||||
_progressView.frame = (CGRect){{CGFloor(CGRectGetMidX(containerFrame) - _progressView.frame.size.width / 2.0f), CGFloor(CGRectGetMidY(containerFrame) - _progressView.frame.size.height / 2.0f)}, _progressView.frame.size};
|
||||
}
|
||||
|
||||
if (progressVisible)
|
||||
{
|
||||
if (_progressView.superview == nil)
|
||||
[_containerView addSubview:_progressView];
|
||||
[self layoutProgressView];
|
||||
|
||||
_progressView.alpha = 1.0f;
|
||||
}
|
||||
@@ -2306,8 +2329,9 @@
|
||||
[_progressView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
else
|
||||
else {
|
||||
[_progressView removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
[_progressView setProgress:value cancelEnabled:false animated:animated];
|
||||
@@ -2383,23 +2407,29 @@
|
||||
|
||||
- (void)setPlayButtonHidden:(bool)hidden animated:(bool)animated
|
||||
{
|
||||
// if (animated)
|
||||
// {
|
||||
// _actionButton.hidden = false;
|
||||
// [UIView animateWithDuration:0.15f animations:^
|
||||
// {
|
||||
// _actionButton.alpha = hidden ? 0.0f : 1.0f;
|
||||
// } completion:^(BOOL finished)
|
||||
// {
|
||||
// if (finished)
|
||||
// _actionButton.hidden = hidden;
|
||||
// }];
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _actionButton.alpha = hidden ? 0.0f : 1.0f;
|
||||
// _actionButton.hidden = hidden;
|
||||
// }
|
||||
if (!hidden) {
|
||||
[_progressView setPlay];
|
||||
[self layoutProgressView];
|
||||
}
|
||||
|
||||
if (animated)
|
||||
{
|
||||
_progressView.hidden = false;
|
||||
_progressView.alpha = 0.0f;
|
||||
[UIView animateWithDuration:0.15f animations:^
|
||||
{
|
||||
_progressView.alpha = hidden ? 0.0f : 1.0f;
|
||||
} completion:^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
_progressView.hidden = hidden;
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
_progressView.alpha = hidden ? 0.0f : 1.0f;
|
||||
_progressView.hidden = hidden;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Video Scrubber Data Source & Delegate
|
||||
@@ -2417,10 +2447,7 @@
|
||||
|
||||
- (CGFloat)videoScrubberThumbnailAspectRatio:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
||||
{
|
||||
if (CGSizeEqualToSize(self.item.originalSize, CGSizeZero))
|
||||
return 1.0f;
|
||||
|
||||
return self.item.originalSize.width / self.item.originalSize.height;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
- (void)videoScrubberDidBeginScrubbing:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
||||
@@ -2436,6 +2463,36 @@
|
||||
[previewController beginScrubbing:true];
|
||||
}
|
||||
|
||||
- (void)resetDotImage {
|
||||
UIView *snapshotView = nil;
|
||||
UIView *dotSnapshotView = nil;
|
||||
if (_dotImageView.image != nil) {
|
||||
dotSnapshotView = [_dotMarkerView snapshotViewAfterScreenUpdates:false];
|
||||
dotSnapshotView.frame = _dotMarkerView.frame;
|
||||
[_dotMarkerView.superview addSubview:dotSnapshotView];
|
||||
|
||||
snapshotView = [_dotImageView snapshotViewAfterScreenUpdates:false];
|
||||
snapshotView.frame = [_dotImageView.superview convertRect:_dotImageView.frame toView:_dotMarkerView.superview];
|
||||
[_dotMarkerView.superview addSubview:snapshotView];
|
||||
}
|
||||
|
||||
if (snapshotView != nil) {
|
||||
[UIView animateWithDuration:0.15 animations:^{
|
||||
snapshotView.center = _dotMarkerView.center;
|
||||
snapshotView.transform = CGAffineTransformMakeScale(0.05, 0.05);
|
||||
snapshotView.alpha = 0.0f;
|
||||
dotSnapshotView.transform = CGAffineTransformMakeScale(0.3, 0.3);
|
||||
dotSnapshotView.alpha = 0.0f;
|
||||
} completion:^(BOOL finished) {
|
||||
[snapshotView removeFromSuperview];
|
||||
[dotSnapshotView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
|
||||
_dotImageView.image = nil;
|
||||
_dotMarkerView.hidden = true;
|
||||
}
|
||||
|
||||
- (void)updateDotImage:(bool)animated {
|
||||
AVPlayer *player = _player;
|
||||
if (player == nil) {
|
||||
@@ -2459,19 +2516,7 @@
|
||||
[editor setImage:image forCropRect:adjustments.cropRect cropRotation:0.0 cropOrientation:adjustments.cropOrientation cropMirrored:adjustments.cropMirrored fullSize:false];
|
||||
image = editor.currentResultImage;
|
||||
}
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(160.0, 160.0), false, 1.0);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGContextAddEllipseInRect(context, CGRectMake(0.0, 0.0, 160.0, 160.0));
|
||||
CGContextClip(context);
|
||||
|
||||
CGSize filledSize = TGScaleToFill(image.size, CGSizeMake(160, 160));
|
||||
[image drawInRect:CGRectMake((160.0 - filledSize.width) / 2.0, (160.0 - filledSize.height) / 2.0, filledSize.width, filledSize.height)];
|
||||
|
||||
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
|
||||
TGDispatchOnMainThread(^{
|
||||
if (animated) {
|
||||
UIView *snapshotView = nil;
|
||||
@@ -2499,7 +2544,13 @@
|
||||
}];
|
||||
}
|
||||
|
||||
_dotImageView.image = finalImage;
|
||||
_dotMarkerView.hidden = false;
|
||||
_dotImageView.image = image;
|
||||
_dotImageView.cropRect = _photoEditor.cropRect;
|
||||
_dotImageView.cropOrientation = _photoEditor.cropOrientation;
|
||||
_dotImageView.cropMirrored = _photoEditor.cropMirrored;
|
||||
[_dotImageView updateCropping];
|
||||
|
||||
[_scrubberView addSubview:_dotMarkerView];
|
||||
|
||||
_dotMarkerView.center = CGPointMake([_scrubberView scrubberPositionForPosition:_dotPosition].x + 7.0, 9.5);
|
||||
@@ -2516,7 +2567,7 @@
|
||||
containerFrame.origin.x += screenEdges.left;
|
||||
containerFrame.origin.y += screenEdges.top;
|
||||
|
||||
CGFloat scale = containerFrame.size.width / 160.0;
|
||||
CGFloat scale = (containerFrame.size.width - [TGPhotoAvatarCropView areaInsetSize].width * 2.0) / 160.0;
|
||||
_dotImageView.center = CGPointMake(CGRectGetMidX(containerFrame), CGRectGetMidY(containerFrame));
|
||||
_dotImageView.transform = CGAffineTransformMakeScale(scale, scale);
|
||||
|
||||
@@ -2539,7 +2590,12 @@
|
||||
[_dotImageView addSubview:snapshotView];
|
||||
}
|
||||
|
||||
_dotImageView.image = finalImage;
|
||||
_dotMarkerView.hidden = false;
|
||||
_dotImageView.image = image;
|
||||
_dotImageView.cropRect = _photoEditor.cropRect;
|
||||
_dotImageView.cropOrientation = _photoEditor.cropOrientation;
|
||||
_dotImageView.cropMirrored = _photoEditor.cropMirrored;
|
||||
[_dotImageView updateCropping];
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2594,21 +2650,34 @@
|
||||
|
||||
- (void)videoScrubberDidEndEditing:(TGMediaPickerGalleryVideoScrubber *)videoScrubber
|
||||
{
|
||||
if (_resetDotPosition) {
|
||||
_dotPosition = videoScrubber.trimStartValue;
|
||||
_resetDotPosition = false;
|
||||
}
|
||||
|
||||
[self setVideoEndTime:videoScrubber.trimEndValue];
|
||||
|
||||
[self seekVideo:videoScrubber.trimStartValue];
|
||||
[self stopVideoPlayback:false];
|
||||
[videoScrubber resetToStart];
|
||||
[self startVideoPlayback:true];
|
||||
|
||||
[self setPlayButtonHidden:true animated:false];
|
||||
}
|
||||
|
||||
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber editingStartValueDidChange:(NSTimeInterval)startValue
|
||||
{
|
||||
if (startValue > _dotPosition) {
|
||||
_resetDotPosition = true;
|
||||
[self resetDotImage];
|
||||
}
|
||||
[self seekVideo:startValue];
|
||||
}
|
||||
|
||||
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber editingEndValueDidChange:(NSTimeInterval)endValue
|
||||
{
|
||||
if (endValue < _dotPosition) {
|
||||
_resetDotPosition = true;
|
||||
[self resetDotImage];
|
||||
}
|
||||
[self seekVideo:endValue];
|
||||
}
|
||||
|
||||
@@ -2635,6 +2704,18 @@
|
||||
return timestamps;
|
||||
}
|
||||
|
||||
- (NSArray *)_placeholderThumbnails:(NSArray *)timestamps {
|
||||
NSMutableArray *thumbnails = [[NSMutableArray alloc] init];
|
||||
UIImage *blurredImage = TGBlurredRectangularImage(_screenImage, true, _screenImage.size, _screenImage.size, NULL, nil);
|
||||
for (__unused NSNumber *value in timestamps) {
|
||||
if (thumbnails.count == 0)
|
||||
[thumbnails addObject:_screenImage];
|
||||
else
|
||||
[thumbnails addObject:blurredImage];
|
||||
}
|
||||
return thumbnails;
|
||||
}
|
||||
|
||||
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber requestThumbnailImagesForTimestamps:(NSArray *)timestamps size:(CGSize)size isSummaryThumbnails:(bool)isSummaryThumbnails
|
||||
{
|
||||
if (timestamps.count == 0)
|
||||
@@ -2643,18 +2724,27 @@
|
||||
id<TGMediaEditAdjustments> adjustments = [_photoEditor exportAdjustments];
|
||||
|
||||
SSignal *thumbnailsSignal = nil;
|
||||
if ([self.item isKindOfClass:[TGMediaAsset class]]) {
|
||||
thumbnailsSignal = [TGMediaAssetImageSignals videoThumbnailsForAsset:(TGMediaAsset *)self.item size:size timestamps:timestamps];
|
||||
if (_cachedThumbnails != nil) {
|
||||
thumbnailsSignal = [SSignal single:_cachedThumbnails];
|
||||
} else if ([self.item isKindOfClass:[TGMediaAsset class]]) {
|
||||
thumbnailsSignal = [[SSignal single:[self _placeholderThumbnails:timestamps]] then:[TGMediaAssetImageSignals videoThumbnailsForAsset:(TGMediaAsset *)self.item size:size timestamps:timestamps]];
|
||||
} else if ([self.item isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||
thumbnailsSignal = [[((TGCameraCapturedVideo *)self.item).avAsset takeLast] mapToSignal:^SSignal *(AVAsset *avAsset) {
|
||||
return [TGMediaAssetImageSignals videoThumbnailsForAVAsset:avAsset size:size timestamps:timestamps];
|
||||
return [[SSignal single:[self _placeholderThumbnails:timestamps]] then:[TGMediaAssetImageSignals videoThumbnailsForAVAsset:avAsset size:size timestamps:timestamps]];
|
||||
}];
|
||||
}
|
||||
|
||||
_requestingThumbnails = true;
|
||||
|
||||
__weak TGPhotoEditorController *weakSelf = self;
|
||||
[_thumbnailsDisposable setDisposable:[[[thumbnailsSignal map:^NSArray *(NSArray *images) {
|
||||
[_thumbnailsDisposable setDisposable:[[[[thumbnailsSignal onNext:^(NSArray *images) {
|
||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
return;
|
||||
|
||||
if (strongSelf->_cachedThumbnails == nil)
|
||||
strongSelf->_cachedThumbnails = images;
|
||||
}] map:^NSArray *(NSArray *images) {
|
||||
if (adjustments.toolsApplied) {
|
||||
NSMutableArray *editedImages = [[NSMutableArray alloc] init];
|
||||
PGPhotoEditor *editor = [[PGPhotoEditor alloc] initWithOriginalSize:adjustments.originalSize adjustments:adjustments forVideo:false enableStickers:true];
|
||||
@@ -2681,7 +2771,7 @@
|
||||
[images enumerateObjectsUsingBlock:^(UIImage *image, NSUInteger index, __unused BOOL *stop)
|
||||
{
|
||||
if (index < timestamps.count)
|
||||
[strongSelf->_scrubberView setThumbnailImage:image forTimestamp:[timestamps[index] doubleValue] isSummaryThubmnail:isSummaryThumbnails];
|
||||
[strongSelf->_scrubberView setThumbnailImage:image forTimestamp:[timestamps[index] doubleValue] index:index isSummaryThubmnail:isSummaryThumbnails];
|
||||
}];
|
||||
|
||||
if (strongSelf->_dotImageSnapshotView != nil) {
|
||||
|
||||
Reference in New Issue
Block a user