Merge commit '071a3bdef1672c9311baf5170bb2765939a1b802'

This commit is contained in:
Ali 2020-07-17 01:36:20 +04:00
commit 219d4034fb
15 changed files with 192 additions and 65 deletions

View File

@ -7,6 +7,8 @@
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, readonly) UIView *clipView;
@property (nonatomic, readonly) CGSize originalSize;
@property (nonatomic, assign) CGRect cropRect;
@property (nonatomic, assign) UIImageOrientation cropOrientation;
@ -37,6 +39,7 @@
- (void)animateTransitionOut;
- (void)transitionInFinishedFromCamera:(bool)fromCamera;
- (void)attachEntitiesView;
- (void)closeCurtains;
- (void)openCurtains;

View File

@ -9,6 +9,8 @@
bool _dismissing;
UIView *_transitionView;
bool _noTransitionToSnapshot;
bool _animateScale;
}
@property (nonatomic, weak) id<TGMediaEditableItem> item;
@ -36,6 +38,7 @@
@property (nonatomic, assign) TGPhotoEditorTab availableTabs;
@property (nonatomic, assign) TGPhotoEditorTab switchingFromTab;
@property (nonatomic, assign) TGPhotoEditorTab switchingToTab;
- (void)transitionOutSwitching:(bool)switching completion:(void (^)(void))completion;

View File

@ -13,6 +13,7 @@ typedef enum
TGMediaVideoConversionPresetCompressedVeryHigh,
TGMediaVideoConversionPresetAnimation,
TGMediaVideoConversionPresetVideoMessage,
TGMediaVideoConversionPresetProfileLow,
TGMediaVideoConversionPresetProfile,
TGMediaVideoConversionPresetProfileHigh,
TGMediaVideoConversionPresetProfileVeryHigh,

View File

