Video avatar fixes

This commit is contained in:
Ilya Laktyushin 2020-06-24 20:17:46 +03:00
parent bd2652ac0c
commit 9d435f3f25
15 changed files with 2650 additions and 2583 deletions

View File

@ -5629,3 +5629,6 @@ Any member of this group will be able to see messages in the channel.";
"PrivacySettings.AutoArchiveInfo" = "Automatically archive and mute new chats, groups and channels from non-contacts.";
"Call.RemoteVideoPaused" = "%@'s video paused";
"Settings.SetProfilePhotoOrVideo" = "Set Profile Photo or Video";
"Settings.SetNewProfilePhotoOrVideo" = "Set New Profile Photo or Video";

View File

@ -31,7 +31,8 @@ typedef enum
- (NSDictionary *)dictionary;
- (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset maxDuration:(NSTimeInterval)maxDuration videoStartValue:(NSTimeInterval)videoStartValue;
- (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset maxDuration:(NSTimeInterval)maxDuration;
- (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset videoStartValue:(NSTimeInterval)videoStartValue trimStartValue:(NSTimeInterval)trimStartValue trimEndValue:(NSTimeInterval)trimEndValue;
+ (instancetype)editAdjustmentsWithOriginalSize:(CGSize)originalSize preset:(TGMediaVideoConversionPreset)preset;
+ (instancetype)editAdjustmentsWithPhotoEditorValues:(PGPhotoEditorValues *)values;
+ (instancetype)editAdjustmentsWithDictionary:(NSDictionary *)dictionary;

View File

@ -45,8 +45,8 @@ const CGFloat TGCameraModeControlVerticalInteritemSpace = 29.0f;
_buttons = @
[
[self _createButtonForMode:PGCameraModeSquareVideo title:TGLocalized(@"Camera.VideoMode")],
[self _createButtonForMode:PGCameraModePhoto title:TGLocalized(@"Camera.PhotoMode")],
[self _createButtonForMode:PGCameraModeSquareSwing title:@"SWING"]
[self _createButtonForMode:PGCameraModePhoto title:TGLocalized(@"Camera.PhotoMode")]
// [self _createButtonForMode:PGCameraModeSquareSwing title:@"SWING"]
];
} else {
_buttons = @

View File

@ -24,6 +24,7 @@
@property (nonatomic, assign) bool disableZoom;
@property (nonatomic, assign) bool disableTimeDisplay;
@property (nonatomic, readonly) bool isScrubbing;
@property (nonatomic, assign) bool isPlaying;
@property (nonatomic, assign) NSTimeInterval value;
- (void)setValue:(NSTimeInterval)value resetPosition:(bool)resetPosition;

View File

@ -1043,6 +1043,10 @@ typedef enum
return true;
}
- (bool)isScrubbing {
return _scrubbing;
}
- (void)handlePress:(UILongPressGestureRecognizer *)gestureRecognizer
{
switch (gestureRecognizer.state)

View File

@ -1261,7 +1261,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
+ (bool)keepAudioForPreset:(TGMediaVideoConversionPreset)preset
{
return preset != TGMediaVideoConversionPresetAnimation;
return preset != TGMediaVideoConversionPresetAnimation && preset != TGMediaVideoConversionPresetProfile;
}
+ (NSDictionary *)audioSettingsForPreset:(TGMediaVideoConversionPreset)preset
@ -1338,7 +1338,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
return 300;
case TGMediaVideoConversionPresetProfile:
return 1800;
return 1400;
default:
return 900;
@ -1369,7 +1369,7 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer,
case TGMediaVideoConversionPresetAnimation:
case TGMediaVideoConversionPresetProfile:
return 32;
return 0;
default:
return 32;

View File

@ -12,5 +12,7 @@
- (void)setScrubberPlaying:(bool)value;
- (NSTimeInterval)coverPosition;
- (NSTimeInterval)trimStartValue;
- (NSTimeInterval)trimEndValue;
@end

View File

@ -146,8 +146,9 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
_scrubberView.disableZoom = true;
_scrubberView.disableTimeDisplay = true;
_scrubberView.trimStartValue = 0.0;
_scrubberView.trimEndValue = MIN(10.0, self.item.originalDuration);
_scrubberView.maximumLength = 10.0;
_scrubberView.trimEndValue = MIN(9.9, self.item.originalDuration);
[_scrubberView setTrimApplied:self.item.originalDuration > 9.9];
_scrubberView.maximumLength = 9.9;
[_scrubberView reloadData];
[_scrubberView resetToStart];
}
@ -269,7 +270,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
UIView *snapshotView = nil;
POPSpringAnimation *snapshotAnimation = nil;
if (saving && CGRectIsNull(targetFrame) && parentView != nil)
if (saving && CGRectIsNull(targetFrame))
{
snapshotView = [previewView snapshotViewAfterScreenUpdates:false];
snapshotView.frame = previewView.frame;
@ -277,6 +278,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
CGSize fittedSize = TGScaleToSize(previewView.frame.size, self.view.frame.size);
targetFrame = CGRectMake((self.view.frame.size.width - fittedSize.width) / 2, (self.view.frame.size.height - fittedSize.height) / 2, fittedSize.width, fittedSize.height);
if (parentView != nil)
[parentView addSubview:snapshotView];
snapshotAnimation = [TGPhotoEditorAnimation prepareTransitionAnimationForPropertyNamed:kPOPViewFrame];
@ -685,6 +687,9 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
_flashView.alpha = 0.0f;
} completion:^(BOOL finished) {
TGDispatchAfter(1.0, dispatch_get_main_queue(), ^{
if (_scrubberView.isScrubbing) {
return;
}
[UIView animateWithDuration:0.2 animations:^{
_areaMaskView.alpha = 0.0f;
_coverLabel.alpha = 0.7f;
@ -882,4 +887,12 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
return _scrubberView.value;
}
- (NSTimeInterval)trimStartValue {
return _scrubberView.trimStartValue;
}
- (NSTimeInterval)trimEndValue {
return _scrubberView.trimEndValue;
}
@end

View File

@ -1613,7 +1613,10 @@
TGPaintingData *paintingData = _photoEditor.paintingData;
bool saving = true;
NSTimeInterval coverPosition = 0.0;
NSTimeInterval videoStartValue = 0.0;
NSTimeInterval trimStartValue = 0.0;
NSTimeInterval trimEndValue = 0.0;
if ([_currentTabController isKindOfClass:[TGPhotoPaintController class]])
{
TGPhotoPaintController *paintController = (TGPhotoPaintController *)_currentTabController;
@ -1633,7 +1636,9 @@
} else if ([_currentTabController isKindOfClass:[TGPhotoAvatarPreviewController class]])
{
TGPhotoAvatarPreviewController *previewController = (TGPhotoAvatarPreviewController *)_currentTabController;
coverPosition = previewController.coverPosition;
videoStartValue = previewController.coverPosition;
trimStartValue = previewController.trimStartValue;
trimEndValue = previewController.trimEndValue;
}
TGVideoEditAdjustments *adjustments = [_photoEditor exportAdjustmentsWithPaintingData:paintingData];
@ -1657,11 +1662,10 @@
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform = true;
generator.maximumSize = TGFitSize(videoDimensions, CGSizeMake(1280.0f, 1280.0f));
generator.requestedTimeToleranceAfter = kCMTimeZero;
generator.requestedTimeToleranceBefore = kCMTimeZero;
CGImageRef imageRef = [generator copyCGImageAtTime:CMTimeMakeWithSeconds(coverPosition, NSEC_PER_SEC) actualTime:nil error:NULL];
CGImageRef imageRef = [generator copyCGImageAtTime:CMTimeMakeWithSeconds(videoStartValue, NSEC_PER_SEC) actualTime:nil error:NULL];
UIImage *image = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
@ -1691,7 +1695,7 @@
TGDispatchOnMainThread(^{
if (self.didFinishEditingVideo != nil)
self.didFinishEditingVideo(asset.URL, [adjustments editAdjustmentsWithPreset:TGMediaVideoConversionPresetProfile maxDuration:0.0 videoStartValue:coverPosition], fullImage, nil, true);
self.didFinishEditingVideo(asset.URL, [adjustments editAdjustmentsWithPreset:TGMediaVideoConversionPresetProfile videoStartValue:videoStartValue trimStartValue:trimStartValue trimEndValue:trimEndValue], fullImage, nil, true);
[self transitionOutSaving:true completion:^
{

View File

@ -651,7 +651,7 @@ const NSTimeInterval TGPhotoQualityPreviewDuration = 15.0f;
[self _updateVideoDuration:((TGMediaAsset *)self.item).videoDuration hasAudio:true];
TGVideoEditAdjustments *adjustments = [self.photoEditor exportAdjustments];
adjustments = [adjustments editAdjustmentsWithPreset:self.preset maxDuration:TGPhotoQualityPreviewDuration videoStartValue:0.0];
adjustments = [adjustments editAdjustmentsWithPreset:self.preset maxDuration:TGPhotoQualityPreviewDuration];
__block NSTimeInterval delay = 0.0;
__weak TGPhotoQualityController *weakSelf = self;

View File

@ -153,7 +153,7 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
return adjustments;
}
- (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset maxDuration:(NSTimeInterval)maxDuration videoStartValue:(NSTimeInterval)videoStartValue
- (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset maxDuration:(NSTimeInterval)maxDuration
{
TGVideoEditAdjustments *adjustments = [[[self class] alloc] init];
adjustments->_originalSize = _originalSize;
@ -168,7 +168,7 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
adjustments->_sendAsGif = _sendAsGif;
adjustments->_preset = preset;
adjustments->_toolValues = _toolValues;
adjustments->_videoStartValue = videoStartValue;
adjustments->_videoStartValue = _videoStartValue;
if (maxDuration > DBL_EPSILON)
{
@ -186,6 +186,26 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
return adjustments;
}
- (instancetype)editAdjustmentsWithPreset:(TGMediaVideoConversionPreset)preset videoStartValue:(NSTimeInterval)videoStartValue trimStartValue:(NSTimeInterval)trimStartValue trimEndValue:(NSTimeInterval)trimEndValue
{
TGVideoEditAdjustments *adjustments = [[[self class] alloc] init];
adjustments->_originalSize = _originalSize;
adjustments->_cropRect = _cropRect;
adjustments->_cropOrientation = _cropOrientation;
adjustments->_cropRotation = _cropRotation;
adjustments->_cropLockedAspectRatio = _cropLockedAspectRatio;
adjustments->_cropMirrored = _cropMirrored;
adjustments->_trimStartValue = trimStartValue;
adjustments->_trimEndValue = trimEndValue;
adjustments->_paintingData = _paintingData;
adjustments->_sendAsGif = _sendAsGif;
adjustments->_preset = preset;
adjustments->_toolValues = _toolValues;
adjustments->_videoStartValue = videoStartValue;
return adjustments;
}
- (NSDictionary *)dictionary
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];

View File

@ -27,6 +27,7 @@ private struct EditSettingsItemArguments {
let avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext
let avatarTapAction: () -> Void
let setProfilePhoto: () -> Void
let pushController: (ViewController) -> Void
let presentController: (ViewController) -> Void
@ -60,6 +61,7 @@ public enum EditSettingsEntryTag: ItemListItemTag {
private enum SettingsEntry: ItemListNodeEntry {
case userInfo(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, Peer?, CachedPeerData?, ItemListAvatarAndNameInfoItemState, ItemListAvatarAndNameInfoItemUpdatingAvatar?)
case setProfilePhoto(PresentationTheme, String)
case userInfoNotice(PresentationTheme, String)
case bioText(PresentationTheme, String, String)
@ -73,7 +75,7 @@ private enum SettingsEntry: ItemListNodeEntry {
var section: ItemListSectionId {
switch self {
case .userInfo, .userInfoNotice:
case .userInfo, .setProfilePhoto, .userInfoNotice:
return SettingsSection.info.rawValue
case .bioText, .bioInfo:
return SettingsSection.bio.rawValue
@ -90,20 +92,22 @@ private enum SettingsEntry: ItemListNodeEntry {
switch self {
case .userInfo:
return 0
case .userInfoNotice:
case .setProfilePhoto:
return 1
case .bioText:
case .userInfoNotice:
return 2
case .bioInfo:
case .bioText:
return 3
case .phoneNumber:
case .bioInfo:
return 4
case .username:
case .phoneNumber:
return 5
case .addAccount:
case .username:
return 6
case .logOut:
case .addAccount:
return 7
case .logOut:
return 8
}
}
@ -144,6 +148,12 @@ private enum SettingsEntry: ItemListNodeEntry {
} else {
return false
}
case let .setProfilePhoto(lhsTheme, lhsText):
if case let .setProfilePhoto(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .userInfoNotice(lhsTheme, lhsText):
if case let .userInfoNotice(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
@ -196,33 +206,37 @@ private enum SettingsEntry: ItemListNodeEntry {
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! EditSettingsItemArguments
switch self {
case let .userInfo(theme, strings, dateTimeFormat, peer, cachedData, state, updatingImage):
case let .userInfo(_, _, dateTimeFormat, peer, cachedData, state, updatingImage):
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer, presence: TelegramUserPresence(status: .present(until: Int32.max), lastActivity: 0), cachedData: cachedData, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
arguments.updateEditingName(editingName)
}, avatarTapped: {
arguments.avatarTapAction()
}, context: arguments.avatarAndNameInfoContext, updatingImage: updatingImage)
case let .userInfoNotice(theme, text):
case let .setProfilePhoto(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.setProfilePhoto()
})
case let .userInfoNotice(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .bioText(theme, currentText, placeholder):
case let .bioText(_, currentText, placeholder):
return ItemListMultilineInputItem(presentationData: presentationData, text: currentText, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 70, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in
arguments.updateBioText(currentText, updatedText)
}, tag: EditSettingsEntryTag.bio)
case let .bioInfo(theme, text):
case let .bioInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .phoneNumber(theme, text, number):
case let .phoneNumber(_, text, number):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: number, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.pushController(ChangePhoneNumberIntroController(context: arguments.context, phoneNumber: number))
})
case let .username(theme, text, address):
case let .username(_, text, address):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: address, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.pushController(usernameSetupController(context: arguments.context))
})
case let .addAccount(theme, text):
case let .addAccount(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.addAccount()
})
case let .logOut(theme, text):
case let .logOut(_, text):
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
arguments.logout()
})
@ -291,6 +305,7 @@ private func editSettingsEntries(presentationData: PresentationData, state: Edit
if let peer = peerViewMainPeer(view) as? TelegramUser {
let userInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingName, updatingName: state.updatingName)
entries.append(.userInfo(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, view.cachedData, userInfoState, state.updatingAvatar))
entries.append(.setProfilePhoto(presentationData.theme, peer.photo.isEmpty ? presentationData.strings.Settings_SetProfilePhotoOrVideo : presentationData.strings.Settings_SetNewProfilePhotoOrVideo))
entries.append(.userInfoNotice(presentationData.theme, presentationData.strings.EditProfile_NameAndPhotoHelp))
entries.append(.bioText(presentationData.theme, state.editingBioText, presentationData.strings.UserInfo_About_Placeholder))
@ -357,6 +372,8 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar
return
}
changeProfilePhotoImpl?()
}, setProfilePhoto: {
changeProfilePhotoImpl?()
}, pushController: { controller in
pushControllerImpl?(controller)

View File

@ -660,7 +660,7 @@ private func settingsEntries(account: Account, presentationData: PresentationDat
let userInfoState = ItemListAvatarAndNameInfoItemState(editingName: nil, updatingName: nil)
entries.append(.userInfo(account, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, view.cachedData, userInfoState, state.updatingAvatar))
if peer.photo.isEmpty {
entries.append(.setProfilePhoto(presentationData.theme, presentationData.strings.Settings_SetProfilePhoto))
entries.append(.setProfilePhoto(presentationData.theme, presentationData.strings.Settings_SetProfilePhotoOrVideo))
}
if peer.addressName == nil {
entries.append(.setUsername(presentationData.theme, presentationData.strings.Settings_SetUsername))