mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Video avatar fixes
This commit is contained in:
parent
51a95f3f6f
commit
53572b9631
@ -16,7 +16,7 @@ UIImage *TGReducedAttachmentImage(UIImage *source, CGSize originalSize, bool att
|
|||||||
UIImage *TGBlurredBackgroundImage(UIImage *source, CGSize size);
|
UIImage *TGBlurredBackgroundImage(UIImage *source, CGSize size);
|
||||||
UIImage *TGRoundImage(UIImage *source, CGSize size);
|
UIImage *TGRoundImage(UIImage *source, CGSize size);
|
||||||
UIImage *TGBlurredAlphaImage(UIImage *source, CGSize size);
|
UIImage *TGBlurredAlphaImage(UIImage *source, CGSize size);
|
||||||
UIImage *TGBlurredRectangularImage(UIImage *source, CGSize size, CGSize renderSize, uint32_t *averageColor, void (^pixelProcessingBlock)(void *, int, int, int));
|
UIImage *TGBlurredRectangularImage(UIImage *source, bool more, CGSize size, CGSize renderSize, uint32_t *averageColor, void (^pixelProcessingBlock)(void *, int, int, int));
|
||||||
|
|
||||||
UIImage *TGCropBackdropImage(UIImage *source, CGSize size);
|
UIImage *TGCropBackdropImage(UIImage *source, CGSize size);
|
||||||
UIImage *TGCameraPositionSwitchImage(UIImage *source, CGSize size);
|
UIImage *TGCameraPositionSwitchImage(UIImage *source, CGSize size);
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@class AVPlayer;
|
@class PGPhotoEditorView;
|
||||||
|
|
||||||
@interface TGPhotoAvatarCropView : UIView
|
@interface TGPhotoAvatarCropView : UIView
|
||||||
|
|
||||||
|
@property (nonatomic, readonly) PGPhotoEditorView *fullPreviewView;
|
||||||
|
|
||||||
@property (nonatomic, strong) UIImage *image;
|
@property (nonatomic, strong) UIImage *image;
|
||||||
@property (nonatomic, strong) AVPlayer *player;
|
|
||||||
|
|
||||||
@property (nonatomic, readonly) CGSize originalSize;
|
@property (nonatomic, readonly) CGSize originalSize;
|
||||||
@property (nonatomic, assign) CGRect cropRect;
|
@property (nonatomic, assign) CGRect cropRect;
|
||||||
@ -16,6 +17,8 @@
|
|||||||
@property (nonatomic, copy) void(^interactionBegan)(void);
|
@property (nonatomic, copy) void(^interactionBegan)(void);
|
||||||
@property (nonatomic, copy) void(^interactionEnded)(void);
|
@property (nonatomic, copy) void(^interactionEnded)(void);
|
||||||
|
|
||||||
|
@property (nonatomic, copy) void(^tapped)(void);
|
||||||
|
|
||||||
@property (nonatomic, readonly) bool isTracking;
|
@property (nonatomic, readonly) bool isTracking;
|
||||||
@property (nonatomic, readonly) bool isAnimating;
|
@property (nonatomic, readonly) bool isAnimating;
|
||||||
|
|
||||||
@ -35,7 +38,6 @@
|
|||||||
- (void)transitionInFinishedFromCamera:(bool)fromCamera;
|
- (void)transitionInFinishedFromCamera:(bool)fromCamera;
|
||||||
|
|
||||||
- (void)invalidateCropRect;
|
- (void)invalidateCropRect;
|
||||||
- (void)invalidateVideoView;
|
|
||||||
|
|
||||||
- (UIImage *)currentImage;
|
- (UIImage *)currentImage;
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ typedef enum
|
|||||||
TGMediaVideoConversionPresetCompressedVeryHigh,
|
TGMediaVideoConversionPresetCompressedVeryHigh,
|
||||||
TGMediaVideoConversionPresetAnimation,
|
TGMediaVideoConversionPresetAnimation,
|
||||||
TGMediaVideoConversionPresetVideoMessage,
|
TGMediaVideoConversionPresetVideoMessage,
|
||||||
TGMediaVideoConversionPresetProfile
|
TGMediaVideoConversionPresetProfile,
|
||||||
|
TGMediaVideoConversionPresetProfileHigh,
|
||||||
|
TGMediaVideoConversionPresetPassthrough
|
||||||
} TGMediaVideoConversionPreset;
|
} TGMediaVideoConversionPreset;
|
||||||
|
|
||||||
@interface TGVideoEditAdjustments : NSObject <TGMediaEditAdjustments>
|
@interface TGVideoEditAdjustments : NSObject <TGMediaEditAdjustments>
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
@property (nonatomic, readonly) bool enableStickers;
|
@property (nonatomic, readonly) bool enableStickers;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) bool cropOnLast;
|
||||||
|
|
||||||
@property (nonatomic, readonly) bool forVideo;
|
@property (nonatomic, readonly) bool forVideo;
|
||||||
|
|
||||||
@property (nonatomic, assign) bool standalone;
|
@property (nonatomic, assign) bool standalone;
|
||||||
|
@ -391,7 +391,7 @@
|
|||||||
_currentProcessChain = processChain;
|
_currentProcessChain = processChain;
|
||||||
|
|
||||||
GPUImageOutput <GPUImageInput> *lastFilter = ((PGPhotoProcessPass *)_currentProcessChain.firstObject).filter;
|
GPUImageOutput <GPUImageInput> *lastFilter = ((PGPhotoProcessPass *)_currentProcessChain.firstObject).filter;
|
||||||
if (_cropFilter != nil) {
|
if (_cropFilter != nil && !self.cropOnLast) {
|
||||||
[_currentInput addTarget:_cropFilter];
|
[_currentInput addTarget:_cropFilter];
|
||||||
[_cropFilter addTarget:lastFilter];
|
[_cropFilter addTarget:lastFilter];
|
||||||
} else {
|
} else {
|
||||||
@ -411,13 +411,24 @@
|
|||||||
}
|
}
|
||||||
_finalFilter = lastFilter;
|
_finalFilter = lastFilter;
|
||||||
|
|
||||||
|
if (_cropFilter != nil && self.cropOnLast) {
|
||||||
|
for (PGPhotoEditorView *view in _additionalOutputs) {
|
||||||
|
[_finalFilter addTarget:view];
|
||||||
|
}
|
||||||
|
[_finalFilter addTarget:_cropFilter];
|
||||||
|
_finalFilter = _cropFilter;
|
||||||
|
|
||||||
|
if (previewOutput != nil) {
|
||||||
|
[_finalFilter addTarget:previewOutput.imageView];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (previewOutput != nil) {
|
if (previewOutput != nil) {
|
||||||
[_finalFilter addTarget:previewOutput.imageView];
|
[_finalFilter addTarget:previewOutput.imageView];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PGPhotoEditorView *view in _additionalOutputs) {
|
for (PGPhotoEditorView *view in _additionalOutputs) {
|
||||||
[_finalFilter addTarget:view];
|
[_finalFilter addTarget:view];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_histogramGenerator != nil && !self.standalone) {
|
if (_histogramGenerator != nil && !self.standalone) {
|
||||||
[_finalFilter addTarget:_histogramGenerator];
|
[_finalFilter addTarget:_histogramGenerator];
|
||||||
@ -428,6 +439,9 @@
|
|||||||
- (void)setAdditionalOutputs:(NSArray *)additionalOutputs {
|
- (void)setAdditionalOutputs:(NSArray *)additionalOutputs {
|
||||||
_additionalOutputs = additionalOutputs;
|
_additionalOutputs = additionalOutputs;
|
||||||
|
|
||||||
|
if (_finalFilter == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
[_finalFilter removeAllTargets];
|
[_finalFilter removeAllTargets];
|
||||||
|
|
||||||
if (self.previewOutput != nil) {
|
if (self.previewOutput != nil) {
|
||||||
|
@ -1703,7 +1703,7 @@ UIImage *TGBlurredAlphaImage(UIImage *source, CGSize size)
|
|||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIImage *TGBlurredRectangularImage(UIImage *source, CGSize size, CGSize renderSize, uint32_t *averageColor, void (^pixelProcessingBlock)(void *, int, int, int))
|
UIImage *TGBlurredRectangularImage(UIImage *source, bool more, CGSize size, CGSize renderSize, uint32_t *averageColor, void (^pixelProcessingBlock)(void *, int, int, int))
|
||||||
{
|
{
|
||||||
CGSize fittedSize = fitSize(size, CGSizeMake(90, 90));
|
CGSize fittedSize = fitSize(size, CGSizeMake(90, 90));
|
||||||
CGSize fittedRenderSize = CGSizeMake(fittedSize.width / size.width * renderSize.width, fittedSize.height / size.height * renderSize.height);
|
CGSize fittedRenderSize = CGSizeMake(fittedSize.width / size.width * renderSize.width, fittedSize.height / size.height * renderSize.height);
|
||||||
@ -1733,7 +1733,12 @@ UIImage *TGBlurredRectangularImage(UIImage *source, CGSize size, CGSize renderSi
|
|||||||
[source drawInRect:CGRectMake((blurredContextSize.width - fittedRenderSize.width) / 2.0f, (blurredContextSize.height - fittedRenderSize.height) / 2.0f, fittedRenderSize.width, fittedRenderSize.height) blendMode:kCGBlendModeCopy alpha:1.0f];
|
[source drawInRect:CGRectMake((blurredContextSize.width - fittedRenderSize.width) / 2.0f, (blurredContextSize.height - fittedRenderSize.height) / 2.0f, fittedRenderSize.width, fittedRenderSize.height) blendMode:kCGBlendModeCopy alpha:1.0f];
|
||||||
UIGraphicsPopContext();
|
UIGraphicsPopContext();
|
||||||
|
|
||||||
|
if (more) {
|
||||||
|
fastBlurMore((int)blurredContextSize.width, (int)blurredContextSize.height, (int)blurredBytesPerRow, blurredMemory);
|
||||||
|
fastBlurMore((int)blurredContextSize.width, (int)blurredContextSize.height, (int)blurredBytesPerRow, blurredMemory);
|
||||||
|
} else {
|
||||||
fastBlur((int)blurredContextSize.width, (int)blurredContextSize.height, (int)blurredBytesPerRow, blurredMemory);
|
fastBlur((int)blurredContextSize.width, (int)blurredContextSize.height, (int)blurredBytesPerRow, blurredMemory);
|
||||||
|
}
|
||||||
|
|
||||||
if (averageColor != NULL)
|
if (averageColor != NULL)
|
||||||
{
|
{
|
||||||
@ -2283,12 +2288,12 @@ UIImage *TGCropBackdropImage(UIImage *source, CGSize size)
|
|||||||
|
|
||||||
UIImage *TGCameraPositionSwitchImage(UIImage *source, CGSize size)
|
UIImage *TGCameraPositionSwitchImage(UIImage *source, CGSize size)
|
||||||
{
|
{
|
||||||
return TGBlurredRectangularImage(source, size, size, NULL, nil);
|
return TGBlurredRectangularImage(source, false, size, size, NULL, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIImage *TGCameraModeSwitchImage(UIImage *source, CGSize size)
|
UIImage *TGCameraModeSwitchImage(UIImage *source, CGSize size)
|
||||||
{
|
{
|
||||||
return TGBlurredRectangularImage(source, size, size, NULL, nil);
|
return TGBlurredRectangularImage(source, false, size, size, NULL, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
UIImage *TGScaleAndCropImageToPixelSize(UIImage *source, CGSize size, CGSize renderSize, uint32_t *averageColor, void (^pixelProcessingBlock)(void *, int, int, int))
|
UIImage *TGScaleAndCropImageToPixelSize(UIImage *source, CGSize size, CGSize renderSize, uint32_t *averageColor, void (^pixelProcessingBlock)(void *, int, int, int))
|
||||||
|
@ -707,8 +707,13 @@
|
|||||||
if (grouping && selectedItems.count > 1)
|
if (grouping && selectedItems.count > 1)
|
||||||
groupedId = @([self generateGroupedId]);
|
groupedId = @([self generateGroupedId]);
|
||||||
|
|
||||||
for (TGMediaAsset *asset in selectedItems)
|
for (TGMediaAsset *item in selectedItems)
|
||||||
{
|
{
|
||||||
|
TGMediaAsset *asset = item;
|
||||||
|
if ([asset isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||||
|
asset = ((TGCameraCapturedVideo *)asset).originalAsset;
|
||||||
|
}
|
||||||
|
|
||||||
switch (asset.type)
|
switch (asset.type)
|
||||||
{
|
{
|
||||||
case TGMediaAssetPhotoType:
|
case TGMediaAssetPhotoType:
|
||||||
@ -1044,84 +1049,77 @@
|
|||||||
|
|
||||||
case TGMediaAssetGifType:
|
case TGMediaAssetGifType:
|
||||||
{
|
{
|
||||||
NSString *caption = [editingContext captionForItem:asset];
|
TGCameraCapturedVideo *video = (TGCameraCapturedVideo *)item;
|
||||||
NSArray *entities = [editingContext entitiesForItem:asset];
|
|
||||||
|
|
||||||
[signals addObject:[[[TGMediaAssetImageSignals imageDataForAsset:asset allowNetworkAccess:false] mapToSignal:^SSignal *(TGMediaAssetImageData *assetData)
|
TGVideoEditAdjustments *adjustments = (TGVideoEditAdjustments *)[editingContext adjustmentsForItem:video];
|
||||||
{
|
NSString *caption = [editingContext captionForItem:video];
|
||||||
NSString *tempFileName = TGTemporaryFileName(nil);
|
NSArray *entities = [editingContext entitiesForItem:video];
|
||||||
NSData *data = assetData.imageData;
|
NSNumber *timer = [editingContext timerForItem:video];
|
||||||
|
|
||||||
const char *gif87Header = "GIF87";
|
UIImage *(^cropVideoThumbnail)(UIImage *, CGSize, CGSize, bool) = ^UIImage *(UIImage *image, CGSize targetSize, CGSize sourceSize, bool resize)
|
||||||
const char *gif89Header = "GIF89";
|
|
||||||
if (data.length >= 5 && (!memcmp(data.bytes, gif87Header, 5) || !memcmp(data.bytes, gif89Header, 5)))
|
|
||||||
{
|
{
|
||||||
return [[[TGGifConverter convertGifToMp4:data] map:^id(NSDictionary *result)
|
if ([adjustments cropAppliedForAvatar:false] || adjustments.hasPainting || adjustments.toolsApplied)
|
||||||
{
|
{
|
||||||
NSString *filePath = result[@"path"];
|
CGRect scaledCropRect = CGRectMake(adjustments.cropRect.origin.x * image.size.width / adjustments.originalSize.width, adjustments.cropRect.origin.y * image.size.height / adjustments.originalSize.height, adjustments.cropRect.size.width * image.size.width / adjustments.originalSize.width, adjustments.cropRect.size.height * image.size.height / adjustments.originalSize.height);
|
||||||
|
UIImage *paintingImage = adjustments.paintingData.stillImage;
|
||||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
if (paintingImage == nil) {
|
||||||
dict[@"type"] = @"file";
|
paintingImage = adjustments.paintingData.image;
|
||||||
dict[@"tempFileUrl"] = [NSURL fileURLWithPath:filePath];
|
|
||||||
dict[@"fileName"] = @"animation.mp4";
|
|
||||||
dict[@"mimeType"] = @"video/mp4";
|
|
||||||
dict[@"isAnimation"] = @true;
|
|
||||||
if (result[@"dimensions"] != nil) {
|
|
||||||
dict[@"dimensions"] = result[@"dimensions"];
|
|
||||||
}
|
}
|
||||||
if (result[@"duration"] != nil) {
|
if (adjustments.toolsApplied) {
|
||||||
dict[@"duration"] = result[@"duration"];
|
image = [PGPhotoEditor resultImageForImage:image adjustments:adjustments];
|
||||||
}
|
}
|
||||||
if (result[@"previewImage"] != nil) {
|
return TGPhotoEditorCrop(image, paintingImage, adjustments.cropOrientation, 0, scaledCropRect, adjustments.cropMirrored, targetSize, sourceSize, resize);
|
||||||
dict[@"previewImage"] = result[@"previewImage"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id generatedItem = descriptionGenerator(dict, caption, entities, nil);
|
return image;
|
||||||
return generatedItem;
|
};
|
||||||
}] catch:^SSignal *(id error)
|
|
||||||
|
CGSize imageSize = TGFillSize(video.originalSize, CGSizeMake(512, 512));
|
||||||
|
SSignal *trimmedVideoThumbnailSignal = [[video avAsset] mapToSignal:^SSignal *(AVURLAsset *avAsset) {
|
||||||
|
return [[TGMediaAssetImageSignals videoThumbnailForAVAsset:avAsset size:imageSize timestamp:CMTimeMakeWithSeconds(adjustments.trimStartValue, NSEC_PER_SEC)] map:^UIImage *(UIImage *image)
|
||||||
{
|
{
|
||||||
[data writeToURL:[NSURL fileURLWithPath:tempFileName] atomically:true];
|
return cropVideoThumbnail(image, TGScaleToFill(video.originalSize, CGSizeMake(512, 512)), video.originalSize, true);
|
||||||
|
|
||||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
|
||||||
dict[@"type"] = @"file";
|
|
||||||
dict[@"tempFileUrl"] = [NSURL fileURLWithPath:tempFileName];
|
|
||||||
dict[@"fileName"] = assetData.fileName;
|
|
||||||
dict[@"mimeType"] = TGMimeTypeForFileUTI(assetData.fileUTI);
|
|
||||||
|
|
||||||
id generatedItem = descriptionGenerator(dict, caption, entities, nil);
|
|
||||||
return [SSignal single:generatedItem];
|
|
||||||
}];
|
}];
|
||||||
}
|
}];
|
||||||
else
|
|
||||||
|
SSignal *videoThumbnailSignal = [[video thumbnailImageSignal] map:^UIImage *(UIImage *image)
|
||||||
{
|
{
|
||||||
[data writeToURL:[NSURL fileURLWithPath:tempFileName] atomically:true];
|
return cropVideoThumbnail(image, image.size, image.size, false);
|
||||||
|
}];
|
||||||
|
|
||||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
SSignal *thumbnailSignal = adjustments.trimStartValue > FLT_EPSILON ? trimmedVideoThumbnailSignal : videoThumbnailSignal;
|
||||||
dict[@"type"] = @"file";
|
|
||||||
dict[@"tempFileUrl"] = [NSURL fileURLWithPath:tempFileName];
|
|
||||||
dict[@"fileName"] = assetData.fileName;
|
|
||||||
dict[@"mimeType"] = TGMimeTypeForFileUTI(assetData.fileUTI);
|
|
||||||
|
|
||||||
id generatedItem = descriptionGenerator(dict, caption, entities, nil);
|
TGMediaVideoConversionPreset preset = TGMediaVideoConversionPresetAnimation;
|
||||||
return [SSignal single:generatedItem];
|
if (adjustments != nil) {
|
||||||
|
adjustments = [adjustments editAdjustmentsWithPreset:preset maxDuration:0.0];
|
||||||
|
} else {
|
||||||
|
adjustments = [TGVideoEditAdjustments editAdjustmentsWithOriginalSize:video.originalSize preset:preset];
|
||||||
}
|
}
|
||||||
}] catch:^SSignal *(id error)
|
CGSize dimensions = [TGMediaVideoConverter dimensionsFor:video.originalSize adjustments:adjustments preset:preset];
|
||||||
{
|
NSTimeInterval duration = adjustments.trimApplied ? (adjustments.trimEndValue - adjustments.trimStartValue) : video.videoDuration;
|
||||||
if (![error isKindOfClass:[NSNumber class]])
|
|
||||||
return [SSignal complete];
|
|
||||||
|
|
||||||
return [inlineThumbnailSignal(asset) map:^id(UIImage *image)
|
[signals addObject:[thumbnailSignal map:^id(UIImage *image)
|
||||||
{
|
{
|
||||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||||
dict[@"type"] = @"cloudPhoto";
|
dict[@"type"] = @"cameraVideo";
|
||||||
dict[@"document"] = @true;
|
dict[@"url"] = ((TGCameraCapturedVideo *)item).immediateAVAsset.URL;
|
||||||
dict[@"asset"] = asset;
|
|
||||||
dict[@"previewImage"] = image;
|
dict[@"previewImage"] = image;
|
||||||
|
dict[@"adjustments"] = adjustments;
|
||||||
|
dict[@"dimensions"] = [NSValue valueWithCGSize:dimensions];
|
||||||
|
dict[@"duration"] = @(duration);
|
||||||
|
|
||||||
|
if (adjustments.paintingData.stickers.count > 0)
|
||||||
|
dict[@"stickers"] = adjustments.paintingData.stickers;
|
||||||
|
if (timer != nil)
|
||||||
|
dict[@"timer"] = timer;
|
||||||
|
else if (groupedId != nil && !hasAnyTimers)
|
||||||
|
dict[@"groupedId"] = groupedId;
|
||||||
|
|
||||||
id generatedItem = descriptionGenerator(dict, caption, entities, nil);
|
id generatedItem = descriptionGenerator(dict, caption, entities, nil);
|
||||||
return generatedItem;
|
return generatedItem;
|
||||||
}];
|
|
||||||
}]];
|
}]];
|
||||||
|
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@
|
|||||||
};
|
};
|
||||||
[itemViews addObject:carouselItem];
|
[itemViews addObject:carouselItem];
|
||||||
|
|
||||||
TGMenuSheetButtonItemView *galleryItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:TGLocalized(@"AttachmentMenu.PhotoOrVideo") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
TGMenuSheetButtonItemView *galleryItem = [[TGMenuSheetButtonItemView alloc] initWithTitle:_signup ? TGLocalized(@"Common.ChoosePhoto") : TGLocalized(@"AttachmentMenu.PhotoOrVideo") type:TGMenuSheetButtonTypeDefault fontSize:20.0 action:^
|
||||||
{
|
{
|
||||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||||
if (strongSelf == nil)
|
if (strongSelf == nil)
|
||||||
|
@ -1635,7 +1635,7 @@
|
|||||||
[images enumerateObjectsUsingBlock:^(UIImage *image, NSUInteger index, __unused BOOL *stop)
|
[images enumerateObjectsUsingBlock:^(UIImage *image, NSUInteger index, __unused BOOL *stop)
|
||||||
{
|
{
|
||||||
if (index < timestamps.count)
|
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];
|
||||||
}];
|
}];
|
||||||
} completed:^
|
} completed:^
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,9 @@
|
|||||||
- (void)ignoreThumbnails;
|
- (void)ignoreThumbnails;
|
||||||
- (void)resetThumbnails;
|
- (void)resetThumbnails;
|
||||||
|
|
||||||
- (void)setThumbnailImage:(UIImage *)image forTimestamp:(NSTimeInterval)timestamp isSummaryThubmnail:(bool)isSummaryThumbnail;
|
- (void)updateThumbnails;
|
||||||
|
|
||||||
|
- (void)setThumbnailImage:(UIImage *)image forTimestamp:(NSTimeInterval)timestamp index:(NSInteger)index isSummaryThubmnail:(bool)isSummaryThumbnail;
|
||||||
|
|
||||||
- (void)setRecipientName:(NSString *)recipientName;
|
- (void)setRecipientName:(NSString *)recipientName;
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ typedef enum
|
|||||||
NSTimeInterval _duration;
|
NSTimeInterval _duration;
|
||||||
|
|
||||||
bool _ignoreThumbnailLoad;
|
bool _ignoreThumbnailLoad;
|
||||||
bool _fadingThumbnailViews;
|
|
||||||
CGFloat _thumbnailAspectRatio;
|
CGFloat _thumbnailAspectRatio;
|
||||||
NSArray *_summaryTimestamps;
|
NSArray *_summaryTimestamps;
|
||||||
NSMutableArray *_summaryThumbnailViews;
|
NSMutableArray *_summaryThumbnailViews;
|
||||||
@ -741,6 +740,41 @@ typedef enum
|
|||||||
[self _resetZooming];
|
[self _resetZooming];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)updateThumbnails {
|
||||||
|
UIView *snapshotView = [_summaryThumbnailWrapperView snapshotViewAfterScreenUpdates:true];
|
||||||
|
snapshotView.frame = _summaryThumbnailWrapperView.frame;
|
||||||
|
[_summaryThumbnailWrapperView.superview insertSubview:snapshotView aboveSubview:_summaryThumbnailWrapperView];
|
||||||
|
|
||||||
|
id<TGMediaPickerGalleryVideoScrubberDataSource> dataSource = self.dataSource;
|
||||||
|
if ([dataSource respondsToSelector:@selector(videoScrubberOriginalSize:cropRect:cropOrientation:cropMirrored:)])
|
||||||
|
_originalSize = [dataSource videoScrubberOriginalSize:self cropRect:&_cropRect cropOrientation:&_cropOrientation cropMirrored:&_cropMirrored];
|
||||||
|
|
||||||
|
for (TGMediaPickerGalleryVideoScrubberThumbnailView *view in _summaryThumbnailWrapperView.subviews) {
|
||||||
|
view.cropRect = _cropRect;
|
||||||
|
view.cropOrientation = _cropOrientation;
|
||||||
|
view.cropMirrored = _cropMirrored;
|
||||||
|
[view updateCropping];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TGMediaPickerGalleryVideoScrubberThumbnailView *view in _zoomedThumbnailWrapperView.subviews) {
|
||||||
|
view.cropRect = _cropRect;
|
||||||
|
view.cropOrientation = _cropOrientation;
|
||||||
|
view.cropMirrored = _cropMirrored;
|
||||||
|
[view updateCropping];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshotView != nil)
|
||||||
|
{
|
||||||
|
[UIView animateWithDuration:0.2f animations:^
|
||||||
|
{
|
||||||
|
snapshotView.alpha = 0.0f;
|
||||||
|
} completion:^(__unused BOOL finished)
|
||||||
|
{
|
||||||
|
[snapshotView removeFromSuperview];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)reloadData
|
- (void)reloadData
|
||||||
{
|
{
|
||||||
[self reloadDataAndReset:true];
|
[self reloadDataAndReset:true];
|
||||||
@ -771,23 +805,29 @@ typedef enum
|
|||||||
[self reloadThumbnails];
|
[self reloadThumbnails];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setThumbnailImage:(UIImage *)image forTimestamp:(NSTimeInterval)__unused timestamp isSummaryThubmnail:(bool)isSummaryThumbnail
|
- (void)setThumbnailImage:(UIImage *)image forTimestamp:(NSTimeInterval)__unused timestamp index:(NSInteger)index isSummaryThubmnail:(bool)isSummaryThumbnail
|
||||||
{
|
{
|
||||||
TGMediaPickerGalleryVideoScrubberThumbnailView *thumbnailView = [[TGMediaPickerGalleryVideoScrubberThumbnailView alloc] initWithImage:image originalSize:_originalSize cropRect:_cropRect cropOrientation:_cropOrientation cropMirrored:_cropMirrored];
|
bool exists = false;
|
||||||
|
|
||||||
if (isSummaryThumbnail)
|
if (isSummaryThumbnail)
|
||||||
{
|
{
|
||||||
|
if (_summaryThumbnailViews.count >= index + 1) {
|
||||||
|
exists = true;
|
||||||
|
[_summaryThumbnailViews[index] setImage:image animated:true];
|
||||||
|
} else {
|
||||||
|
TGMediaPickerGalleryVideoScrubberThumbnailView *thumbnailView = [[TGMediaPickerGalleryVideoScrubberThumbnailView alloc] initWithImage:image originalSize:_originalSize cropRect:_cropRect cropOrientation:_cropOrientation cropMirrored:_cropMirrored];
|
||||||
[_summaryThumbnailWrapperView addSubview:thumbnailView];
|
[_summaryThumbnailWrapperView addSubview:thumbnailView];
|
||||||
[_summaryThumbnailViews addObject:thumbnailView];
|
[_summaryThumbnailViews addObject:thumbnailView];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
TGMediaPickerGalleryVideoScrubberThumbnailView *thumbnailView = [[TGMediaPickerGalleryVideoScrubberThumbnailView alloc] initWithImage:image originalSize:_originalSize cropRect:_cropRect cropOrientation:_cropOrientation cropMirrored:_cropMirrored];
|
||||||
[_zoomedThumbnailWrapperView addSubview:thumbnailView];
|
[_zoomedThumbnailWrapperView addSubview:thumbnailView];
|
||||||
[_zoomedThumbnailViews addObject:thumbnailView];
|
[_zoomedThumbnailViews addObject:thumbnailView];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((isSummaryThumbnail && _summaryThumbnailViews.count == _summaryTimestamps.count)
|
if (!exists && ((isSummaryThumbnail && _summaryThumbnailViews.count == _summaryTimestamps.count)
|
||||||
|| (!isSummaryThumbnail && _zoomedThumbnailViews.count == _zoomedTimestamps.count))
|
|| (!isSummaryThumbnail && _zoomedThumbnailViews.count == _zoomedTimestamps.count)))
|
||||||
{
|
{
|
||||||
if (!_ignoreThumbnailLoad)
|
if (!_ignoreThumbnailLoad)
|
||||||
{
|
{
|
||||||
@ -806,13 +846,11 @@ typedef enum
|
|||||||
|
|
||||||
if (snapshotView != nil)
|
if (snapshotView != nil)
|
||||||
{
|
{
|
||||||
_fadingThumbnailViews = true;
|
[UIView animateWithDuration:0.2f animations:^
|
||||||
[UIView animateWithDuration:0.3f animations:^
|
|
||||||
{
|
{
|
||||||
snapshotView.alpha = 0.0f;
|
snapshotView.alpha = 0.0f;
|
||||||
} completion:^(__unused BOOL finished)
|
} completion:^(__unused BOOL finished)
|
||||||
{
|
{
|
||||||
_fadingThumbnailViews = false;
|
|
||||||
[snapshotView removeFromSuperview];
|
[snapshotView removeFromSuperview];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,16 @@
|
|||||||
|
|
||||||
@interface TGMediaPickerGalleryVideoScrubberThumbnailView : UIView
|
@interface TGMediaPickerGalleryVideoScrubberThumbnailView : UIView
|
||||||
|
|
||||||
|
@property (nonatomic, assign) CGRect cropRect;
|
||||||
|
@property (nonatomic, assign) UIImageOrientation cropOrientation;
|
||||||
|
@property (nonatomic, assign) bool cropMirrored;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) UIImage *image;
|
||||||
|
- (void)setImage:(UIImage *)image animated:(bool)animated;
|
||||||
|
|
||||||
- (instancetype)initWithImage:(UIImage *)image originalSize:(CGSize)originalSize cropRect:(CGRect)cropRect cropOrientation:(UIImageOrientation)cropOrientation cropMirrored:(bool)cropMirrored;
|
- (instancetype)initWithImage:(UIImage *)image originalSize:(CGSize)originalSize cropRect:(CGRect)cropRect cropOrientation:(UIImageOrientation)cropOrientation cropMirrored:(bool)cropMirrored;
|
||||||
|
|
||||||
- (void)updateCropping;
|
- (void)updateCropping;
|
||||||
|
- (void)updateCropping:(bool)animated;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -7,9 +7,6 @@
|
|||||||
@interface TGMediaPickerGalleryVideoScrubberThumbnailView ()
|
@interface TGMediaPickerGalleryVideoScrubberThumbnailView ()
|
||||||
{
|
{
|
||||||
CGSize _originalSize;
|
CGSize _originalSize;
|
||||||
CGRect _cropRect;
|
|
||||||
UIImageOrientation _cropOrientation;
|
|
||||||
bool _cropMirrored;
|
|
||||||
|
|
||||||
UIImageView *_imageView;
|
UIImageView *_imageView;
|
||||||
UIView *_stripeView;
|
UIView *_stripeView;
|
||||||
@ -53,13 +50,49 @@
|
|||||||
{
|
{
|
||||||
[super setFrame:frame];
|
[super setFrame:frame];
|
||||||
|
|
||||||
if (_imageView == nil)
|
|
||||||
return;
|
|
||||||
|
|
||||||
[self updateCropping];
|
[self updateCropping];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setImage:(UIImage *)image
|
||||||
|
{
|
||||||
|
_image = image;
|
||||||
|
_imageView.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setImage:(UIImage *)image animated:(bool)animated
|
||||||
|
{
|
||||||
|
if (animated) {
|
||||||
|
UIView *snapshotView = [self snapshotViewAfterScreenUpdates:false];
|
||||||
|
[self addSubview:snapshotView];
|
||||||
|
|
||||||
|
[self setImage:image];
|
||||||
|
|
||||||
|
[UIView animateWithDuration:0.2f animations:^
|
||||||
|
{
|
||||||
|
snapshotView.alpha = 0.0f;
|
||||||
|
} completion:^(__unused BOOL finished)
|
||||||
|
{
|
||||||
|
[snapshotView removeFromSuperview];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
[self setImage:image];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateCropping {
|
- (void)updateCropping {
|
||||||
|
[self updateCropping:false];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateCropping:(bool)animated {
|
||||||
|
if (_imageView.image == nil || _cropRect.size.width < FLT_EPSILON)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIView *snapshotView;
|
||||||
|
if (animated) {
|
||||||
|
snapshotView = [self snapshotViewAfterScreenUpdates:false];
|
||||||
|
[self addSubview:snapshotView];
|
||||||
|
}
|
||||||
|
|
||||||
CGAffineTransform transform = CGAffineTransformMakeRotation(TGRotationForOrientation(_cropOrientation));
|
CGAffineTransform transform = CGAffineTransformMakeRotation(TGRotationForOrientation(_cropOrientation));
|
||||||
if (_cropMirrored)
|
if (_cropMirrored)
|
||||||
transform = CGAffineTransformScale(transform, -1.0f, 1.0f);
|
transform = CGAffineTransformScale(transform, -1.0f, 1.0f);
|
||||||
@ -83,11 +116,22 @@
|
|||||||
cropRect = CGRectMake(originalSize.width - cropRect.size.width - cropRect.origin.x, originalSize.height - cropRect.size.height - cropRect.origin.y, cropRect.size.width, cropRect.size.height);
|
cropRect = CGRectMake(originalSize.width - cropRect.size.width - cropRect.origin.x, originalSize.height - cropRect.size.height - cropRect.origin.y, cropRect.size.width, cropRect.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat ratio = self.frame.size.width / cropRect.size.width;
|
CGFloat ratio = self.bounds.size.width / cropRect.size.width;
|
||||||
_imageView.frame = CGRectMake(-cropRect.origin.x * ratio, -cropRect.origin.y * ratio, originalSize.width * ratio, originalSize.height * ratio);
|
_imageView.frame = CGRectMake(-cropRect.origin.x * ratio, -cropRect.origin.y * ratio, originalSize.width * ratio, originalSize.height * ratio);
|
||||||
|
|
||||||
CGFloat thickness = 1.0f - TGRetinaPixel;
|
CGFloat thickness = 1.0f - TGRetinaPixel;
|
||||||
_stripeView.frame = CGRectMake(self.frame.size.width - thickness, 0, thickness, self.frame.size.height);
|
_stripeView.frame = CGRectMake(self.bounds.size.width - thickness, 0, thickness, self.bounds.size.height);
|
||||||
|
|
||||||
|
if (snapshotView != nil)
|
||||||
|
{
|
||||||
|
[UIView animateWithDuration:0.2f animations:^
|
||||||
|
{
|
||||||
|
snapshotView.alpha = 0.0f;
|
||||||
|
} completion:^(__unused BOOL finished)
|
||||||
|
{
|
||||||
|
[snapshotView removeFromSuperview];
|
||||||
|
}];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -125,7 +125,7 @@
|
|||||||
|
|
||||||
CGSize dimensions = [avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject.naturalSize;
|
CGSize dimensions = [avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject.naturalSize;
|
||||||
TGMediaVideoConversionPreset preset = adjustments.sendAsGif ? TGMediaVideoConversionPresetAnimation : [self presetFromAdjustments:adjustments];
|
TGMediaVideoConversionPreset preset = adjustments.sendAsGif ? TGMediaVideoConversionPresetAnimation : [self presetFromAdjustments:adjustments];
|
||||||
if (!CGSizeEqualToSize(dimensions, CGSizeZero) && preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetVideoMessage && preset != TGMediaVideoConversionPresetProfile)
|
if (!CGSizeEqualToSize(dimensions, CGSizeZero) && preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetVideoMessage && preset != TGMediaVideoConversionPresetProfile && preset != TGMediaVideoConversionPresetProfileHigh && preset != TGMediaVideoConversionPresetPassthrough)
|
||||||
{
|
{
|
||||||
TGMediaVideoConversionPreset bestPreset = [self bestAvailablePresetForDimensions:dimensions];
|
TGMediaVideoConversionPreset bestPreset = [self bestAvailablePresetForDimensions:dimensions];
|
||||||
if (preset > bestPreset)
|
if (preset > bestPreset)
|
||||||
@ -182,7 +182,9 @@
|
|||||||
if (watcher != nil)
|
if (watcher != nil)
|
||||||
liveUploadData = [watcher fileUpdated:true];
|
liveUploadData = [watcher fileUpdated:true];
|
||||||
|
|
||||||
contextResult = [TGMediaVideoConversionResult resultWithFileURL:outputUrl fileSize:0 duration:CMTimeGetSeconds(resultContext.timeRange.duration) dimensions:resultContext.dimensions coverImage:coverImage liveUploadData:liveUploadData];
|
NSUInteger fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:outputUrl.path error:nil] fileSize];
|
||||||
|
|
||||||
|
contextResult = [TGMediaVideoConversionResult resultWithFileURL:outputUrl fileSize:fileSize duration:CMTimeGetSeconds(resultContext.timeRange.duration) dimensions:resultContext.dimensions coverImage:coverImage liveUploadData:liveUploadData];
|
||||||
return [resultContext finishedContext];
|
return [resultContext finishedContext];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@ -581,6 +583,9 @@
|
|||||||
if (output == nil)
|
if (output == nil)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (preset == TGMediaVideoConversionPresetPassthrough)
|
||||||
|
outputSettings = nil;
|
||||||
|
|
||||||
AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:composition error:error];
|
AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:composition error:error];
|
||||||
if (assetReader == nil)
|
if (assetReader == nil)
|
||||||
return false;
|
return false;
|
||||||
@ -1252,6 +1257,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
|
|||||||
return (CGSize){ 240.0f, 240.0f };
|
return (CGSize){ 240.0f, 240.0f };
|
||||||
|
|
||||||
case TGMediaVideoConversionPresetProfile:
|
case TGMediaVideoConversionPresetProfile:
|
||||||
|
case TGMediaVideoConversionPresetProfileHigh:
|
||||||
return (CGSize){ 800.0f, 800.0f };
|
return (CGSize){ 800.0f, 800.0f };
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1261,7 +1267,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
|
|||||||
|
|
||||||
+ (bool)keepAudioForPreset:(TGMediaVideoConversionPreset)preset
|
+ (bool)keepAudioForPreset:(TGMediaVideoConversionPreset)preset
|
||||||
{
|
{
|
||||||
return preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetProfile;
|
return preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetProfile && preset != TGMediaVideoConversionPresetProfileHigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSDictionary *)audioSettingsForPreset:(TGMediaVideoConversionPreset)preset
|
+ (NSDictionary *)audioSettingsForPreset:(TGMediaVideoConversionPreset)preset
|
||||||
@ -1340,6 +1346,9 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
|
|||||||
case TGMediaVideoConversionPresetProfile:
|
case TGMediaVideoConversionPresetProfile:
|
||||||
return 1400;
|
return 1400;
|
||||||
|
|
||||||
|
case TGMediaVideoConversionPresetProfileHigh:
|
||||||
|
return 2000;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 900;
|
return 900;
|
||||||
}
|
}
|
||||||
@ -1369,6 +1378,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
|
|||||||
|
|
||||||
case TGMediaVideoConversionPresetAnimation:
|
case TGMediaVideoConversionPresetAnimation:
|
||||||
case TGMediaVideoConversionPresetProfile:
|
case TGMediaVideoConversionPresetProfile:
|
||||||
|
case TGMediaVideoConversionPresetProfileHigh:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1397,6 +1407,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
|
|||||||
|
|
||||||
case TGMediaVideoConversionPresetAnimation:
|
case TGMediaVideoConversionPresetAnimation:
|
||||||
case TGMediaVideoConversionPresetProfile:
|
case TGMediaVideoConversionPresetProfile:
|
||||||
|
case TGMediaVideoConversionPresetProfileHigh:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -97,7 +97,6 @@ const CGFloat TGPhotoAvatarCropButtonsWrapperSize = 61.0f;
|
|||||||
if (strongSelf == nil)
|
if (strongSelf == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PGPhotoEditor *photoEditor = strongSelf.photoEditor;
|
|
||||||
photoEditor.cropRect = strongSelf->_cropView.cropRect;
|
photoEditor.cropRect = strongSelf->_cropView.cropRect;
|
||||||
photoEditor.cropOrientation = strongSelf->_cropView.cropOrientation;
|
photoEditor.cropOrientation = strongSelf->_cropView.cropOrientation;
|
||||||
photoEditor.cropMirrored = strongSelf->_cropView.cropMirrored;
|
photoEditor.cropMirrored = strongSelf->_cropView.cropMirrored;
|
||||||
@ -210,7 +209,6 @@ const CGFloat TGPhotoAvatarCropButtonsWrapperSize = 61.0f;
|
|||||||
|
|
||||||
- (void)setPlayer:(AVPlayer *)player
|
- (void)setPlayer:(AVPlayer *)player
|
||||||
{
|
{
|
||||||
[_cropView setPlayer:player];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setSnapshotImage:(UIImage *)snapshotImage
|
- (void)setSnapshotImage:(UIImage *)snapshotImage
|
||||||
@ -277,7 +275,6 @@ const CGFloat TGPhotoAvatarCropButtonsWrapperSize = 61.0f;
|
|||||||
{
|
{
|
||||||
[_cropView hideImageForCustomTransition];
|
[_cropView hideImageForCustomTransition];
|
||||||
[_cropView animateTransitionOutSwitching:false];
|
[_cropView animateTransitionOutSwitching:false];
|
||||||
[_cropView invalidateVideoView];
|
|
||||||
|
|
||||||
[UIView animateWithDuration:0.3f animations:^
|
[UIView animateWithDuration:0.3f animations:^
|
||||||
{
|
{
|
||||||
@ -290,7 +287,6 @@ const CGFloat TGPhotoAvatarCropButtonsWrapperSize = 61.0f;
|
|||||||
_dismissing = true;
|
_dismissing = true;
|
||||||
|
|
||||||
[_cropView animateTransitionOutSwitching:switching];
|
[_cropView animateTransitionOutSwitching:switching];
|
||||||
[_cropView invalidateVideoView];
|
|
||||||
|
|
||||||
if (switching)
|
if (switching)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#import <LegacyComponents/TGPhotoEditorAnimation.h>
|
#import <LegacyComponents/TGPhotoEditorAnimation.h>
|
||||||
#import "TGPhotoEditorInterfaceAssets.h"
|
#import "TGPhotoEditorInterfaceAssets.h"
|
||||||
|
|
||||||
#import "TGModernGalleryVideoView.h"
|
#import "PGPhotoEditorView.h"
|
||||||
|
|
||||||
const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
||||||
|
|
||||||
@ -21,7 +21,6 @@ const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
|||||||
UIScrollView *_scrollView;
|
UIScrollView *_scrollView;
|
||||||
UIView *_wrapperView;
|
UIView *_wrapperView;
|
||||||
UIImageView *_imageView;
|
UIImageView *_imageView;
|
||||||
TGModernGalleryVideoView *_videoView;
|
|
||||||
UIView *_snapshotView;
|
UIView *_snapshotView;
|
||||||
CGSize _snapshotSize;
|
CGSize _snapshotSize;
|
||||||
|
|
||||||
@ -65,8 +64,13 @@ const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
|||||||
|
|
||||||
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _wrapperView.frame.size.width, _wrapperView.frame.size.height)];
|
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _wrapperView.frame.size.width, _wrapperView.frame.size.height)];
|
||||||
_imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
_imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||||
|
_imageView.userInteractionEnabled = false;
|
||||||
[_wrapperView addSubview:_imageView];
|
[_wrapperView addSubview:_imageView];
|
||||||
|
|
||||||
|
_fullPreviewView = [[PGPhotoEditorView alloc] initWithFrame:_imageView.frame];
|
||||||
|
_fullPreviewView.userInteractionEnabled = false;
|
||||||
|
[_wrapperView addSubview:_fullPreviewView];
|
||||||
|
|
||||||
_topOverlayView = [[UIView alloc] initWithFrame:CGRectZero];
|
_topOverlayView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
_topOverlayView.backgroundColor = [TGPhotoEditorInterfaceAssets cropTransparentOverlayColor];
|
_topOverlayView.backgroundColor = [TGPhotoEditorInterfaceAssets cropTransparentOverlayColor];
|
||||||
_topOverlayView.userInteractionEnabled = false;
|
_topOverlayView.userInteractionEnabled = false;
|
||||||
@ -92,10 +96,18 @@ const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
|||||||
[self addSubview:_areaMaskView];
|
[self addSubview:_areaMaskView];
|
||||||
|
|
||||||
[self updateCircleImageWithReferenceSize:screenSize];
|
[self updateCircleImageWithReferenceSize:screenSize];
|
||||||
|
|
||||||
|
UITapGestureRecognizer *tapRecognier = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
||||||
|
[_wrapperView addGestureRecognizer:tapRecognier];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)handleTap:(UITapGestureRecognizer *)gestureRecognizer {
|
||||||
|
if (self.tapped != nil)
|
||||||
|
self.tapped();
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateCircleImageWithReferenceSize:(CGSize)referenceSize
|
- (void)updateCircleImageWithReferenceSize:(CGSize)referenceSize
|
||||||
{
|
{
|
||||||
CGFloat shortSide = MIN(referenceSize.width, referenceSize.height);
|
CGFloat shortSide = MIN(referenceSize.width, referenceSize.height);
|
||||||
@ -139,23 +151,6 @@ const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
|||||||
[self reloadImageIfNeeded];
|
[self reloadImageIfNeeded];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setPlayer:(AVPlayer *)player
|
|
||||||
{
|
|
||||||
_player = player;
|
|
||||||
|
|
||||||
_videoView = [[TGModernGalleryVideoView alloc] initWithFrame:_imageView.bounds player:player];
|
|
||||||
_videoView.frame = _imageView.frame;
|
|
||||||
_videoView.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
|
||||||
_videoView.playerLayer.opaque = false;
|
|
||||||
_videoView.playerLayer.backgroundColor = nil;
|
|
||||||
[_imageView.superview insertSubview:_videoView aboveSubview:_imageView];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)invalidateVideoView
|
|
||||||
{
|
|
||||||
_videoView.player = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)reloadImageIfNeeded
|
- (void)reloadImageIfNeeded
|
||||||
{
|
{
|
||||||
if (!_imageReloadingNeeded)
|
if (!_imageReloadingNeeded)
|
||||||
@ -415,7 +410,7 @@ const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
|||||||
{
|
{
|
||||||
_cropMirrored = cropMirrored;
|
_cropMirrored = cropMirrored;
|
||||||
_imageView.transform = CGAffineTransformMakeScale(self.cropMirrored ? -1.0f : 1.0f, 1.0f);
|
_imageView.transform = CGAffineTransformMakeScale(self.cropMirrored ? -1.0f : 1.0f, 1.0f);
|
||||||
_videoView.transform = _imageView.transform;
|
_fullPreviewView.transform = _imageView.transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invalidateCropRect
|
- (void)invalidateCropRect
|
||||||
@ -489,24 +484,6 @@ const CGFloat TGPhotoAvatarCropViewOverscreenSize = 1000;
|
|||||||
|
|
||||||
- (void)transitionInFinishedFromCamera:(bool)fromCamera
|
- (void)transitionInFinishedFromCamera:(bool)fromCamera
|
||||||
{
|
{
|
||||||
// if (fromCamera)
|
|
||||||
// {
|
|
||||||
// [UIView animateWithDuration:0.3f animations:^
|
|
||||||
// {
|
|
||||||
// _topOverlayView.alpha = 1.0f;
|
|
||||||
// _leftOverlayView.alpha = 1.0f;
|
|
||||||
// _rightOverlayView.alpha = 1.0f;
|
|
||||||
// _bottomOverlayView.alpha = 1.0f;
|
|
||||||
// }];
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// _topOverlayView.alpha = 1.0f;
|
|
||||||
// _leftOverlayView.alpha = 1.0f;
|
|
||||||
// _rightOverlayView.alpha = 1.0f;
|
|
||||||
// _bottomOverlayView.alpha = 1.0f;
|
|
||||||
// }
|
|
||||||
|
|
||||||
_scrollView.hidden = false;
|
_scrollView.hidden = false;
|
||||||
_scrollView.backgroundColor = [UIColor clearColor];
|
_scrollView.backgroundColor = [UIColor clearColor];
|
||||||
|
|
||||||
|
@ -7,9 +7,22 @@
|
|||||||
|
|
||||||
@interface TGPhotoAvatarPreviewController : TGPhotoEditorTabController
|
@interface TGPhotoAvatarPreviewController : TGPhotoEditorTabController
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView scrubberView:(TGMediaPickerGalleryVideoScrubber *)scrubberView dotImageView:(UIImageView *)dotImageView;
|
@property (nonatomic, assign) bool switching;
|
||||||
|
@property (nonatomic, assign) bool skipTransitionIn;
|
||||||
|
@property (nonatomic, assign) bool fromCamera;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) void (^croppingChanged)(void);
|
||||||
|
@property (nonatomic, copy) void (^togglePlayback)(void);
|
||||||
|
|
||||||
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView scrubberView:(TGMediaPickerGalleryVideoScrubber *)scrubberView dotImageView:(UIView *)dotImageView;
|
||||||
|
|
||||||
|
- (void)setImage:(UIImage *)image;
|
||||||
|
- (void)setSnapshotImage:(UIImage *)snapshotImage;
|
||||||
|
- (void)setSnapshotView:(UIView *)snapshotView;
|
||||||
|
|
||||||
- (void)beginScrubbing:(bool)flash;
|
- (void)beginScrubbing:(bool)flash;
|
||||||
- (void)endScrubbing:(bool)flash completion:(bool (^)(void))completion;
|
- (void)endScrubbing:(bool)flash completion:(bool (^)(void))completion;
|
||||||
|
|
||||||
|
- (void)_finishedTransitionIn;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#import "TGPhotoEditorController.h"
|
#import "TGPhotoEditorController.h"
|
||||||
#import "TGPhotoEditorPreviewView.h"
|
#import "TGPhotoEditorPreviewView.h"
|
||||||
#import "TGPhotoEditorSparseView.h"
|
#import "TGPhotoAvatarCropView.h"
|
||||||
|
|
||||||
#import "TGMediaPickerGalleryVideoScrubber.h"
|
#import "TGMediaPickerGalleryVideoScrubber.h"
|
||||||
#import "TGModernGalleryVideoView.h"
|
#import "TGModernGalleryVideoView.h"
|
||||||
@ -23,17 +23,21 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
@interface TGPhotoAvatarPreviewController ()
|
@interface TGPhotoAvatarPreviewController ()
|
||||||
{
|
{
|
||||||
bool _appeared;
|
bool _appeared;
|
||||||
|
UIImage *_imagePendingLoad;
|
||||||
|
UIView *_snapshotView;
|
||||||
|
UIImage *_snapshotImage;
|
||||||
|
|
||||||
TGPhotoEditorSparseView *_wrapperView;
|
UIView *_wrapperView;
|
||||||
TGMediaPickerGalleryVideoScrubber *_scrubberView;
|
|
||||||
|
|
||||||
UIImageView *_dotImageView;
|
TGPhotoAvatarCropView *_cropView;
|
||||||
|
|
||||||
UIView *_portraitToolsWrapperView;
|
UIView *_portraitToolsWrapperView;
|
||||||
UIView *_landscapeToolsWrapperView;
|
UIView *_landscapeToolsWrapperView;
|
||||||
UIView *_portraitWrapperBackgroundView;
|
UIView *_portraitWrapperBackgroundView;
|
||||||
UIView *_landscapeWrapperBackgroundView;
|
UIView *_landscapeWrapperBackgroundView;
|
||||||
|
|
||||||
|
TGMediaPickerGalleryVideoScrubber *_scrubberView;
|
||||||
|
UIView *_dotImageView;
|
||||||
UIView *_videoAreaView;
|
UIView *_videoAreaView;
|
||||||
UIView *_flashView;
|
UIView *_flashView;
|
||||||
UIView *_portraitToolControlView;
|
UIView *_portraitToolControlView;
|
||||||
@ -48,7 +52,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
|
|
||||||
@implementation TGPhotoAvatarPreviewController
|
@implementation TGPhotoAvatarPreviewController
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView scrubberView:(TGMediaPickerGalleryVideoScrubber *)scrubberView dotImageView:(UIImageView *)dotImageView
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView scrubberView:(TGMediaPickerGalleryVideoScrubber *)scrubberView dotImageView:(UIView *)dotImageView
|
||||||
{
|
{
|
||||||
self = [super initWithContext:context];
|
self = [super initWithContext:context];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
@ -67,12 +71,73 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
[super loadView];
|
[super loadView];
|
||||||
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||||
|
|
||||||
[self.view addSubview:_previewView];
|
// [self.view addSubview:_previewView];
|
||||||
|
|
||||||
if (self.item.isVideo) {
|
_wrapperView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
_wrapperView = [[TGPhotoEditorSparseView alloc] initWithFrame:CGRectZero];
|
|
||||||
[self.view addSubview:_wrapperView];
|
[self.view addSubview:_wrapperView];
|
||||||
|
|
||||||
|
__weak TGPhotoAvatarPreviewController *weakSelf = self;
|
||||||
|
void(^interactionBegan)(void) = ^
|
||||||
|
{
|
||||||
|
__strong TGPhotoAvatarPreviewController *strongSelf = weakSelf;
|
||||||
|
if (strongSelf == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.controlVideoPlayback(false);
|
||||||
|
};
|
||||||
|
void(^interactionEnded)(void) = ^
|
||||||
|
{
|
||||||
|
__strong TGPhotoAvatarPreviewController *strongSelf = weakSelf;
|
||||||
|
if (strongSelf == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ([strongSelf shouldAutorotate])
|
||||||
|
[TGViewController attemptAutorotation];
|
||||||
|
|
||||||
|
self.controlVideoPlayback(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
PGPhotoEditor *photoEditor = self.photoEditor;
|
||||||
|
_cropView = [[TGPhotoAvatarCropView alloc] initWithOriginalSize:photoEditor.originalSize screenSize:[self referenceViewSize]];
|
||||||
|
[_cropView setCropRect:photoEditor.cropRect];
|
||||||
|
[_cropView setCropOrientation:photoEditor.cropOrientation];
|
||||||
|
[_cropView setCropMirrored:photoEditor.cropMirrored];
|
||||||
|
_cropView.tapped = ^{
|
||||||
|
__strong TGPhotoAvatarPreviewController *strongSelf = weakSelf;
|
||||||
|
if (strongSelf == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strongSelf.togglePlayback != nil)
|
||||||
|
strongSelf.togglePlayback();
|
||||||
|
};
|
||||||
|
_cropView.croppingChanged = ^
|
||||||
|
{
|
||||||
|
__strong TGPhotoAvatarPreviewController *strongSelf = weakSelf;
|
||||||
|
if (strongSelf == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
photoEditor.cropRect = strongSelf->_cropView.cropRect;
|
||||||
|
photoEditor.cropOrientation = strongSelf->_cropView.cropOrientation;
|
||||||
|
photoEditor.cropMirrored = strongSelf->_cropView.cropMirrored;
|
||||||
|
|
||||||
|
if (strongSelf.croppingChanged != nil)
|
||||||
|
strongSelf.croppingChanged();
|
||||||
|
};
|
||||||
|
if (_snapshotView != nil)
|
||||||
|
{
|
||||||
|
[_cropView setSnapshotView:_snapshotView];
|
||||||
|
_snapshotView = nil;
|
||||||
|
}
|
||||||
|
else if (_snapshotImage != nil)
|
||||||
|
{
|
||||||
|
[_cropView setSnapshotImage:_snapshotImage];
|
||||||
|
_snapshotImage = nil;
|
||||||
|
}
|
||||||
|
_cropView.interactionBegan = interactionBegan;
|
||||||
|
_cropView.interactionEnded = interactionEnded;
|
||||||
|
[_wrapperView addSubview:_cropView];
|
||||||
|
|
||||||
|
if (self.item.isVideo) {
|
||||||
_portraitToolsWrapperView = [[UIView alloc] initWithFrame:CGRectZero];
|
_portraitToolsWrapperView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
_portraitToolsWrapperView.alpha = 0.0f;
|
_portraitToolsWrapperView.alpha = 0.0f;
|
||||||
[_wrapperView addSubview:_portraitToolsWrapperView];
|
[_wrapperView addSubview:_portraitToolsWrapperView];
|
||||||
@ -117,22 +182,78 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewWillAppear:(BOOL)animated
|
||||||
|
{
|
||||||
|
[super viewWillAppear:animated];
|
||||||
|
|
||||||
|
self.photoEditor.additionalOutputs = @[_cropView.fullPreviewView];
|
||||||
|
|
||||||
|
if (_appeared)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (self.initialAppearance && self.skipTransitionIn)
|
||||||
|
{
|
||||||
|
[self _finishedTransitionInWithView:nil];
|
||||||
|
if (self.finishedTransitionIn != nil)
|
||||||
|
{
|
||||||
|
self.finishedTransitionIn();
|
||||||
|
self.finishedTransitionIn = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self transitionIn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidAppear:(BOOL)animated
|
- (void)viewDidAppear:(BOOL)animated
|
||||||
{
|
{
|
||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
|
|
||||||
|
_appeared = true;
|
||||||
|
|
||||||
|
if (_imagePendingLoad != nil)
|
||||||
|
[_cropView setImage:_imagePendingLoad];
|
||||||
|
|
||||||
[self transitionIn];
|
[self transitionIn];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)shouldAutorotate
|
- (BOOL)shouldAutorotate
|
||||||
{
|
{
|
||||||
TGPhotoEditorPreviewView *previewView = self.previewView;
|
TGPhotoEditorPreviewView *previewView = self.previewView;
|
||||||
return (!previewView.isTracking && [super shouldAutorotate]);
|
return (!previewView.isTracking && !_cropView.isTracking && [super shouldAutorotate]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (bool)isDismissAllowed
|
- (bool)isDismissAllowed
|
||||||
{
|
{
|
||||||
return _appeared;
|
return _appeared && !_cropView.isTracking && !_cropView.isAnimating;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
- (void)setImage:(UIImage *)image
|
||||||
|
{
|
||||||
|
if (_dismissing && !_switching)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_appeared)
|
||||||
|
{
|
||||||
|
_imagePendingLoad = image;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[_cropView setImage:image];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSnapshotImage:(UIImage *)snapshotImage
|
||||||
|
{
|
||||||
|
_snapshotImage = snapshotImage;
|
||||||
|
[_cropView _replaceSnapshotImage:snapshotImage];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSnapshotView:(UIView *)snapshotView
|
||||||
|
{
|
||||||
|
_snapshotView = snapshotView;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Transition
|
#pragma mark - Transition
|
||||||
@ -142,6 +263,8 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
_scrubberView.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
_scrubberView.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||||
_scrubberView.layer.shouldRasterize = true;
|
_scrubberView.layer.shouldRasterize = true;
|
||||||
|
|
||||||
|
[_cropView animateTransitionIn];
|
||||||
|
|
||||||
[UIView animateWithDuration:0.3f animations:^
|
[UIView animateWithDuration:0.3f animations:^
|
||||||
{
|
{
|
||||||
_portraitToolsWrapperView.alpha = 1.0f;
|
_portraitToolsWrapperView.alpha = 1.0f;
|
||||||
@ -190,6 +313,9 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
_dismissing = true;
|
_dismissing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[_cropView animateTransitionOutSwitching:switching];
|
||||||
|
self.photoEditor.additionalOutputs = @[];
|
||||||
|
|
||||||
TGPhotoEditorPreviewView *previewView = self.previewView;
|
TGPhotoEditorPreviewView *previewView = self.previewView;
|
||||||
previewView.touchedUp = nil;
|
previewView.touchedUp = nil;
|
||||||
previewView.touchedDown = nil;
|
previewView.touchedDown = nil;
|
||||||
@ -233,6 +359,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
_portraitToolsWrapperView.alpha = 0.0f;
|
_portraitToolsWrapperView.alpha = 0.0f;
|
||||||
_landscapeToolsWrapperView.alpha = 0.0f;
|
_landscapeToolsWrapperView.alpha = 0.0f;
|
||||||
_videoAreaView.alpha = 0.0f;
|
_videoAreaView.alpha = 0.0f;
|
||||||
|
_dotImageView.alpha = 0.0f;
|
||||||
} completion:^(__unused BOOL finished)
|
} completion:^(__unused BOOL finished)
|
||||||
{
|
{
|
||||||
if (completion != nil)
|
if (completion != nil)
|
||||||
@ -308,42 +435,49 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
previewView.hidden = false;
|
previewView.hidden = false;
|
||||||
[previewView performTransitionInIfNeeded];
|
[previewView performTransitionInIfNeeded];
|
||||||
|
|
||||||
|
[_cropView transitionInFinishedFromCamera:(self.fromCamera && self.initialAppearance)];
|
||||||
|
|
||||||
PGPhotoEditor *photoEditor = self.photoEditor;
|
PGPhotoEditor *photoEditor = self.photoEditor;
|
||||||
[photoEditor processAnimated:false completion:nil];
|
[photoEditor processAnimated:false completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)_finishedTransitionIn
|
||||||
|
{
|
||||||
|
// [_cropView animateTransitionIn];
|
||||||
|
[_cropView transitionInFinishedFromCamera:true];
|
||||||
|
|
||||||
|
self.finishedTransitionIn();
|
||||||
|
self.finishedTransitionIn = nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)prepareForCustomTransitionOut
|
- (void)prepareForCustomTransitionOut
|
||||||
{
|
{
|
||||||
|
[_cropView hideImageForCustomTransition];
|
||||||
|
[_cropView animateTransitionOutSwitching:false];
|
||||||
|
|
||||||
_previewView.hidden = true;
|
_previewView.hidden = true;
|
||||||
[UIView animateWithDuration:0.3f animations:^
|
[UIView animateWithDuration:0.3f animations:^
|
||||||
{
|
{
|
||||||
_portraitToolsWrapperView.alpha = 0.0f;
|
_portraitToolsWrapperView.alpha = 0.0f;
|
||||||
_landscapeToolsWrapperView.alpha = 0.0f;
|
_landscapeToolsWrapperView.alpha = 0.0f;
|
||||||
_videoAreaView.alpha = 0.0f;
|
_videoAreaView.alpha = 0.0f;
|
||||||
|
_dotImageView.alpha = 0.0f;
|
||||||
} completion:nil];
|
} completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGRect)transitionOutReferenceFrame
|
- (CGRect)transitionOutReferenceFrame
|
||||||
{
|
{
|
||||||
TGPhotoEditorPreviewView *previewView = _previewView;
|
return [_cropView cropRectFrameForView:self.view];
|
||||||
return previewView.frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIView *)transitionOutReferenceView
|
- (UIView *)transitionOutReferenceView
|
||||||
{
|
{
|
||||||
return _previewView;
|
return [_cropView cropSnapshotView];
|
||||||
}
|
|
||||||
|
|
||||||
- (UIView *)snapshotView
|
|
||||||
{
|
|
||||||
TGPhotoEditorPreviewView *previewView = self.previewView;
|
|
||||||
return [previewView originalSnapshotView];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)currentResultRepresentation
|
- (id)currentResultRepresentation
|
||||||
{
|
{
|
||||||
return [self snapshotView];
|
return [_cropView cropSnapshotView];
|
||||||
// return TGPaintCombineCroppedImages(self.photoEditor.currentResultImage, self.photoEditor.paintingData.image, true, self.photoEditor.originalSize, self.photoEditor.cropRect, self.photoEditor.cropOrientation, self.photoEditor.cropRotation, self.photoEditor.cropMirrored);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Layout
|
#pragma mark - Layout
|
||||||
@ -400,8 +534,6 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
CGSize referenceSize = [self referenceViewSize];
|
CGSize referenceSize = [self referenceViewSize];
|
||||||
|
|
||||||
CGFloat screenSide = MAX(referenceSize.width, referenceSize.height);
|
CGFloat screenSide = MAX(referenceSize.width, referenceSize.height);
|
||||||
_wrapperView.frame = CGRectMake((referenceSize.width - screenSide) / 2, (referenceSize.height - screenSide) / 2, screenSide, screenSide);
|
|
||||||
|
|
||||||
CGFloat panelSize = UIInterfaceOrientationIsPortrait(orientation) ? TGPhotoAvatarPreviewPanelSize : TGPhotoAvatarPreviewLandscapePanelSize;
|
CGFloat panelSize = UIInterfaceOrientationIsPortrait(orientation) ? TGPhotoAvatarPreviewPanelSize : TGPhotoAvatarPreviewLandscapePanelSize;
|
||||||
|
|
||||||
CGFloat panelToolbarPortraitSize = panelSize + TGPhotoEditorToolbarSize;
|
CGFloat panelToolbarPortraitSize = panelSize + TGPhotoEditorToolbarSize;
|
||||||
@ -421,14 +553,11 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
[UIView performWithoutAnimation:^
|
[UIView performWithoutAnimation:^
|
||||||
{
|
{
|
||||||
_landscapeToolsWrapperView.frame = CGRectMake(0, screenEdges.top, panelToolbarLandscapeSize, _landscapeToolsWrapperView.frame.size.height);
|
_landscapeToolsWrapperView.frame = CGRectMake(0, screenEdges.top, panelToolbarLandscapeSize, _landscapeToolsWrapperView.frame.size.height);
|
||||||
// _landscapeCollectionView.frame = CGRectMake(panelToolbarLandscapeSize - panelSize, 0, panelSize, _landscapeCollectionView.frame.size.height);
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
_landscapeToolsWrapperView.frame = CGRectMake(screenEdges.left, screenEdges.top, panelToolbarLandscapeSize, referenceSize.height);
|
_landscapeToolsWrapperView.frame = CGRectMake(screenEdges.left, screenEdges.top, panelToolbarLandscapeSize, referenceSize.height);
|
||||||
// _landscapeCollectionView.frame = CGRectMake(_landscapeCollectionView.frame.origin.x, _landscapeCollectionView.frame.origin.y, _landscapeCollectionView.frame.size.width, _landscapeToolsWrapperView.frame.size.height);
|
|
||||||
|
|
||||||
_portraitToolsWrapperView.frame = CGRectMake(screenEdges.left, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
_portraitToolsWrapperView.frame = CGRectMake(screenEdges.left, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
||||||
// _portraitCollectionView.frame = CGRectMake(0, 0, _portraitToolsWrapperView.frame.size.width, panelSize);
|
|
||||||
|
|
||||||
_portraitToolsWrapperView.frame = CGRectMake((screenSide - referenceSize.width) / 2, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
_portraitToolsWrapperView.frame = CGRectMake((screenSide - referenceSize.width) / 2, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
||||||
}
|
}
|
||||||
@ -439,14 +568,12 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
[UIView performWithoutAnimation:^
|
[UIView performWithoutAnimation:^
|
||||||
{
|
{
|
||||||
_landscapeToolsWrapperView.frame = CGRectMake(screenSide - panelToolbarLandscapeSize, screenEdges.top, panelToolbarLandscapeSize, _landscapeToolsWrapperView.frame.size.height);
|
_landscapeToolsWrapperView.frame = CGRectMake(screenSide - panelToolbarLandscapeSize, screenEdges.top, panelToolbarLandscapeSize, _landscapeToolsWrapperView.frame.size.height);
|
||||||
// _landscapeCollectionView.frame = CGRectMake(0, 0, panelSize, _landscapeCollectionView.frame.size.height);
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
_landscapeToolsWrapperView.frame = CGRectMake(screenEdges.right - panelToolbarLandscapeSize, screenEdges.top, panelToolbarLandscapeSize, referenceSize.height);
|
_landscapeToolsWrapperView.frame = CGRectMake(screenEdges.right - panelToolbarLandscapeSize, screenEdges.top, panelToolbarLandscapeSize, referenceSize.height);
|
||||||
// _landscapeCollectionView.frame = CGRectMake(_landscapeCollectionView.frame.origin.x, _landscapeCollectionView.frame.origin.y, _landscapeCollectionView.frame.size.width, _landscapeToolsWrapperView.frame.size.height);
|
|
||||||
|
|
||||||
_portraitToolsWrapperView.frame = CGRectMake(screenEdges.top, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
_portraitToolsWrapperView.frame = CGRectMake(screenEdges.top, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
||||||
// _portraitCollectionView.frame = CGRectMake(0, 0, _portraitToolsWrapperView.frame.size.width, panelSize);
|
|
||||||
|
|
||||||
_portraitToolsWrapperView.frame = CGRectMake((screenSide - referenceSize.width) / 2, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
_portraitToolsWrapperView.frame = CGRectMake((screenSide - referenceSize.width) / 2, screenSide - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
||||||
}
|
}
|
||||||
@ -465,12 +592,10 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
else
|
else
|
||||||
x = screenSide - TGPhotoAvatarPreviewPanelSize;
|
x = screenSide - TGPhotoAvatarPreviewPanelSize;
|
||||||
_landscapeToolsWrapperView.frame = CGRectMake(x, screenEdges.top, panelToolbarLandscapeSize, referenceSize.height);
|
_landscapeToolsWrapperView.frame = CGRectMake(x, screenEdges.top, panelToolbarLandscapeSize, referenceSize.height);
|
||||||
// _landscapeCollectionView.frame = CGRectMake(_landscapeCollectionView.frame.origin.x, _landscapeCollectionView.frame.origin.y, panelSize, _landscapeToolsWrapperView.frame.size.height);
|
|
||||||
|
|
||||||
_portraitToolsWrapperView.frame = CGRectMake(screenEdges.left, screenEdges.bottom - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
_portraitToolsWrapperView.frame = CGRectMake(screenEdges.left, screenEdges.bottom - panelToolbarPortraitSize, referenceSize.width, panelToolbarPortraitSize);
|
||||||
|
|
||||||
_coverLabel.frame = CGRectMake(floor((_portraitToolsWrapperView.frame.size.width - _coverLabel.frame.size.width) / 2.0), CGRectGetMaxY(_scrubberView.frame) + 6.0, _coverLabel.frame.size.width, _coverLabel.frame.size.height);
|
_coverLabel.frame = CGRectMake(floor((_portraitToolsWrapperView.frame.size.width - _coverLabel.frame.size.width) / 2.0), CGRectGetMaxY(_scrubberView.frame) + 6.0, _coverLabel.frame.size.width, _coverLabel.frame.size.height);
|
||||||
// _portraitCollectionView.frame = CGRectMake(0, 0, _portraitToolsWrapperView.frame.size.width, panelSize);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -499,13 +624,29 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
|
|
||||||
- (void)updateLayout:(UIInterfaceOrientation)orientation
|
- (void)updateLayout:(UIInterfaceOrientation)orientation
|
||||||
{
|
{
|
||||||
if ([self inFormSheet] || TGIsPad())
|
orientation = [self effectiveOrientation:orientation];
|
||||||
orientation = UIInterfaceOrientationPortrait;
|
|
||||||
|
|
||||||
if (!_dismissing)
|
CGSize referenceSize = [self referenceViewSize];
|
||||||
[self updateToolViews];
|
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
|
||||||
|
[_cropView updateCircleImageWithReferenceSize:referenceSize];
|
||||||
|
|
||||||
|
CGFloat screenSide = MAX(referenceSize.width, referenceSize.height);
|
||||||
|
_wrapperView.frame = CGRectMake((referenceSize.width - screenSide) / 2, (referenceSize.height - screenSide) / 2, screenSide, screenSide);
|
||||||
|
|
||||||
|
UIEdgeInsets screenEdges = UIEdgeInsetsMake((screenSide - self.view.frame.size.height) / 2, (screenSide - self.view.frame.size.width) / 2, (screenSide + self.view.frame.size.height) / 2, (screenSide + self.view.frame.size.width) / 2);
|
||||||
|
|
||||||
|
if (_dismissing)
|
||||||
|
return;
|
||||||
|
|
||||||
[self updatePreviewView];
|
[self updatePreviewView];
|
||||||
|
[self updateToolViews];
|
||||||
|
|
||||||
|
CGRect containerFrame = [TGPhotoEditorTabController photoContainerFrameForParentViewFrame:CGRectMake(0, 0, referenceSize.width, referenceSize.height) toolbarLandscapeSize:self.toolbarLandscapeSize orientation:orientation panelSize:0.0f hasOnScreenNavigation:self.hasOnScreenNavigation];
|
||||||
|
containerFrame = CGRectOffset(containerFrame, screenEdges.left, screenEdges.top);
|
||||||
|
|
||||||
|
CGFloat shortSide = MIN(referenceSize.width, referenceSize.height);
|
||||||
|
CGFloat diameter = shortSide - [TGPhotoAvatarCropView areaInsetSize].width * 2;
|
||||||
|
_cropView.frame = CGRectMake(containerFrame.origin.x + (containerFrame.size.width - diameter) / 2, containerFrame.origin.y + (containerFrame.size.height - diameter) / 2, diameter, diameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (TGPhotoEditorTab)availableTabs
|
- (TGPhotoEditorTab)availableTabs
|
||||||
@ -555,11 +696,11 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
|||||||
#pragma mark - Cropping
|
#pragma mark - Cropping
|
||||||
|
|
||||||
- (void)rotate {
|
- (void)rotate {
|
||||||
// [_cropView rotate90DegreesCCWAnimated:true];
|
[_cropView rotate90DegreesCCWAnimated:true];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mirror {
|
- (void)mirror {
|
||||||
// [_cropView mirror];
|
[_cropView mirror];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)beginScrubbing:(bool)flash
|
- (void)beginScrubbing:(bool)flash
|
||||||
|
@ -39,11 +39,13 @@
|
|||||||
#import "TGPhotoToolsController.h"
|
#import "TGPhotoToolsController.h"
|
||||||
#import "TGPhotoPaintController.h"
|
#import "TGPhotoPaintController.h"
|
||||||
#import "TGPhotoQualityController.h"
|
#import "TGPhotoQualityController.h"
|
||||||
#import "TGPhotoAvatarCropController.h"
|
|
||||||
#import "TGPhotoAvatarPreviewController.h"
|
#import "TGPhotoAvatarPreviewController.h"
|
||||||
|
|
||||||
|
#import "TGPhotoAvatarCropView.h"
|
||||||
|
|
||||||
#import "TGMessageImageViewOverlayView.h"
|
#import "TGMessageImageViewOverlayView.h"
|
||||||
#import "TGMediaPickerGalleryVideoScrubber.h"
|
#import "TGMediaPickerGalleryVideoScrubber.h"
|
||||||
|
#import "TGMediaPickerGalleryVideoScrubberThumbnailView.h"
|
||||||
|
|
||||||
#import "TGMenuSheetController.h"
|
#import "TGMenuSheetController.h"
|
||||||
|
|
||||||
@ -107,11 +109,13 @@
|
|||||||
|
|
||||||
bool _wasPlaying;
|
bool _wasPlaying;
|
||||||
bool _initializedScrubber;
|
bool _initializedScrubber;
|
||||||
|
NSArray *_cachedThumbnails;
|
||||||
TGMediaPickerGalleryVideoScrubber *_scrubberView;
|
TGMediaPickerGalleryVideoScrubber *_scrubberView;
|
||||||
|
|
||||||
|
bool _resetDotPosition;
|
||||||
NSTimeInterval _dotPosition;
|
NSTimeInterval _dotPosition;
|
||||||
UIImageView *_dotMarkerView;
|
UIImageView *_dotMarkerView;
|
||||||
UIImageView *_dotImageView;
|
TGMediaPickerGalleryVideoScrubberThumbnailView *_dotImageView;
|
||||||
UIView *_dotImageSnapshotView;
|
UIView *_dotImageSnapshotView;
|
||||||
|
|
||||||
bool _requestingThumbnails;
|
bool _requestingThumbnails;
|
||||||
@ -154,6 +158,7 @@
|
|||||||
_photoEditor = [[PGPhotoEditor alloc] initWithOriginalSize:_item.originalSize adjustments:adjustments forVideo:item.isVideo enableStickers:(intent & TGPhotoEditorControllerSignupAvatarIntent) == 0];
|
_photoEditor = [[PGPhotoEditor alloc] initWithOriginalSize:_item.originalSize adjustments:adjustments forVideo:item.isVideo enableStickers:(intent & TGPhotoEditorControllerSignupAvatarIntent) == 0];
|
||||||
if ([self presentedForAvatarCreation])
|
if ([self presentedForAvatarCreation])
|
||||||
{
|
{
|
||||||
|
_photoEditor.cropOnLast = true;
|
||||||
CGFloat shortSide = MIN(_item.originalSize.width, _item.originalSize.height);
|
CGFloat shortSide = MIN(_item.originalSize.width, _item.originalSize.height);
|
||||||
_photoEditor.cropRect = CGRectMake((_item.originalSize.width - shortSide) / 2, (_item.originalSize.height - shortSide) / 2, shortSide, shortSide);
|
_photoEditor.cropRect = CGRectMake((_item.originalSize.width - shortSide) / 2, (_item.originalSize.height - shortSide) / 2, shortSide, shortSide);
|
||||||
}
|
}
|
||||||
@ -209,6 +214,10 @@
|
|||||||
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
|
_containerView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||||
[_wrapperView addSubview:_containerView];
|
[_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;
|
__weak TGPhotoEditorController *weakSelf = self;
|
||||||
|
|
||||||
void(^toolbarCancelPressed)(void) = ^
|
void(^toolbarCancelPressed)(void) = ^
|
||||||
@ -247,7 +256,7 @@
|
|||||||
switch (tab)
|
switch (tab)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
[strongSelf presentEditorTab:tab];
|
[strongSelf presentTab:tab];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGPhotoEditorToolsTab:
|
case TGPhotoEditorToolsTab:
|
||||||
@ -257,7 +266,7 @@
|
|||||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoToolsController class]])
|
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoToolsController class]])
|
||||||
[strongSelf->_currentTabController handleTabAction:tab];
|
[strongSelf->_currentTabController handleTabAction:tab];
|
||||||
else
|
else
|
||||||
[strongSelf presentEditorTab:TGPhotoEditorToolsTab];
|
[strongSelf presentTab:TGPhotoEditorToolsTab];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGPhotoEditorPaintTab:
|
case TGPhotoEditorPaintTab:
|
||||||
@ -265,7 +274,7 @@
|
|||||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoPaintController class]])
|
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoPaintController class]])
|
||||||
[strongSelf->_currentTabController handleTabAction:tab];
|
[strongSelf->_currentTabController handleTabAction:tab];
|
||||||
else
|
else
|
||||||
[strongSelf presentEditorTab:TGPhotoEditorPaintTab];
|
[strongSelf presentTab:TGPhotoEditorPaintTab];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TGPhotoEditorStickerTab:
|
case TGPhotoEditorStickerTab:
|
||||||
@ -276,7 +285,7 @@
|
|||||||
case TGPhotoEditorRotateTab:
|
case TGPhotoEditorRotateTab:
|
||||||
case TGPhotoEditorMirrorTab:
|
case TGPhotoEditorMirrorTab:
|
||||||
case TGPhotoEditorAspectRatioTab:
|
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];
|
[strongSelf->_currentTabController handleTabAction:tab];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -322,9 +331,15 @@
|
|||||||
[_scrubberView addSubview:_dotMarkerView];
|
[_scrubberView addSubview:_dotMarkerView];
|
||||||
_dotMarkerView.center = CGPointMake(30.0, -20.0);
|
_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;
|
_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)];
|
UITapGestureRecognizer *dotTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDotTap)];
|
||||||
[_dotImageView addGestureRecognizer:dotTapRecognizer];
|
[_dotImageView addGestureRecognizer:dotTapRecognizer];
|
||||||
|
|
||||||
@ -337,7 +352,7 @@
|
|||||||
|
|
||||||
[self detectFaces];
|
[self detectFaces];
|
||||||
|
|
||||||
[self presentEditorTab:_currentTab];
|
[self presentTab:_currentTab];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)handleDotTap {
|
- (void)handleDotTap {
|
||||||
@ -495,12 +510,7 @@
|
|||||||
|
|
||||||
TGDispatchOnMainThread(^
|
TGDispatchOnMainThread(^
|
||||||
{
|
{
|
||||||
if ([strongSelf->_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
[strongSelf->_previewView performTransitionInWithCompletion:^{}];
|
||||||
[(TGPhotoAvatarCropController *)strongSelf->_currentTabController setPlayer:strongSelf->_player];
|
|
||||||
|
|
||||||
[strongSelf->_previewView performTransitionInWithCompletion:^
|
|
||||||
{
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (strongSelf->_scheduledVideoPlayback) {
|
if (strongSelf->_scheduledVideoPlayback) {
|
||||||
strongSelf->_scheduledVideoPlayback = false;
|
strongSelf->_scheduledVideoPlayback = false;
|
||||||
@ -519,12 +529,14 @@
|
|||||||
if (strongSelf->_dismissed)
|
if (strongSelf->_dismissed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (progressVisible)
|
|
||||||
strongSelf->_hadProgress = true;
|
|
||||||
[strongSelf setProgressVisible:progressVisible value:progress animated:true];
|
[strongSelf setProgressVisible:progressVisible value:progress animated:true];
|
||||||
[strongSelf updateDoneButtonEnabled:doneEnabled animated:true];
|
[strongSelf updateDoneButtonEnabled:doneEnabled animated:true];
|
||||||
|
if (progressVisible)
|
||||||
|
strongSelf->_hadProgress = true;
|
||||||
|
|
||||||
|
if (strongSelf->_hadProgress && !progressVisible) {
|
||||||
|
[strongSelf->_progressView setPlay];
|
||||||
|
|
||||||
if (strongSelf->_hadProgress) {
|
|
||||||
[strongSelf->_scrubberView reloadThumbnails];
|
[strongSelf->_scrubberView reloadThumbnails];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -566,8 +578,8 @@
|
|||||||
- (void)_setupPlaybackStartedObserver
|
- (void)_setupPlaybackStartedObserver
|
||||||
{
|
{
|
||||||
CMTime startTime = CMTimeMake(10, 100);
|
CMTime startTime = CMTimeMake(10, 100);
|
||||||
if (_photoEditor.trimStartValue > DBL_EPSILON)
|
if (_scrubberView.trimStartValue > DBL_EPSILON)
|
||||||
startTime = CMTimeMakeWithSeconds(_photoEditor.trimStartValue + 0.1, NSEC_PER_SEC);
|
startTime = CMTimeMakeWithSeconds(_scrubberView.trimStartValue + 0.1, NSEC_PER_SEC);
|
||||||
|
|
||||||
__weak TGPhotoEditorController *weakSelf = self;
|
__weak TGPhotoEditorController *weakSelf = self;
|
||||||
_playerStartedObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:startTime]] queue:NULL usingBlock:^
|
_playerStartedObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:startTime]] queue:NULL usingBlock:^
|
||||||
@ -589,14 +601,13 @@
|
|||||||
if (_playerReachedEndObserver != nil)
|
if (_playerReachedEndObserver != nil)
|
||||||
[_player removeTimeObserver:_playerReachedEndObserver];
|
[_player removeTimeObserver:_playerReachedEndObserver];
|
||||||
|
|
||||||
PGPhotoEditor *photoEditor = _photoEditor;
|
|
||||||
CMTime endTime = CMTimeSubtract(_player.currentItem.duration, CMTimeMake(10, 100));
|
CMTime endTime = CMTimeSubtract(_player.currentItem.duration, CMTimeMake(10, 100));
|
||||||
if (photoEditor.trimEndValue > DBL_EPSILON && photoEditor.trimEndValue < CMTimeGetSeconds(_player.currentItem.duration))
|
if (_scrubberView.trimEndValue > DBL_EPSILON && _scrubberView.trimEndValue < CMTimeGetSeconds(_player.currentItem.duration))
|
||||||
endTime = CMTimeMakeWithSeconds(photoEditor.trimEndValue - 0.1, NSEC_PER_SEC);
|
endTime = CMTimeMakeWithSeconds(_scrubberView.trimEndValue - 0.1, NSEC_PER_SEC);
|
||||||
|
|
||||||
CMTime startTime = CMTimeMake(5, 100);
|
CMTime startTime = CMTimeMake(5, 100);
|
||||||
if (photoEditor.trimStartValue > DBL_EPSILON)
|
if (_scrubberView.trimStartValue > DBL_EPSILON)
|
||||||
startTime = CMTimeMakeWithSeconds(photoEditor.trimStartValue + 0.05, NSEC_PER_SEC);
|
startTime = CMTimeMakeWithSeconds(_scrubberView.trimStartValue + 0.05, NSEC_PER_SEC);
|
||||||
|
|
||||||
__weak TGPhotoEditorController *weakSelf = self;
|
__weak TGPhotoEditorController *weakSelf = self;
|
||||||
_playerReachedEndObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:endTime]] queue:NULL usingBlock:^
|
_playerReachedEndObserver = [_player addBoundaryTimeObserverForTimes:@[[NSValue valueWithCMTime:endTime]] queue:NULL usingBlock:^
|
||||||
@ -604,7 +615,7 @@
|
|||||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil && !strongSelf->_dismissed) {
|
if (strongSelf != nil && !strongSelf->_dismissed) {
|
||||||
[strongSelf->_player seekToTime:startTime];
|
[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) {
|
if (reset) {
|
||||||
NSTimeInterval startPosition = 0.0f;
|
NSTimeInterval startPosition = 0.0f;
|
||||||
if (_photoEditor.trimStartValue > DBL_EPSILON)
|
if (_scrubberView.trimStartValue > DBL_EPSILON)
|
||||||
startPosition = _photoEditor.trimStartValue;
|
startPosition = _scrubberView.trimStartValue;
|
||||||
|
|
||||||
CMTime targetTime = CMTimeMakeWithSeconds(startPosition, NSEC_PER_SEC);
|
CMTime targetTime = CMTimeMakeWithSeconds(startPosition, NSEC_PER_SEC);
|
||||||
[_player.currentItem seekToTime:targetTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
|
[_player.currentItem seekToTime:targetTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
|
||||||
@ -650,6 +661,8 @@
|
|||||||
[_player removeObserver:self forKeyPath:@"rate" context:nil];
|
[_player removeObserver:self forKeyPath:@"rate" context:nil];
|
||||||
_registeredKeypathObserver = false;
|
_registeredKeypathObserver = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[_scrubberView setIsPlaying:false];
|
||||||
}
|
}
|
||||||
|
|
||||||
_isPlaying = false;
|
_isPlaying = false;
|
||||||
@ -1064,7 +1077,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)presentEditorTab:(TGPhotoEditorTab)tab
|
- (void)presentTab:(TGPhotoEditorTab)tab
|
||||||
{
|
{
|
||||||
if (_switchingTab || (tab == _currentTab && _currentTabController != nil))
|
if (_switchingTab || (tab == _currentTab && _currentTabController != nil))
|
||||||
return;
|
return;
|
||||||
@ -1087,7 +1100,7 @@
|
|||||||
|
|
||||||
transitionReferenceFrame = [currentController transitionOutReferenceFrame];
|
transitionReferenceFrame = [currentController transitionOutReferenceFrame];
|
||||||
transitionReferenceView = [currentController transitionOutReferenceView];
|
transitionReferenceView = [currentController transitionOutReferenceView];
|
||||||
transitionNoTransitionView = [currentController isKindOfClass:[TGPhotoAvatarCropController class]];
|
transitionNoTransitionView = [currentController isKindOfClass:[TGPhotoAvatarPreviewController class]];
|
||||||
|
|
||||||
currentController.switchingToTab = tab;
|
currentController.switchingToTab = tab;
|
||||||
[currentController transitionOutSwitching:true completion:^
|
[currentController transitionOutSwitching:true completion:^
|
||||||
@ -1142,59 +1155,15 @@
|
|||||||
TGPhotoEditorTabController *controller = nil;
|
TGPhotoEditorTabController *controller = nil;
|
||||||
switch (tab)
|
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:
|
case TGPhotoEditorCropTab:
|
||||||
{
|
{
|
||||||
__block UIView *initialBackgroundView = nil;
|
__block UIView *initialBackgroundView = nil;
|
||||||
|
|
||||||
if ([self presentedForAvatarCreation])
|
if ([self presentedForAvatarCreation])
|
||||||
{
|
{
|
||||||
TGPhotoAvatarCropController *cropController = [[TGPhotoAvatarCropController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
|
||||||
|
|
||||||
bool skipInitialTransition = (![self presentedFromCamera] && self.navigationController != nil) || self.skipInitialTransition;
|
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.fromCamera = [self presentedFromCamera];
|
||||||
cropController.skipTransitionIn = skipInitialTransition;
|
cropController.skipTransitionIn = skipInitialTransition;
|
||||||
if (snapshotView != nil)
|
if (snapshotView != nil)
|
||||||
@ -1212,6 +1181,30 @@
|
|||||||
[strongSelf stopVideoPlayback:false];
|
[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)
|
cropController.beginTransitionIn = ^UIView *(CGRect *referenceFrame, UIView **parentView, bool *noTransitionView)
|
||||||
{
|
{
|
||||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||||
@ -1306,17 +1299,13 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
[self updateDoneButtonEnabled:!image.degraded animated:true];
|
[self updateDoneButtonEnabled:!image.degraded animated:true];
|
||||||
if (image.degraded)
|
if (image.degraded) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
self.fullSizeImage = image;
|
self.fullSizeImage = image;
|
||||||
[cropController setImage:image];
|
[cropController setImage:image];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
controller = cropController;
|
controller = cropController;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1415,6 +1404,50 @@
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case TGPhotoEditorToolsTab:
|
||||||
{
|
{
|
||||||
TGPhotoToolsController *toolsController = [[TGPhotoToolsController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
TGPhotoToolsController *toolsController = [[TGPhotoToolsController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView];
|
||||||
@ -1495,15 +1528,8 @@
|
|||||||
|
|
||||||
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
__strong TGPhotoEditorController *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil) {
|
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;
|
return transitionReferenceView;
|
||||||
};
|
};
|
||||||
@ -1516,10 +1542,6 @@
|
|||||||
if (isInitialAppearance && strongSelf.finishedTransitionIn != nil)
|
if (isInitialAppearance && strongSelf.finishedTransitionIn != nil)
|
||||||
strongSelf.finishedTransitionIn();
|
strongSelf.finishedTransitionIn();
|
||||||
|
|
||||||
if ([currentController isKindOfClass:[TGPhotoAvatarCropController class]]) {
|
|
||||||
[strongSelf startVideoPlayback:false];
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf->_switchingTab = false;
|
strongSelf->_switchingTab = false;
|
||||||
};
|
};
|
||||||
previewController.controlVideoPlayback = ^(bool play) {
|
previewController.controlVideoPlayback = ^(bool play) {
|
||||||
@ -1684,8 +1706,8 @@
|
|||||||
|
|
||||||
- (void)dismissEditor
|
- (void)dismissEditor
|
||||||
{
|
{
|
||||||
if ((![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]] && ![_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]]) && [self presentedForAvatarCreation]) {
|
if (![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]] && [self presentedForAvatarCreation]) {
|
||||||
[self presentEditorTab:TGPhotoEditorPreviewTab];
|
[self presentTab:TGPhotoEditorPreviewTab];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1778,7 +1800,7 @@
|
|||||||
- (void)doneButtonPressed
|
- (void)doneButtonPressed
|
||||||
{
|
{
|
||||||
if ([self presentedForAvatarCreation] && ![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]]) {
|
if ([self presentedForAvatarCreation] && ![_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]]) {
|
||||||
[self presentEditorTab:TGPhotoEditorPreviewTab];
|
[self presentTab:TGPhotoEditorPreviewTab];
|
||||||
} else {
|
} else {
|
||||||
[self applyEditor];
|
[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);
|
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(^{
|
TGDispatchOnMainThread(^{
|
||||||
if (self.didFinishEditingVideo != nil)
|
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];
|
[self dismissAnimated:true];
|
||||||
});
|
});
|
||||||
@ -2250,15 +2275,15 @@
|
|||||||
- (void)_setScreenImage:(UIImage *)screenImage
|
- (void)_setScreenImage:(UIImage *)screenImage
|
||||||
{
|
{
|
||||||
_screenImage = screenImage;
|
_screenImage = screenImage;
|
||||||
if ([_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
if ([_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]])
|
||||||
[(TGPhotoAvatarCropController *)_currentTabController setSnapshotImage:screenImage];
|
[(TGPhotoAvatarPreviewController *)_currentTabController setSnapshotImage:screenImage];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_finishedTransitionIn
|
- (void)_finishedTransitionIn
|
||||||
{
|
{
|
||||||
_switchingTab = false;
|
_switchingTab = false;
|
||||||
if ([_currentTabController isKindOfClass:[TGPhotoAvatarCropController class]])
|
if ([_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]])
|
||||||
[(TGPhotoAvatarCropController *)_currentTabController _finishedTransitionIn];
|
[(TGPhotoAvatarPreviewController *)_currentTabController _finishedTransitionIn];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)toolbarLandscapeSize
|
- (CGFloat)toolbarLandscapeSize
|
||||||
@ -2271,14 +2296,9 @@
|
|||||||
return _transitionWrapperView;
|
return _transitionWrapperView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setProgressVisible:(bool)progressVisible value:(CGFloat)value animated:(bool)animated
|
- (void)layoutProgressView {
|
||||||
{
|
if (_progressView.superview == nil)
|
||||||
_progressVisible = progressVisible;
|
[_containerView addSubview:_progressView];
|
||||||
|
|
||||||
if (progressVisible && _progressView == nil)
|
|
||||||
{
|
|
||||||
_progressView = [[TGMessageImageViewOverlayView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 50.0f, 50.0f)];
|
|
||||||
_progressView.userInteractionEnabled = false;
|
|
||||||
|
|
||||||
CGSize referenceSize = [self referenceViewSize];
|
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];
|
CGRect containerFrame = [TGPhotoEditorTabController photoContainerFrameForParentViewFrame:CGRectMake(0, 0, referenceSize.width, referenceSize.height) toolbarLandscapeSize:self.toolbarLandscapeSize orientation:self.effectiveOrientation panelSize:0.0 hasOnScreenNavigation:self.hasOnScreenNavigation];
|
||||||
@ -2286,10 +2306,13 @@
|
|||||||
_progressView.frame = (CGRect){{CGFloor(CGRectGetMidX(containerFrame) - _progressView.frame.size.width / 2.0f), CGFloor(CGRectGetMidY(containerFrame) - _progressView.frame.size.height / 2.0f)}, _progressView.frame.size};
|
_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)
|
if (progressVisible)
|
||||||
{
|
{
|
||||||
if (_progressView.superview == nil)
|
[self layoutProgressView];
|
||||||
[_containerView addSubview:_progressView];
|
|
||||||
|
|
||||||
_progressView.alpha = 1.0f;
|
_progressView.alpha = 1.0f;
|
||||||
}
|
}
|
||||||
@ -2306,9 +2329,10 @@
|
|||||||
[_progressView removeFromSuperview];
|
[_progressView removeFromSuperview];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
[_progressView removeFromSuperview];
|
[_progressView removeFromSuperview];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[_progressView setProgress:value cancelEnabled:false animated:animated];
|
[_progressView setProgress:value cancelEnabled:false animated:animated];
|
||||||
}
|
}
|
||||||
@ -2383,23 +2407,29 @@
|
|||||||
|
|
||||||
- (void)setPlayButtonHidden:(bool)hidden animated:(bool)animated
|
- (void)setPlayButtonHidden:(bool)hidden animated:(bool)animated
|
||||||
{
|
{
|
||||||
// if (animated)
|
if (!hidden) {
|
||||||
// {
|
[_progressView setPlay];
|
||||||
// _actionButton.hidden = false;
|
[self layoutProgressView];
|
||||||
// [UIView animateWithDuration:0.15f animations:^
|
}
|
||||||
// {
|
|
||||||
// _actionButton.alpha = hidden ? 0.0f : 1.0f;
|
if (animated)
|
||||||
// } completion:^(BOOL finished)
|
{
|
||||||
// {
|
_progressView.hidden = false;
|
||||||
// if (finished)
|
_progressView.alpha = 0.0f;
|
||||||
// _actionButton.hidden = hidden;
|
[UIView animateWithDuration:0.15f animations:^
|
||||||
// }];
|
{
|
||||||
// }
|
_progressView.alpha = hidden ? 0.0f : 1.0f;
|
||||||
// else
|
} completion:^(BOOL finished)
|
||||||
// {
|
{
|
||||||
// _actionButton.alpha = hidden ? 0.0f : 1.0f;
|
if (finished)
|
||||||
// _actionButton.hidden = hidden;
|
_progressView.hidden = hidden;
|
||||||
// }
|
}];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_progressView.alpha = hidden ? 0.0f : 1.0f;
|
||||||
|
_progressView.hidden = hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Video Scrubber Data Source & Delegate
|
#pragma mark - Video Scrubber Data Source & Delegate
|
||||||
@ -2417,10 +2447,7 @@
|
|||||||
|
|
||||||
- (CGFloat)videoScrubberThumbnailAspectRatio:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
- (CGFloat)videoScrubberThumbnailAspectRatio:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
||||||
{
|
{
|
||||||
if (CGSizeEqualToSize(self.item.originalSize, CGSizeZero))
|
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
|
||||||
return self.item.originalSize.width / self.item.originalSize.height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)videoScrubberDidBeginScrubbing:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
- (void)videoScrubberDidBeginScrubbing:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber
|
||||||
@ -2436,6 +2463,36 @@
|
|||||||
[previewController beginScrubbing:true];
|
[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 {
|
- (void)updateDotImage:(bool)animated {
|
||||||
AVPlayer *player = _player;
|
AVPlayer *player = _player;
|
||||||
if (player == nil) {
|
if (player == nil) {
|
||||||
@ -2460,18 +2517,6 @@
|
|||||||
image = editor.currentResultImage;
|
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(^{
|
TGDispatchOnMainThread(^{
|
||||||
if (animated) {
|
if (animated) {
|
||||||
UIView *snapshotView = nil;
|
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];
|
[_scrubberView addSubview:_dotMarkerView];
|
||||||
|
|
||||||
_dotMarkerView.center = CGPointMake([_scrubberView scrubberPositionForPosition:_dotPosition].x + 7.0, 9.5);
|
_dotMarkerView.center = CGPointMake([_scrubberView scrubberPositionForPosition:_dotPosition].x + 7.0, 9.5);
|
||||||
@ -2516,7 +2567,7 @@
|
|||||||
containerFrame.origin.x += screenEdges.left;
|
containerFrame.origin.x += screenEdges.left;
|
||||||
containerFrame.origin.y += screenEdges.top;
|
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.center = CGPointMake(CGRectGetMidX(containerFrame), CGRectGetMidY(containerFrame));
|
||||||
_dotImageView.transform = CGAffineTransformMakeScale(scale, scale);
|
_dotImageView.transform = CGAffineTransformMakeScale(scale, scale);
|
||||||
|
|
||||||
@ -2539,7 +2590,12 @@
|
|||||||
[_dotImageView addSubview:snapshotView];
|
[_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
|
- (void)videoScrubberDidEndEditing:(TGMediaPickerGalleryVideoScrubber *)videoScrubber
|
||||||
{
|
{
|
||||||
|
if (_resetDotPosition) {
|
||||||
|
_dotPosition = videoScrubber.trimStartValue;
|
||||||
|
_resetDotPosition = false;
|
||||||
|
}
|
||||||
|
|
||||||
[self setVideoEndTime:videoScrubber.trimEndValue];
|
[self setVideoEndTime:videoScrubber.trimEndValue];
|
||||||
|
|
||||||
[self seekVideo:videoScrubber.trimStartValue];
|
[videoScrubber resetToStart];
|
||||||
[self stopVideoPlayback:false];
|
[self startVideoPlayback:true];
|
||||||
|
|
||||||
[self setPlayButtonHidden:true animated:false];
|
[self setPlayButtonHidden:true animated:false];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber editingStartValueDidChange:(NSTimeInterval)startValue
|
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber editingStartValueDidChange:(NSTimeInterval)startValue
|
||||||
{
|
{
|
||||||
|
if (startValue > _dotPosition) {
|
||||||
|
_resetDotPosition = true;
|
||||||
|
[self resetDotImage];
|
||||||
|
}
|
||||||
[self seekVideo:startValue];
|
[self seekVideo:startValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber editingEndValueDidChange:(NSTimeInterval)endValue
|
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber editingEndValueDidChange:(NSTimeInterval)endValue
|
||||||
{
|
{
|
||||||
|
if (endValue < _dotPosition) {
|
||||||
|
_resetDotPosition = true;
|
||||||
|
[self resetDotImage];
|
||||||
|
}
|
||||||
[self seekVideo:endValue];
|
[self seekVideo:endValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2635,6 +2704,18 @@
|
|||||||
return timestamps;
|
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
|
- (void)videoScrubber:(TGMediaPickerGalleryVideoScrubber *)__unused videoScrubber requestThumbnailImagesForTimestamps:(NSArray *)timestamps size:(CGSize)size isSummaryThumbnails:(bool)isSummaryThumbnails
|
||||||
{
|
{
|
||||||
if (timestamps.count == 0)
|
if (timestamps.count == 0)
|
||||||
@ -2643,18 +2724,27 @@
|
|||||||
id<TGMediaEditAdjustments> adjustments = [_photoEditor exportAdjustments];
|
id<TGMediaEditAdjustments> adjustments = [_photoEditor exportAdjustments];
|
||||||
|
|
||||||
SSignal *thumbnailsSignal = nil;
|
SSignal *thumbnailsSignal = nil;
|
||||||
if ([self.item isKindOfClass:[TGMediaAsset class]]) {
|
if (_cachedThumbnails != nil) {
|
||||||
thumbnailsSignal = [TGMediaAssetImageSignals videoThumbnailsForAsset:(TGMediaAsset *)self.item size:size timestamps:timestamps];
|
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]]) {
|
} else if ([self.item isKindOfClass:[TGCameraCapturedVideo class]]) {
|
||||||
thumbnailsSignal = [[((TGCameraCapturedVideo *)self.item).avAsset takeLast] mapToSignal:^SSignal *(AVAsset *avAsset) {
|
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;
|
_requestingThumbnails = true;
|
||||||
|
|
||||||
__weak TGPhotoEditorController *weakSelf = self;
|
__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) {
|
if (adjustments.toolsApplied) {
|
||||||
NSMutableArray *editedImages = [[NSMutableArray alloc] init];
|
NSMutableArray *editedImages = [[NSMutableArray alloc] init];
|
||||||
PGPhotoEditor *editor = [[PGPhotoEditor alloc] initWithOriginalSize:adjustments.originalSize adjustments:adjustments forVideo:false enableStickers:true];
|
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)
|
[images enumerateObjectsUsingBlock:^(UIImage *image, NSUInteger index, __unused BOOL *stop)
|
||||||
{
|
{
|
||||||
if (index < timestamps.count)
|
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) {
|
if (strongSelf->_dotImageSnapshotView != nil) {
|
||||||
|
@ -130,6 +130,8 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
|
|||||||
TGVideoEditAdjustments *adjustments = [[[self class] alloc] init];
|
TGVideoEditAdjustments *adjustments = [[[self class] alloc] init];
|
||||||
adjustments->_originalSize = originalSize;
|
adjustments->_originalSize = originalSize;
|
||||||
adjustments->_preset = preset;
|
adjustments->_preset = preset;
|
||||||
|
if (preset == TGMediaVideoConversionPresetAnimation)
|
||||||
|
adjustments->_sendAsGif = true;
|
||||||
|
|
||||||
return adjustments;
|
return adjustments;
|
||||||
}
|
}
|
||||||
@ -165,10 +167,10 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
|
|||||||
adjustments->_trimStartValue = _trimStartValue;
|
adjustments->_trimStartValue = _trimStartValue;
|
||||||
adjustments->_trimEndValue = _trimEndValue;
|
adjustments->_trimEndValue = _trimEndValue;
|
||||||
adjustments->_paintingData = _paintingData;
|
adjustments->_paintingData = _paintingData;
|
||||||
adjustments->_sendAsGif = _sendAsGif;
|
|
||||||
adjustments->_preset = preset;
|
adjustments->_preset = preset;
|
||||||
adjustments->_toolValues = _toolValues;
|
adjustments->_toolValues = _toolValues;
|
||||||
adjustments->_videoStartValue = _videoStartValue;
|
adjustments->_videoStartValue = _videoStartValue;
|
||||||
|
adjustments->_sendAsGif = preset == TGMediaVideoConversionPresetAnimation ? true : _sendAsGif;
|
||||||
|
|
||||||
if (maxDuration > DBL_EPSILON)
|
if (maxDuration > DBL_EPSILON)
|
||||||
{
|
{
|
||||||
|
@ -66,13 +66,13 @@ public enum AvatarGalleryEntry: Equatable {
|
|||||||
public static func ==(lhs: AvatarGalleryEntry, rhs: AvatarGalleryEntry) -> Bool {
|
public static func ==(lhs: AvatarGalleryEntry, rhs: AvatarGalleryEntry) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
case let .topImage(lhsRepresentations, lhsIndexData, lhsImmediateThumbnailData):
|
case let .topImage(lhsRepresentations, lhsIndexData, lhsImmediateThumbnailData):
|
||||||
if case let .topImage(rhsRepresentations, rhsIndexData, rhsImmediateThumbnailData) = rhs, lhsRepresentations == rhsRepresentations, lhsIndexData == rhsIndexData, lhsImmediateThumbnailData != rhsImmediateThumbnailData {
|
if case let .topImage(rhsRepresentations, rhsIndexData, rhsImmediateThumbnailData) = rhs, lhsRepresentations == rhsRepresentations, lhsIndexData == rhsIndexData, lhsImmediateThumbnailData == rhsImmediateThumbnailData {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .image(lhsId, lhsImageReference, lhsRepresentations, lhsVideoRepresentations, lhsPeer, lhsDate, lhsIndexData, lhsMessageId, lhsImmediateThumbnailData):
|
case let .image(lhsId, lhsImageReference, lhsRepresentations, lhsVideoRepresentations, lhsPeer, lhsDate, lhsIndexData, lhsMessageId, lhsImmediateThumbnailData):
|
||||||
if case let .image(rhsId, rhsImageReference, rhsRepresentations, rhsVideoRepresentations, rhsPeer, rhsDate, rhsIndexData, rhsMessageId, rhsImmediateThumbnailData) = rhs, lhsId == rhsId, lhsImageReference == rhsImageReference, lhsRepresentations == rhsRepresentations, lhsVideoRepresentations == rhsVideoRepresentations, arePeersEqual(lhsPeer, rhsPeer), lhsDate == rhsDate, lhsIndexData == rhsIndexData, lhsMessageId == rhsMessageId, lhsImmediateThumbnailData != rhsImmediateThumbnailData {
|
if case let .image(rhsId, rhsImageReference, rhsRepresentations, rhsVideoRepresentations, rhsPeer, rhsDate, rhsIndexData, rhsMessageId, rhsImmediateThumbnailData) = rhs, lhsId == rhsId, lhsImageReference == rhsImageReference, lhsRepresentations == rhsRepresentations, lhsVideoRepresentations == rhsVideoRepresentations, arePeersEqual(lhsPeer, rhsPeer), lhsDate == rhsDate, lhsIndexData == rhsIndexData, lhsMessageId == rhsMessageId, lhsImmediateThumbnailData == rhsImmediateThumbnailData {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -265,7 +265,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||||||
} : nil, setMain: { [weak self] in
|
} : nil, setMain: { [weak self] in
|
||||||
self?.setMainEntry(entry)
|
self?.setMainEntry(entry)
|
||||||
})
|
})
|
||||||
}), centralItemIndex: 0, synchronous: !isFirstTime)
|
}), centralItemIndex: strongSelf.centralEntryIndex, synchronous: !isFirstTime)
|
||||||
|
|
||||||
let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in
|
let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in
|
||||||
strongSelf?.didSetReady = true
|
strongSelf?.didSetReady = true
|
||||||
|
@ -549,6 +549,13 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar
|
|||||||
|
|
||||||
let completedVideoImpl: (UIImage, URL, TGVideoEditAdjustments?) -> Void = { image, url, adjustments in
|
let completedVideoImpl: (UIImage, URL, TGVideoEditAdjustments?) -> Void = { image, url, adjustments in
|
||||||
if let data = image.jpegData(compressionQuality: 0.6) {
|
if let data = image.jpegData(compressionQuality: 0.6) {
|
||||||
|
let photoResource = LocalFileMediaResource(fileId: arc4random64())
|
||||||
|
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
|
||||||
|
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: photoResource)
|
||||||
|
updateState {
|
||||||
|
$0.withUpdatedUpdatingAvatar(.image(representation, true))
|
||||||
|
}
|
||||||
|
|
||||||
let signal = Signal<TelegramMediaResource, UploadPeerPhotoError> { subscriber in
|
let signal = Signal<TelegramMediaResource, UploadPeerPhotoError> { subscriber in
|
||||||
var filteredPath = url.path
|
var filteredPath = url.path
|
||||||
if filteredPath.hasPrefix("file://") {
|
if filteredPath.hasPrefix("file://") {
|
||||||
@ -568,6 +575,10 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar
|
|||||||
|
|
||||||
let signalDisposable = signal.start(next: { next in
|
let signalDisposable = signal.start(next: { next in
|
||||||
if let result = next as? TGMediaVideoConversionResult {
|
if let result = next as? TGMediaVideoConversionResult {
|
||||||
|
if let image = result.coverImage, let data = image.jpegData(compressionQuality: 0.7) {
|
||||||
|
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
|
||||||
|
}
|
||||||
|
|
||||||
var value = stat()
|
var value = stat()
|
||||||
if stat(result.fileURL.path, &value) == 0 {
|
if stat(result.fileURL.path, &value) == 0 {
|
||||||
if let data = try? Data(contentsOf: result.fileURL) {
|
if let data = try? Data(contentsOf: result.fileURL) {
|
||||||
@ -577,7 +588,7 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar
|
|||||||
} else {
|
} else {
|
||||||
resource = LocalFileMediaResource(fileId: arc4random64())
|
resource = LocalFileMediaResource(fileId: arc4random64())
|
||||||
}
|
}
|
||||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||||
subscriber.putNext(resource)
|
subscriber.putNext(resource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,16 +606,9 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
|
||||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
|
||||||
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource)
|
|
||||||
updateState {
|
|
||||||
$0.withUpdatedUpdatingAvatar(.image(representation, true))
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAvatarDisposable.set((signal
|
updateAvatarDisposable.set((signal
|
||||||
|> mapToSignal { videoResource in
|
|> mapToSignal { videoResource in
|
||||||
return updateAccountPhoto(account: context.account, resource: resource, videoResource: videoResource, mapResourceToAvatarSizes: { resource, representations in
|
return updateAccountPhoto(account: context.account, resource: photoResource, videoResource: videoResource, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} |> deliverOnMainQueue).start(next: { result in
|
} |> deliverOnMainQueue).start(next: { result in
|
||||||
|
@ -1314,6 +1314,15 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
|
|
||||||
let completedVideoImpl: (UIImage, URL, TGVideoEditAdjustments?) -> Void = { image, url, adjustments in
|
let completedVideoImpl: (UIImage, URL, TGVideoEditAdjustments?) -> Void = { image, url, adjustments in
|
||||||
if let data = image.jpegData(compressionQuality: 0.6) {
|
if let data = image.jpegData(compressionQuality: 0.6) {
|
||||||
|
let photoResource = LocalFileMediaResource(fileId: arc4random64())
|
||||||
|
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
|
||||||
|
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: photoResource)
|
||||||
|
updateState { state in
|
||||||
|
var state = state
|
||||||
|
state.updatingAvatar = .image(representation, true)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
let signal = Signal<TelegramMediaResource, UploadPeerPhotoError> { subscriber in
|
let signal = Signal<TelegramMediaResource, UploadPeerPhotoError> { subscriber in
|
||||||
var filteredPath = url.path
|
var filteredPath = url.path
|
||||||
if filteredPath.hasPrefix("file://") {
|
if filteredPath.hasPrefix("file://") {
|
||||||
@ -1333,6 +1342,10 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
|
|
||||||
let signalDisposable = signal.start(next: { next in
|
let signalDisposable = signal.start(next: { next in
|
||||||
if let result = next as? TGMediaVideoConversionResult {
|
if let result = next as? TGMediaVideoConversionResult {
|
||||||
|
if let image = result.coverImage, let data = image.jpegData(compressionQuality: 0.7) {
|
||||||
|
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
|
||||||
|
}
|
||||||
|
|
||||||
var value = stat()
|
var value = stat()
|
||||||
if stat(result.fileURL.path, &value) == 0 {
|
if stat(result.fileURL.path, &value) == 0 {
|
||||||
if let data = try? Data(contentsOf: result.fileURL) {
|
if let data = try? Data(contentsOf: result.fileURL) {
|
||||||
@ -1342,7 +1355,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
} else {
|
} else {
|
||||||
resource = LocalFileMediaResource(fileId: arc4random64())
|
resource = LocalFileMediaResource(fileId: arc4random64())
|
||||||
}
|
}
|
||||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||||
subscriber.putNext(resource)
|
subscriber.putNext(resource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1360,18 +1373,9 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
|
||||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
|
||||||
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource)
|
|
||||||
updateState { state in
|
|
||||||
var state = state
|
|
||||||
state.updatingAvatar = .image(representation, true)
|
|
||||||
return state
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAvatarDisposable.set((signal
|
updateAvatarDisposable.set((signal
|
||||||
|> mapToSignal { videoResource in
|
|> mapToSignal { videoResource in
|
||||||
return updateAccountPhoto(account: context.account, resource: resource, videoResource: videoResource, mapResourceToAvatarSizes: { resource, representations in
|
return updateAccountPhoto(account: context.account, resource: photoResource, videoResource: videoResource, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} |> deliverOnMainQueue).start(next: { result in
|
} |> deliverOnMainQueue).start(next: { result in
|
||||||
|
@ -182,7 +182,7 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect,
|
|||||||
let resource: TelegramMediaResource
|
let resource: TelegramMediaResource
|
||||||
if let liveUploadData = liveUploadData as? LegacyLiveUploadInterfaceResult, resourceAdjustments == nil, let data = try? Data(contentsOf: videoUrl) {
|
if let liveUploadData = liveUploadData as? LegacyLiveUploadInterfaceResult, resourceAdjustments == nil, let data = try? Data(contentsOf: videoUrl) {
|
||||||
resource = LocalFileMediaResource(fileId: liveUploadData.id)
|
resource = LocalFileMediaResource(fileId: liveUploadData.id)
|
||||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||||
} else {
|
} else {
|
||||||
resource = LocalFileVideoMediaResource(randomId: arc4random64(), path: videoUrl.path, adjustments: resourceAdjustments)
|
resource = LocalFileVideoMediaResource(randomId: arc4random64(), path: videoUrl.path, adjustments: resourceAdjustments)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user