mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Avatar fixes
This commit is contained in:
parent
2d25f92cbe
commit
fe904af993
@ -8512,7 +8512,7 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Common.Paste" = "Paste";
|
||||
|
||||
"PhotoEditor.SelectCoverFrameSuggestion" = "Choose a cover for profile video";
|
||||
"PhotoEditor.SelectCoverFrameSuggestion" = "Choose a cover for this video";
|
||||
|
||||
"GroupInfo.TitleMembers_1" = "%@ Member";
|
||||
"GroupInfo.TitleMembers_any" = "%@ Members";
|
||||
|
@ -608,9 +608,7 @@ private struct Line {
|
||||
}
|
||||
|
||||
final class Texture {
|
||||
#if !targetEnvironment(simulator)
|
||||
let buffer: MTLBuffer?
|
||||
#endif
|
||||
|
||||
let width: Int
|
||||
let height: Int
|
||||
@ -628,6 +626,7 @@ final class Texture {
|
||||
|
||||
if #available(iOS 12.0, *) {
|
||||
#if targetEnvironment(simulator)
|
||||
self.buffer = nil
|
||||
let textureDescriptor = MTLTextureDescriptor()
|
||||
textureDescriptor.textureType = .type2D
|
||||
textureDescriptor.pixelFormat = .bgra8Unorm
|
||||
|
@ -409,13 +409,6 @@ final class PenTool: DrawingElement {
|
||||
|
||||
let r = min(limitRange, length)
|
||||
|
||||
// var r = limitRange - length
|
||||
// if r < 0 {
|
||||
// r = 0
|
||||
// }
|
||||
|
||||
// print(r * lowerer)
|
||||
|
||||
return (r * lowerer) + constant
|
||||
}
|
||||
|
||||
|
@ -978,6 +978,7 @@ public class StickerPickerScreen: ViewController {
|
||||
|
||||
var dismissing = false
|
||||
if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) {
|
||||
self.controller?.completion(nil)
|
||||
self.controller?.dismiss(animated: true, completion: nil)
|
||||
dismissing = true
|
||||
} else if self.isExpanded {
|
||||
|
@ -22,6 +22,7 @@ public class MediaDustNode: ASDisplayNode {
|
||||
private var isExploding = false
|
||||
|
||||
public var revealed: () -> Void = {}
|
||||
public var tapped: () -> Void = {}
|
||||
|
||||
public override init() {
|
||||
self.emitterNode = ASDisplayNode()
|
||||
@ -120,6 +121,8 @@ public class MediaDustNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
|
||||
self.tapped()
|
||||
|
||||
self.isRevealed = true
|
||||
self.isExploding = true
|
||||
|
||||
@ -255,8 +258,7 @@ public class MediaDustNode: ASDisplayNode {
|
||||
self.emitter?.birthRate = min(100000.0, square * 0.02)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public func update(size: CGSize, color: UIColor, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, color)
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
@property (nonatomic) bool hasSchedule;
|
||||
@property (nonatomic) bool reminder;
|
||||
@property (nonatomic) bool forum;
|
||||
@property (nonatomic) bool isSuggesting;
|
||||
@property (nonatomic, copy) void (^presentScheduleController)(bool, void (^)(int32_t));
|
||||
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
||||
|
||||
|
@ -64,6 +64,10 @@ typedef enum
|
||||
@property (nonatomic, assign) bool hasSilentPosting;
|
||||
@property (nonatomic, assign) bool hasSchedule;
|
||||
@property (nonatomic, assign) bool reminder;
|
||||
|
||||
@property (nonatomic, assign) bool forum;
|
||||
@property (nonatomic, assign) bool isSuggesting;
|
||||
|
||||
@property (nonatomic, copy) void (^presentScheduleController)(bool, void (^)(int32_t));
|
||||
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
||||
|
||||
|
@ -30,7 +30,7 @@ typedef void (^TGMediaAvatarPresentImpl)(id<LegacyComponentsContext>, void (^)(U
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasDeleteButton:(bool)hasDeleteButton saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasDeleteButton:(bool)hasDeleteButton personalPhoto:(bool)personalPhoto saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasSearchButton:(bool)hasSearchButton hasDeleteButton:(bool)hasDeleteButton hasViewButton:(bool)hasViewButton personalPhoto:(bool)personalPhoto isVideo:(bool)isVideo saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia signup:(bool)signup forum:(bool)forum title:(NSString *)title;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasSearchButton:(bool)hasSearchButton hasDeleteButton:(bool)hasDeleteButton hasViewButton:(bool)hasViewButton personalPhoto:(bool)personalPhoto isVideo:(bool)isVideo saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia signup:(bool)signup forum:(bool)forum title:(NSString *)title isSuggesting:(bool)isSuggesting;
|
||||
- (TGMenuSheetController *)present;
|
||||
|
||||
@end
|
||||
|
@ -30,6 +30,10 @@
|
||||
@property (nonatomic, assign) bool hasSilentPosting;
|
||||
@property (nonatomic, assign) bool hasSchedule;
|
||||
@property (nonatomic, assign) bool reminder;
|
||||
|
||||
@property (nonatomic, assign) bool forum;
|
||||
@property (nonatomic, assign) bool isSuggesting;
|
||||
|
||||
@property (nonatomic, copy) void (^presentScheduleController)(bool, void (^)(int32_t));
|
||||
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
||||
|
||||
|
@ -22,7 +22,8 @@ typedef enum {
|
||||
TGPhotoEditorControllerWebIntent = (1 << 3),
|
||||
TGPhotoEditorControllerVideoIntent = (1 << 4),
|
||||
TGPhotoEditorControllerForumAvatarIntent = (1 << 5),
|
||||
TGPhotoEditorControllerSuggestedAvatarIntent = (1 << 6)
|
||||
TGPhotoEditorControllerSuggestedAvatarIntent = (1 << 6),
|
||||
TGPhotoEditorControllerSuggestingAvatarIntent = (1 << 7)
|
||||
} TGPhotoEditorControllerIntent;
|
||||
|
||||
@interface TGPhotoEditorController : TGOverlayController
|
||||
|
@ -915,6 +915,9 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
||||
if (_forum) {
|
||||
intent |= TGPhotoEditorControllerForumAvatarIntent;
|
||||
}
|
||||
if (_isSuggesting) {
|
||||
intent |= TGPhotoEditorControllerSuggestingAvatarIntent;
|
||||
}
|
||||
|
||||
TGPhotoEditorController *controller = [[TGPhotoEditorController alloc] initWithContext:[windowManager context] item:editableItem intent:intent adjustments:nil caption:nil screenImage:thumbnailImage availableTabs:[TGPhotoEditorController defaultTabsForAvatarIntent] selectedTab:TGPhotoEditorCropTab];
|
||||
controller.editingContext = _editingContext;
|
||||
|
@ -260,6 +260,8 @@
|
||||
pickerController.hasSilentPosting = strongController.hasSilentPosting;
|
||||
pickerController.hasSchedule = strongController.hasSchedule;
|
||||
pickerController.reminder = strongController.reminder;
|
||||
pickerController.forum = strongController.forum;
|
||||
pickerController.isSuggesting = strongController.isSuggesting;
|
||||
pickerController.presentScheduleController = strongController.presentScheduleController;
|
||||
pickerController.presentTimerController = strongController.presentTimerController;
|
||||
[strongController pushViewController:pickerController animated:true];
|
||||
@ -363,6 +365,16 @@
|
||||
self.pickerController.reminder = reminder;
|
||||
}
|
||||
|
||||
- (void)setForum:(bool)forum {
|
||||
_forum = forum;
|
||||
self.pickerController.forum = forum;
|
||||
}
|
||||
|
||||
- (void)setIsSuggesting:(bool)isSuggesting {
|
||||
_isSuggesting = isSuggesting;
|
||||
self.pickerController.isSuggesting = isSuggesting;
|
||||
}
|
||||
|
||||
- (void)setPresentScheduleController:(void (^)(bool, void (^)(int32_t)))presentScheduleController {
|
||||
_presentScheduleController = [presentScheduleController copy];
|
||||
self.pickerController.presentScheduleController = presentScheduleController;
|
||||
|
@ -435,6 +435,14 @@
|
||||
intent = TGPhotoEditorControllerSignupAvatarIntent;
|
||||
}
|
||||
|
||||
if (self.forum) {
|
||||
intent |= TGPhotoEditorControllerForumAvatarIntent;
|
||||
}
|
||||
|
||||
if (self.isSuggesting) {
|
||||
intent |= TGPhotoEditorControllerSuggestingAvatarIntent;
|
||||
}
|
||||
|
||||
id<TGMediaEditableItem> editableItem = asset;
|
||||
if (asset.type == TGMediaAssetGifType) {
|
||||
editableItem = [[TGCameraCapturedVideo alloc] initWithAsset:asset livePhoto:false];
|
||||
|
@ -28,6 +28,7 @@
|
||||
bool _isVideo;
|
||||
bool _forum;
|
||||
NSString *_title;
|
||||
bool _isSuggesting;
|
||||
}
|
||||
@end
|
||||
|
||||
@ -40,10 +41,10 @@
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasDeleteButton:(bool)hasDeleteButton personalPhoto:(bool)personalPhoto saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia
|
||||
{
|
||||
return [self initWithContext:context parentController:parentController hasSearchButton:false hasDeleteButton:hasDeleteButton hasViewButton:false personalPhoto:personalPhoto isVideo:false saveEditedPhotos:saveEditedPhotos saveCapturedMedia:saveCapturedMedia signup:false forum:false title:nil];
|
||||
return [self initWithContext:context parentController:parentController hasSearchButton:false hasDeleteButton:hasDeleteButton hasViewButton:false personalPhoto:personalPhoto isVideo:false saveEditedPhotos:saveEditedPhotos saveCapturedMedia:saveCapturedMedia signup:false forum:false title:nil isSuggesting:false];
|
||||
}
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasSearchButton:(bool)hasSearchButton hasDeleteButton:(bool)hasDeleteButton hasViewButton:(bool)hasViewButton personalPhoto:(bool)personalPhoto isVideo:(bool)isVideo saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia signup:(bool)signup forum:(bool)forum title:(NSString *)title
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController hasSearchButton:(bool)hasSearchButton hasDeleteButton:(bool)hasDeleteButton hasViewButton:(bool)hasViewButton personalPhoto:(bool)personalPhoto isVideo:(bool)isVideo saveEditedPhotos:(bool)saveEditedPhotos saveCapturedMedia:(bool)saveCapturedMedia signup:(bool)signup forum:(bool)forum title:(NSString *)title isSuggesting:(bool)isSuggesting
|
||||
{
|
||||
self = [super init];
|
||||
if (self != nil)
|
||||
@ -60,6 +61,7 @@
|
||||
_signup = signup;
|
||||
_forum = forum;
|
||||
_title = title;
|
||||
_isSuggesting = isSuggesting;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -99,6 +101,7 @@
|
||||
}
|
||||
|
||||
TGAttachmentCarouselItemView *carouselItem = [[TGAttachmentCarouselItemView alloc] initWithContext:_context camera:true selfPortrait:_personalPhoto forProfilePhoto:true assetType:_signup ? TGMediaAssetPhotoType : TGMediaAssetAnyType saveEditedPhotos:_saveEditedPhotos allowGrouping:false];
|
||||
carouselItem.isSuggesting = _isSuggesting;
|
||||
carouselItem.forum = _forum;
|
||||
carouselItem.stickersContext = _stickersContext;
|
||||
carouselItem.parentController = _parentController;
|
||||
@ -456,6 +459,8 @@
|
||||
TGMediaAssetsController *controller = [TGMediaAssetsController controllerWithContext:context assetGroup:group intent:strongSelf->_signup ? TGMediaAssetsControllerSetSignupProfilePhotoIntent : TGMediaAssetsControllerSetProfilePhotoIntent recipientName:nil saveEditedPhotos:strongSelf->_saveEditedPhotos allowGrouping:false selectionLimit:10];
|
||||
__weak TGMediaAssetsController *weakController = controller;
|
||||
controller.stickersContext = _stickersContext;
|
||||
controller.forum = _forum;
|
||||
controller.isSuggesting = _isSuggesting;
|
||||
controller.avatarCompletionBlock = ^(UIImage *resultImage)
|
||||
{
|
||||
__strong TGMediaAvatarMenuMixin *strongSelf = weakSelf;
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView isForum:(bool)isForum isSuggestion:(bool)isSuggestion senderName:(NSString *)senderName;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView isForum:(bool)isForum isSuggestion:(bool)isSuggestion isSuggesting:(bool)isSuggesting senderName:(NSString *)senderName;
|
||||
|
||||
- (void)setImage:(UIImage *)image;
|
||||
- (void)setSnapshotImage:(UIImage *)snapshotImage;
|
||||
|
@ -57,6 +57,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
|
||||
bool _isForum;
|
||||
bool _isSuggestion;
|
||||
bool _isSuggesting;
|
||||
NSString *_senderName;
|
||||
}
|
||||
|
||||
@ -67,7 +68,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
|
||||
@implementation TGPhotoAvatarPreviewController
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView isForum:(bool)isForum isSuggestion:(bool)isSuggestion senderName:(NSString *)senderName {
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context photoEditor:(PGPhotoEditor *)photoEditor previewView:(TGPhotoEditorPreviewView *)previewView isForum:(bool)isForum isSuggestion:(bool)isSuggestion isSuggesting:(bool)isSuggesting senderName:(NSString *)senderName {
|
||||
self = [super initWithContext:context];
|
||||
if (self != nil)
|
||||
{
|
||||
@ -75,6 +76,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
self.previewView = previewView;
|
||||
_isForum = isForum;
|
||||
_isSuggestion = isSuggestion;
|
||||
_isSuggesting = isSuggesting;
|
||||
_senderName = senderName;
|
||||
}
|
||||
return self;
|
||||
@ -184,7 +186,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
_coverLabel.backgroundColor = [UIColor clearColor];
|
||||
_coverLabel.font = TGSystemFontOfSize(14.0f);
|
||||
_coverLabel.textColor = [UIColor whiteColor];
|
||||
_coverLabel.text = _isSuggestion ? TGLocalized(@"PhotoEditor.SelectCoverFrameSuggestion") : TGLocalized(@"PhotoEditor.SelectCoverFrame");
|
||||
_coverLabel.text = _isSuggesting ? TGLocalized(@"PhotoEditor.SelectCoverFrameSuggestion") : TGLocalized(@"PhotoEditor.SelectCoverFrame");
|
||||
[_coverLabel sizeToFit];
|
||||
[_portraitToolsWrapperView addSubview:_coverLabel];
|
||||
|
||||
@ -207,7 +209,9 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
_subtitleLabel.numberOfLines = 2;
|
||||
_subtitleLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_subtitleLabel.text = [NSString stringWithFormat:self.item.isVideo ? TGLocalized(@"Conversation.SuggestedVideoText") : TGLocalized(@"Conversation.SuggestedPhotoText"), _senderName];
|
||||
[_wrapperView addSubview:_subtitleLabel];
|
||||
if (!self.item.isVideo) {
|
||||
[_wrapperView addSubview:_subtitleLabel];
|
||||
}
|
||||
|
||||
if (!self.item.isVideo) {
|
||||
_cancelButton = [[TGModernButton alloc] init];
|
||||
@ -215,7 +219,6 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
_cancelButton.titleLabel.font = TGSystemFontOfSize(17.0);
|
||||
[_cancelButton sizeToFit];
|
||||
[_cancelButton addTarget:self action:@selector(cancelButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_wrapperView addSubview:_cancelButton];
|
||||
|
||||
if (_stickersContext != nil) {
|
||||
_doneButton = [_stickersContext solidRoundedButton:self.item.isVideo ? TGLocalized(@"PhotoEditor.SetAsMyVideo") : TGLocalized(@"PhotoEditor.SetAsMyPhoto") action:^{
|
||||
@ -887,7 +890,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
|
||||
_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);
|
||||
|
||||
_titleLabel.frame = CGRectMake(screenEdges.left + floor((referenceSize.width - _titleLabel.frame.size.width) / 2.0), screenEdges.top + floor((44.0 - _titleLabel.frame.size.height) / 2.0), _titleLabel.frame.size.width, _titleLabel.frame.size.height);
|
||||
_subtitleLabel.frame = CGRectMake(screenEdges.left + floor((referenceSize.width - _subtitleLabel.frame.size.width) / 2.0), screenEdges.bottom - 56.0 - buttonSize.height - subtitleSize.height - 8.0, subtitleSize.width, subtitleSize.height);
|
||||
_subtitleLabel.frame = CGRectMake(screenEdges.left + floor((referenceSize.width - _subtitleLabel.frame.size.width) / 2.0), screenEdges.bottom - 56.0 - buttonSize.height - subtitleSize.height - 16.0, subtitleSize.width, subtitleSize.height);
|
||||
|
||||
_cancelButton.frame = CGRectMake(screenEdges.left + 16.0, screenEdges.top + floor((44.0 - _cancelButton.frame.size.height) / 2.0), _cancelButton.frame.size.width, _cancelButton.frame.size.height);
|
||||
|
||||
|
@ -1145,6 +1145,11 @@
|
||||
return _intent & (TGPhotoEditorControllerSuggestedAvatarIntent);
|
||||
}
|
||||
|
||||
- (bool)presentedForSuggestingAvatar
|
||||
{
|
||||
return _intent & (TGPhotoEditorControllerSuggestingAvatarIntent);
|
||||
}
|
||||
|
||||
#pragma mark - Transition
|
||||
|
||||
- (void)transitionIn
|
||||
@ -1317,7 +1322,7 @@
|
||||
TGPhotoEditorBackButton backButtonType = TGPhotoEditorBackButtonCancel;
|
||||
TGPhotoEditorDoneButton doneButtonType = TGPhotoEditorDoneButtonCheck;
|
||||
|
||||
if ([self presentedForSuggestedAvatar]) {
|
||||
if ([self presentedForSuggestedAvatar] && !_item.isVideo) {
|
||||
[_portraitToolbarView setCancelDoneButtonsHidden:tab == TGPhotoEditorCropTab animated:!isInitialAppearance];
|
||||
}
|
||||
|
||||
@ -1336,7 +1341,7 @@
|
||||
{
|
||||
bool skipInitialTransition = (![self presentedFromCamera] && self.navigationController != nil) || self.skipInitialTransition;
|
||||
|
||||
TGPhotoAvatarPreviewController *cropController = [[TGPhotoAvatarPreviewController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView isForum:[self presentedForForumAvatarCreation] isSuggestion:[self presentedForSuggestedAvatar] senderName:self.senderName];
|
||||
TGPhotoAvatarPreviewController *cropController = [[TGPhotoAvatarPreviewController alloc] initWithContext:_context photoEditor:_photoEditor previewView:_previewView isForum:[self presentedForForumAvatarCreation] isSuggestion:[self presentedForSuggestedAvatar] isSuggesting:[self presentedForSuggestingAvatar] senderName:self.senderName];
|
||||
cropController.stickersContext = _stickersContext;
|
||||
cropController.scrubberView = _scrubberView;
|
||||
cropController.dotImageView = _dotImageView;
|
||||
|
@ -545,18 +545,18 @@
|
||||
if (hidden) {
|
||||
_cancelButton.modernHighlight = false;
|
||||
}
|
||||
_cancelButton.hidden = false;
|
||||
// _cancelButton.hidden = false;
|
||||
_doneButton.hidden = false;
|
||||
|
||||
[UIView animateWithDuration:0.2f
|
||||
animations:^
|
||||
{
|
||||
_cancelButton.alpha = targetAlpha;
|
||||
// _cancelButton.alpha = targetAlpha;
|
||||
_doneButton.alpha = targetAlpha;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
_animatingCancelDoneButtons = false;
|
||||
_cancelButton.hidden = hidden;
|
||||
// _cancelButton.hidden = hidden;
|
||||
_doneButton.hidden = hidden;
|
||||
|
||||
if (hidden) {
|
||||
@ -571,9 +571,9 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
_cancelButton.alpha = targetAlpha;
|
||||
// _cancelButton.alpha = targetAlpha;
|
||||
_doneButton.alpha = targetAlpha;
|
||||
_cancelButton.hidden = hidden;
|
||||
// _cancelButton.hidden = hidden;
|
||||
_doneButton.hidden = hidden;
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,7 @@
|
||||
id<LegacyComponentsOverlayWindowManager> windowManager = [context makeOverlayWindowManager];
|
||||
|
||||
id<TGMediaEditableItem> editableItem;
|
||||
if (image != nil) {
|
||||
editableItem = image;
|
||||
} else if (video != nil) {
|
||||
if (video != nil) {
|
||||
if (![video.path.lowercaseString hasSuffix:@".mp4"]) {
|
||||
NSString *tmpPath = NSTemporaryDirectory();
|
||||
int64_t fileId = 0;
|
||||
@ -31,6 +29,8 @@
|
||||
}
|
||||
|
||||
editableItem = [[TGCameraCapturedVideo alloc] initWithURL:video];
|
||||
} else if (image != nil) {
|
||||
editableItem = image;
|
||||
}
|
||||
|
||||
void (^present)(UIImage *) = ^(UIImage *screenImage) {
|
||||
|
@ -23,7 +23,7 @@ public func presentLegacyAvatarPicker(holder: Atomic<NSObject?>, signup: Bool, t
|
||||
|
||||
present(legacyController, nil)
|
||||
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: false, hasDeleteButton: false, hasViewButton: openCurrent != nil, personalPhoto: true, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: signup, forum: false, title: nil)!
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: false, hasDeleteButton: false, hasViewButton: openCurrent != nil, personalPhoto: true, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: signup, forum: false, title: nil, isSuggesting: false)!
|
||||
let _ = holder.swap(mixin)
|
||||
mixin.didFinishWithImage = { image in
|
||||
guard let image = image else {
|
||||
@ -53,21 +53,36 @@ public func presentLegacyAvatarPicker(holder: Atomic<NSObject?>, signup: Bool, t
|
||||
}
|
||||
|
||||
public func legacyAvatarEditor(context: AccountContext, media: AnyMediaReference, transitionView: UIView?, senderName: String? = nil, present: @escaping (ViewController, Any?) -> Void, imageCompletion: @escaping (UIImage) -> Void, videoCompletion: @escaping (UIImage, URL, TGVideoEditAdjustments) -> Void) {
|
||||
let _ = (fetchMediaData(context: context, postbox: context.account.postbox, userLocation: .other, mediaReference: media)
|
||||
|> deliverOnMainQueue).start(next: { (value, isImage) in
|
||||
guard case let .data(data) = value, data.complete else {
|
||||
return
|
||||
let isVideo = !((media.media as? TelegramMediaImage)?.videoRepresentations.isEmpty ?? true)
|
||||
|
||||
let imageSignal = fetchMediaData(context: context, postbox: context.account.postbox, userLocation: .other, mediaReference: media, forceVideo: false)
|
||||
|> map { (value, _) -> (UIImage?, Bool) in
|
||||
if case let .data(data) = value, data.complete {
|
||||
return (UIImage(contentsOfFile: data.path), true)
|
||||
} else {
|
||||
return (nil, false)
|
||||
}
|
||||
|
||||
var image: UIImage?
|
||||
var url: URL?
|
||||
if let maybeImage = UIImage(contentsOfFile: data.path) {
|
||||
image = maybeImage
|
||||
} else if data.complete {
|
||||
url = URL(fileURLWithPath: data.path)
|
||||
}
|
||||
|
||||
let videoSignal = isVideo ? fetchMediaData(context: context, postbox: context.account.postbox, userLocation: .other, mediaReference: media, forceVideo: true)
|
||||
|> map { (value, isImage) -> (URL?, Bool) in
|
||||
if case let .data(data) = value, data.complete && !isImage {
|
||||
return (URL(fileURLWithPath: data.path), true)
|
||||
} else {
|
||||
return (nil, false)
|
||||
}
|
||||
|
||||
if image == nil && url == nil {
|
||||
} : .single((nil, true))
|
||||
|
||||
let signals = combineLatest(queue: Queue.mainQueue(),
|
||||
imageSignal,
|
||||
videoSignal
|
||||
)
|
||||
|> filter { image, video in
|
||||
return image.1 && video.1
|
||||
}
|
||||
|
||||
let _ = signals.start(next: { image, video in
|
||||
if image.0 == nil && video.0 == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -92,7 +107,7 @@ public func legacyAvatarEditor(context: AccountContext, media: AnyMediaReference
|
||||
|
||||
present(legacyController, nil)
|
||||
|
||||
TGPhotoVideoEditor.present(with: legacyController.context, parentController: emptyController, image: image, video: url, stickersContext: paintStickersContext, transitionView: transitionView, senderName: senderName, didFinishWithImage: { image in
|
||||
TGPhotoVideoEditor.present(with: legacyController.context, parentController: emptyController, image: image.0, video: video.0, stickersContext: paintStickersContext, transitionView: transitionView, senderName: senderName, didFinishWithImage: { image in
|
||||
if let image = image {
|
||||
imageCompletion(image)
|
||||
}
|
||||
|
@ -518,6 +518,7 @@ private let fadeWidth: CGFloat = 70.0
|
||||
|
||||
public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
private let context: AccountContext
|
||||
private let isSettings: Bool
|
||||
public var peer: Peer?
|
||||
|
||||
public let controlsContainerNode: ASDisplayNode
|
||||
@ -648,8 +649,9 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
self.playerUpdateTimer = nil
|
||||
}
|
||||
|
||||
public init(context: AccountContext) {
|
||||
public init(context: AccountContext, isSettings: Bool = false) {
|
||||
self.context = context
|
||||
self.isSettings = isSettings
|
||||
|
||||
self.contentNode = ASDisplayNode()
|
||||
|
||||
@ -780,8 +782,10 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
self.controlsContainerNode.addSubnode(self.stripContainerNode)
|
||||
self.controlsClippingNode.addSubnode(self.controlsContainerNode)
|
||||
self.controlsClippingOffsetNode.addSubnode(self.controlsClippingNode)
|
||||
self.stripContainerNode.addSubnode(self.setByYouNode)
|
||||
self.stripContainerNode.addSubnode(self.setByYouImageNode)
|
||||
if self.isSettings {
|
||||
self.stripContainerNode.addSubnode(self.setByYouNode)
|
||||
self.stripContainerNode.addSubnode(self.setByYouImageNode)
|
||||
}
|
||||
|
||||
self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
|
@ -15,14 +15,17 @@ public enum FetchMediaDataState {
|
||||
case data(MediaResourceData)
|
||||
}
|
||||
|
||||
public func fetchMediaData(context: AccountContext, postbox: Postbox, userLocation: MediaResourceUserLocation, mediaReference: AnyMediaReference) -> Signal<(FetchMediaDataState, Bool), NoError> {
|
||||
public func fetchMediaData(context: AccountContext, postbox: Postbox, userLocation: MediaResourceUserLocation, mediaReference: AnyMediaReference, forceVideo: Bool = false) -> Signal<(FetchMediaDataState, Bool), NoError> {
|
||||
var resource: MediaResource?
|
||||
var isImage = true
|
||||
var fileExtension: String?
|
||||
var userContentType: MediaResourceUserContentType = .other
|
||||
if let image = mediaReference.media as? TelegramMediaImage {
|
||||
userContentType = .image
|
||||
if let representation = largestImageRepresentation(image.representations) {
|
||||
if let video = image.videoRepresentations.first, forceVideo {
|
||||
resource = video.resource
|
||||
isImage = false
|
||||
} else if let representation = largestImageRepresentation(image.representations) {
|
||||
resource = representation.resource
|
||||
}
|
||||
} else if let file = mediaReference.media as? TelegramMediaFile {
|
||||
|
@ -627,8 +627,8 @@ public func privacyAndSecurityController(
|
||||
hasTwoStepAuth: Bool? = nil,
|
||||
loginEmailPattern: Signal<String?, NoError>? = nil,
|
||||
updatedTwoStepAuthData: (() -> Void)? = nil,
|
||||
requestPublicPhotoSetup: (() -> Void)? = nil,
|
||||
requestPublicPhotoRemove: (() -> Void)? = nil
|
||||
requestPublicPhotoSetup: ((@escaping (UIImage?) -> Void) -> Void)? = nil,
|
||||
requestPublicPhotoRemove: ((@escaping () -> Void) -> Void)? = nil
|
||||
) -> ViewController {
|
||||
let statePromise = ValuePromise(PrivacyAndSecurityControllerState(), ignoreRepeated: true)
|
||||
let stateValue = Atomic(value: PrivacyAndSecurityControllerState())
|
||||
@ -819,10 +819,10 @@ public func privacyAndSecurityController(
|
||||
|> deliverOnMainQueue
|
||||
currentInfoDisposable.set(signal.start(next: { [weak currentInfoDisposable] info in
|
||||
if let info = info {
|
||||
pushControllerImpl?(selectivePrivacySettingsController(context: context, kind: .profilePhoto, current: info.profilePhoto, requestPublicPhotoSetup: {
|
||||
requestPublicPhotoSetup?()
|
||||
}, requestPublicPhotoRemove: {
|
||||
requestPublicPhotoRemove?()
|
||||
pushControllerImpl?(selectivePrivacySettingsController(context: context, kind: .profilePhoto, current: info.profilePhoto, requestPublicPhotoSetup: { completion in
|
||||
requestPublicPhotoSetup?(completion)
|
||||
}, requestPublicPhotoRemove: { completion in
|
||||
requestPublicPhotoRemove?(completion)
|
||||
}, updated: { updated, _, _ in
|
||||
if let currentInfoDisposable = currentInfoDisposable {
|
||||
let applySetting: Signal<Void, NoError> = privacySettingsPromise.get()
|
||||
|
@ -106,7 +106,7 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
||||
case nobody(PresentationTheme, String, Bool)
|
||||
case settingInfo(PresentationTheme, String, String)
|
||||
case setPublicPhoto(PresentationTheme, String)
|
||||
case removePublicPhoto(PresentationTheme, String, EnginePeer, TelegramMediaImage?)
|
||||
case removePublicPhoto(PresentationTheme, String, EnginePeer, TelegramMediaImage?, UIImage?)
|
||||
case publicPhotoInfo(PresentationTheme, String)
|
||||
case exceptionsHeader(PresentationTheme, String)
|
||||
case disableFor(PresentationTheme, String, String)
|
||||
@ -253,8 +253,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .removePublicPhoto(lhsTheme, lhsText, lhsPeer, lhsRep):
|
||||
if case let .removePublicPhoto(rhsTheme, rhsText, rhsPeer, rhsRep) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsPeer == rhsPeer, lhsRep == rhsRep {
|
||||
case let .removePublicPhoto(lhsTheme, lhsText, lhsPeer, lhsRep, lhsImage):
|
||||
if case let .removePublicPhoto(rhsTheme, rhsText, rhsPeer, rhsRep, rhsImage) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsPeer == rhsPeer, lhsRep == rhsRep, lhsImage === rhsImage {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -415,8 +415,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPhotoIcon(theme), title: text, sectionId: self.section, height: .generic, color: .accent, editing: false, action: {
|
||||
arguments.setPublicPhoto?()
|
||||
})
|
||||
case let .removePublicPhoto(_, text, peer, image):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: nil, iconSignal: peerAvatarCompleteImage(account: arguments.context.account, peer: peer, forceProvidedRepresentation: true, representation: image?.representationForDisplayAtSize(PixelDimensions(width: 28, height: 28)), size: CGSize(width: 28.0, height: 28.0)), title: text, sectionId: self.section, height: .generic, color: .destructive, editing: false, action: {
|
||||
case let .removePublicPhoto(_, text, peer, image, completeImage):
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: completeImage, iconSignal: completeImage == nil ? peerAvatarCompleteImage(account: arguments.context.account, peer: peer, forceProvidedRepresentation: true, representation: image?.representationForDisplayAtSize(PixelDimensions(width: 28, height: 28)), size: CGSize(width: 28.0, height: 28.0)) : nil, title: text, sectionId: self.section, height: .generic, color: .destructive, editing: false, action: {
|
||||
arguments.removePublicPhoto?()
|
||||
})
|
||||
case let .publicPhotoInfo(_, text):
|
||||
@ -498,8 +498,10 @@ private struct SelectivePrivacySettingsControllerState: Equatable {
|
||||
let callIntegrationAvailable: Bool?
|
||||
let callIntegrationEnabled: Bool?
|
||||
let phoneDiscoveryEnabled: Bool?
|
||||
|
||||
let uploadedPhoto: UIImage?
|
||||
|
||||
init(setting: SelectivePrivacySettingType, enableFor: [PeerId: SelectivePrivacyPeer], disableFor: [PeerId: SelectivePrivacyPeer], saving: Bool, callDataSaving: VoiceCallDataSaving?, callP2PMode: SelectivePrivacySettingType?, callP2PEnableFor: [PeerId: SelectivePrivacyPeer]?, callP2PDisableFor: [PeerId: SelectivePrivacyPeer]?, callIntegrationAvailable: Bool?, callIntegrationEnabled: Bool?, phoneDiscoveryEnabled: Bool?) {
|
||||
init(setting: SelectivePrivacySettingType, enableFor: [PeerId: SelectivePrivacyPeer], disableFor: [PeerId: SelectivePrivacyPeer], saving: Bool, callDataSaving: VoiceCallDataSaving?, callP2PMode: SelectivePrivacySettingType?, callP2PEnableFor: [PeerId: SelectivePrivacyPeer]?, callP2PDisableFor: [PeerId: SelectivePrivacyPeer]?, callIntegrationAvailable: Bool?, callIntegrationEnabled: Bool?, phoneDiscoveryEnabled: Bool?, uploadedPhoto: UIImage?) {
|
||||
self.setting = setting
|
||||
self.enableFor = enableFor
|
||||
self.disableFor = disableFor
|
||||
@ -511,6 +513,7 @@ private struct SelectivePrivacySettingsControllerState: Equatable {
|
||||
self.callIntegrationAvailable = callIntegrationAvailable
|
||||
self.callIntegrationEnabled = callIntegrationEnabled
|
||||
self.phoneDiscoveryEnabled = phoneDiscoveryEnabled
|
||||
self.uploadedPhoto = uploadedPhoto
|
||||
}
|
||||
|
||||
static func ==(lhs: SelectivePrivacySettingsControllerState, rhs: SelectivePrivacySettingsControllerState) -> Bool {
|
||||
@ -547,44 +550,51 @@ private struct SelectivePrivacySettingsControllerState: Equatable {
|
||||
if lhs.phoneDiscoveryEnabled != rhs.phoneDiscoveryEnabled {
|
||||
return false
|
||||
}
|
||||
if lhs.uploadedPhoto !== rhs.uploadedPhoto {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func withUpdatedSetting(_ setting: SelectivePrivacySettingType) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedEnableFor(_ enableFor: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedDisableFor(_ disableFor: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedSaving(_ saving: Bool) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedCallP2PMode(_ mode: SelectivePrivacySettingType) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: mode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: mode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedCallP2PEnableFor(_ enableFor: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: enableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: enableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedCallP2PDisableFor(_ disableFor: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: disableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: disableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedCallsIntegrationEnabled(_ enabled: Bool) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: enabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: enabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedPhoneDiscoveryEnabled(_ phoneDiscoveryEnabled: Bool) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: phoneDiscoveryEnabled)
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: phoneDiscoveryEnabled, uploadedPhoto: self.uploadedPhoto)
|
||||
}
|
||||
|
||||
func withUpdatedUploadedPhoto(_ uploadedPhoto: UIImage?) -> SelectivePrivacySettingsControllerState {
|
||||
return SelectivePrivacySettingsControllerState(setting: self.setting, enableFor: self.enableFor, disableFor: self.disableFor, saving: self.saving, callDataSaving: self.callDataSaving, callP2PMode: self.callP2PMode, callP2PEnableFor: self.callP2PEnableFor, callP2PDisableFor: self.callP2PDisableFor, callIntegrationAvailable: self.callIntegrationAvailable, callIntegrationEnabled: self.callIntegrationEnabled, phoneDiscoveryEnabled: self.phoneDiscoveryEnabled, uploadedPhoto: uploadedPhoto)
|
||||
}
|
||||
}
|
||||
|
||||
@ -680,7 +690,7 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
|
||||
if case .profilePhoto = kind, let peer = peer, state.setting != .everybody {
|
||||
if let publicPhoto = publicPhoto {
|
||||
entries.append(.setPublicPhoto(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_UpdatePublicPhoto))
|
||||
entries.append(.removePublicPhoto(presentationData.theme, !publicPhoto.videoRepresentations.isEmpty ? presentationData.strings.Privacy_ProfilePhoto_RemovePublicVideo : presentationData.strings.Privacy_ProfilePhoto_RemovePublicPhoto, peer, publicPhoto))
|
||||
entries.append(.removePublicPhoto(presentationData.theme, !publicPhoto.videoRepresentations.isEmpty ? presentationData.strings.Privacy_ProfilePhoto_RemovePublicVideo : presentationData.strings.Privacy_ProfilePhoto_RemovePublicPhoto, peer, publicPhoto, state.uploadedPhoto))
|
||||
} else {
|
||||
entries.append(.setPublicPhoto(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_SetPublicPhoto))
|
||||
}
|
||||
@ -738,8 +748,8 @@ func selectivePrivacySettingsController(
|
||||
phoneDiscoveryEnabled: Bool? = nil,
|
||||
voipConfiguration: VoipConfiguration? = nil,
|
||||
callIntegrationAvailable: Bool? = nil,
|
||||
requestPublicPhotoSetup: (() -> Void)? = nil,
|
||||
requestPublicPhotoRemove: (() -> Void)? = nil,
|
||||
requestPublicPhotoSetup: ((@escaping (UIImage?) -> Void) -> Void)? = nil,
|
||||
requestPublicPhotoRemove: ((@escaping () -> Void) -> Void)? = nil,
|
||||
updated: @escaping (SelectivePrivacySettings, (SelectivePrivacySettings, VoiceCallSettings)?, Bool?) -> Void
|
||||
) -> ViewController {
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
@ -771,7 +781,7 @@ func selectivePrivacySettingsController(
|
||||
}
|
||||
}
|
||||
|
||||
let initialState = SelectivePrivacySettingsControllerState(setting: SelectivePrivacySettingType(current), enableFor: initialEnableFor, disableFor: initialDisableFor, saving: false, callDataSaving: callSettings?.1.dataSaving, callP2PMode: callSettings != nil ? SelectivePrivacySettingType(callSettings!.0) : nil, callP2PEnableFor: initialCallP2PEnableFor, callP2PDisableFor: initialCallP2PDisableFor, callIntegrationAvailable: callIntegrationAvailable, callIntegrationEnabled: callSettings?.1.enableSystemIntegration, phoneDiscoveryEnabled: phoneDiscoveryEnabled)
|
||||
let initialState = SelectivePrivacySettingsControllerState(setting: SelectivePrivacySettingType(current), enableFor: initialEnableFor, disableFor: initialDisableFor, saving: false, callDataSaving: callSettings?.1.dataSaving, callP2PMode: callSettings != nil ? SelectivePrivacySettingType(callSettings!.0) : nil, callP2PEnableFor: initialCallP2PEnableFor, callP2PDisableFor: initialCallP2PDisableFor, callIntegrationAvailable: callIntegrationAvailable, callIntegrationEnabled: callSettings?.1.enableSystemIntegration, phoneDiscoveryEnabled: phoneDiscoveryEnabled, uploadedPhoto: nil)
|
||||
|
||||
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
|
||||
let stateValue = Atomic(value: initialState)
|
||||
@ -1036,9 +1046,28 @@ func selectivePrivacySettingsController(
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
|
||||
}, setPublicPhoto: {
|
||||
requestPublicPhotoSetup?()
|
||||
requestPublicPhotoSetup?({ result in
|
||||
var result = result
|
||||
if let image = result {
|
||||
result = generateImage(CGSize(width: 28.0, height: 28.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
context.addPath(CGPath(ellipseIn: CGRect(origin: .zero, size: size), transform: nil))
|
||||
context.clip()
|
||||
if let cgImage = image.cgImage {
|
||||
context.draw(cgImage, in: CGRect(origin: .zero, size: size))
|
||||
}
|
||||
}, opaque: false)
|
||||
}
|
||||
updateState { state in
|
||||
return state.withUpdatedUploadedPhoto(result)
|
||||
}
|
||||
})
|
||||
}, removePublicPhoto: {
|
||||
requestPublicPhotoRemove?()
|
||||
requestPublicPhotoRemove?({
|
||||
updateState { state in
|
||||
return state.withUpdatedUploadedPhoto(nil)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
let peer = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
||||
@ -1082,7 +1111,7 @@ func selectivePrivacySettingsController(
|
||||
title = presentationData.strings.Privacy_VoiceMessages
|
||||
}
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: selectivePrivacySettingsControllerEntries(presentationData: presentationData, kind: kind, state: state, peerName: peerName ?? "", phoneNumber: phoneNumber, peer: peer, publicPhoto: publicPhoto), style: .blocks, animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: selectivePrivacySettingsControllerEntries(presentationData: presentationData, kind: kind, state: state, peerName: peerName ?? "", phoneNumber: phoneNumber, peer: peer, publicPhoto: publicPhoto), style: .blocks, animateChanges: true)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -6165,7 +6165,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
||||
// return controller
|
||||
// }
|
||||
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos && !fromGallery, hasViewButton: false, personalPhoto: peerId.namespace == Namespaces.Peer.CloudUser, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: false, title: nil)!
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos && !fromGallery, hasViewButton: false, personalPhoto: peerId.namespace == Namespaces.Peer.CloudUser, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: false, title: nil, isSuggesting: false)!
|
||||
mixin.forceDark = true
|
||||
mixin.stickersContext = paintStickersContext
|
||||
let _ = strongSelf.currentAvatarMixin.swap(mixin)
|
||||
|
@ -185,6 +185,9 @@ private class ExtendedMediaOverlayNode: ASDisplayNode {
|
||||
private var maskView: UIView?
|
||||
private var maskLayer: CAShapeLayer?
|
||||
|
||||
var isRevealed = false
|
||||
var tapped: () -> Void = {}
|
||||
|
||||
override init() {
|
||||
self.blurredImageNode = TransformImageNode()
|
||||
|
||||
@ -252,6 +255,12 @@ private class ExtendedMediaOverlayNode: ASDisplayNode {
|
||||
self.maskLayer = maskLayer
|
||||
}
|
||||
|
||||
func reveal() {
|
||||
self.blurredImageNode.removeFromSupernode()
|
||||
self.dustNode.removeFromSupernode()
|
||||
self.isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
func update(size: CGSize, text: String, imageSignal: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize, CGSize)?, imageFrame: CGRect, corners: ImageCorners?) {
|
||||
let spacing: CGFloat = 2.0
|
||||
let padding: CGFloat = 10.0
|
||||
@ -268,9 +277,13 @@ private class ExtendedMediaOverlayNode: ASDisplayNode {
|
||||
self.isUserInteractionEnabled = !self.dustNode.isRevealed
|
||||
|
||||
self.dustNode.revealed = { [weak self] in
|
||||
self?.isRevealed = true
|
||||
self?.blurredImageNode.removeFromSupernode()
|
||||
self?.isUserInteractionEnabled = false
|
||||
}
|
||||
self.dustNode.tapped = { [weak self] in
|
||||
self?.tapped()
|
||||
}
|
||||
} else {
|
||||
self.blurredImageNode.isHidden = true
|
||||
self.isUserInteractionEnabled = false
|
||||
@ -377,23 +390,30 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
var visibilityPromise = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||
var visibility: Bool = false {
|
||||
didSet {
|
||||
if let videoNode = self.videoNode {
|
||||
if self.visibility {
|
||||
if !videoNode.canAttachContent {
|
||||
videoNode.canAttachContent = true
|
||||
if videoNode.hasAttachedContext {
|
||||
videoNode.play()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
videoNode.canAttachContent = false
|
||||
}
|
||||
}
|
||||
self.animatedStickerNode?.visibility = self.visibility
|
||||
self.visibilityPromise.set(self.visibility)
|
||||
self.updateVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
private var internallyVisible = true
|
||||
private func updateVisibility() {
|
||||
let visibility = self.visibility && self.internallyVisible
|
||||
|
||||
if let videoNode = self.videoNode {
|
||||
if visibility {
|
||||
if !videoNode.canAttachContent {
|
||||
videoNode.canAttachContent = true
|
||||
if videoNode.hasAttachedContext {
|
||||
videoNode.play()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
videoNode.canAttachContent = false
|
||||
}
|
||||
}
|
||||
self.animatedStickerNode?.visibility = visibility
|
||||
self.visibilityPromise.set(visibility)
|
||||
}
|
||||
|
||||
var activateLocalContent: (InteractiveMediaNodeActivateContent) -> Void = { _ in }
|
||||
var activatePinch: ((PinchSourceContainerNode) -> Void)?
|
||||
var updateMessageReaction: ((Message, ChatControllerInteractionReaction) -> Void)?
|
||||
@ -1034,6 +1054,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
updateImageSignal = { synchronousLoad, _ in
|
||||
return mediaGridMessageVideo(postbox: context.account.postbox, userLocation: .peer(message.id.peerId), videoReference: .message(message: MessageReference(message), media: file), onlyFullSize: currentMedia?.id?.namespace == Namespaces.Media.LocalFile, autoFetchFullSizeThumbnail: true)
|
||||
}
|
||||
updateBlurredImageSignal = { synchronousLoad, _ in
|
||||
return chatSecretMessageVideo(account: context.account, userLocation: .peer(message.id.peerId), videoReference: .message(message: MessageReference(message), media: file))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1319,6 +1342,11 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute }), strongSelf.extendedMediaOverlayNode == nil {
|
||||
strongSelf.internallyVisible = false
|
||||
}
|
||||
|
||||
if let videoNode = strongSelf.videoNode {
|
||||
if !(replaceVideoNode ?? false), let decoration = videoNode.decoration as? ChatBubbleVideoDecoration, decoration.corners != corners {
|
||||
decoration.updateCorners(corners)
|
||||
@ -1327,7 +1355,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
videoNode.updateLayout(size: arguments.drawingSize, transition: .immediate)
|
||||
videoNode.frame = CGRect(origin: CGPoint(), size: imageFrame.size)
|
||||
|
||||
if strongSelf.visibility {
|
||||
if strongSelf.visibility && strongSelf.internallyVisible {
|
||||
if !videoNode.canAttachContent {
|
||||
videoNode.canAttachContent = true
|
||||
if videoNode.hasAttachedContext {
|
||||
@ -1892,6 +1920,10 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
if displaySpoiler {
|
||||
if self.extendedMediaOverlayNode == nil {
|
||||
let extendedMediaOverlayNode = ExtendedMediaOverlayNode()
|
||||
extendedMediaOverlayNode.tapped = { [weak self] in
|
||||
self?.internallyVisible = true
|
||||
self?.updateVisibility()
|
||||
}
|
||||
self.extendedMediaOverlayNode = extendedMediaOverlayNode
|
||||
self.pinchContainerNode.contentNode.insertSubnode(extendedMediaOverlayNode, aboveSubnode: self.imageNode)
|
||||
}
|
||||
@ -1979,6 +2011,12 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
||||
}
|
||||
|
||||
func updateIsHidden(_ isHidden: Bool) {
|
||||
if isHidden && !self.internallyVisible {
|
||||
self.internallyVisible = true
|
||||
self.updateVisibility()
|
||||
self.extendedMediaOverlayNode?.reveal()
|
||||
}
|
||||
|
||||
if let badgeNode = self.badgeNode, badgeNode.isHidden != isHidden {
|
||||
if isHidden {
|
||||
badgeNode.isHidden = true
|
||||
|
@ -14,6 +14,9 @@ import TelegramStringFormatting
|
||||
import WallpaperBackgroundNode
|
||||
import ReactionSelectionNode
|
||||
import PhotoResources
|
||||
import UniversalMediaPlayer
|
||||
import TelegramUniversalVideoContent
|
||||
import GalleryUI
|
||||
|
||||
class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode {
|
||||
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?
|
||||
@ -22,6 +25,10 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
private let subtitleNode: TextNode
|
||||
private let imageNode: TransformImageNode
|
||||
|
||||
fileprivate var videoNode: UniversalVideoNode?
|
||||
private var videoContent: NativeVideoContent?
|
||||
private var videoStartTimestamp: Double?
|
||||
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
private let buttonStarsNode: PremiumStarsNode
|
||||
private let buttonTitleNode: TextNode
|
||||
@ -195,6 +202,7 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
|
||||
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
|
||||
if let photo = photo {
|
||||
if mediaUpdated {
|
||||
strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(context: item.context, userLocation: .peer(item.message.id.peerId), photoReference: .message(message: MessageReference(item.message), media: photo), displayAtSize: nil, storeToDownloadsPeerType: nil).start())
|
||||
@ -207,11 +215,49 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
let apply = makeImageLayout(arguments)
|
||||
apply()
|
||||
|
||||
strongSelf.imageNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
|
||||
strongSelf.imageNode.frame = imageFrame
|
||||
}
|
||||
|
||||
if let photo = photo, let video = photo.videoRepresentations.last, let id = photo.id?.id {
|
||||
let videoFileReference = FileMediaReference.message(message: MessageReference(item.message), media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
let videoContent = NativeVideoContent(id: .profileVideo(id, "action"), userLocation: .peer(item.message.id.peerId), fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear)
|
||||
if videoContent.id != strongSelf.videoContent?.id {
|
||||
let mediaManager = item.context.sharedContext.mediaManager
|
||||
let videoNode = UniversalVideoNode(postbox: item.context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .secondaryOverlay)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
videoNode.ownsContentNodeUpdated = { [weak self] owns in
|
||||
if let strongSelf = self {
|
||||
strongSelf.videoNode?.isHidden = !owns
|
||||
}
|
||||
}
|
||||
strongSelf.videoContent = videoContent
|
||||
strongSelf.videoNode = videoNode
|
||||
|
||||
videoNode.updateLayout(size: imageSize, transition: .immediate)
|
||||
videoNode.frame = imageFrame
|
||||
videoNode.clipsToBounds = true
|
||||
videoNode.cornerRadius = imageFrame.width / 2.0
|
||||
|
||||
strongSelf.addSubnode(videoNode)
|
||||
|
||||
videoNode.canAttachContent = true
|
||||
if let videoStartTimestamp = video.startTimestamp {
|
||||
videoNode.seek(videoStartTimestamp)
|
||||
} else {
|
||||
videoNode.seek(0.0)
|
||||
}
|
||||
videoNode.play()
|
||||
|
||||
}
|
||||
} else if let videoNode = strongSelf.videoNode {
|
||||
strongSelf.videoContent = nil
|
||||
strongSelf.videoNode = nil
|
||||
|
||||
videoNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize)
|
||||
let mediaBackgroundFrame = imageFrame.insetBy(dx: -2.0, dy: -2.0)
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize)
|
||||
let mediaBackgroundFrame = backgroundFrame.insetBy(dx: -2.0, dy: -2.0)
|
||||
strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame
|
||||
|
||||
strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)
|
||||
|
@ -454,7 +454,7 @@ public func createChannelController(context: AccountContext) -> ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: false, title: nil)!
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: false, title: nil, isSuggesting: false)!
|
||||
let _ = currentAvatarMixin.swap(mixin)
|
||||
mixin.requestSearchController = { assetsController in
|
||||
let controller = WebSearchController(context: context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in
|
||||
|
@ -727,7 +727,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
|
||||
}
|
||||
}
|
||||
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: false, title: nil)!
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: false, title: nil, isSuggesting: false)!
|
||||
let _ = currentAvatarMixin.swap(mixin)
|
||||
mixin.requestSearchController = { assetsController in
|
||||
let controller = WebSearchController(context: context, peer: peer, chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in
|
||||
|
@ -919,7 +919,7 @@ final class PeerInfoAvatarListNode: ASDisplayNode {
|
||||
|
||||
self.avatarContainerNode = PeerInfoAvatarTransformContainerNode(context: context)
|
||||
self.listContainerTransformNode = ASDisplayNode()
|
||||
self.listContainerNode = PeerInfoAvatarListContainerNode(context: context)
|
||||
self.listContainerNode = PeerInfoAvatarListContainerNode(context: context, isSettings: isSettings)
|
||||
self.listContainerNode.clipsToBounds = true
|
||||
self.listContainerNode.isHidden = true
|
||||
|
||||
|
@ -2878,7 +2878,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, sourceCorners: .round, remoteEntries: entriesPromise, skipInitial: true, centralEntryIndex: centralEntry.flatMap { entries.firstIndex(of: $0) }, replaceRootController: { controller, ready in
|
||||
})
|
||||
galleryController.openAvatarSetup = { [weak self] completion in
|
||||
self?.openAvatarForEditing(fromGallery: true, completion: completion)
|
||||
self?.openAvatarForEditing(fromGallery: true, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
}
|
||||
galleryController.avatarPhotoEditCompletion = { [weak self] image in
|
||||
self?.updateProfilePhoto(image, mode: .generic)
|
||||
@ -6810,7 +6812,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
dismissStatus = { [weak statusController] in
|
||||
statusController?.dismiss()
|
||||
}
|
||||
self.controller?.presentInGlobalOverlay(statusController)
|
||||
if let topController = self.controller?.navigationController?.topViewController as? ViewController {
|
||||
topController.presentInGlobalOverlay(statusController)
|
||||
} else {
|
||||
self.controller?.presentInGlobalOverlay(statusController)
|
||||
}
|
||||
}
|
||||
|
||||
self.updateAvatarDisposable.set((signal
|
||||
@ -6976,7 +6982,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
dismissStatus = { [weak statusController] in
|
||||
statusController?.dismiss()
|
||||
}
|
||||
self.controller?.presentInGlobalOverlay(statusController)
|
||||
if let topController = self.controller?.navigationController?.topViewController as? ViewController {
|
||||
topController.presentInGlobalOverlay(statusController)
|
||||
} else {
|
||||
self.controller?.presentInGlobalOverlay(statusController)
|
||||
}
|
||||
}
|
||||
|
||||
let peerId = self.peerId
|
||||
@ -7048,7 +7058,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}))
|
||||
}
|
||||
|
||||
fileprivate func openAvatarForEditing(mode: PeerInfoAvatarEditingMode = .generic, fromGallery: Bool = false, completion: @escaping () -> Void = {}) {
|
||||
fileprivate func openAvatarForEditing(mode: PeerInfoAvatarEditingMode = .generic, fromGallery: Bool = false, completion: @escaping (UIImage?) -> Void = { _ in }) {
|
||||
guard let peer = self.data?.peer, mode != .generic || canEditPeerInfo(context: self.context, peer: peer, chatLocation: self.chatLocation, threadData: self.data?.threadData) else {
|
||||
return
|
||||
}
|
||||
@ -7141,7 +7151,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
confirmationAction = nil
|
||||
}
|
||||
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasDeleteButton, hasViewButton: false, personalPhoto: strongSelf.isSettings, isVideo: currentIsVideo, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: isForum, title: title)!
|
||||
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasDeleteButton, hasViewButton: false, personalPhoto: strongSelf.isSettings, isVideo: currentIsVideo, saveEditedPhotos: false, saveCapturedMedia: false, signup: false, forum: isForum, title: title, isSuggesting: mode == .suggest)!
|
||||
mixin.stickersContext = paintStickersContext
|
||||
let _ = strongSelf.currentAvatarMixin.swap(mixin)
|
||||
mixin.requestSearchController = { [weak self] assetsController in
|
||||
@ -7156,7 +7166,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
(strongSelf.controller?.navigationController?.topViewController as? ViewController)?.push(controller)
|
||||
|
||||
if fromGallery {
|
||||
completion()
|
||||
completion(nil)
|
||||
}
|
||||
}
|
||||
if let confirmationTextPhoto, let confirmationAction {
|
||||
@ -7181,13 +7191,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
mixin.didFinishWithImage = { [weak self] image in
|
||||
if let image = image {
|
||||
completion()
|
||||
completion(image)
|
||||
self?.updateProfilePhoto(image, mode: mode)
|
||||
}
|
||||
}
|
||||
mixin.didFinishWithVideo = { [weak self] image, asset, adjustments in
|
||||
if let image = image, let asset = asset {
|
||||
completion()
|
||||
completion(image)
|
||||
self?.updateProfileVideo(image, asset: asset, adjustments: adjustments, mode: mode)
|
||||
}
|
||||
}
|
||||
@ -7214,12 +7224,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
})
|
||||
}
|
||||
|
||||
fileprivate func openAvatarRemoval(mode: PeerInfoAvatarEditingMode, peer: EnginePeer? = nil, item: PeerInfoAvatarListItem? = nil) {
|
||||
fileprivate func openAvatarRemoval(mode: PeerInfoAvatarEditingMode, peer: EnginePeer? = nil, item: PeerInfoAvatarListItem? = nil, completion: @escaping () -> Void = {}) {
|
||||
let proceed = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
completion()
|
||||
|
||||
if let item = item {
|
||||
strongSelf.deleteProfilePhoto(item)
|
||||
}
|
||||
@ -7392,13 +7404,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
)
|
||||
}
|
||||
}, requestPublicPhotoSetup: { [weak self] in
|
||||
}, requestPublicPhotoSetup: { [weak self] completion in
|
||||
if let strongSelf = self {
|
||||
strongSelf.openAvatarForEditing(mode: .fallback)
|
||||
strongSelf.openAvatarForEditing(mode: .fallback, completion: completion)
|
||||
}
|
||||
}, requestPublicPhotoRemove: { [weak self] in
|
||||
}, requestPublicPhotoRemove: { [weak self] completion in
|
||||
if let strongSelf = self {
|
||||
strongSelf.openAvatarRemoval(mode: .fallback)
|
||||
strongSelf.openAvatarRemoval(mode: .fallback, completion: completion)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user