@ -125,7 +125,7 @@
CGSize dimensions = [avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject.naturalSize;
TGMediaVideoConversionPreset preset = adjustments.sendAsGif ? TGMediaVideoConversionPresetAnimation : [self presetFromAdjustments:adjustments];
if (!CGSizeEqualToSize(dimensions, CGSizeZero) && preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetVideoMessage && preset != TGMediaVideoConversionPresetProfile && preset != TGMediaVideoConversionPresetProfileHigh && preset != TGMediaVideoConversionPresetProfileVeryHigh && preset != TGMediaVideoConversionPresetPassthrough)
if (!CGSizeEqualToSize(dimensions, CGSizeZero) && preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetVideoMessage && preset != TGMediaVideoConversionPresetProfile && preset != TGMediaVideoConversionPresetProfileLow && preset != TGMediaVideoConversionPresetProfileHigh && preset != TGMediaVideoConversionPresetProfileVeryHigh && preset != TGMediaVideoConversionPresetPassthrough)
{
TGMediaVideoConversionPreset bestPreset = [self bestAvailablePresetForDimensions:dimensions];
if (preset > bestPreset)
@ -240,7 +240,7 @@
return;
TGMediaVideoConversionPreset preset = TGMediaVideoConversionPresetAnimation;
if (adjustments.preset == TGMediaVideoConversionPresetProfile || adjustments.preset == TGMediaVideoConversionPresetProfileHigh || adjustments.preset == TGMediaVideoConversionPresetProfileVeryHigh) {
if (adjustments.preset == TGMediaVideoConversionPresetProfile || adjustments.preset != TGMediaVideoConversionPresetProfileLow || adjustments.preset == TGMediaVideoConversionPresetProfileHigh || adjustments.preset == TGMediaVideoConversionPresetProfileVeryHigh) {
preset = adjustments.preset;
}
@ -355,7 +355,7 @@
if (TGOrientationIsSideward(adjustments.cropOrientation, NULL))
outputDimensions = CGSizeMake(outputDimensions.height, outputDimensions.width);
if ((preset == TGMediaVideoConversionPresetProfile || preset == TGMediaVideoConversionPresetProfileHigh || preset == TGMediaVideoConversionPresetProfileVeryHigh) && MIN(outputDimensions.width, outputDimensions.height) < 160.0) {
if ((preset == TGMediaVideoConversionPresetProfile || preset == TGMediaVideoConversionPresetProfileLow || preset == TGMediaVideoConversionPresetProfileHigh || preset == TGMediaVideoConversionPresetProfileVeryHigh) && MIN(outputDimensions.width, outputDimensions.height) < 160.0) {
outputDimensions = CGSizeMake(160.0, 160.0);
}
@ -1255,6 +1255,9 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
case TGMediaVideoConversionPresetVideoMessage:
return (CGSize){ 240.0f, 240.0f };
case TGMediaVideoConversionPresetProfileLow:
return (CGSize){ 720.0f, 720.0f };
case TGMediaVideoConversionPresetProfile:
case TGMediaVideoConversionPresetProfileHigh:
case TGMediaVideoConversionPresetProfileVeryHigh:
@ -1267,7 +1270,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
+ (bool)keepAudioForPreset:(TGMediaVideoConversionPreset)preset
{
return preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetProfile && preset != TGMediaVideoConversionPresetProfileHigh && preset != TGMediaVideoConversionPresetProfileVeryHigh;
return preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetProfile && preset != TGMediaVideoConversionPresetProfileLow && preset != TGMediaVideoConversionPresetProfileHigh && preset != TGMediaVideoConversionPresetProfileVeryHigh;
}
+ (NSDictionary *)audioSettingsForPreset:(TGMediaVideoConversionPreset)preset
@ -1346,6 +1349,9 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
case TGMediaVideoConversionPresetProfile:
return 1500;
case TGMediaVideoConversionPresetProfileLow:
return 1100;
case TGMediaVideoConversionPresetProfileHigh:
return 2000;
@ -1381,6 +1387,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
case TGMediaVideoConversionPresetAnimation:
case TGMediaVideoConversionPresetProfile:
case TGMediaVideoConversionPresetProfileLow:
case TGMediaVideoConversionPresetProfileHigh:
case TGMediaVideoConversionPresetProfileVeryHigh:
return 0;
@ -1411,6 +1418,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
case TGMediaVideoConversionPresetAnimation:
case TGMediaVideoConversionPresetProfile:
case TGMediaVideoConversionPresetProfileLow:
case TGMediaVideoConversionPresetProfileHigh:
case TGMediaVideoConversionPresetProfileVeryHigh:
return 0;

View File

@ -146,10 +146,19 @@ const CGFloat TGPhotoAvatarCropViewCurtainMargin = 200;
UITapGestureRecognizer *tapRecognier = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
[_wrapperView addGestureRecognizer:tapRecognier];
_clipView = [[UIView alloc] init];
_clipView.clipsToBounds = true;
_clipView.userInteractionEnabled = false;
[self addSubview:_clipView];
}
return self;
}
- (void)attachEntitiesView {
[_entitiesWrapperView addSubview:_fullEntitiesView];
}
- (void)dealloc
{
_scrollView.delegate = nil;
@ -644,6 +653,8 @@ const CGFloat TGPhotoAvatarCropViewCurtainMargin = 200;
{
[self _layoutOverlayViews];
_clipView.frame = self.bounds;
_flashView.frame = self.bounds;
if (_scrollView.superview == nil)

View File

@ -16,6 +16,7 @@
#import "TGMediaPickerGalleryVideoScrubber.h"
#import "TGModernGalleryVideoView.h"
#import "TGPhotoEntitiesContainerView.h"
#import "TGPhotoPaintController.h"
@ -257,6 +258,58 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
[self.view insertSubview:_transitionView belowSubview:_wrapperView];
}
- (void)animateTransitionIn {
if (self.initialAppearance) {
[super animateTransitionIn];
return;
} else {
_animateScale = true;
[self transitEntities:_previewView];
[super animateTransitionIn];
}
}
+ (CGRect)fittedCropRect:(CGRect)cropRect originalSize:(CGSize)originalSize fitSize:(CGSize)fitSize {
CGSize fittedOriginalSize = TGScaleToSize(originalSize, fitSize);
CGFloat scale = fittedOriginalSize.width / originalSize.width;
CGSize size = fittedOriginalSize;
return CGRectMake(-cropRect.origin.x * scale, -cropRect.origin.y * scale, size.width, size.height);
}
- (void)transitEntities:(UIView *)parentView {
UIView *containerView = [[UIView alloc] init];
[parentView addSubview:containerView];
containerView.frame = CGRectMake(0.0, 0.0, _fullEntitiesView.frame.size.width, _fullEntitiesView.frame.size.height);
[containerView addSubview:_fullEntitiesView];
CGFloat paintingScale = _fullEntitiesView.frame.size.width / _photoEditor.originalSize.width;
_fullEntitiesView.frame = CGRectMake(-_photoEditor.cropRect.origin.x * paintingScale, -_photoEditor.cropRect.origin.y * paintingScale, _fullEntitiesView.frame.size.width, _fullEntitiesView.frame.size.height);
CGFloat cropScale = 1.0;
if (_photoEditor.originalSize.width > _photoEditor.originalSize.height) {
cropScale = _photoEditor.originalSize.height / _photoEditor.cropRect.size.height;
} else {
cropScale = _photoEditor.originalSize.width / _photoEditor.cropRect.size.width;
}
UIImageOrientation imageOrientation = _photoEditor.cropOrientation;
if ([parentView isKindOfClass:[TGPhotoEditorPreviewView class]])
imageOrientation = UIImageOrientationUp;
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(TGRotationForOrientation(imageOrientation));
if ([parentView isKindOfClass:[TGPhotoEditorPreviewView class]] && _photoEditor.cropMirrored) {
rotationTransform = CGAffineTransformMakeScale(-1.0, 1.0);
}
CGFloat scale = parentView.frame.size.width / _fullEntitiesView.frame.size.width;
containerView.transform = CGAffineTransformScale(rotationTransform, scale * cropScale, scale * cropScale);
containerView.frame = CGRectMake(0.0, 0.0, parentView.frame.size.width, parentView.frame.size.height);
}
- (void)transitionIn
{
if (_portraitToolsWrapperView.frame.size.height < FLT_EPSILON) {
@ -373,13 +426,22 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
[_cropView closeCurtains];
[self transitEntities:_cropView.clipView];
CGAffineTransform initialTransform = _previewView.transform;
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionLayoutSubviews animations:^
{
_previewView.frame = targetFrame;
CGFloat scale = targetFrame.size.width / _previewView.frame.size.width;
_previewView.center = CGPointMake(CGRectGetMidX(targetFrame), CGRectGetMidY(targetFrame));
_previewView.transform = CGAffineTransformScale(initialTransform, scale, scale);
_cropView.center = CGPointMake(CGRectGetMidX(targetCropViewFrame), CGRectGetMidY(targetCropViewFrame));
_cropView.transform = CGAffineTransformMakeScale(targetCropViewScale, targetCropViewScale);
} completion:^(__unused BOOL finished)
{
{
_fullEntitiesView.frame = CGRectMake(0, 0, _fullEntitiesView.frame.size.width, _fullEntitiesView.frame.size.height);
_previewView.transform = initialTransform;
_previewView.frame = targetFrame;
[_cropView removeFromSuperview];
_previewView.alpha = 1.0;
if (self.finishedTransitionOut != nil)
@ -504,8 +566,13 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
{
_appeared = true;
if (!self.initialAppearance) {
[_fullEntitiesView.superview removeFromSuperview];
_fullEntitiesView.frame = CGRectMake(0, 0, _fullEntitiesView.frame.size.width, _fullEntitiesView.frame.size.height);
[_cropView attachEntitiesView];
}
if ([transitionView isKindOfClass:[TGPhotoEditorPreviewView class]]) {
} else {
[transitionView removeFromSuperview];
}

View File

@ -1171,6 +1171,7 @@
UIView *snapshotView = nil;
TGPhotoEditorTabController *currentController = _currentTabController;
TGPhotoEditorTab switchingFromTab = TGPhotoEditorNoneTab;
if (currentController != nil)
{
if (![currentController isDismissAllowed])
@ -1178,13 +1179,18 @@
[self savePaintingData];
bool resetTransform = false;
if ([self presentedForAvatarCreation] && tab == TGPhotoEditorCropTab && [currentController isKindOfClass:[TGPhotoPaintController class]]) {
resetTransform = true;
}
currentController.switchingToTab = tab;
[currentController transitionOutSwitching:true completion:^
{
[currentController removeFromParentViewController];
[currentController.view removeFromSuperview];
if ([self presentedForAvatarCreation] && tab == TGPhotoEditorCropTab) {
if (resetTransform) {
_previewView.transform = CGAffineTransformIdentity;
}
}];
@ -1200,6 +1206,9 @@
{
_backgroundView.alpha = 0.0f;
} completion:nil];
switchingFromTab = TGPhotoEditorCropTab;
} else if ([currentController isKindOfClass:[TGPhotoToolsController class]]) {
switchingFromTab = TGPhotoEditorToolsTab;
}
isInitialAppearance = false;
@ -1281,7 +1290,7 @@
cropController.toolbarLandscapeSize = TGPhotoEditorToolbarSize;
cropController.controlVideoPlayback = ^(bool play) {
__strong TGPhotoEditorController *strongSelf = weakSelf;
if (strongSelf == nil)
if (strongSelf == nil || strongSelf->_progressVisible)
return;
if (play) {
[strongSelf startVideoPlayback:false];
@ -1297,7 +1306,7 @@
};
cropController.togglePlayback = ^{
__strong TGPhotoEditorController *strongSelf = weakSelf;
if (strongSelf == nil || !strongSelf->_item.isVideo)
if (strongSelf == nil || !strongSelf->_item.isVideo || strongSelf->_progressVisible)
return;
if (strongSelf->_isPlaying) {
@ -1613,6 +1622,7 @@
_currentTabController = controller;
_currentTabController.item = _item;
_currentTabController.intent = _intent;
_currentTabController.switchingFromTab = switchingFromTab;
_currentTabController.initialAppearance = isInitialAppearance;
if (![_currentTabController isKindOfClass:[TGPhotoPaintController class]])
@ -1983,8 +1993,10 @@
preset = TGMediaVideoConversionPresetProfileVeryHigh;
} else if (duration <= 5.0) {
preset = TGMediaVideoConversionPresetProfileHigh;
} else {
} else if (duration <= 8.0) {
preset = TGMediaVideoConversionPresetProfile;
} else {
preset = TGMediaVideoConversionPresetProfileLow;
}
TGDispatchOnMainThread(^{

View File

@ -169,22 +169,34 @@ const CGFloat TGPhotoEditorToolbarSize = 49.0f;
_transitionInProgress = true;
CGAffineTransform initialTransform = _transitionView.transform;
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionLayoutSubviews animations:^
{
_transitionView.frame = _transitionTargetFrame;
if (_animateScale) {
CGFloat scale = _transitionTargetFrame.size.width / _transitionView.frame.size.width;
_transitionView.center = CGPointMake(CGRectGetMidX(_transitionTargetFrame), CGRectGetMidY(_transitionTargetFrame));
_transitionView.transform = CGAffineTransformScale(initialTransform, scale, scale);
} else {
_transitionView.frame = _transitionTargetFrame;
}
} completion:^(BOOL finished) {
_transitionInProgress = false;
UIView *transitionView = _transitionView;
_transitionView = nil;
if (self.finishedTransitionIn != nil)
{
self.finishedTransitionIn();
self.finishedTransitionIn = nil;
}
[self _finishedTransitionInWithView:transitionView];
UIView *transitionView = _transitionView;
_transitionView = nil;
if (_animateScale) {
_transitionView.transform = initialTransform;
_transitionView.frame = _transitionTargetFrame;
}
if (self.finishedTransitionIn != nil)
{
self.finishedTransitionIn();
self.finishedTransitionIn = nil;
}
[self _finishedTransitionInWithView:transitionView];
}];
}

View File

@ -99,6 +99,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
bool _appeared;
bool _skipEntitiesSetup;
bool _entitiesReady;
TGPhotoPaintFont *_selectedTextFont;
TGPhotoPaintTextEntityStyle _selectedTextStyle;
@ -268,7 +269,9 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
[strongSelf updateSettingsButton];
};
[_contentWrapperView addSubview:_entitiesContainerView];
if (!_skipEntitiesSetup) {
[_contentWrapperView addSubview:_entitiesContainerView];
}
_undoManager.entitiesContainer = _entitiesContainerView;
_dimView = [[UIView alloc] init];
@ -1816,7 +1819,6 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
if (self.presentedForAvatarCreation) {
_canvasView.hidden = true;
_entitiesContainerView.hidden = true;
}
}
@ -1865,7 +1867,7 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
[self setupCanvas];
_entitiesContainerView.hidden = false;
TGPhotoEditorPreviewView *previewView = _previewView;
[previewView setPaintingHidden:true];
previewView.hidden = false;
@ -1887,8 +1889,10 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
CGPoint boundsCenter = TGPaintCenterOfRect(_contentWrapperView.bounds);
_entitiesContainerView.center = TGPaintAddPoints(boundsCenter, offset);
[_contentWrapperView addSubview:_entitiesContainerView];
if (!_skipEntitiesSetup || _entitiesReady) {
[_contentWrapperView addSubview:_entitiesContainerView];
}
_entitiesReady = true;
[self resetScrollView];
}
@ -2322,6 +2326,13 @@ const CGFloat TGPhotoPaintStickerKeyboardSize = 260.0f;
previewView.frame = previewFrame;
if ([self presentedForAvatarCreation]) {
CGAffineTransform transform = CGAffineTransformMakeRotation(TGRotationForOrientation(photoEditor.cropOrientation));
if (photoEditor.cropMirrored)
transform = CGAffineTransformScale(transform, -1.0f, 1.0f);
previewView.transform = transform;
}
CGSize fittedOriginalSize = CGSizeMake(originalSize.width * ratio, originalSize.height * ratio);
CGSize rotatedSize = TGRotatedContentSize(fittedOriginalSize, rotation);
CGPoint centerPoint = CGPointMake(rotatedSize.width / 2.0f, rotatedSize.height / 2.0f);

View File

@ -35,6 +35,7 @@ const CGFloat TGPhotoEditorToolsLandscapePanelSize = TGPhotoEditorToolsPanelSize
bool _appeared;
bool _scheduledTransitionIn;
CGFloat _cellWidth;
int _entitiesReady;
NSArray *_allTools;
NSArray *_simpleTools;
@ -107,26 +108,27 @@ const CGFloat TGPhotoEditorToolsLandscapePanelSize = TGPhotoEditorToolsPanelSize
}
- (void)layoutEntitiesView {
CGSize fittedContentSize = [TGPhotoPaintController fittedContentSize:_photoEditor.cropRect orientation:_photoEditor.cropOrientation originalSize:_photoEditor.originalSize];
CGRect fittedCropRect = [TGPhotoPaintController fittedCropRect:_photoEditor.cropRect originalSize:_photoEditor.originalSize keepOriginalSize:false];
_entitiesWrapperView.frame = CGRectMake(0.0f, 0.0f, fittedContentSize.width, fittedContentSize.height);
if (_entitiesReady < 2 || _dismissing)
return;
CGRect rect = [TGPhotoPaintController fittedCropRect:self.photoEditor.cropRect originalSize:self.photoEditor.originalSize keepOriginalSize:true];
_entitiesView.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
_entitiesView.transform = CGAffineTransformMakeRotation(_photoEditor.cropRotation);
_entitiesWrapperView.transform = CGAffineTransformIdentity;
_entitiesWrapperView.frame = CGRectMake(0.0, 0.0, _entitiesView.frame.size.width, _entitiesView.frame.size.height);
[_entitiesWrapperView addSubview:_entitiesView];
CGSize fittedOriginalSize = TGScaleToSize(_photoEditor.originalSize, [TGPhotoPaintController maximumPaintingSize]);
CGSize rotatedSize = TGRotatedContentSize(fittedOriginalSize, _photoEditor.cropRotation);
CGPoint centerPoint = CGPointMake(rotatedSize.width / 2.0f, rotatedSize.height / 2.0f);
CGFloat paintingScale = _entitiesView.frame.size.width / _photoEditor.originalSize.width;
_entitiesView.frame = CGRectMake(-_photoEditor.cropRect.origin.x * paintingScale, -_photoEditor.cropRect.origin.y * paintingScale, _entitiesView.frame.size.width, _entitiesView.frame.size.height);
CGFloat scale = fittedOriginalSize.width / _photoEditor.originalSize.width;
CGPoint offset = TGPaintSubtractPoints(centerPoint, [TGPhotoPaintController fittedCropRect:_photoEditor.cropRect centerScale:scale]);
CGPoint boundsCenter = TGPaintCenterOfRect(_entitiesWrapperView.bounds);
_entitiesView.center = TGPaintAddPoints(boundsCenter, offset);
if (_entitiesView.superview != _entitiesWrapperView) {
[_entitiesWrapperView addSubview:_entitiesView];
CGFloat cropScale = 1.0;
if (_photoEditor.originalSize.width > _photoEditor.originalSize.height) {
cropScale = _photoEditor.originalSize.height / _photoEditor.cropRect.size.height;
} else {
cropScale = _photoEditor.originalSize.width / _photoEditor.cropRect.size.width;
}
CGFloat scale = _previewView.frame.size.width / _entitiesView.frame.size.width;
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(TGRotationForOrientation(_photoEditor.cropOrientation));
_entitiesWrapperView.transform = CGAffineTransformScale(rotationTransform, scale * cropScale, scale * cropScale);
_entitiesWrapperView.frame = [_previewView convertRect:_previewView.bounds toView:_entitiesWrapperView.superview];
}
- (void)loadView
@ -507,6 +509,9 @@ const CGFloat TGPhotoEditorToolsLandscapePanelSize = TGPhotoEditorToolsPanelSize
TGPhotoEditorPreviewView *previewView = _previewView;
previewView.hidden = false;
[previewView performTransitionInIfNeeded];
_entitiesReady++;
[self layoutEntitiesView];
}
- (void)prepareForCustomTransitionOut

View File

@ -268,7 +268,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
if video != previousVideoRepresentations?.last {
let mediaManager = self.context.sharedContext.mediaManager
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: entry.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
let videoContent = NativeVideoContent(id: .profileVideo(id, category), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: true, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
let videoContent = NativeVideoContent(id: .profileVideo(id, category), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: true, useLargeThumbnail: true, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
let videoNode = UniversalVideoNode(postbox: self.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .overlay)
videoNode.isUserInteractionEnabled = false
videoNode.isHidden = true

View File

@ -326,14 +326,14 @@ private func chatMessageImageFileThumbnailDatas(account: Account, fileReference:
return signal
}
private func chatMessageVideoDatas(postbox: Postbox, fileReference: FileMediaReference, thumbnailSize: Bool = false, onlyFullSize: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false) -> Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError> {
private func chatMessageVideoDatas(postbox: Postbox, fileReference: FileMediaReference, thumbnailSize: Bool = false, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false) -> Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError> {
let fullSizeResource = fileReference.media.resource
var reducedSizeResource: MediaResource?
if let videoThumbnail = fileReference.media.videoThumbnails.first {
reducedSizeResource = videoThumbnail.resource
}
let thumbnailRepresentation = smallestImageRepresentation(fileReference.media.previewRepresentations)
let thumbnailRepresentation = useLargeThumbnail ? largestImageRepresentation(fileReference.media.previewRepresentations) : smallestImageRepresentation(fileReference.media.previewRepresentations)
let thumbnailResource = thumbnailRepresentation?.resource
let maybeFullSize = postbox.mediaBox.cachedResourceRepresentation(fullSizeResource, representation: thumbnailSize ? CachedScaledVideoFirstFrameRepresentation(size: CGSize(width: 160.0, height: 160.0)) : CachedVideoFirstFrameRepresentation(), complete: false, fetch: false, attemptSynchronously: synchronousLoad)
@ -1320,14 +1320,14 @@ public func gifPaneVideoThumbnail(account: Account, videoReference: FileMediaRef
}
}
public func mediaGridMessageVideo(postbox: Postbox, videoReference: FileMediaReference, onlyFullSize: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
return internalMediaGridMessageVideo(postbox: postbox, videoReference: videoReference, onlyFullSize: onlyFullSize, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail, overlayColor: overlayColor, nilForEmptyResult: nilForEmptyResult, useMiniThumbnailIfAvailable: useMiniThumbnailIfAvailable)
public func mediaGridMessageVideo(postbox: Postbox, videoReference: FileMediaReference, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
return internalMediaGridMessageVideo(postbox: postbox, videoReference: videoReference, onlyFullSize: onlyFullSize, useLargeThumbnail: useLargeThumbnail, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail, overlayColor: overlayColor, nilForEmptyResult: nilForEmptyResult, useMiniThumbnailIfAvailable: useMiniThumbnailIfAvailable)
|> map {
return $0.1
}
}
public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: FileMediaReference, imageReference: ImageMediaReference? = nil, onlyFullSize: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false) -> Signal<(() -> CGSize?, (TransformImageArguments) -> DrawingContext?), NoError> {
public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: FileMediaReference, imageReference: ImageMediaReference? = nil, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false) -> Signal<(() -> CGSize?, (TransformImageArguments) -> DrawingContext?), NoError> {
let signal: Signal<Tuple3<Data?, Tuple2<Data, String>?, Bool>, NoError>
if let imageReference = imageReference {
signal = chatMessagePhotoDatas(postbox: postbox, photoReference: imageReference, tryAdditionalRepresentations: true, synchronousLoad: synchronousLoad)
@ -1338,7 +1338,7 @@ public func internalMediaGridMessageVideo(postbox: Postbox, videoReference: File
return Tuple(thumbnailData, fullSizeData.flatMap({ Tuple($0, "") }), fullSizeComplete)
}
} else {
signal = chatMessageVideoDatas(postbox: postbox, fileReference: videoReference, onlyFullSize: onlyFullSize, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail)
signal = chatMessageVideoDatas(postbox: postbox, fileReference: videoReference, onlyFullSize: onlyFullSize, useLargeThumbnail: useLargeThumbnail, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail)
}
return signal

View File

@ -351,7 +351,7 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
if let video = videoRepresentations.last, let peerReference = PeerReference(self.peer) {
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
if videoContent.id != self.videoContent?.id {
self.videoContent = videoContent
@ -1278,7 +1278,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
if let video = videoRepresentations.last, let peerReference = PeerReference(peer) {
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
if videoContent.id != self.videoContent?.id {
self.videoNode?.removeFromSupernode()
@ -1564,7 +1564,7 @@ final class PeerInfoEditingAvatarNode: ASDisplayNode {
if let video = videoRepresentations.last, let peerReference = PeerReference(peer) {
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.representation.resource, previewRepresentations: representations.map { $0.representation }, videoThumbnails: [], immediateThumbnailData: immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.representation.dimensions, flags: [])]))
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
let videoContent = NativeVideoContent(id: .profileVideo(id, nil), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.representation.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.representation.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
if videoContent.id != self.videoContent?.id {
self.videoNode?.removeFromSupernode()

View File

@ -31,13 +31,14 @@ public final class NativeVideoContent: UniversalVideoContent {
public let baseRate: Double
let fetchAutomatically: Bool
let onlyFullSizeThumbnail: Bool
let useLargeThumbnail: Bool
let autoFetchFullSizeThumbnail: Bool
let startTimestamp: Double?
let continuePlayingWithoutSoundOnLostAudioSession: Bool
let placeholderColor: UIColor
let tempFilePath: String?
public init(id: NativeVideoContentId, fileReference: FileMediaReference, imageReference: ImageMediaReference? = nil, streamVideo: MediaPlayerStreaming = .none, loopVideo: Bool = false, enableSound: Bool = true, baseRate: Double = 1.0, fetchAutomatically: Bool = true, onlyFullSizeThumbnail: Bool = false, autoFetchFullSizeThumbnail: Bool = false, startTimestamp: Double? = nil, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor = .white, tempFilePath: String? = nil) {
public init(id: NativeVideoContentId, fileReference: FileMediaReference, imageReference: ImageMediaReference? = nil, streamVideo: MediaPlayerStreaming = .none, loopVideo: Bool = false, enableSound: Bool = true, baseRate: Double = 1.0, fetchAutomatically: Bool = true, onlyFullSizeThumbnail: Bool = false, useLargeThumbnail: Bool = false, autoFetchFullSizeThumbnail: Bool = false, startTimestamp: Double? = nil, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor = .white, tempFilePath: String? = nil) {
self.id = id
self.nativeId = id
self.fileReference = fileReference
@ -62,6 +63,7 @@ public final class NativeVideoContent: UniversalVideoContent {
self.baseRate = baseRate
self.fetchAutomatically = fetchAutomatically
self.onlyFullSizeThumbnail = onlyFullSizeThumbnail
self.useLargeThumbnail = useLargeThumbnail
self.autoFetchFullSizeThumbnail = autoFetchFullSizeThumbnail
self.startTimestamp = startTimestamp
self.continuePlayingWithoutSoundOnLostAudioSession = continuePlayingWithoutSoundOnLostAudioSession
@ -70,7 +72,7 @@ public final class NativeVideoContent: UniversalVideoContent {
}
public func makeContentNode(postbox: Postbox, audioSession: ManagedAudioSession) -> UniversalVideoContentNode & ASDisplayNode {
return NativeVideoContentNode(postbox: postbox, audioSessionManager: audioSession, fileReference: self.fileReference, imageReference: self.imageReference, streamVideo: self.streamVideo, loopVideo: self.loopVideo, enableSound: self.enableSound, baseRate: self.baseRate, fetchAutomatically: self.fetchAutomatically, onlyFullSizeThumbnail: self.onlyFullSizeThumbnail, autoFetchFullSizeThumbnail: self.autoFetchFullSizeThumbnail, startTimestamp: self.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: self.continuePlayingWithoutSoundOnLostAudioSession, placeholderColor: self.placeholderColor, tempFilePath: self.tempFilePath)
return NativeVideoContentNode(postbox: postbox, audioSessionManager: audioSession, fileReference: self.fileReference, imageReference: self.imageReference, streamVideo: self.streamVideo, loopVideo: self.loopVideo, enableSound: self.enableSound, baseRate: self.baseRate, fetchAutomatically: self.fetchAutomatically, onlyFullSizeThumbnail: self.onlyFullSizeThumbnail, useLargeThumbnail: self.useLargeThumbnail, autoFetchFullSizeThumbnail: self.autoFetchFullSizeThumbnail, startTimestamp: self.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: self.continuePlayingWithoutSoundOnLostAudioSession, placeholderColor: self.placeholderColor, tempFilePath: self.tempFilePath)
}
public func isEqual(to other: UniversalVideoContent) -> Bool {
@ -143,7 +145,7 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
private var shouldPlay: Bool = false
init(postbox: Postbox, audioSessionManager: ManagedAudioSession, fileReference: FileMediaReference, imageReference: ImageMediaReference?, streamVideo: MediaPlayerStreaming, loopVideo: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, onlyFullSizeThumbnail: Bool, autoFetchFullSizeThumbnail: Bool, startTimestamp: Double?, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor, tempFilePath: String?) {
init(postbox: Postbox, audioSessionManager: ManagedAudioSession, fileReference: FileMediaReference, imageReference: ImageMediaReference?, streamVideo: MediaPlayerStreaming, loopVideo: Bool, enableSound: Bool, baseRate: Double, fetchAutomatically: Bool, onlyFullSizeThumbnail: Bool, useLargeThumbnail: Bool, autoFetchFullSizeThumbnail: Bool, startTimestamp: Double?, continuePlayingWithoutSoundOnLostAudioSession: Bool = false, placeholderColor: UIColor, tempFilePath: String?) {
self.postbox = postbox
self.fileReference = fileReference
self.placeholderColor = placeholderColor
@ -180,7 +182,7 @@ private final class NativeVideoContentNode: ASDisplayNode, UniversalVideoContent
self?.performActionAtEnd()
}
self.imageNode.setSignal(internalMediaGridMessageVideo(postbox: postbox, videoReference: fileReference, imageReference: imageReference, onlyFullSize: onlyFullSizeThumbnail, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail || fileReference.media.isInstantVideo) |> map { [weak self] getSize, getData in
self.imageNode.setSignal(internalMediaGridMessageVideo(postbox: postbox, videoReference: fileReference, imageReference: imageReference, onlyFullSize: onlyFullSizeThumbnail, useLargeThumbnail: useLargeThumbnail, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail || fileReference.media.isInstantVideo) |> map { [weak self] getSize, getData in
Queue.mainQueue().async {
if let strongSelf = self, strongSelf.dimensions == nil {
if let dimensions = getSize() {

View File

@ -43,7 +43,6 @@ private final class ProfileDataPhotoPreloadContext {
let disposable: Disposable
var value: Any?
var skipNext = false
var emptyTimer: SwiftSignalKit.Timer?
init(disposable: Disposable) {
@ -211,9 +210,6 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl {
let context: ProfileDataPhotoPreloadContext
if let current = self.profileDataPhotoPreloadContexts[peerId] {
context = current
if let _ = context.value {
context.skipNext = true
}
} else {
let disposable = MetaDisposable()
context = ProfileDataPhotoPreloadContext(disposable: disposable)
@ -223,10 +219,6 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl {
guard let context = context else {
return
}
if context.skipNext {
context.skipNext = false
return
}
context.value = value
for f in context.subscribers.copyItems() {
f(value)