mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-06 17:00:13 +00:00
Various improvements
This commit is contained in:
parent
4bf5df909c
commit
c0bfe87449
@ -13659,10 +13659,13 @@ Sorry for the inconvenience.";
|
|||||||
"Gift.Wear.GetBenefits" = "and get these benefits:";
|
"Gift.Wear.GetBenefits" = "and get these benefits:";
|
||||||
"Gift.Wear.Badge.Title" = "Radiant Badge";
|
"Gift.Wear.Badge.Title" = "Radiant Badge";
|
||||||
"Gift.Wear.Badge.Text" = "The glittering icon of this item will be displayed next to your name.";
|
"Gift.Wear.Badge.Text" = "The glittering icon of this item will be displayed next to your name.";
|
||||||
|
"Gift.Wear.Badge.ChannelText" = "The glittering icon of this item will be displayed next to your channel's name.";
|
||||||
"Gift.Wear.Design.Title" = "Unqiue Profile Design";
|
"Gift.Wear.Design.Title" = "Unqiue Profile Design";
|
||||||
"Gift.Wear.Design.Text" = "Your profile page will get the color and the symbol of this item.";
|
"Gift.Wear.Design.Text" = "Your profile page will get the color and the symbol of this item.";
|
||||||
|
"Gift.Wear.Design.ChannelText" = "Your channel's page will get the color and the symbol of this item.";
|
||||||
"Gift.Wear.Proof.Title" = "Proof of Ownership";
|
"Gift.Wear.Proof.Title" = "Proof of Ownership";
|
||||||
"Gift.Wear.Proof.Text" = "Tapping the icon of this item next to your name will show its info and owner.";
|
"Gift.Wear.Proof.Text" = "Tapping the icon of this item next to your name will show its info and owner.";
|
||||||
|
"Gift.Wear.Proof.ChannelText" = "Tapping the icon of this item next to your channel's name will show its info and owner.";
|
||||||
"Gift.Wear.Start" = "Start Wearing";
|
"Gift.Wear.Start" = "Start Wearing";
|
||||||
|
|
||||||
"Gift.View.Header.Transfer" = "transfer";
|
"Gift.View.Header.Transfer" = "transfer";
|
||||||
@ -13766,7 +13769,7 @@ Sorry for the inconvenience.";
|
|||||||
"PeerInfo.Gifts.NoResults.ViewAll" = "View All Gifts";
|
"PeerInfo.Gifts.NoResults.ViewAll" = "View All Gifts";
|
||||||
|
|
||||||
|
|
||||||
"Gift.Displayed.ChannelText" = "The gift is now shown on channel's Page.";
|
"Gift.Displayed.ChannelText" = "The gift is now shown on the channel's Page.";
|
||||||
"Gift.Hidden.ChannelText" = "The gift is removed from channel's Page.";
|
"Gift.Hidden.ChannelText" = "The gift is removed from the channel's Page.";
|
||||||
|
|
||||||
"Gift.Upgrade.AddChannelName" = "Add channel name to the gift";
|
"Gift.Upgrade.AddChannelName" = "Add channel name to the gift";
|
||||||
|
|||||||
@ -109,11 +109,12 @@ public final class ContactSelectionControllerParams {
|
|||||||
public let displayCallIcons: Bool
|
public let displayCallIcons: Bool
|
||||||
public let multipleSelection: Bool
|
public let multipleSelection: Bool
|
||||||
public let requirePhoneNumbers: Bool
|
public let requirePhoneNumbers: Bool
|
||||||
|
public let allowChannelsInSearch: Bool
|
||||||
public let confirmation: (ContactListPeer) -> Signal<Bool, NoError>
|
public let confirmation: (ContactListPeer) -> Signal<Bool, NoError>
|
||||||
public let openProfile: ((EnginePeer) -> Void)?
|
public let openProfile: ((EnginePeer) -> Void)?
|
||||||
public let sendMessage: ((EnginePeer) -> Void)?
|
public let sendMessage: ((EnginePeer) -> Void)?
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: ContactSelectionControllerMode = .generic, autoDismiss: Bool = true, title: @escaping (PresentationStrings) -> String, options: Signal<[ContactListAdditionalOption], NoError> = .single([]), displayDeviceContacts: Bool = false, displayCallIcons: Bool = false, multipleSelection: Bool = false, requirePhoneNumbers: Bool = false, confirmation: @escaping (ContactListPeer) -> Signal<Bool, NoError> = { _ in .single(true) }, openProfile: ((EnginePeer) -> Void)? = nil, sendMessage: ((EnginePeer) -> Void)? = nil) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: ContactSelectionControllerMode = .generic, autoDismiss: Bool = true, title: @escaping (PresentationStrings) -> String, options: Signal<[ContactListAdditionalOption], NoError> = .single([]), displayDeviceContacts: Bool = false, displayCallIcons: Bool = false, multipleSelection: Bool = false, requirePhoneNumbers: Bool = false, allowChannelsInSearch: Bool = false, confirmation: @escaping (ContactListPeer) -> Signal<Bool, NoError> = { _ in .single(true) }, openProfile: ((EnginePeer) -> Void)? = nil, sendMessage: ((EnginePeer) -> Void)? = nil) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.updatedPresentationData = updatedPresentationData
|
self.updatedPresentationData = updatedPresentationData
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
@ -124,6 +125,7 @@ public final class ContactSelectionControllerParams {
|
|||||||
self.displayCallIcons = displayCallIcons
|
self.displayCallIcons = displayCallIcons
|
||||||
self.multipleSelection = multipleSelection
|
self.multipleSelection = multipleSelection
|
||||||
self.requirePhoneNumbers = requirePhoneNumbers
|
self.requirePhoneNumbers = requirePhoneNumbers
|
||||||
|
self.allowChannelsInSearch = allowChannelsInSearch
|
||||||
self.confirmation = confirmation
|
self.confirmation = confirmation
|
||||||
self.openProfile = openProfile
|
self.openProfile = openProfile
|
||||||
self.sendMessage = sendMessage
|
self.sendMessage = sendMessage
|
||||||
|
|||||||
@ -277,7 +277,7 @@ public struct PremiumConfiguration {
|
|||||||
minChannelWallpaperLevel: get(data["channel_wallpaper_level_min"]) ?? defaultValue.minChannelWallpaperLevel,
|
minChannelWallpaperLevel: get(data["channel_wallpaper_level_min"]) ?? defaultValue.minChannelWallpaperLevel,
|
||||||
minChannelCustomWallpaperLevel: get(data["channel_custom_wallpaper_level_min"]) ?? defaultValue.minChannelCustomWallpaperLevel,
|
minChannelCustomWallpaperLevel: get(data["channel_custom_wallpaper_level_min"]) ?? defaultValue.minChannelCustomWallpaperLevel,
|
||||||
minChannelRestrictAdsLevel: get(data["channel_restrict_sponsored_level_min"]) ?? defaultValue.minChannelRestrictAdsLevel,
|
minChannelRestrictAdsLevel: get(data["channel_restrict_sponsored_level_min"]) ?? defaultValue.minChannelRestrictAdsLevel,
|
||||||
minChannelWearGiftLevel: get(data["channel_wear_collectible_level_min"]) ?? defaultValue.minChannelWearGiftLevel,
|
minChannelWearGiftLevel: get(data["channel_emoji_status_level_min"]) ?? defaultValue.minChannelWearGiftLevel,
|
||||||
minGroupProfileIconLevel: get(data["group_profile_bg_icon_level_min"]) ?? defaultValue.minGroupProfileIconLevel,
|
minGroupProfileIconLevel: get(data["group_profile_bg_icon_level_min"]) ?? defaultValue.minGroupProfileIconLevel,
|
||||||
minGroupEmojiStatusLevel: get(data["group_emoji_status_level_min"]) ?? defaultValue.minGroupEmojiStatusLevel,
|
minGroupEmojiStatusLevel: get(data["group_emoji_status_level_min"]) ?? defaultValue.minGroupEmojiStatusLevel,
|
||||||
minGroupWallpaperLevel: get(data["group_wallpaper_level_min"]) ?? defaultValue.minGroupWallpaperLevel,
|
minGroupWallpaperLevel: get(data["group_wallpaper_level_min"]) ?? defaultValue.minGroupWallpaperLevel,
|
||||||
|
|||||||
@ -207,6 +207,7 @@ public struct ContactsSearchCategories: OptionSet {
|
|||||||
public static let cloudContacts = ContactsSearchCategories(rawValue: 1 << 0)
|
public static let cloudContacts = ContactsSearchCategories(rawValue: 1 << 0)
|
||||||
public static let global = ContactsSearchCategories(rawValue: 1 << 1)
|
public static let global = ContactsSearchCategories(rawValue: 1 << 1)
|
||||||
public static let deviceContacts = ContactsSearchCategories(rawValue: 1 << 2)
|
public static let deviceContacts = ContactsSearchCategories(rawValue: 1 << 2)
|
||||||
|
public static let channels = ContactsSearchCategories(rawValue: 1 << 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ContactsSearchContainerNode: SearchDisplayControllerContentNode {
|
public final class ContactsSearchContainerNode: SearchDisplayControllerContentNode {
|
||||||
@ -449,7 +450,10 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
if let remotePeers = remotePeers {
|
if let remotePeers = remotePeers {
|
||||||
for peer in remotePeers.0 {
|
for peer in remotePeers.0 {
|
||||||
if !(peer.peer is TelegramUser) {
|
if !(peer.peer is TelegramUser) {
|
||||||
continue
|
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info, categories.contains(.channels) {
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let user = peer.peer as? TelegramUser {
|
if let user = peer.peer as? TelegramUser {
|
||||||
@ -488,7 +492,10 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
}
|
}
|
||||||
for peer in remotePeers.1 {
|
for peer in remotePeers.1 {
|
||||||
if !(peer.peer is TelegramUser) {
|
if !(peer.peer is TelegramUser) {
|
||||||
continue
|
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info, categories.contains(.channels) {
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let user = peer.peer as? TelegramUser, requirePhoneNumbers {
|
if let user = peer.peer as? TelegramUser, requirePhoneNumbers {
|
||||||
|
|||||||
@ -65,6 +65,7 @@ typedef enum
|
|||||||
@property (nonatomic, assign) bool hasSilentPosting;
|
@property (nonatomic, assign) bool hasSilentPosting;
|
||||||
@property (nonatomic, assign) bool hasSchedule;
|
@property (nonatomic, assign) bool hasSchedule;
|
||||||
@property (nonatomic, assign) bool reminder;
|
@property (nonatomic, assign) bool reminder;
|
||||||
|
@property (nonatomic, assign) bool hasCoverButton;
|
||||||
|
|
||||||
@property (nonatomic, assign) bool forum;
|
@property (nonatomic, assign) bool forum;
|
||||||
@property (nonatomic, assign) bool isSuggesting;
|
@property (nonatomic, assign) bool isSuggesting;
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
@property (nonatomic, assign) bool hasSilentPosting;
|
@property (nonatomic, assign) bool hasSilentPosting;
|
||||||
@property (nonatomic, assign) bool hasSchedule;
|
@property (nonatomic, assign) bool hasSchedule;
|
||||||
@property (nonatomic, assign) bool reminder;
|
@property (nonatomic, assign) bool reminder;
|
||||||
|
@property (nonatomic, assign) bool hasCoverButton;
|
||||||
|
|
||||||
@property (nonatomic, assign) bool forum;
|
@property (nonatomic, assign) bool forum;
|
||||||
@property (nonatomic, assign) bool isSuggesting;
|
@property (nonatomic, assign) bool isSuggesting;
|
||||||
|
|||||||
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
@property (nonatomic, readonly) UIView *timerButton;
|
@property (nonatomic, readonly) UIView *timerButton;
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasSelectionPanel:(bool)hasSelectionPanel hasCameraButton:(bool)hasCameraButton recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages;
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasSelectionPanel:(bool)hasSelectionPanel hasCameraButton:(bool)hasCameraButton recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages hasCoverButton:(bool)hasCoverButton;
|
||||||
|
|
||||||
- (void)setSelectedItemsModel:(TGMediaPickerGallerySelectedItemsModel *)selectedItemsModel;
|
- (void)setSelectedItemsModel:(TGMediaPickerGallerySelectedItemsModel *)selectedItemsModel;
|
||||||
- (void)setEditorTabPressed:(void (^)(TGPhotoEditorTab tab))editorTabPressed;
|
- (void)setEditorTabPressed:(void (^)(TGPhotoEditorTab tab))editorTabPressed;
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
@property (nonatomic, readonly) TGMediaSelectionContext *selectionContext;
|
||||||
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
@property (nonatomic, strong) id<TGPhotoPaintStickersContext> stickersContext;
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context items:(NSArray *)items focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages;
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context items:(NSArray *)items focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages hasCoverButton:(bool)hasCoverButton;
|
||||||
|
|
||||||
- (void)presentPhotoEditorForItem:(id<TGModernGalleryEditableItem>)item tab:(TGPhotoEditorTab)tab;
|
- (void)presentPhotoEditorForItem:(id<TGModernGalleryEditableItem>)item tab:(TGPhotoEditorTab)tab;
|
||||||
- (void)presentPhotoEditorForItem:(id<TGModernGalleryEditableItem>)item tab:(TGPhotoEditorTab)tab snapshots:(NSArray *)snapshots fromRect:(CGRect)fromRect;
|
- (void)presentPhotoEditorForItem:(id<TGModernGalleryEditableItem>)item tab:(TGPhotoEditorTab)tab snapshots:(NSArray *)snapshots fromRect:(CGRect)fromRect;
|
||||||
|
|||||||
@ -31,9 +31,9 @@
|
|||||||
@property (nonatomic, copy) void (^presentScheduleController)(bool, void (^)(int32_t));
|
@property (nonatomic, copy) void (^presentScheduleController)(bool, void (^)(int32_t));
|
||||||
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
@property (nonatomic, copy) void (^presentTimerController)(void (^)(int32_t));
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder hasCoverButton:(bool)hasCoverButton stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder hasCoverButton:(bool)hasCoverButton stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext;
|
||||||
|
|
||||||
- (void)present;
|
- (void)present;
|
||||||
- (void)updateWithFetchResult:(TGMediaAssetFetchResult *)fetchResult;
|
- (void)updateWithFetchResult:(TGMediaAssetFetchResult *)fetchResult;
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
- (void)setController:(UIViewController *(^)(void))closePressed;
|
- (void)setController:(UIViewController *(^)(void))closePressed;
|
||||||
- (void)setClosePressed:(void (^)())closePressed;
|
- (void)setClosePressed:(void (^)())closePressed;
|
||||||
- (void)setScrollViewOffsetRequested:(void (^)(CGFloat offset))scrollViewOffsetRequested;
|
- (void)setScrollViewOffsetRequested:(void (^)(CGFloat offset))scrollViewOffsetRequested;
|
||||||
|
- (void)setGesturesEnabled:(void (^)(bool enabled))setGesturesEnabled;
|
||||||
|
|
||||||
- (void)itemFocused:(id<TGModernGalleryItem>)item itemView:(TGModernGalleryItemView *)itemView;
|
- (void)itemFocused:(id<TGModernGalleryItem>)item itemView:(TGModernGalleryItemView *)itemView;
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,8 @@
|
|||||||
@property (nonatomic, strong) UIView<TGModernGalleryDefaultFooterAccessoryView> *defaultFooterAccessoryLeftView;
|
@property (nonatomic, strong) UIView<TGModernGalleryDefaultFooterAccessoryView> *defaultFooterAccessoryLeftView;
|
||||||
@property (nonatomic, strong) UIView<TGModernGalleryDefaultFooterAccessoryView> *defaultFooterAccessoryRightView;
|
@property (nonatomic, strong) UIView<TGModernGalleryDefaultFooterAccessoryView> *defaultFooterAccessoryRightView;
|
||||||
|
|
||||||
|
@property (nonatomic, assign) bool gesturesEnabled;
|
||||||
|
|
||||||
- (void)_setItem:(id<TGModernGalleryItem>)item;
|
- (void)_setItem:(id<TGModernGalleryItem>)item;
|
||||||
- (void)setItem:(id<TGModernGalleryItem>)item synchronously:(bool)synchronously;
|
- (void)setItem:(id<TGModernGalleryItem>)item synchronously:(bool)synchronously;
|
||||||
|
|
||||||
|
|||||||
@ -839,7 +839,7 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500;
|
|||||||
if ([cell isKindOfClass:[TGAttachmentAssetCell class]])
|
if ([cell isKindOfClass:[TGAttachmentAssetCell class]])
|
||||||
thumbnailImage = cell.imageView.image;
|
thumbnailImage = cell.imageView.image;
|
||||||
|
|
||||||
TGMediaPickerModernGalleryMixin *mixin = [[TGMediaPickerModernGalleryMixin alloc] initWithContext:_context item:asset fetchResult:_fetchResult parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext hasCaptions:(_allowCaptions && !_forProfilePhoto) allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:_inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:self.asFile itemsLimit:TGAttachmentDisplayedAssetLimit recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder stickersContext:self.stickersContext];
|
TGMediaPickerModernGalleryMixin *mixin = [[TGMediaPickerModernGalleryMixin alloc] initWithContext:_context item:asset fetchResult:_fetchResult parentController:self.parentController thumbnailImage:thumbnailImage selectionContext:_selectionContext editingContext:_editingContext hasCaptions:(_allowCaptions && !_forProfilePhoto) allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:_inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:self.asFile itemsLimit:TGAttachmentDisplayedAssetLimit recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder hasCoverButton:false stickersContext:self.stickersContext];
|
||||||
mixin.presentScheduleController = self.presentScheduleController;
|
mixin.presentScheduleController = self.presentScheduleController;
|
||||||
mixin.presentTimerController = self.presentTimerController;
|
mixin.presentTimerController = self.presentTimerController;
|
||||||
__weak TGAttachmentCarouselItemView *weakSelf = self;
|
__weak TGAttachmentCarouselItemView *weakSelf = self;
|
||||||
|
|||||||
@ -1536,7 +1536,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
|||||||
}];
|
}];
|
||||||
|
|
||||||
bool hasCamera = !self.inhibitMultipleCapture && (((_intent == TGCameraControllerGenericIntent || _intent == TGCameraControllerGenericPhotoOnlyIntent || _intent == TGCameraControllerGenericVideoOnlyIntent) && !_shortcut) || (_intent == TGCameraControllerPassportMultipleIntent));
|
bool hasCamera = !self.inhibitMultipleCapture && (((_intent == TGCameraControllerGenericIntent || _intent == TGCameraControllerGenericPhotoOnlyIntent || _intent == TGCameraControllerGenericVideoOnlyIntent) && !_shortcut) || (_intent == TGCameraControllerPassportMultipleIntent));
|
||||||
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:galleryItems focusItem:focusItem selectionContext:_items.count > 1 ? selectionContext : nil editingContext:editingContext hasCaptions:self.allowCaptions allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:_intent == TGCameraControllerPassportIntent || _intent == TGCameraControllerPassportIdIntent || _intent == TGCameraControllerPassportMultipleIntent inhibitDocumentCaptions:self.inhibitDocumentCaptions hasSelectionPanel:true hasCamera:hasCamera recipientName:self.recipientName isScheduledMessages:false];
|
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:galleryItems focusItem:focusItem selectionContext:_items.count > 1 ? selectionContext : nil editingContext:editingContext hasCaptions:self.allowCaptions allowCaptionEntities:self.allowCaptionEntities hasTimer:self.hasTimer onlyCrop:_intent == TGCameraControllerPassportIntent || _intent == TGCameraControllerPassportIdIntent || _intent == TGCameraControllerPassportMultipleIntent inhibitDocumentCaptions:self.inhibitDocumentCaptions hasSelectionPanel:true hasCamera:hasCamera recipientName:self.recipientName isScheduledMessages:false hasCoverButton:false];
|
||||||
model.inhibitMute = self.inhibitMute;
|
model.inhibitMute = self.inhibitMute;
|
||||||
model.controller = galleryController;
|
model.controller = galleryController;
|
||||||
model.stickersContext = self.stickersContext;
|
model.stickersContext = self.stickersContext;
|
||||||
|
|||||||
@ -260,6 +260,7 @@
|
|||||||
pickerController.hasSilentPosting = strongController.hasSilentPosting;
|
pickerController.hasSilentPosting = strongController.hasSilentPosting;
|
||||||
pickerController.hasSchedule = strongController.hasSchedule;
|
pickerController.hasSchedule = strongController.hasSchedule;
|
||||||
pickerController.reminder = strongController.reminder;
|
pickerController.reminder = strongController.reminder;
|
||||||
|
pickerController.hasCoverButton = strongController.hasCoverButton;
|
||||||
pickerController.forum = strongController.forum;
|
pickerController.forum = strongController.forum;
|
||||||
pickerController.isSuggesting = strongController.isSuggesting;
|
pickerController.isSuggesting = strongController.isSuggesting;
|
||||||
pickerController.presentScheduleController = strongController.presentScheduleController;
|
pickerController.presentScheduleController = strongController.presentScheduleController;
|
||||||
@ -365,6 +366,12 @@
|
|||||||
self.pickerController.reminder = reminder;
|
self.pickerController.reminder = reminder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setHasCoverButton:(bool)hasCoverButton
|
||||||
|
{
|
||||||
|
_hasCoverButton = hasCoverButton;
|
||||||
|
self.pickerController.hasCoverButton = hasCoverButton;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setForum:(bool)forum {
|
- (void)setForum:(bool)forum {
|
||||||
_forum = forum;
|
_forum = forum;
|
||||||
self.pickerController.forum = forum;
|
self.pickerController.forum = forum;
|
||||||
|
|||||||
@ -359,7 +359,7 @@
|
|||||||
|
|
||||||
- (TGMediaPickerModernGalleryMixin *)_galleryMixinForContext:(id<LegacyComponentsContext>)context item:(id)item thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities inhibitDocumentCaptions:(bool)inhibitDocumentCaptions asFile:(bool)asFile
|
- (TGMediaPickerModernGalleryMixin *)_galleryMixinForContext:(id<LegacyComponentsContext>)context item:(id)item thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities inhibitDocumentCaptions:(bool)inhibitDocumentCaptions asFile:(bool)asFile
|
||||||
{
|
{
|
||||||
return [[TGMediaPickerModernGalleryMixin alloc] initWithContext:context item:item fetchResult:_fetchResult parentController:self thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:asFile itemsLimit:0 recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder stickersContext:self.stickersContext];
|
return [[TGMediaPickerModernGalleryMixin alloc] initWithContext:context item:item fetchResult:_fetchResult parentController:self thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:self.hasTimer onlyCrop:self.onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:self.inhibitMute asFile:asFile itemsLimit:0 recipientName:self.recipientName hasSilentPosting:self.hasSilentPosting hasSchedule:self.hasSchedule reminder:self.reminder hasCoverButton:self.hasCoverButton stickersContext:self.stickersContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (TGMediaPickerModernGalleryMixin *)galleryMixinForIndexPath:(NSIndexPath *)indexPath previewMode:(bool)previewMode outAsset:(TGMediaAsset **)outAsset
|
- (TGMediaPickerModernGalleryMixin *)galleryMixinForIndexPath:(NSIndexPath *)indexPath previewMode:(bool)previewMode outAsset:(TGMediaAsset **)outAsset
|
||||||
|
|||||||
@ -117,6 +117,7 @@
|
|||||||
|
|
||||||
void (^_closePressed)();
|
void (^_closePressed)();
|
||||||
void (^_scrollViewOffsetRequested)(CGFloat offset);
|
void (^_scrollViewOffsetRequested)(CGFloat offset);
|
||||||
|
void (^_setGesturesEnabled)(bool offset);
|
||||||
|
|
||||||
id<LegacyComponentsContext> _context;
|
id<LegacyComponentsContext> _context;
|
||||||
|
|
||||||
@ -132,7 +133,7 @@
|
|||||||
|
|
||||||
@synthesize safeAreaInset = _safeAreaInset;
|
@synthesize safeAreaInset = _safeAreaInset;
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasSelectionPanel:(bool)hasSelectionPanel hasCameraButton:(bool)hasCameraButton recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext hasSelectionPanel:(bool)hasSelectionPanel hasCameraButton:(bool)hasCameraButton recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages hasCoverButton:(bool)hasCoverButton
|
||||||
{
|
{
|
||||||
self = [super initWithFrame:CGRectZero];
|
self = [super initWithFrame:CGRectZero];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
@ -159,10 +160,7 @@
|
|||||||
|
|
||||||
_wrapperView = [[TGMediaPickerGalleryWrapperView alloc] initWithFrame:CGRectZero];
|
_wrapperView = [[TGMediaPickerGalleryWrapperView alloc] initWithFrame:CGRectZero];
|
||||||
[self addSubview:_wrapperView];
|
[self addSubview:_wrapperView];
|
||||||
|
|
||||||
_headerWrapperView = [[UIView alloc] init];
|
|
||||||
[_wrapperView addSubview:_headerWrapperView];
|
|
||||||
|
|
||||||
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
||||||
void(^toolbarCancelPressed)(void) = ^
|
void(^toolbarCancelPressed)(void) = ^
|
||||||
{
|
{
|
||||||
@ -247,16 +245,18 @@
|
|||||||
// [_cameraButton setHidden:true animated:false];
|
// [_cameraButton setHidden:true animated:false];
|
||||||
}
|
}
|
||||||
|
|
||||||
_coverButton = [[TGMediaPickerCoverButton alloc] initWithFrame:CGRectMake(0, 0, 120, 26) gallery:false];
|
if (hasCoverButton) {
|
||||||
_coverButton.hidden = true;
|
_coverButton = [[TGMediaPickerCoverButton alloc] initWithFrame:CGRectMake(0, 0, 180, 26) gallery:false];
|
||||||
[_coverButton addTarget:self action:@selector(coverButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
_coverButton.hidden = true;
|
||||||
[_wrapperView addSubview:_coverButton];
|
[_coverButton addTarget:self action:@selector(coverButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
[_wrapperView addSubview:_coverButton];
|
||||||
_coverGalleryButton = [[TGMediaPickerCoverButton alloc] initWithFrame:CGRectMake(0, 0, 120, 26) gallery:true];
|
|
||||||
_coverGalleryButton.hidden = true;
|
_coverGalleryButton = [[TGMediaPickerCoverButton alloc] initWithFrame:CGRectMake(0, 0, 180, 26) gallery:true];
|
||||||
[_coverGalleryButton addTarget:self action:@selector(coverGalleryButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
_coverGalleryButton.hidden = true;
|
||||||
[_wrapperView addSubview:_coverGalleryButton];
|
[_coverGalleryButton addTarget:self action:@selector(coverGalleryButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
[_wrapperView addSubview:_coverGalleryButton];
|
||||||
|
}
|
||||||
|
|
||||||
if (_selectionContext != nil)
|
if (_selectionContext != nil)
|
||||||
{
|
{
|
||||||
_checkButton = [[TGCheckButtonView alloc] initWithStyle:TGCheckButtonStyleGallery];
|
_checkButton = [[TGCheckButtonView alloc] initWithStyle:TGCheckButtonStyleGallery];
|
||||||
@ -426,6 +426,9 @@
|
|||||||
_captionMixin.stickersContext = stickersContext;
|
_captionMixin.stickersContext = stickersContext;
|
||||||
[_captionMixin createInputPanelIfNeeded];
|
[_captionMixin createInputPanelIfNeeded];
|
||||||
|
|
||||||
|
_headerWrapperView = [[UIView alloc] init];
|
||||||
|
[_wrapperView addSubview:_headerWrapperView];
|
||||||
|
|
||||||
TGPhotoEditorDoneButton doneButton = isScheduledMessages ? TGPhotoEditorDoneButtonSchedule : TGPhotoEditorDoneButtonSend;
|
TGPhotoEditorDoneButton doneButton = isScheduledMessages ? TGPhotoEditorDoneButtonSchedule : TGPhotoEditorDoneButtonSend;
|
||||||
|
|
||||||
_portraitToolbarView = [[TGPhotoToolbarView alloc] initWithContext:_context backButton:TGPhotoEditorBackButtonBack doneButton:doneButton solidBackground:false];
|
_portraitToolbarView = [[TGPhotoToolbarView alloc] initWithContext:_context backButton:TGPhotoEditorBackButtonBack doneButton:doneButton solidBackground:false];
|
||||||
@ -442,33 +445,35 @@
|
|||||||
if ([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad)
|
if ([UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad)
|
||||||
[_wrapperView addSubview:_landscapeToolbarView];
|
[_wrapperView addSubview:_landscapeToolbarView];
|
||||||
|
|
||||||
_cancelCoverButton = [[TGModernButton alloc] init];
|
if (hasCoverButton) {
|
||||||
_cancelCoverButton.hidden = true;
|
_cancelCoverButton = [[TGModernButton alloc] init];
|
||||||
_cancelCoverButton.titleLabel.font = TGSystemFontOfSize(17.0);
|
_cancelCoverButton.hidden = true;
|
||||||
[_cancelCoverButton setTitle:TGLocalized(@"Common.Cancel") forState:UIControlStateNormal];
|
_cancelCoverButton.titleLabel.font = TGSystemFontOfSize(17.0);
|
||||||
[_cancelCoverButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
[_cancelCoverButton setTitle:TGLocalized(@"Common.Cancel") forState:UIControlStateNormal];
|
||||||
[_cancelCoverButton addTarget:self action:@selector(cancelCoverButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
[_cancelCoverButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||||
[_cancelCoverButton sizeToFit];
|
[_cancelCoverButton addTarget:self action:@selector(cancelCoverButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||||
[_wrapperView addSubview:_cancelCoverButton];
|
[_cancelCoverButton sizeToFit];
|
||||||
|
[_wrapperView addSubview:_cancelCoverButton];
|
||||||
_coverTitleLabel = [[UILabel alloc] init];
|
|
||||||
_coverTitleLabel.hidden = true;
|
_coverTitleLabel = [[UILabel alloc] init];
|
||||||
_coverTitleLabel.textColor = [UIColor whiteColor];
|
_coverTitleLabel.hidden = true;
|
||||||
_coverTitleLabel.font = TGBoldSystemFontOfSize(17.0);
|
_coverTitleLabel.textColor = [UIColor whiteColor];
|
||||||
_coverTitleLabel.text = TGLocalized(@"Media.SelectFrame");
|
_coverTitleLabel.font = TGBoldSystemFontOfSize(17.0);
|
||||||
[_coverTitleLabel sizeToFit];
|
_coverTitleLabel.text = TGLocalized(@"Media.SelectFrame");
|
||||||
[_wrapperView addSubview:_coverTitleLabel];
|
[_coverTitleLabel sizeToFit];
|
||||||
|
[_wrapperView addSubview:_coverTitleLabel];
|
||||||
_saveCoverButton = [[TGModernButton alloc] init];
|
|
||||||
_saveCoverButton.clipsToBounds = true;
|
_saveCoverButton = [[TGModernButton alloc] init];
|
||||||
_saveCoverButton.layer.cornerRadius = 10.0;
|
_saveCoverButton.clipsToBounds = true;
|
||||||
_saveCoverButton.hidden = true;
|
_saveCoverButton.layer.cornerRadius = 10.0;
|
||||||
[_saveCoverButton setBackgroundColor:UIColorRGB(0x007aff)];
|
_saveCoverButton.hidden = true;
|
||||||
_saveCoverButton.titleLabel.font = TGBoldSystemFontOfSize(17.0);
|
[_saveCoverButton setBackgroundColor:UIColorRGB(0x007aff)];
|
||||||
[_saveCoverButton setTitle:TGLocalized(@"Media.SaveCover") forState:UIControlStateNormal];
|
_saveCoverButton.titleLabel.font = TGBoldSystemFontOfSize(17.0);
|
||||||
[_saveCoverButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
[_saveCoverButton setTitle:TGLocalized(@"Media.SaveCover") forState:UIControlStateNormal];
|
||||||
[_saveCoverButton addTarget:self action:@selector(saveCoverButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
[_saveCoverButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
|
||||||
[_wrapperView addSubview:_saveCoverButton];
|
[_saveCoverButton addTarget:self action:@selector(saveCoverButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
[_wrapperView addSubview:_saveCoverButton];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -554,6 +559,11 @@
|
|||||||
_scrollViewOffsetRequested = [scrollViewOffsetRequested copy];
|
_scrollViewOffsetRequested = [scrollViewOffsetRequested copy];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setGesturesEnabled:(void (^)(bool))setGesturesEnabled
|
||||||
|
{
|
||||||
|
_setGesturesEnabled = [setGesturesEnabled copy];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setEditorTabPressed:(void (^)(TGPhotoEditorTab tab))editorTabPressed
|
- (void)setEditorTabPressed:(void (^)(TGPhotoEditorTab tab))editorTabPressed
|
||||||
{
|
{
|
||||||
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
__weak TGMediaPickerGalleryInterfaceView *weakSelf = self;
|
||||||
@ -634,7 +644,7 @@
|
|||||||
[_checkButton setNumber:[_selectionContext indexOfItem:selectableItem]];
|
[_checkButton setNumber:[_selectionContext indexOfItem:selectableItem]];
|
||||||
signal = [_selectionContext itemInformativeSelectedSignal:selectableItem];
|
signal = [_selectionContext itemInformativeSelectedSignal:selectableItem];
|
||||||
[_itemSelectedDisposable setDisposable:[signal startStrictWithNext:^(TGMediaSelectionChange *next)
|
[_itemSelectedDisposable setDisposable:[signal startStrictWithNext:^(TGMediaSelectionChange *next)
|
||||||
{
|
{
|
||||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||||
if (strongSelf == nil)
|
if (strongSelf == nil)
|
||||||
return;
|
return;
|
||||||
@ -648,7 +658,7 @@
|
|||||||
|
|
||||||
__weak TGModernGalleryItemView *weakItemView = itemView;
|
__weak TGModernGalleryItemView *weakItemView = itemView;
|
||||||
[_itemAvailabilityDisposable setDisposable:[[[itemView contentAvailabilityStateSignal] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
[_itemAvailabilityDisposable setDisposable:[[[itemView contentAvailabilityStateSignal] deliverOn:[SQueue mainQueue]] startStrictWithNext:^(id next)
|
||||||
{
|
{
|
||||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||||
__strong TGModernGalleryItemView *strongItemView = weakItemView;
|
__strong TGModernGalleryItemView *strongItemView = weakItemView;
|
||||||
if (strongSelf == nil || strongItemView == nil)
|
if (strongSelf == nil || strongItemView == nil)
|
||||||
@ -678,7 +688,13 @@
|
|||||||
}
|
}
|
||||||
strongSelf->_muteButton.hidden = !sendableAsGif;
|
strongSelf->_muteButton.hidden = !sendableAsGif;
|
||||||
|
|
||||||
bool canHaveCover = [strongItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]];
|
bool canHaveCover = false;
|
||||||
|
if ([strongItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]]) {
|
||||||
|
TGMediaPickerGalleryVideoItemView *itemView = (TGMediaPickerGalleryVideoItemView *)strongItemView;
|
||||||
|
if (itemView.editableMediaItem.originalDuration >= 60.0) {
|
||||||
|
canHaveCover = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
strongSelf->_coverButton.hidden = !canHaveCover;
|
strongSelf->_coverButton.hidden = !canHaveCover;
|
||||||
}
|
}
|
||||||
} file:__FILE_NAME__ line:__LINE__]];
|
} file:__FILE_NAME__ line:__LINE__]];
|
||||||
@ -863,6 +879,9 @@
|
|||||||
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]]) {
|
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]]) {
|
||||||
[(TGMediaPickerGalleryVideoItemView *)currentItemView prepareForCoverEditing];
|
[(TGMediaPickerGalleryVideoItemView *)currentItemView prepareForCoverEditing];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setGesturesEnabled(false);
|
||||||
|
_currentItemView.gesturesEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)coverEditorTransitionOut {
|
- (void)coverEditorTransitionOut {
|
||||||
@ -894,6 +913,9 @@
|
|||||||
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]]) {
|
if ([currentItemView isKindOfClass:[TGMediaPickerGalleryVideoItemView class]]) {
|
||||||
[(TGMediaPickerGalleryVideoItemView *)currentItemView returnFromCoverEditing];
|
[(TGMediaPickerGalleryVideoItemView *)currentItemView returnFromCoverEditing];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setGesturesEnabled(true);
|
||||||
|
_currentItemView.gesturesEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cancelCoverButtonPressed
|
- (void)cancelCoverButtonPressed
|
||||||
@ -1609,25 +1631,35 @@
|
|||||||
{
|
{
|
||||||
UIView *view = [super hitTest:point withEvent:event];
|
UIView *view = [super hitTest:point withEvent:event];
|
||||||
|
|
||||||
if (view == _photoCounterButton
|
if (_coverTitleLabel.hidden) {
|
||||||
|| view == _checkButton
|
if (view == _photoCounterButton
|
||||||
|| view == _muteButton
|
|| view == _checkButton
|
||||||
|| view == _groupButton
|
|| view == _muteButton
|
||||||
|| view == _cameraButton
|
|| view == _groupButton
|
||||||
|| view == _coverButton
|
|| view == _cameraButton
|
||||||
|| view == _cancelCoverButton
|
|| view == _coverButton
|
||||||
|| view == _saveCoverButton
|
|| view == _cancelCoverButton
|
||||||
|| view == _coverGalleryButton
|
|| view == _saveCoverButton
|
||||||
|| [view isDescendantOfView:_headerWrapperView]
|
|| view == _coverGalleryButton
|
||||||
|| [view isDescendantOfView:_portraitToolbarView]
|
|| [view isDescendantOfView:_headerWrapperView]
|
||||||
|| [view isDescendantOfView:_landscapeToolbarView]
|
|| [view isDescendantOfView:_portraitToolbarView]
|
||||||
|| [view isDescendantOfView:_selectedPhotosView]
|
|| [view isDescendantOfView:_landscapeToolbarView]
|
||||||
|| [view isDescendantOfView:_captionMixin.inputPanelView]
|
|| [view isDescendantOfView:_selectedPhotosView]
|
||||||
|| ([view isDescendantOfView:_captionMixin.dismissView] && _captionMixin.dismissView.alpha > 0.0)
|
|| [view isDescendantOfView:_captionMixin.inputPanelView]
|
||||||
|| [view isKindOfClass:[TGMenuButtonView class]])
|
|| ([view isDescendantOfView:_captionMixin.dismissView] && _captionMixin.dismissView.alpha > 0.0)
|
||||||
|
|| [view isKindOfClass:[TGMenuButtonView class]])
|
||||||
{
|
|
||||||
return view;
|
{
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (view == _cancelCoverButton
|
||||||
|
|| view == _saveCoverButton
|
||||||
|
|| view == _coverGalleryButton
|
||||||
|
|| [view isDescendantOfView:_headerWrapperView])
|
||||||
|
{
|
||||||
|
return view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
@ -1982,7 +2014,7 @@
|
|||||||
|
|
||||||
_landscapeToolbarView.frame = CGRectMake(_landscapeToolbarView.frame.origin.x, screenEdges.top, TGPhotoEditorToolbarSize, self.frame.size.height);
|
_landscapeToolbarView.frame = CGRectMake(_landscapeToolbarView.frame.origin.x, screenEdges.top, TGPhotoEditorToolbarSize, self.frame.size.height);
|
||||||
|
|
||||||
_headerWrapperView.frame = CGRectMake(screenEdges.left, _portraitToolbarView.frame.origin.y - 64.0 - [_captionMixin.inputPanel baseHeight], self.frame.size.width, 64.0);
|
_headerWrapperView.frame = CGRectMake(screenEdges.left, _portraitToolbarView.frame.origin.y - 64.0 - [_captionMixin.inputPanel baseHeight], self.frame.size.width, 72.0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
NSString *_recipientName;
|
NSString *_recipientName;
|
||||||
bool _hasCamera;
|
bool _hasCamera;
|
||||||
bool _isScheduledMessages;
|
bool _isScheduledMessages;
|
||||||
|
bool _hasCoverButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, weak) TGPhotoEditorController *editorController;
|
@property (nonatomic, weak) TGPhotoEditorController *editorController;
|
||||||
@ -48,7 +49,7 @@
|
|||||||
|
|
||||||
@implementation TGMediaPickerGalleryModel
|
@implementation TGMediaPickerGalleryModel
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context items:(NSArray *)items focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context items:(NSArray *)items focusItem:(id<TGModernGalleryItem>)focusItem selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions hasSelectionPanel:(bool)hasSelectionPanel hasCamera:(bool)hasCamera recipientName:(NSString *)recipientName isScheduledMessages:(bool)isScheduledMessages hasCoverButton:(bool)hasCoverButton
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
@ -70,6 +71,7 @@
|
|||||||
_recipientName = recipientName;
|
_recipientName = recipientName;
|
||||||
_hasCamera = hasCamera;
|
_hasCamera = hasCamera;
|
||||||
_isScheduledMessages = isScheduledMessages;
|
_isScheduledMessages = isScheduledMessages;
|
||||||
|
_hasCoverButton = hasCoverButton;
|
||||||
|
|
||||||
__weak TGMediaPickerGalleryModel *weakSelf = self;
|
__weak TGMediaPickerGalleryModel *weakSelf = self;
|
||||||
if (selectionContext != nil)
|
if (selectionContext != nil)
|
||||||
@ -179,7 +181,7 @@
|
|||||||
if (_interfaceView == nil)
|
if (_interfaceView == nil)
|
||||||
{
|
{
|
||||||
__weak TGMediaPickerGalleryModel *weakSelf = self;
|
__weak TGMediaPickerGalleryModel *weakSelf = self;
|
||||||
_interfaceView = [[TGMediaPickerGalleryInterfaceView alloc] initWithContext:_context focusItem:_initialFocusItem selectionContext:_selectionContext editingContext:_editingContext stickersContext:_stickersContext hasSelectionPanel:_hasSelectionPanel hasCameraButton:_hasCamera recipientName:_recipientName isScheduledMessages:_isScheduledMessages];
|
_interfaceView = [[TGMediaPickerGalleryInterfaceView alloc] initWithContext:_context focusItem:_initialFocusItem selectionContext:_selectionContext editingContext:_editingContext stickersContext:_stickersContext hasSelectionPanel:_hasSelectionPanel hasCameraButton:_hasCamera recipientName:_recipientName isScheduledMessages:_isScheduledMessages hasCoverButton:_hasCoverButton];
|
||||||
_interfaceView.hasCaptions = _hasCaptions;
|
_interfaceView.hasCaptions = _hasCaptions;
|
||||||
_interfaceView.allowCaptionEntities = _allowCaptionEntities;
|
_interfaceView.allowCaptionEntities = _allowCaptionEntities;
|
||||||
_interfaceView.hasTimer = _hasTimer;
|
_interfaceView.hasTimer = _hasTimer;
|
||||||
|
|||||||
@ -120,6 +120,8 @@
|
|||||||
|
|
||||||
CMTime _chaseTime;
|
CMTime _chaseTime;
|
||||||
bool _chasingTime;
|
bool _chasingTime;
|
||||||
|
|
||||||
|
bool _isCoverEditing;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic, strong) TGMediaPickerGalleryVideoItem *item;
|
@property (nonatomic, strong) TGMediaPickerGalleryVideoItem *item;
|
||||||
@ -763,12 +765,14 @@
|
|||||||
|
|
||||||
- (void)prepareForCoverEditing
|
- (void)prepareForCoverEditing
|
||||||
{
|
{
|
||||||
|
_isCoverEditing = true;
|
||||||
[self setPlayButtonHidden:true animated:true];
|
[self setPlayButtonHidden:true animated:true];
|
||||||
[self stop];
|
[self stop];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)returnFromCoverEditing
|
- (void)returnFromCoverEditing
|
||||||
{
|
{
|
||||||
|
_isCoverEditing = false;
|
||||||
if (![self usePhotoBehavior])
|
if (![self usePhotoBehavior])
|
||||||
[self setPlayButtonHidden:false animated:true];
|
[self setPlayButtonHidden:false animated:true];
|
||||||
}
|
}
|
||||||
@ -1272,6 +1276,9 @@
|
|||||||
|
|
||||||
- (void)playPressed
|
- (void)playPressed
|
||||||
{
|
{
|
||||||
|
if (!self.gesturesEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
if (_downloadRequired)
|
if (_downloadRequired)
|
||||||
[self _download];
|
[self _download];
|
||||||
else
|
else
|
||||||
@ -1437,7 +1444,12 @@
|
|||||||
if (_wasPlayingBeforeScrubbing) {
|
if (_wasPlayingBeforeScrubbing) {
|
||||||
[self play];
|
[self play];
|
||||||
} else {
|
} else {
|
||||||
[self setPlayButtonHidden:false animated:true];
|
if (!_isCoverEditing)
|
||||||
|
[self setPlayButtonHidden:false animated:true];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (videoScrubber == _coverScrubberView) {
|
||||||
|
[_coverScrubberView setValue:_scrubberView.value resetPosition:true];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -138,8 +138,8 @@ typedef enum
|
|||||||
static UIImage *leftCurtain;
|
static UIImage *leftCurtain;
|
||||||
static UIImage *rightCurtain;
|
static UIImage *rightCurtain;
|
||||||
dispatch_once(&onceToken, ^
|
dispatch_once(&onceToken, ^
|
||||||
{
|
{
|
||||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(24.0f, 40.0f), false, 0.0f);
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(11.0f, 40.0f), false, 0.0f);
|
||||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||||
|
|
||||||
CGContextSetFillColorWithColor(context, UIColorRGBA(0x000000, 0.8).CGColor);
|
CGContextSetFillColorWithColor(context, UIColorRGBA(0x000000, 0.8).CGColor);
|
||||||
@ -150,11 +150,11 @@ typedef enum
|
|||||||
leftCurtain = UIGraphicsGetImageFromCurrentImageContext();
|
leftCurtain = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
UIGraphicsEndImageContext();
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(24.0f, 40.0f), false, 0.0f);
|
UIGraphicsBeginImageContextWithOptions(CGSizeMake(11.0f, 40.0f), false, 0.0f);
|
||||||
context = UIGraphicsGetCurrentContext();
|
context = UIGraphicsGetCurrentContext();
|
||||||
|
|
||||||
CGContextSetFillColorWithColor(context, UIColorRGBA(0x000000, 0.8).CGColor);
|
CGContextSetFillColorWithColor(context, UIColorRGBA(0x000000, 0.8).CGColor);
|
||||||
path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(-16.0, 0, 40, 40) cornerRadius:9.0];
|
path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(-29.0, 0, 40, 40) cornerRadius:9.0];
|
||||||
CGContextAddPath(context, path.CGPath);
|
CGContextAddPath(context, path.CGPath);
|
||||||
CGContextFillPath(context);
|
CGContextFillPath(context);
|
||||||
|
|
||||||
@ -163,12 +163,12 @@ typedef enum
|
|||||||
});
|
});
|
||||||
|
|
||||||
_leftCurtainView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
|
_leftCurtainView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
|
||||||
_leftCurtainView.image = [leftCurtain stretchableImageWithLeftCapWidth:11 topCapHeight:20];
|
_leftCurtainView.image = [leftCurtain resizableImageWithCapInsets:UIEdgeInsetsMake(0, 11, 0, 0)];
|
||||||
_leftCurtainView.clipsToBounds = true;
|
_leftCurtainView.clipsToBounds = true;
|
||||||
[_wrapperView addSubview:_leftCurtainView];
|
[_wrapperView addSubview:_leftCurtainView];
|
||||||
|
|
||||||
_rightCurtainView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
|
_rightCurtainView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
|
||||||
_rightCurtainView.image = [rightCurtain stretchableImageWithLeftCapWidth:11 topCapHeight:20];
|
_rightCurtainView.image = [rightCurtain resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 11)];
|
||||||
_rightCurtainView.clipsToBounds = true;
|
_rightCurtainView.clipsToBounds = true;
|
||||||
[_wrapperView addSubview:_rightCurtainView];
|
[_wrapperView addSubview:_rightCurtainView];
|
||||||
|
|
||||||
@ -409,7 +409,7 @@ typedef enum
|
|||||||
[_dotHandle addGestureRecognizer:_dotPanGestureRecognizer];
|
[_dotHandle addGestureRecognizer:_dotPanGestureRecognizer];
|
||||||
|
|
||||||
_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
|
||||||
_tapGestureRecognizer.enabled = false;
|
_tapGestureRecognizer.enabled = cover;
|
||||||
[_trimView addGestureRecognizer:_tapGestureRecognizer];
|
[_trimView addGestureRecognizer:_tapGestureRecognizer];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@ -40,17 +40,17 @@
|
|||||||
|
|
||||||
@implementation TGMediaPickerModernGalleryMixin
|
@implementation TGMediaPickerModernGalleryMixin
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder hasCoverButton:(bool)hasCoverButton stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||||
{
|
{
|
||||||
return [self initWithContext:context item:item fetchResult:fetchResult momentList:nil parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:recipientName hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder stickersContext:stickersContext];
|
return [self initWithContext:context item:item fetchResult:fetchResult momentList:nil parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:recipientName hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder hasCoverButton:hasCoverButton stickersContext:stickersContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder hasCoverButton:(bool)hasCoverButton stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||||
{
|
{
|
||||||
return [self initWithContext:context item:item fetchResult:nil momentList:momentList parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:nil hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder stickersContext:stickersContext];
|
return [self initWithContext:context item:item fetchResult:nil momentList:momentList parentController:parentController thumbnailImage:thumbnailImage selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions inhibitMute:inhibitMute asFile:asFile itemsLimit:itemsLimit recipientName:nil hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder hasCoverButton:hasCoverButton stickersContext:stickersContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context item:(id)item fetchResult:(TGMediaAssetFetchResult *)fetchResult momentList:(TGMediaAssetMomentList *)momentList parentController:(TGViewController *)parentController thumbnailImage:(UIImage *)thumbnailImage selectionContext:(TGMediaSelectionContext *)selectionContext editingContext:(TGMediaEditingContext *)editingContext hasCaptions:(bool)hasCaptions allowCaptionEntities:(bool)allowCaptionEntities hasTimer:(bool)hasTimer onlyCrop:(bool)onlyCrop inhibitDocumentCaptions:(bool)inhibitDocumentCaptions inhibitMute:(bool)inhibitMute asFile:(bool)asFile itemsLimit:(NSUInteger)itemsLimit recipientName:(NSString *)recipientName hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder hasCoverButton:(bool)hasCoverButton stickersContext:(id<TGPhotoPaintStickersContext>)stickersContext
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
NSArray *galleryItems = [self prepareGalleryItemsForFetchResult:fetchResult selectionContext:selectionContext editingContext:editingContext stickersContext:stickersContext asFile:asFile enumerationBlock:enumerationBlock];
|
NSArray *galleryItems = [self prepareGalleryItemsForFetchResult:fetchResult selectionContext:selectionContext editingContext:editingContext stickersContext:stickersContext asFile:asFile enumerationBlock:enumerationBlock];
|
||||||
|
|
||||||
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:[_windowManager context] items:galleryItems focusItem:focusItem selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions hasSelectionPanel:true hasCamera:false recipientName:recipientName isScheduledMessages:false];
|
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:[_windowManager context] items:galleryItems focusItem:focusItem selectionContext:selectionContext editingContext:editingContext hasCaptions:hasCaptions allowCaptionEntities:allowCaptionEntities hasTimer:hasTimer onlyCrop:onlyCrop inhibitDocumentCaptions:inhibitDocumentCaptions hasSelectionPanel:true hasCamera:false recipientName:recipientName isScheduledMessages:false hasCoverButton:hasCoverButton];
|
||||||
_galleryModel = model;
|
_galleryModel = model;
|
||||||
model.stickersContext = stickersContext;
|
model.stickersContext = stickersContext;
|
||||||
model.inhibitMute = inhibitMute;
|
model.inhibitMute = inhibitMute;
|
||||||
|
|||||||
@ -790,6 +790,7 @@ const CGFloat TGPhotoCounterButtonMaskFade = 18;
|
|||||||
UIImageView *_thumbnailView;
|
UIImageView *_thumbnailView;
|
||||||
UILabel *_label;
|
UILabel *_label;
|
||||||
|
|
||||||
|
CGFloat _labelWidth;
|
||||||
bool _gallery;
|
bool _gallery;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,9 +806,15 @@ const CGFloat TGPhotoCounterButtonMaskFade = 18;
|
|||||||
self.exclusiveTouch = true;
|
self.exclusiveTouch = true;
|
||||||
_gallery = gallery;
|
_gallery = gallery;
|
||||||
|
|
||||||
CGFloat width = _gallery ? 168.0 : 98.0;
|
UIFont *font = [TGFont boldSystemFontOfSize:14];
|
||||||
|
NSString *title = _gallery ? TGLocalized(@"Media.ChooseFromGallery") : TGLocalized(@"Media.EditCover");
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
CGFloat width = floor([title sizeWithFont:font].width) + 28.0f;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
_labelWidth = width;
|
||||||
|
|
||||||
_wrapperView = [[UIView alloc] initWithFrame:CGRectMake((120 - width) / 2.0, 0, width, 26)];
|
_wrapperView = [[UIView alloc] initWithFrame:CGRectMake(TGScreenPixelFloor((180 - width) / 2.0), 0, width, 26)];
|
||||||
_wrapperView.userInteractionEnabled = false;
|
_wrapperView.userInteractionEnabled = false;
|
||||||
[self addSubview:_wrapperView];
|
[self addSubview:_wrapperView];
|
||||||
|
|
||||||
@ -825,9 +832,9 @@ const CGFloat TGPhotoCounterButtonMaskFade = 18;
|
|||||||
|
|
||||||
_label = [[UILabel alloc] initWithFrame:CGRectZero];
|
_label = [[UILabel alloc] initWithFrame:CGRectZero];
|
||||||
_label.backgroundColor = [UIColor clearColor];
|
_label.backgroundColor = [UIColor clearColor];
|
||||||
_label.font = [TGFont boldSystemFontOfSize:14];
|
_label.font = font;
|
||||||
_label.textColor = [UIColor whiteColor];
|
_label.textColor = [UIColor whiteColor];
|
||||||
_label.text = _gallery ? TGLocalized(@"Media.ChooseFromGallery") : TGLocalized(@"Media.EditCover");
|
_label.text = title;
|
||||||
[_label sizeToFit];
|
[_label sizeToFit];
|
||||||
_label.frame = CGRectMake(10.0, (26.0 - _label.frame.size.height) / 2.0, _label.frame.size.width, _label.frame.size.height);
|
_label.frame = CGRectMake(10.0, (26.0 - _label.frame.size.height) / 2.0, _label.frame.size.width, _label.frame.size.height);
|
||||||
[_wrapperView addSubview:_label];
|
[_wrapperView addSubview:_label];
|
||||||
@ -846,15 +853,15 @@ const CGFloat TGPhotoCounterButtonMaskFade = 18;
|
|||||||
_thumbnailView.hidden = false;
|
_thumbnailView.hidden = false;
|
||||||
_thumbnailView.image = image;
|
_thumbnailView.image = image;
|
||||||
|
|
||||||
_wrapperView.frame = CGRectMake(0, 0, 120, 26);
|
CGFloat width = _labelWidth + 22.0;
|
||||||
_backgroundView.frame = CGRectMake(0.0f, 0, 120, 26);
|
_wrapperView.frame = CGRectMake(TGScreenPixelFloor((180 - width) / 2.0), 0, width, 26);
|
||||||
|
_backgroundView.frame = CGRectMake(0.0f, 0, width, 26);
|
||||||
_label.frame = CGRectMake(10.0 + 22.0, (26.0 - _label.frame.size.height) / 2.0, _label.frame.size.width, _label.frame.size.height);
|
_label.frame = CGRectMake(10.0 + 22.0, (26.0 - _label.frame.size.height) / 2.0, _label.frame.size.width, _label.frame.size.height);
|
||||||
} else {
|
} else {
|
||||||
_thumbnailView.hidden = true;
|
_thumbnailView.hidden = true;
|
||||||
|
|
||||||
CGFloat width = _gallery ? 168.0 : 98.0;
|
CGFloat width = _labelWidth;
|
||||||
|
_wrapperView.frame = CGRectMake(TGScreenPixelFloor((180 - width) / 2.0), 0, width, 26);
|
||||||
_wrapperView.frame = CGRectMake(11, 0, width, 26);
|
|
||||||
_backgroundView.frame = CGRectMake(0.0f, 0, width, 26);
|
_backgroundView.frame = CGRectMake(0.0f, 0, width, 26);
|
||||||
_label.frame = CGRectMake(10.0, (26.0 - _label.frame.size.height) / 2.0, _label.frame.size.width, _label.frame.size.height);
|
_label.frame = CGRectMake(10.0, (26.0 - _label.frame.size.height) / 2.0, _label.frame.size.width, _label.frame.size.height);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,4 +15,9 @@
|
|||||||
_coverScrubberView.frame = CGRectMake(_safeAreaInset.left, _scrubberView.frame.origin.y + 16.0, self.frame.size.width - _safeAreaInset.left - _safeAreaInset.right, _scrubberView.frame.size.height);
|
_coverScrubberView.frame = CGRectMake(_safeAreaInset.left, _scrubberView.frame.origin.y + 16.0, self.frame.size.width - _safeAreaInset.left - _safeAreaInset.right, _scrubberView.frame.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
|
||||||
|
CGRect bounds = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height + 16.0);
|
||||||
|
return CGRectContainsPoint(bounds, point);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -355,6 +355,9 @@
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setGesturesEnabled:(void (^)(bool))setGesturesEnabled {
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil)
|
if (self != nil)
|
||||||
{
|
{
|
||||||
|
_gesturesEnabled = true;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -95,7 +96,7 @@
|
|||||||
|
|
||||||
- (bool)allowsScrollingAtPoint:(CGPoint)__unused point
|
- (bool)allowsScrollingAtPoint:(CGPoint)__unused point
|
||||||
{
|
{
|
||||||
return true;
|
return _gesturesEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (SSignal *)contentAvailabilityStateSignal
|
- (SSignal *)contentAvailabilityStateSignal
|
||||||
|
|||||||
@ -84,6 +84,12 @@ static const CGFloat swipeDistanceThreshold = 128.0f;
|
|||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
[strongSelf setScrollViewVerticalOffset:offset];
|
[strongSelf setScrollViewVerticalOffset:offset];
|
||||||
};
|
};
|
||||||
|
_interfaceView.gesturesEnabled = ^(bool enabled)
|
||||||
|
{
|
||||||
|
__strong TGModernGalleryView *strongSelf = weakSelf;
|
||||||
|
if (strongSelf != nil)
|
||||||
|
[strongSelf setGesturesEnabled:enabled];
|
||||||
|
};
|
||||||
[self addSubview:_interfaceView];
|
[self addSubview:_interfaceView];
|
||||||
|
|
||||||
bool hasSwipeGesture = true;
|
bool hasSwipeGesture = true;
|
||||||
@ -111,6 +117,10 @@ static const CGFloat swipeDistanceThreshold = 128.0f;
|
|||||||
return (_dismissProgress < FLT_EPSILON && (_interfaceView == nil || ![_interfaceView respondsToSelector:@selector(shouldAutorotate)] || [_interfaceView shouldAutorotate]));
|
return (_dismissProgress < FLT_EPSILON && (_interfaceView == nil || ![_interfaceView respondsToSelector:@selector(shouldAutorotate)] || [_interfaceView shouldAutorotate]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setGesturesEnabled:(bool)gesturesEnabled {
|
||||||
|
_scrollViewContainer.gestureRecognizers.firstObject.enabled = gesturesEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
- (CGRect)_boundsFrame
|
- (CGRect)_boundsFrame
|
||||||
{
|
{
|
||||||
CGRect bounds = (CGRect){CGPointZero, self.frame.size};
|
CGRect bounds = (CGRect){CGPointZero, self.frame.size};
|
||||||
|
|||||||
@ -178,7 +178,7 @@
|
|||||||
galleryItem.editingContext = editingContext;
|
galleryItem.editingContext = editingContext;
|
||||||
galleryItem.stickersContext = stickersContext;
|
galleryItem.stickersContext = stickersContext;
|
||||||
|
|
||||||
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:@[galleryItem] focusItem:galleryItem selectionContext:nil editingContext:editingContext hasCaptions:true allowCaptionEntities:true hasTimer:false onlyCrop:false inhibitDocumentCaptions:false hasSelectionPanel:false hasCamera:false recipientName:recipientName isScheduledMessages:false];
|
TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:windowContext items:@[galleryItem] focusItem:galleryItem selectionContext:nil editingContext:editingContext hasCaptions:true allowCaptionEntities:true hasTimer:false onlyCrop:false inhibitDocumentCaptions:false hasSelectionPanel:false hasCamera:false recipientName:recipientName isScheduledMessages:false hasCoverButton:false];
|
||||||
model.controller = galleryController;
|
model.controller = galleryController;
|
||||||
model.stickersContext = stickersContext;
|
model.stickersContext = stickersContext;
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,9 @@ public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, co
|
|||||||
}
|
}
|
||||||
controller.hasSchedule = hasSchedule
|
controller.hasSchedule = hasSchedule
|
||||||
controller.reminder = peer.id == context.account.peerId
|
controller.reminder = peer.id == context.account.peerId
|
||||||
|
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||||
|
controller.hasCoverButton = true
|
||||||
|
}
|
||||||
controller.presentScheduleController = { media, done in
|
controller.presentScheduleController = { media, done in
|
||||||
presentSchedulePicker(media, { time in
|
presentSchedulePicker(media, { time in
|
||||||
done?(time)
|
done?(time)
|
||||||
|
|||||||
@ -104,6 +104,10 @@ enum LegacyMediaPickerGallerySource {
|
|||||||
func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, threadTitle: String?, chatLocation: ChatLocation?, isScheduledMessages: Bool, presentationData: PresentationData, source: LegacyMediaPickerGallerySource, immediateThumbnail: UIImage?, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, hasSilentPosting: Bool, hasSchedule: Bool, hasTimer: Bool, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (String) -> UIView?, completed: @escaping (TGMediaSelectableItem & TGMediaEditableItem, Bool, Int32?, @escaping () -> Void) -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void, finishedTransitionIn: @escaping () -> Void, willTransitionOut: @escaping () -> Void, dismissAll: @escaping () -> Void, editCover: @escaping (CGSize, @escaping (UIImage) -> Void) -> Void = { _, _ in }) -> TGModernGalleryController {
|
func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, threadTitle: String?, chatLocation: ChatLocation?, isScheduledMessages: Bool, presentationData: PresentationData, source: LegacyMediaPickerGallerySource, immediateThumbnail: UIImage?, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, hasSilentPosting: Bool, hasSchedule: Bool, hasTimer: Bool, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (String) -> UIView?, completed: @escaping (TGMediaSelectableItem & TGMediaEditableItem, Bool, Int32?, @escaping () -> Void) -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void, finishedTransitionIn: @escaping () -> Void, willTransitionOut: @escaping () -> Void, dismissAll: @escaping () -> Void, editCover: @escaping (CGSize, @escaping (UIImage) -> Void) -> Void = { _, _ in }) -> TGModernGalleryController {
|
||||||
let reminder = peer?.id == context.account.peerId
|
let reminder = peer?.id == context.account.peerId
|
||||||
let hasSilentPosting = hasSilentPosting && peer?.id != context.account.peerId
|
let hasSilentPosting = hasSilentPosting && peer?.id != context.account.peerId
|
||||||
|
var hasCoverButton = false
|
||||||
|
if case let .channel(channel) = peer, case .broadcast = channel.info {
|
||||||
|
hasCoverButton = true
|
||||||
|
}
|
||||||
|
|
||||||
let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil)
|
let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil)
|
||||||
legacyController.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style
|
legacyController.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style
|
||||||
@ -139,7 +143,7 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: true, allowCaptionEntities: true, hasTimer: hasTimer, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: true, hasCamera: false, recipientName: recipientName, isScheduledMessages: isScheduledMessages)!
|
let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: true, allowCaptionEntities: true, hasTimer: hasTimer, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: true, hasCamera: false, recipientName: recipientName, isScheduledMessages: isScheduledMessages, hasCoverButton: hasCoverButton)!
|
||||||
model.stickersContext = paintStickersContext
|
model.stickersContext = paintStickersContext
|
||||||
controller.model = model
|
controller.model = model
|
||||||
model.controller = controller
|
model.controller = controller
|
||||||
|
|||||||
@ -646,7 +646,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
case .noAds:
|
case .noAds:
|
||||||
textString = strings.ChannelBoost_EnableNoAdsLevelText("\(requiredLevel)").string
|
textString = strings.ChannelBoost_EnableNoAdsLevelText("\(requiredLevel)").string
|
||||||
case .wearGift:
|
case .wearGift:
|
||||||
textString = strings.ChannelBoost_EnableNoAdsLevelText("\(requiredLevel)").string
|
textString = strings.ChannelBoost_WearGiftLevelText("\(requiredLevel)").string
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let boostsString = strings.ChannelBoost_MoreBoostsNeeded_Boosts(Int32(remaining))
|
let boostsString = strings.ChannelBoost_MoreBoostsNeeded_Boosts(Int32(remaining))
|
||||||
|
|||||||
@ -914,7 +914,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1301522832] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
dict[1301522832] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
||||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
||||||
dict[46953416] = { return Api.StarGift.parse_starGift($0) }
|
dict[46953416] = { return Api.StarGift.parse_starGift($0) }
|
||||||
dict[-1145732050] = { return Api.StarGift.parse_starGiftUnique($0) }
|
dict[-218202550] = { return Api.StarGift.parse_starGiftUnique($0) }
|
||||||
dict[-1809377438] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
|
dict[-1809377438] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
|
||||||
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
|
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
|
||||||
dict[-524291476] = { return Api.StarGiftAttribute.parse_starGiftAttributeOriginalDetails($0) }
|
dict[-524291476] = { return Api.StarGiftAttribute.parse_starGiftAttributeOriginalDetails($0) }
|
||||||
|
|||||||
@ -575,7 +575,7 @@ public extension Api {
|
|||||||
public extension Api {
|
public extension Api {
|
||||||
enum StarGift: TypeConstructorDescription {
|
enum StarGift: TypeConstructorDescription {
|
||||||
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?)
|
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?)
|
||||||
case starGiftUnique(flags: Int32, id: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32)
|
case starGiftUnique(flags: Int32, id: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -594,9 +594,9 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(lastSaleDate!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(lastSaleDate!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt64(upgradeStars!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 3) != 0 {serializeInt64(upgradeStars!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let attributes, let availabilityIssued, let availabilityTotal):
|
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-1145732050)
|
buffer.appendInt32(-218202550)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt64(id, buffer: buffer, boxed: false)
|
serializeInt64(id, buffer: buffer, boxed: false)
|
||||||
@ -605,6 +605,7 @@ public extension Api {
|
|||||||
serializeInt32(num, buffer: buffer, boxed: false)
|
serializeInt32(num, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {ownerId!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 0) != 0 {ownerId!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(ownerName!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 1) != 0 {serializeString(ownerName!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 2) != 0 {serializeString(ownerAddress!, buffer: buffer, boxed: false)}
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
buffer.appendInt32(Int32(attributes.count))
|
buffer.appendInt32(Int32(attributes.count))
|
||||||
for item in attributes {
|
for item in attributes {
|
||||||
@ -620,8 +621,8 @@ public extension Api {
|
|||||||
switch self {
|
switch self {
|
||||||
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars):
|
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars):
|
||||||
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any)])
|
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any)])
|
||||||
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let attributes, let availabilityIssued, let availabilityTotal):
|
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal):
|
||||||
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any)])
|
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,14 +683,16 @@ public extension Api {
|
|||||||
} }
|
} }
|
||||||
var _7: String?
|
var _7: String?
|
||||||
if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) }
|
if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) }
|
||||||
var _8: [Api.StarGiftAttribute]?
|
var _8: String?
|
||||||
|
if Int(_1!) & Int(1 << 2) != 0 {_8 = parseString(reader) }
|
||||||
|
var _9: [Api.StarGiftAttribute]?
|
||||||
if let _ = reader.readInt32() {
|
if let _ = reader.readInt32() {
|
||||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftAttribute.self)
|
_9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftAttribute.self)
|
||||||
}
|
}
|
||||||
var _9: Int32?
|
|
||||||
_9 = reader.readInt32()
|
|
||||||
var _10: Int32?
|
var _10: Int32?
|
||||||
_10 = reader.readInt32()
|
_10 = reader.readInt32()
|
||||||
|
var _11: Int32?
|
||||||
|
_11 = reader.readInt32()
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
@ -697,11 +700,12 @@ public extension Api {
|
|||||||
let _c5 = _5 != nil
|
let _c5 = _5 != nil
|
||||||
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
|
||||||
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
|
||||||
let _c8 = _8 != nil
|
let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil
|
||||||
let _c9 = _9 != nil
|
let _c9 = _9 != nil
|
||||||
let _c10 = _10 != nil
|
let _c10 = _10 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
let _c11 = _11 != nil
|
||||||
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, title: _3!, slug: _4!, num: _5!, ownerId: _6, ownerName: _7, attributes: _8!, availabilityIssued: _9!, availabilityTotal: _10!)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
|
||||||
|
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, title: _3!, slug: _4!, num: _5!, ownerId: _6, ownerName: _7, ownerAddress: _8, attributes: _9!, availabilityIssued: _10!, availabilityTotal: _11!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -5560,9 +5560,9 @@ public extension Api.functions.messages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, topMsgId: Int32?, scheduleDate: Int32?, sendAs: Api.InputPeer?, quickReplyShortcut: Api.InputQuickReplyShortcut?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, topMsgId: Int32?, scheduleDate: Int32?, sendAs: Api.InputPeer?, quickReplyShortcut: Api.InputQuickReplyShortcut?, videoTimestamp: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(-721186296)
|
buffer.appendInt32(1836374536)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
fromPeer.serialize(buffer, true)
|
fromPeer.serialize(buffer, true)
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
@ -5580,7 +5580,8 @@ public extension Api.functions.messages {
|
|||||||
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 17) != 0 {quickReplyShortcut!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 17) != 0 {quickReplyShortcut!.serialize(buffer, true)}
|
||||||
return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("topMsgId", String(describing: topMsgId)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs)), ("quickReplyShortcut", String(describing: quickReplyShortcut))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
if Int(flags) & Int(1 << 20) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
|
||||||
|
return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("topMsgId", String(describing: topMsgId)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs)), ("quickReplyShortcut", String(describing: quickReplyShortcut)), ("videoTimestamp", String(describing: videoTimestamp))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
|||||||
@ -851,23 +851,54 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
|||||||
switch result {
|
switch result {
|
||||||
case let .media(media, key):
|
case let .media(media, key):
|
||||||
if !forceReupload, let file = media as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
|
if !forceReupload, let file = media as? TelegramMediaFile, let resource = file.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
|
||||||
var flags: Int32 = 0
|
|
||||||
var ttlSeconds: Int32?
|
|
||||||
if let autoclearMessageAttribute = autoclearMessageAttribute {
|
|
||||||
flags |= 1 << 0
|
|
||||||
ttlSeconds = autoclearMessageAttribute.timeout
|
|
||||||
}
|
|
||||||
|
|
||||||
for attribute in attributes {
|
var videoCoverSignal: Signal<UploadedMediaThumbnailResult, PendingMessageUploadError> = .single(.none)
|
||||||
if let _ = attribute as? MediaSpoilerMessageAttribute {
|
if let cover = file.videoCover, let resource = cover.representations.first?.resource {
|
||||||
flags |= 1 << 2
|
let fileReference: AnyMediaReference
|
||||||
|
if let partialReference = file.partialReference {
|
||||||
|
fileReference = partialReference.mediaReference(media)
|
||||||
|
} else {
|
||||||
|
fileReference = .standalone(media: media)
|
||||||
|
}
|
||||||
|
videoCoverSignal = uploadedVideoCover(network: network, postbox: postbox, resourceReference: fileReference.resourceReference(resource), peerId: peerId)
|
||||||
|
|> mapError { _ -> PendingMessageUploadError in return .generic }
|
||||||
|
|> map { result in
|
||||||
|
if let result = result {
|
||||||
|
return .photo(result)
|
||||||
|
} else {
|
||||||
|
return .none
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return .single(.progress(PendingMessageUploadedContentProgress(progress: 1.0)))
|
return videoCoverSignal
|
||||||
|> then(
|
|> mapToSignal { videoCover -> Signal<PendingMessageUploadedContentResult, PendingMessageUploadError> in
|
||||||
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: nil, videoTimestamp: nil, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
var flags: Int32 = 0
|
||||||
)
|
var ttlSeconds: Int32?
|
||||||
|
if let autoclearMessageAttribute = autoclearMessageAttribute {
|
||||||
|
flags |= 1 << 0
|
||||||
|
ttlSeconds = autoclearMessageAttribute.timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
for attribute in attributes {
|
||||||
|
if let _ = attribute as? MediaSpoilerMessageAttribute {
|
||||||
|
flags |= 1 << 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoCoverPhoto: Api.InputPhoto?
|
||||||
|
if case let .photo(photo) = videoCover {
|
||||||
|
videoCoverPhoto = photo
|
||||||
|
}
|
||||||
|
if let _ = videoCoverPhoto {
|
||||||
|
flags |= 1 << 3
|
||||||
|
}
|
||||||
|
|
||||||
|
return .single(.progress(PendingMessageUploadedContentProgress(progress: 1.0)))
|
||||||
|
|> then(
|
||||||
|
.single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(Api.InputMedia.inputMediaDocument(flags: flags, id: Api.InputDocument.inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)), videoCover: videoCoverPhoto, videoTimestamp: nil, ttlSeconds: ttlSeconds, query: nil), text), reuploadInfo: nil, cacheReferenceKey: nil)))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
referenceKey = key
|
referenceKey = key
|
||||||
case let .localReference(key):
|
case let .localReference(key):
|
||||||
|
|||||||
@ -442,7 +442,7 @@ private func sendUploadedMessageContent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
|
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
|
||||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: nil), tag: dependencyTag)
|
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: nil, videoTimestamp: nil), tag: dependencyTag)
|
||||||
|> map(NetworkRequestResult.result)
|
|> map(NetworkRequestResult.result)
|
||||||
} else {
|
} else {
|
||||||
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))
|
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))
|
||||||
|
|||||||
@ -926,7 +926,7 @@ public final class PendingMessageManager {
|
|||||||
} else if let inputSourcePeerId = forwardPeerIds.first, let inputSourcePeer = transaction.getPeer(inputSourcePeerId).flatMap(apiInputPeer) {
|
} else if let inputSourcePeerId = forwardPeerIds.first, let inputSourcePeer = transaction.getPeer(inputSourcePeerId).flatMap(apiInputPeer) {
|
||||||
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messages[0].0.id)
|
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messages[0].0.id)
|
||||||
|
|
||||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut), tag: dependencyTag)
|
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: nil), tag: dependencyTag)
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "Invalid forward source"))
|
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "Invalid forward source"))
|
||||||
@ -1521,7 +1521,7 @@ public final class PendingMessageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
|
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
|
||||||
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut), tag: dependencyTag)
|
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: nil), tag: dependencyTag)
|
||||||
|> map(NetworkRequestResult.result)
|
|> map(NetworkRequestResult.result)
|
||||||
} else {
|
} else {
|
||||||
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))
|
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))
|
||||||
|
|||||||
@ -662,6 +662,15 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
peerIds.append(senderId)
|
peerIds.append(senderId)
|
||||||
}
|
}
|
||||||
return peerIds
|
return peerIds
|
||||||
|
case let .starGiftUnique(_, _, _, _, _, _, _, peerId, senderId, _):
|
||||||
|
var peerIds: [PeerId] = []
|
||||||
|
if let peerId {
|
||||||
|
peerIds.append(peerId)
|
||||||
|
}
|
||||||
|
if let senderId {
|
||||||
|
peerIds.append(senderId)
|
||||||
|
}
|
||||||
|
return peerIds
|
||||||
default:
|
default:
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ func _internal_forwardGameWithScore(account: Account, messageId: MessageId, to p
|
|||||||
flags |= (1 << 13)
|
flags |= (1 << 13)
|
||||||
}
|
}
|
||||||
|
|
||||||
return account.network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, topMsgId: threadId.flatMap { Int32(clamping: $0) }, scheduleDate: nil, sendAs: sendAsInputPeer, quickReplyShortcut: nil))
|
return account.network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, topMsgId: threadId.flatMap { Int32(clamping: $0) }, scheduleDate: nil, sendAs: sendAsInputPeer, quickReplyShortcut: nil, videoTimestamp: nil))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
|
|||||||
@ -207,6 +207,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
case slug
|
case slug
|
||||||
case ownerPeerId
|
case ownerPeerId
|
||||||
case ownerName
|
case ownerName
|
||||||
|
case ownerAddress
|
||||||
case attributes
|
case attributes
|
||||||
case availability
|
case availability
|
||||||
}
|
}
|
||||||
@ -281,8 +282,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
)
|
)
|
||||||
case 3:
|
case 3:
|
||||||
self = .originalInfo(
|
self = .originalInfo(
|
||||||
senderPeerId: try container.decodeIfPresent(Int64.self, forKey: .sendPeerId).flatMap { EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) },
|
senderPeerId: try container.decodeIfPresent(Int64.self, forKey: .sendPeerId).flatMap { EnginePeer.Id($0) },
|
||||||
recipientPeerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(try container.decode(Int64.self, forKey: .recipientPeerId))),
|
recipientPeerId: EnginePeer.Id(try container.decode(Int64.self, forKey: .recipientPeerId)),
|
||||||
date: try container.decode(Int32.self, forKey: .date),
|
date: try container.decode(Int32.self, forKey: .date),
|
||||||
text: try container.decodeIfPresent(String.self, forKey: .text),
|
text: try container.decodeIfPresent(String.self, forKey: .text),
|
||||||
entities: try container.decodeIfPresent([MessageTextEntity].self, forKey: .entities)
|
entities: try container.decodeIfPresent([MessageTextEntity].self, forKey: .entities)
|
||||||
@ -319,8 +320,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
)
|
)
|
||||||
case 3:
|
case 3:
|
||||||
self = .originalInfo(
|
self = .originalInfo(
|
||||||
senderPeerId: decoder.decodeOptionalInt64ForKey(CodingKeys.sendPeerId.rawValue).flatMap { EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value($0)) },
|
senderPeerId: decoder.decodeOptionalInt64ForKey(CodingKeys.sendPeerId.rawValue).flatMap { EnginePeer.Id($0) },
|
||||||
recipientPeerId: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(decoder.decodeInt64ForKey(CodingKeys.recipientPeerId.rawValue, orElse: 0))),
|
recipientPeerId: EnginePeer.Id(decoder.decodeInt64ForKey(CodingKeys.recipientPeerId.rawValue, orElse: 0)),
|
||||||
date: decoder.decodeInt32ForKey(CodingKeys.date.rawValue, orElse: 0),
|
date: decoder.decodeInt32ForKey(CodingKeys.date.rawValue, orElse: 0),
|
||||||
text: decoder.decodeOptionalStringForKey(CodingKeys.text.rawValue),
|
text: decoder.decodeOptionalStringForKey(CodingKeys.text.rawValue),
|
||||||
entities: decoder.decodeObjectArrayWithDecoderForKey(CodingKeys.entities.rawValue)
|
entities: decoder.decodeObjectArrayWithDecoderForKey(CodingKeys.entities.rawValue)
|
||||||
@ -354,8 +355,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
try container.encode(rarity, forKey: .rarity)
|
try container.encode(rarity, forKey: .rarity)
|
||||||
case let .originalInfo(senderPeerId, recipientPeerId, date, text, entities):
|
case let .originalInfo(senderPeerId, recipientPeerId, date, text, entities):
|
||||||
try container.encode(Int32(3), forKey: .type)
|
try container.encode(Int32(3), forKey: .type)
|
||||||
try container.encodeIfPresent(senderPeerId?.id._internalGetInt64Value(), forKey: .sendPeerId)
|
try container.encodeIfPresent(senderPeerId?.toInt64(), forKey: .sendPeerId)
|
||||||
try container.encode(recipientPeerId.id._internalGetInt64Value(), forKey: .recipientPeerId)
|
try container.encode(recipientPeerId.toInt64(), forKey: .recipientPeerId)
|
||||||
try container.encode(date, forKey: .date)
|
try container.encode(date, forKey: .date)
|
||||||
try container.encodeIfPresent(text, forKey: .text)
|
try container.encodeIfPresent(text, forKey: .text)
|
||||||
try container.encodeIfPresent(entities, forKey: .entities)
|
try container.encodeIfPresent(entities, forKey: .entities)
|
||||||
@ -385,11 +386,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
case let .originalInfo(senderPeerId, recipientPeerId, date, text, entities):
|
case let .originalInfo(senderPeerId, recipientPeerId, date, text, entities):
|
||||||
encoder.encodeInt32(3, forKey: CodingKeys.type.rawValue)
|
encoder.encodeInt32(3, forKey: CodingKeys.type.rawValue)
|
||||||
if let senderPeerId {
|
if let senderPeerId {
|
||||||
encoder.encodeInt64(senderPeerId.id._internalGetInt64Value(), forKey: CodingKeys.sendPeerId.rawValue)
|
encoder.encodeInt64(senderPeerId.toInt64(), forKey: CodingKeys.sendPeerId.rawValue)
|
||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: CodingKeys.sendPeerId.rawValue)
|
encoder.encodeNil(forKey: CodingKeys.sendPeerId.rawValue)
|
||||||
}
|
}
|
||||||
encoder.encodeInt64(recipientPeerId.id._internalGetInt64Value(), forKey: CodingKeys.recipientPeerId.rawValue)
|
encoder.encodeInt64(recipientPeerId.toInt64(), forKey: CodingKeys.recipientPeerId.rawValue)
|
||||||
encoder.encodeInt32(date, forKey: CodingKeys.date.rawValue)
|
encoder.encodeInt32(date, forKey: CodingKeys.date.rawValue)
|
||||||
if let text {
|
if let text {
|
||||||
encoder.encodeString(text, forKey: CodingKeys.text.rawValue)
|
encoder.encodeString(text, forKey: CodingKeys.text.rawValue)
|
||||||
@ -434,6 +435,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
public enum Owner: Equatable {
|
public enum Owner: Equatable {
|
||||||
case peerId(EnginePeer.Id)
|
case peerId(EnginePeer.Id)
|
||||||
case name(String)
|
case name(String)
|
||||||
|
case address(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DecodingError: Error {
|
public enum DecodingError: Error {
|
||||||
@ -465,7 +467,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.number = try container.decode(Int32.self, forKey: .number)
|
self.number = try container.decode(Int32.self, forKey: .number)
|
||||||
self.slug = try container.decodeIfPresent(String.self, forKey: .slug) ?? ""
|
self.slug = try container.decodeIfPresent(String.self, forKey: .slug) ?? ""
|
||||||
if let ownerId = try container.decodeIfPresent(Int64.self, forKey: .ownerPeerId) {
|
if let ownerId = try container.decodeIfPresent(Int64.self, forKey: .ownerPeerId) {
|
||||||
self.owner = .peerId(EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(ownerId)))
|
self.owner = .peerId(EnginePeer.Id(ownerId))
|
||||||
|
} else if let ownerAddress = try container.decodeIfPresent(String.self, forKey: .ownerAddress) {
|
||||||
|
self.owner = .address(ownerAddress)
|
||||||
} else if let ownerName = try container.decodeIfPresent(String.self, forKey: .ownerName) {
|
} else if let ownerName = try container.decodeIfPresent(String.self, forKey: .ownerName) {
|
||||||
self.owner = .name(ownerName)
|
self.owner = .name(ownerName)
|
||||||
} else {
|
} else {
|
||||||
@ -481,7 +485,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.number = decoder.decodeInt32ForKey(CodingKeys.number.rawValue, orElse: 0)
|
self.number = decoder.decodeInt32ForKey(CodingKeys.number.rawValue, orElse: 0)
|
||||||
self.slug = decoder.decodeStringForKey(CodingKeys.slug.rawValue, orElse: "")
|
self.slug = decoder.decodeStringForKey(CodingKeys.slug.rawValue, orElse: "")
|
||||||
if let ownerId = decoder.decodeOptionalInt64ForKey(CodingKeys.ownerPeerId.rawValue) {
|
if let ownerId = decoder.decodeOptionalInt64ForKey(CodingKeys.ownerPeerId.rawValue) {
|
||||||
self.owner = .peerId(EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(ownerId)))
|
self.owner = .peerId(EnginePeer.Id(ownerId))
|
||||||
|
} else if let ownerAddress = decoder.decodeOptionalStringForKey(CodingKeys.ownerAddress.rawValue) {
|
||||||
|
self.owner = .address(ownerAddress)
|
||||||
} else if let ownerName = decoder.decodeOptionalStringForKey(CodingKeys.ownerName.rawValue) {
|
} else if let ownerName = decoder.decodeOptionalStringForKey(CodingKeys.ownerName.rawValue) {
|
||||||
self.owner = .name(ownerName)
|
self.owner = .name(ownerName)
|
||||||
} else {
|
} else {
|
||||||
@ -499,9 +505,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
try container.encode(self.slug, forKey: .slug)
|
try container.encode(self.slug, forKey: .slug)
|
||||||
switch self.owner {
|
switch self.owner {
|
||||||
case let .peerId(peerId):
|
case let .peerId(peerId):
|
||||||
try container.encode(peerId.id._internalGetInt64Value(), forKey: .ownerPeerId)
|
try container.encode(peerId.toInt64(), forKey: .ownerPeerId)
|
||||||
case let .name(name):
|
case let .name(name):
|
||||||
try container.encode(name, forKey: .ownerName)
|
try container.encode(name, forKey: .ownerName)
|
||||||
|
case let .address(address):
|
||||||
|
try container.encode(address, forKey: .ownerAddress)
|
||||||
}
|
}
|
||||||
try container.encode(self.attributes, forKey: .attributes)
|
try container.encode(self.attributes, forKey: .attributes)
|
||||||
try container.encode(self.availability, forKey: .availability)
|
try container.encode(self.availability, forKey: .availability)
|
||||||
@ -514,9 +522,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
encoder.encodeString(self.slug, forKey: CodingKeys.slug.rawValue)
|
encoder.encodeString(self.slug, forKey: CodingKeys.slug.rawValue)
|
||||||
switch self.owner {
|
switch self.owner {
|
||||||
case let .peerId(peerId):
|
case let .peerId(peerId):
|
||||||
encoder.encodeInt64(peerId.id._internalGetInt64Value(), forKey: CodingKeys.ownerPeerId.rawValue)
|
encoder.encodeInt64(peerId.toInt64(), forKey: CodingKeys.ownerPeerId.rawValue)
|
||||||
case let .name(name):
|
case let .name(name):
|
||||||
encoder.encodeString(name, forKey: CodingKeys.ownerName.rawValue)
|
encoder.encodeString(name, forKey: CodingKeys.ownerName.rawValue)
|
||||||
|
case let .address(address):
|
||||||
|
encoder.encodeString(address, forKey: CodingKeys.ownerAddress.rawValue)
|
||||||
}
|
}
|
||||||
encoder.encodeObjectArray(self.attributes, forKey: CodingKeys.attributes.rawValue)
|
encoder.encodeObjectArray(self.attributes, forKey: CodingKeys.attributes.rawValue)
|
||||||
encoder.encodeObject(self.availability, forKey: CodingKeys.availability.rawValue)
|
encoder.encodeObject(self.availability, forKey: CodingKeys.availability.rawValue)
|
||||||
@ -605,9 +615,11 @@ extension StarGift {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
self = .generic(StarGift.Gift(id: id, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars))
|
self = .generic(StarGift.Gift(id: id, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars))
|
||||||
case let .starGiftUnique(_, id, title, slug, num, ownerPeerId, ownerName, attributes, availabilityIssued, availabilityTotal):
|
case let .starGiftUnique(_, id, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal):
|
||||||
let owner: StarGift.UniqueGift.Owner
|
let owner: StarGift.UniqueGift.Owner
|
||||||
if let ownerId = ownerPeerId?.peerId {
|
if let ownerAddress {
|
||||||
|
owner = .address(ownerAddress)
|
||||||
|
} else if let ownerId = ownerPeerId?.peerId {
|
||||||
owner = .peerId(ownerId)
|
owner = .peerId(ownerId)
|
||||||
} else if let ownerName {
|
} else if let ownerName {
|
||||||
owner = .name(ownerName)
|
owner = .name(ownerName)
|
||||||
|
|||||||
@ -835,6 +835,10 @@ public extension TelegramEngine {
|
|||||||
return _internal_updatePeerEmojiStatus(account: self.account, peerId: peerId, fileId: fileId, expirationDate: expirationDate)
|
return _internal_updatePeerEmojiStatus(account: self.account, peerId: peerId, fileId: fileId, expirationDate: expirationDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func updatePeerStarGiftStatus(peerId: EnginePeer.Id, starGift: StarGift.UniqueGift, expirationDate: Int32?) -> Signal<Never, UpdatePeerEmojiStatusError> {
|
||||||
|
return _internal_updatePeerStarGiftStatus(account: self.account, peerId: peerId, starGift: starGift, expirationDate: expirationDate)
|
||||||
|
}
|
||||||
|
|
||||||
public func checkChannelRevenueWithdrawalAvailability() -> Signal<Never, RequestRevenueWithdrawalError> {
|
public func checkChannelRevenueWithdrawalAvailability() -> Signal<Never, RequestRevenueWithdrawalError> {
|
||||||
return _internal_checkChannelRevenueWithdrawalAvailability(account: self.account)
|
return _internal_checkChannelRevenueWithdrawalAvailability(account: self.account)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -308,3 +308,61 @@ func _internal_updatePeerEmojiStatus(account: Account, peerId: PeerId, fileId: I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_updatePeerStarGiftStatus(account: Account, peerId: PeerId, starGift: StarGift.UniqueGift, expirationDate: Int32?) -> Signal<Never, UpdatePeerEmojiStatusError> {
|
||||||
|
var flags: Int32 = 0
|
||||||
|
if let _ = expirationDate {
|
||||||
|
flags |= (1 << 0)
|
||||||
|
}
|
||||||
|
var file: TelegramMediaFile?
|
||||||
|
var patternFile: TelegramMediaFile?
|
||||||
|
var innerColor: Int32?
|
||||||
|
var outerColor: Int32?
|
||||||
|
var patternColor: Int32?
|
||||||
|
var textColor: Int32?
|
||||||
|
for attribute in starGift.attributes {
|
||||||
|
switch attribute {
|
||||||
|
case let .model(_, fileValue, _):
|
||||||
|
file = fileValue
|
||||||
|
case let .pattern(_, patternFileValue, _):
|
||||||
|
patternFile = patternFileValue
|
||||||
|
case let .backdrop(_, innerColorValue, outerColorValue, patternColorValue, textColorValue, _):
|
||||||
|
innerColor = innerColorValue
|
||||||
|
outerColor = outerColorValue
|
||||||
|
patternColor = patternColorValue
|
||||||
|
textColor = textColorValue
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let apiEmojiStatus: Api.EmojiStatus
|
||||||
|
var emojiStatus: PeerEmojiStatus?
|
||||||
|
if let file, let patternFile, let innerColor, let outerColor, let patternColor, let textColor {
|
||||||
|
apiEmojiStatus = .inputEmojiStatusCollectible(flags: flags, collectibleId: starGift.id, until: expirationDate)
|
||||||
|
emojiStatus = PeerEmojiStatus(content: .starGift(id: starGift.id, fileId: file.fileId.id, title: starGift.title, slug: starGift.slug, patternFileId: patternFile.fileId.id, innerColor: innerColor, outerColor: outerColor, patternColor: patternColor, textColor: textColor), expirationDate: expirationDate)
|
||||||
|
} else {
|
||||||
|
apiEmojiStatus = .emojiStatusEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.postbox.transaction { transaction -> Api.InputChannel? in
|
||||||
|
if let peer = transaction.getPeer(peerId) as? TelegramChannel {
|
||||||
|
updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedEmojiStatus(emojiStatus)], update: { _, updated in updated })
|
||||||
|
}
|
||||||
|
return transaction.getPeer(peerId).flatMap(apiInputChannel)
|
||||||
|
}
|
||||||
|
|> castError(UpdatePeerEmojiStatusError.self)
|
||||||
|
|> mapToSignal { inputChannel -> Signal<Never, UpdatePeerEmojiStatusError> in
|
||||||
|
guard let inputChannel = inputChannel else {
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
|
return account.network.request(Api.functions.channels.updateEmojiStatus(channel: inputChannel, emojiStatus: apiEmojiStatus))
|
||||||
|
|> ignoreValues
|
||||||
|
|> `catch` { error -> Signal<Never, UpdatePeerEmojiStatusError> in
|
||||||
|
if error.errorDescription == "CHAT_NOT_MODIFIED" {
|
||||||
|
return .complete()
|
||||||
|
} else {
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -464,6 +464,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
private var fetchStatus: MediaResourceStatus?
|
private var fetchStatus: MediaResourceStatus?
|
||||||
private var actualFetchStatus: MediaResourceStatus?
|
private var actualFetchStatus: MediaResourceStatus?
|
||||||
private let fetchDisposable = MetaDisposable()
|
private let fetchDisposable = MetaDisposable()
|
||||||
|
private let coverFetchDisposable = MetaDisposable()
|
||||||
|
|
||||||
private let videoNodeReadyDisposable = MetaDisposable()
|
private let videoNodeReadyDisposable = MetaDisposable()
|
||||||
private let playerStatusDisposable = MetaDisposable()
|
private let playerStatusDisposable = MetaDisposable()
|
||||||
@ -626,6 +627,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
self.videoNodeReadyDisposable.dispose()
|
self.videoNodeReadyDisposable.dispose()
|
||||||
self.playerStatusDisposable.dispose()
|
self.playerStatusDisposable.dispose()
|
||||||
self.fetchDisposable.dispose()
|
self.fetchDisposable.dispose()
|
||||||
|
self.coverFetchDisposable.dispose()
|
||||||
self.secretTimer?.invalidate()
|
self.secretTimer?.invalidate()
|
||||||
self.hlsInlinePlaybackRangeDisposable?.dispose()
|
self.hlsInlinePlaybackRangeDisposable?.dispose()
|
||||||
}
|
}
|
||||||
@ -2125,6 +2127,10 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||||||
strongSelf.fetchDisposable.set(visibilityAwareFetchSignal.startStrict())
|
strongSelf.fetchDisposable.set(visibilityAwareFetchSignal.startStrict())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let file = media as? TelegramMediaFile, let image = file.videoCover, let representation = largestRepresentationForPhoto(image) {
|
||||||
|
strongSelf.coverFetchDisposable.set(messageMediaImageInteractiveFetched(context: context, message: message, image: image, resource: representation.resource, range: representationFetchRangeForDisplayAtSize(representation: representation, dimension: nil), userInitiated: false, storeToDownloadsPeerId: nil).startStrict())
|
||||||
|
}
|
||||||
} else if currentAutomaticDownload != automaticDownload, case .full = automaticDownload {
|
} else if currentAutomaticDownload != automaticDownload, case .full = automaticDownload {
|
||||||
strongSelf.fetchControls.with({ $0 })?.fetch(false)
|
strongSelf.fetchControls.with({ $0 })?.fetch(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/EmojiStatusComponent",
|
"//submodules/TelegramUI/Components/EmojiStatusComponent",
|
||||||
"//submodules/PasswordSetupUI",
|
"//submodules/PasswordSetupUI",
|
||||||
"//submodules/TelegramUI/Components/PeerManagement/OwnershipTransferController",
|
"//submodules/TelegramUI/Components/PeerManagement/OwnershipTransferController",
|
||||||
|
"//submodules/TelegramUI/Components/PremiumLockButtonSubtitleComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import GiftAnimationComponent
|
|||||||
import LottieComponent
|
import LottieComponent
|
||||||
import ContextUI
|
import ContextUI
|
||||||
import TelegramNotices
|
import TelegramNotices
|
||||||
|
import PremiumLockButtonSubtitleComponent
|
||||||
|
|
||||||
private let modelButtonTag = GenericComponentViewTag()
|
private let modelButtonTag = GenericComponentViewTag()
|
||||||
private let backdropButtonTag = GenericComponentViewTag()
|
private let backdropButtonTag = GenericComponentViewTag()
|
||||||
@ -128,6 +129,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
var upgradeForm: BotPaymentForm?
|
var upgradeForm: BotPaymentForm?
|
||||||
var upgradeFormDisposable: Disposable?
|
var upgradeFormDisposable: Disposable?
|
||||||
var upgradeDisposable: Disposable?
|
var upgradeDisposable: Disposable?
|
||||||
|
let levelsDisposable = MetaDisposable()
|
||||||
|
|
||||||
var inWearPreview = false
|
var inWearPreview = false
|
||||||
var pendingWear = false
|
var pendingWear = false
|
||||||
@ -171,6 +173,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
if let fromPeerId = arguments.fromPeerId, !peerIds.contains(fromPeerId) {
|
if let fromPeerId = arguments.fromPeerId, !peerIds.contains(fromPeerId) {
|
||||||
peerIds.append(fromPeerId)
|
peerIds.append(fromPeerId)
|
||||||
}
|
}
|
||||||
|
if case let .message(message) = subject {
|
||||||
|
for media in message.media {
|
||||||
|
peerIds.append(contentsOf: media.peerIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
if case let .unique(gift) = arguments.gift {
|
if case let .unique(gift) = arguments.gift {
|
||||||
if case let .peerId(peerId) = gift.owner {
|
if case let .peerId(peerId) = gift.owner {
|
||||||
peerIds.append(peerId)
|
peerIds.append(peerId)
|
||||||
@ -219,6 +226,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.disposable = combineLatest(queue: Queue.mainQueue(),
|
self.disposable = combineLatest(queue: Queue.mainQueue(),
|
||||||
context.engine.data.get(EngineDataMap(
|
context.engine.data.get(EngineDataMap(
|
||||||
peerIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.Peer in
|
peerIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.Peer in
|
||||||
@ -270,6 +278,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
self.sampleDisposable.dispose()
|
self.sampleDisposable.dispose()
|
||||||
self.upgradeFormDisposable?.dispose()
|
self.upgradeFormDisposable?.dispose()
|
||||||
self.upgradeDisposable?.dispose()
|
self.upgradeDisposable?.dispose()
|
||||||
|
self.levelsDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestUpgradePreview() {
|
func requestUpgradePreview() {
|
||||||
@ -293,7 +302,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
self.inWearPreview = false
|
self.inWearPreview = false
|
||||||
self.updated(transition: .spring(duration: 0.4))
|
self.updated(transition: .spring(duration: 0.4))
|
||||||
|
|
||||||
let _ = self.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).startStandalone()
|
if let arguments = self.subject.arguments, let peerId = arguments.peerId, peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
let _ = self.context.engine.peers.updatePeerStarGiftStatus(peerId: peerId, starGift: uniqueGift, expirationDate: nil).startStandalone()
|
||||||
|
} else {
|
||||||
|
let _ = self.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).startStandalone()
|
||||||
|
}
|
||||||
|
|
||||||
let _ = ApplicationSpecificNotice.incrementStarGiftWearTips(accountManager: self.context.sharedContext.accountManager).startStandalone()
|
let _ = ApplicationSpecificNotice.incrementStarGiftWearTips(accountManager: self.context.sharedContext.accountManager).startStandalone()
|
||||||
}
|
}
|
||||||
@ -303,7 +316,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
self.pendingWear = false
|
self.pendingWear = false
|
||||||
self.updated(transition: .spring(duration: 0.4))
|
self.updated(transition: .spring(duration: 0.4))
|
||||||
|
|
||||||
let _ = self.context.engine.accountData.setEmojiStatus(file: nil, expirationDate: nil).startStandalone()
|
if let arguments = self.subject.arguments, let peerId = arguments.peerId, peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
let _ = self.context.engine.peers.updatePeerEmojiStatus(peerId: peerId, fileId: nil, expirationDate: nil)
|
||||||
|
} else {
|
||||||
|
let _ = self.context.engine.accountData.setEmojiStatus(file: nil, expirationDate: nil).startStandalone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func commitUpgrade() {
|
func commitUpgrade() {
|
||||||
@ -543,7 +560,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
if let uniqueGift {
|
if let uniqueGift {
|
||||||
if showWearPreview {
|
if showWearPreview {
|
||||||
headerHeight = 200.0
|
headerHeight = 200.0
|
||||||
} else if case let .peerId(peerId) = uniqueGift.owner, peerId == component.context.account.peerId {
|
} else if case let .peerId(peerId) = uniqueGift.owner, peerId == component.context.account.peerId || isChannelGift {
|
||||||
headerHeight = 314.0
|
headerHeight = 314.0
|
||||||
} else {
|
} else {
|
||||||
headerHeight = 240.0
|
headerHeight = 240.0
|
||||||
@ -563,11 +580,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
headerSubject = nil
|
headerSubject = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ownerPeerId: EnginePeer.Id
|
||||||
|
if let uniqueGift, case let .peerId(peerId) = uniqueGift.owner {
|
||||||
|
ownerPeerId = peerId
|
||||||
|
} else {
|
||||||
|
ownerPeerId = component.context.account.peerId
|
||||||
|
}
|
||||||
|
|
||||||
var wearPeerNameChild: _UpdatedChildComponent?
|
var wearPeerNameChild: _UpdatedChildComponent?
|
||||||
if showWearPreview, let uniqueGift {
|
if showWearPreview, let uniqueGift {
|
||||||
var peerName = ""
|
var peerName = ""
|
||||||
if let accountPeer = state.peerMap[component.context.account.peerId] {
|
if let ownerPeer = state.peerMap[ownerPeerId] {
|
||||||
peerName = accountPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)
|
peerName = ownerPeer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)
|
||||||
}
|
}
|
||||||
wearPeerNameChild = wearPeerName.update(
|
wearPeerNameChild = wearPeerName.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
@ -675,12 +699,12 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let wearPeerNameChild {
|
if let wearPeerNameChild {
|
||||||
if let accountPeer = state.peerMap[component.context.account.peerId] {
|
if let ownerPeer = state.peerMap[ownerPeerId] {
|
||||||
let wearAvatar = wearAvatar.update(
|
let wearAvatar = wearAvatar.update(
|
||||||
component: AvatarComponent(
|
component: AvatarComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
peer: accountPeer
|
peer: ownerPeer
|
||||||
),
|
),
|
||||||
environment: {},
|
environment: {},
|
||||||
availableSize: CGSize(width: 100.0, height: 100.0),
|
availableSize: CGSize(width: 100.0, height: 100.0),
|
||||||
@ -696,7 +720,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
let wearPeerStatus = wearPeerStatus.update(
|
let wearPeerStatus = wearPeerStatus.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: strings.Presence_online,
|
string: isChannelGift ? strings.Channel_Status : strings.Presence_online,
|
||||||
font: Font.regular(17.0),
|
font: Font.regular(17.0),
|
||||||
textColor: vibrantColor,
|
textColor: vibrantColor,
|
||||||
paragraphAlignment: .center
|
paragraphAlignment: .center
|
||||||
@ -736,7 +760,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: strings.Gift_Wear_Badge_Title,
|
title: strings.Gift_Wear_Badge_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: strings.Gift_Wear_Badge_Text,
|
text: isChannelGift ? strings.Gift_Wear_Badge_ChannelText : strings.Gift_Wear_Badge_Text,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Collectible/Badge",
|
iconName: "Premium/Collectible/Badge",
|
||||||
@ -750,7 +774,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: strings.Gift_Wear_Design_Title,
|
title: strings.Gift_Wear_Design_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: strings.Gift_Wear_Design_Text,
|
text: isChannelGift ? strings.Gift_Wear_Design_ChannelText : strings.Gift_Wear_Design_Text,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/BoostPerk/CoverColor",
|
iconName: "Premium/BoostPerk/CoverColor",
|
||||||
@ -764,7 +788,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: strings.Gift_Wear_Proof_Title,
|
title: strings.Gift_Wear_Proof_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: strings.Gift_Wear_Proof_Text,
|
text: isChannelGift ? strings.Gift_Wear_Proof_ChannelText : strings.Gift_Wear_Proof_Text,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Collectible/Proof",
|
iconName: "Premium/Collectible/Proof",
|
||||||
@ -1249,12 +1273,20 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
case let .name(name):
|
case let .name(name):
|
||||||
tableItems.append(.init(
|
tableItems.append(.init(
|
||||||
id: "anon_owner",
|
id: "name_owner",
|
||||||
title: strings.Gift_Unique_Owner,
|
title: strings.Gift_Unique_Owner,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
MultilineTextComponent(text: .plain(NSAttributedString(string: name, font: tableFont, textColor: tableTextColor)))
|
MultilineTextComponent(text: .plain(NSAttributedString(string: name, font: tableFont, textColor: tableTextColor)))
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
case let .address(address):
|
||||||
|
tableItems.append(.init(
|
||||||
|
id: "address_owner",
|
||||||
|
title: strings.Gift_Unique_Owner,
|
||||||
|
component: AnyComponent(
|
||||||
|
MultilineTextComponent(text: .plain(NSAttributedString(string: address, font: tableMonospaceFont, textColor: tableTextColor)))
|
||||||
|
)
|
||||||
|
))
|
||||||
}
|
}
|
||||||
} else if let peerId = subject.arguments?.fromPeerId, let peer = state.peerMap[peerId] {
|
} else if let peerId = subject.arguments?.fromPeerId, let peer = state.peerMap[peerId] {
|
||||||
var isBot = false
|
var isBot = false
|
||||||
@ -1346,7 +1378,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let uniqueGift {
|
if let uniqueGift {
|
||||||
if case let .peerId(peerId) = uniqueGift.owner, peerId == component.context.account.peerId {
|
if case let .peerId(peerId) = uniqueGift.owner, peerId == component.context.account.peerId || isChannelGift {
|
||||||
let buttonSpacing: CGFloat = 10.0
|
let buttonSpacing: CGFloat = 10.0
|
||||||
let buttonWidth = floor(context.availableSize.width - sideInset * 2.0 - buttonSpacing * 2.0) / 3.0
|
let buttonWidth = floor(context.availableSize.width - sideInset * 2.0 - buttonSpacing * 2.0) / 3.0
|
||||||
let buttonHeight: CGFloat = 58.0
|
let buttonHeight: CGFloat = 58.0
|
||||||
@ -1397,12 +1429,24 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
controller.dismissAllTooltips()
|
controller.dismissAllTooltips()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let canWear: Bool
|
||||||
|
if isChannelGift, case let .channel(channel) = state.peerMap[ownerPeerId] {
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||||
|
let requiredLevel = Int(BoostSubject.wearGift.requiredLevel(group: false, context: component.context, configuration: premiumConfiguration))
|
||||||
|
if let boostLevel = channel.approximateBoostLevel {
|
||||||
|
canWear = boostLevel >= requiredLevel
|
||||||
|
} else {
|
||||||
|
canWear = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
canWear = component.context.isPremium
|
||||||
|
}
|
||||||
let _ = (ApplicationSpecificNotice.getStarGiftWearTips(accountManager: component.context.sharedContext.accountManager)
|
let _ = (ApplicationSpecificNotice.getStarGiftWearTips(accountManager: component.context.sharedContext.accountManager)
|
||||||
|> deliverOnMainQueue).start(next: { [weak state] count in
|
|> deliverOnMainQueue).start(next: { [weak state] count in
|
||||||
guard let state else {
|
guard let state else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !component.context.isPremium || count < 3 {
|
if !canWear || count < 3 {
|
||||||
state.requestWearPreview()
|
state.requestWearPreview()
|
||||||
} else {
|
} else {
|
||||||
state.commitWear(uniqueGift)
|
state.commitWear(uniqueGift)
|
||||||
@ -1856,9 +1900,36 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
let buttonChild: _UpdatedChildComponent
|
let buttonChild: _UpdatedChildComponent
|
||||||
if showWearPreview, let uniqueGift {
|
if showWearPreview, let uniqueGift {
|
||||||
let buttonContent: AnyComponentWithIdentity<Empty>
|
let buttonContent: AnyComponentWithIdentity<Empty>
|
||||||
if !component.context.isPremium {
|
|
||||||
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||||
|
let requiredLevel = Int(BoostSubject.wearGift.requiredLevel(group: false, context: component.context, configuration: premiumConfiguration))
|
||||||
|
|
||||||
|
var canWear = true
|
||||||
|
if isChannelGift, case let .channel(channel) = state.peerMap[ownerPeerId], (channel.approximateBoostLevel ?? 0) < requiredLevel {
|
||||||
|
canWear = false
|
||||||
buttonContent = AnyComponentWithIdentity(
|
buttonContent = AnyComponentWithIdentity(
|
||||||
id: AnyHashable("wear_locked"),
|
id: AnyHashable("wear_channel"),
|
||||||
|
component: AnyComponent(
|
||||||
|
VStack([
|
||||||
|
AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("label"),
|
||||||
|
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Wear_Start, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||||
|
),
|
||||||
|
AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("level"),
|
||||||
|
component: AnyComponent(PremiumLockButtonSubtitleComponent(
|
||||||
|
count: requiredLevel,
|
||||||
|
theme: theme,
|
||||||
|
strings: strings
|
||||||
|
))
|
||||||
|
)
|
||||||
|
], spacing: 3.0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else if !isChannelGift && !component.context.isPremium {
|
||||||
|
canWear = false
|
||||||
|
buttonContent = AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("wear_premium"),
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
HStack([
|
HStack([
|
||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
@ -1888,30 +1959,48 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
action: { [weak state] in
|
action: { [weak state] in
|
||||||
if let state {
|
if let state {
|
||||||
let context = component.context
|
let context = component.context
|
||||||
if !context.isPremium, let controller = controller() as? GiftViewScreen {
|
if !canWear, let controller = controller() as? GiftViewScreen {
|
||||||
controller.dismissAllTooltips()
|
controller.dismissAllTooltips()
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
if isChannelGift {
|
||||||
let text = strings.Gift_View_TooltipPremiumWearing
|
state.levelsDisposable.set(combineLatest(
|
||||||
let tooltipController = UndoOverlayController(
|
queue: Queue.mainQueue(),
|
||||||
presentationData: presentationData,
|
context.engine.peers.getChannelBoostStatus(peerId: ownerPeerId),
|
||||||
content: .premiumPaywall(title: nil, text: text, customUndoText: nil, timeout: nil, linkAction: nil),
|
context.engine.peers.getMyBoostStatus()
|
||||||
position: .bottom,
|
).startStandalone(next: { [weak controller] boostStatus, myBoostStatus in
|
||||||
animateInAsReplacement: false,
|
guard let controller, let boostStatus, let myBoostStatus else {
|
||||||
appearance: UndoOverlayController.Appearance(sideInset: 16.0, bottomInset: 62.0),
|
return
|
||||||
action: { [weak controller] action in
|
|
||||||
if case .info = action {
|
|
||||||
controller?.dismissAllTooltips()
|
|
||||||
let premiumController = context.sharedContext.makePremiumIntroController(context: context, source: .messageEffects, forceDark: false, dismissed: nil)
|
|
||||||
controller?.push(premiumController)
|
|
||||||
Queue.mainQueue().after(0.6, {
|
|
||||||
component.cancel(false)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return false
|
component.cancel(true)
|
||||||
}
|
|
||||||
)
|
let levelsController = context.sharedContext.makePremiumBoostLevelsController(context: context, peerId: ownerPeerId, subject: .wearGift, boostStatus: boostStatus, myBoostStatus: myBoostStatus, forceDark: false, openStats: nil)
|
||||||
controller.present(tooltipController, in: .window(.root))
|
controller.push(levelsController)
|
||||||
|
|
||||||
|
HapticFeedback().impact(.light)
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
let text = strings.Gift_View_TooltipPremiumWearing
|
||||||
|
let tooltipController = UndoOverlayController(
|
||||||
|
presentationData: presentationData,
|
||||||
|
content: .premiumPaywall(title: nil, text: text, customUndoText: nil, timeout: nil, linkAction: nil),
|
||||||
|
position: .bottom,
|
||||||
|
animateInAsReplacement: false,
|
||||||
|
appearance: UndoOverlayController.Appearance(sideInset: 16.0, bottomInset: 62.0),
|
||||||
|
action: { [weak controller] action in
|
||||||
|
if case .info = action {
|
||||||
|
controller?.dismissAllTooltips()
|
||||||
|
let premiumController = context.sharedContext.makePremiumIntroController(context: context, source: .messageEffects, forceDark: false, dismissed: nil)
|
||||||
|
controller?.push(premiumController)
|
||||||
|
Queue.mainQueue().after(0.6, {
|
||||||
|
component.cancel(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
controller.present(tooltipController, in: .window(.root))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
state.commitWear(uniqueGift)
|
state.commitWear(uniqueGift)
|
||||||
if case .wearPreview = component.subject {
|
if case .wearPreview = component.subject {
|
||||||
@ -3655,7 +3744,7 @@ private final class AvatarComponent: Component {
|
|||||||
private weak var state: EmptyComponentState?
|
private weak var state: EmptyComponentState?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 26.0))
|
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 42.0))
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
|||||||
@ -1751,7 +1751,7 @@ func targetSize(cropSize: CGSize, rotateSideward: Bool = false) -> CGSize {
|
|||||||
return CGSize(width: renderWidth, height: renderHeight)
|
return CGSize(width: renderWidth, height: renderHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func recommendedVideoExportConfiguration(values: MediaEditorValues, duration: Double, image: Bool = false, forceFullHd: Bool = false, frameRate: Float, isSticker: Bool = false) -> MediaEditorVideoExport.Configuration {
|
public func recommendedVideoExportConfiguration(values: MediaEditorValues, duration: Double, image: Bool = false, forceFullHd: Bool = false, frameRate: Float, isSticker: Bool = false, isAvatar: Bool = false) -> MediaEditorVideoExport.Configuration {
|
||||||
let compressionProperties: [String: Any]
|
let compressionProperties: [String: Any]
|
||||||
let codecType: Any
|
let codecType: Any
|
||||||
|
|
||||||
@ -1763,7 +1763,17 @@ public func recommendedVideoExportConfiguration(values: MediaEditorValues, durat
|
|||||||
if image {
|
if image {
|
||||||
videoBitrate = 5000
|
videoBitrate = 5000
|
||||||
} else {
|
} else {
|
||||||
if duration < 10 {
|
if isAvatar {
|
||||||
|
if duration <= 2.0 {
|
||||||
|
videoBitrate = 2400
|
||||||
|
} else if duration <= 5.0 {
|
||||||
|
videoBitrate = 2000
|
||||||
|
} else if duration <= 8.0 {
|
||||||
|
videoBitrate = 1500
|
||||||
|
} else {
|
||||||
|
videoBitrate = 1100
|
||||||
|
}
|
||||||
|
} else if duration < 10 {
|
||||||
videoBitrate = 5800
|
videoBitrate = 5800
|
||||||
} else if duration < 20 {
|
} else if duration < 20 {
|
||||||
videoBitrate = 5500
|
videoBitrate = 5500
|
||||||
@ -1797,7 +1807,12 @@ public func recommendedVideoExportConfiguration(values: MediaEditorValues, durat
|
|||||||
|
|
||||||
useHEVC = false
|
useHEVC = false
|
||||||
} else {
|
} else {
|
||||||
if isSticker {
|
if isAvatar {
|
||||||
|
width = 640
|
||||||
|
height = 640
|
||||||
|
frameRate = 30
|
||||||
|
useHEVC = false
|
||||||
|
} else if isSticker {
|
||||||
width = 512
|
width = 512
|
||||||
height = 512
|
height = 512
|
||||||
useVP9 = true
|
useVP9 = true
|
||||||
|
|||||||
@ -147,7 +147,7 @@ extension PeerInfoScreenImpl {
|
|||||||
}
|
}
|
||||||
controller.videoCompletion = { [weak self] image, url, values, markup, commit in
|
controller.videoCompletion = { [weak self] image, url, values, markup, commit in
|
||||||
resultImage = image
|
resultImage = image
|
||||||
self?.updateProfileVideo(image, asset: url, values: values, markup: markup, mode: mode, uploadStatus: uploadStatusPromise)
|
self?.updateProfileVideo(image, video: nil, values: nil, markup: markup, mode: mode, uploadStatus: uploadStatusPromise)
|
||||||
commit()
|
commit()
|
||||||
}
|
}
|
||||||
parentController?.push(controller)
|
parentController?.push(controller)
|
||||||
@ -207,7 +207,7 @@ extension PeerInfoScreenImpl {
|
|||||||
case let .video(video, coverImage, values, _, _):
|
case let .video(video, coverImage, values, _, _):
|
||||||
if let coverImage {
|
if let coverImage {
|
||||||
resultImage = coverImage
|
resultImage = coverImage
|
||||||
self?.updateProfileVideo(coverImage, asset: video, values: values, markup: nil, mode: mode, uploadStatus: uploadStatusPromise)
|
self?.updateProfileVideo(coverImage, video: video, values: values, markup: nil, mode: mode, uploadStatus: uploadStatusPromise)
|
||||||
}
|
}
|
||||||
commit({})
|
commit({})
|
||||||
default:
|
default:
|
||||||
@ -459,7 +459,7 @@ extension PeerInfoScreenImpl {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateProfileVideo(_ image: UIImage, asset: Any?, values: MediaEditorValues?, markup: UploadPeerPhotoMarkup?, mode: PeerInfoAvatarEditingMode, uploadStatus: Promise<PeerInfoAvatarUploadStatus>?) {
|
public func updateProfileVideo(_ image: UIImage, video: MediaEditorScreenImpl.MediaResult.VideoResult?, values: MediaEditorValues?, markup: UploadPeerPhotoMarkup?, mode: PeerInfoAvatarEditingMode, uploadStatus: Promise<PeerInfoAvatarUploadStatus>?) {
|
||||||
var uploadVideo = true
|
var uploadVideo = true
|
||||||
if let _ = markup {
|
if let _ = markup {
|
||||||
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let uploadVideoValue = data["upload_markup_video"] as? Bool, uploadVideoValue {
|
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let uploadVideoValue = data["upload_markup_video"] as? Bool, uploadVideoValue {
|
||||||
@ -482,9 +482,82 @@ extension PeerInfoScreenImpl {
|
|||||||
let context = self.context
|
let context = self.context
|
||||||
|
|
||||||
let videoResource: Signal<TelegramMediaResource?, UploadPeerPhotoError>
|
let videoResource: Signal<TelegramMediaResource?, UploadPeerPhotoError>
|
||||||
if uploadVideo {
|
if uploadVideo, let video, let values {
|
||||||
videoResource = Signal { subscriber in
|
var exportSubject: Signal<(MediaEditorVideoExport.Subject, Double), NoError>?
|
||||||
return EmptyDisposable
|
switch video {
|
||||||
|
case let .imageFile(path):
|
||||||
|
if let image = UIImage(contentsOfFile: path) {
|
||||||
|
exportSubject = .single((.image(image: image), 3.0))
|
||||||
|
}
|
||||||
|
case let .videoFile(path):
|
||||||
|
let asset = AVURLAsset(url: NSURL(fileURLWithPath: path) as URL)
|
||||||
|
exportSubject = .single((.video(asset: asset, isStory: false), asset.duration.seconds))
|
||||||
|
case let .asset(localIdentifier):
|
||||||
|
exportSubject = Signal { subscriber in
|
||||||
|
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil)
|
||||||
|
if fetchResult.count != 0 {
|
||||||
|
let asset = fetchResult.object(at: 0)
|
||||||
|
if asset.mediaType == .video {
|
||||||
|
PHImageManager.default().requestAVAsset(forVideo: asset, options: nil) { avAsset, _, _ in
|
||||||
|
if let avAsset {
|
||||||
|
subscriber.putNext((.video(asset: avAsset, isStory: true), avAsset.duration.seconds))
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let options = PHImageRequestOptions()
|
||||||
|
options.deliveryMode = .highQualityFormat
|
||||||
|
PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .default, options: options) { image, _ in
|
||||||
|
if let image {
|
||||||
|
subscriber.putNext((.image(image: image), 3.0))
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EmptyDisposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let exportSubject {
|
||||||
|
videoResource = exportSubject
|
||||||
|
|> castError(UploadPeerPhotoError.self)
|
||||||
|
|> mapToSignal { exportSubject, duration in
|
||||||
|
return Signal<TelegramMediaResource?, UploadPeerPhotoError> { subscriber in
|
||||||
|
let configuration = recommendedVideoExportConfiguration(values: values, duration: duration, forceFullHd: true, frameRate: 60.0, isAvatar: true)
|
||||||
|
//let outputPath = NSTemporaryDirectory() + "\(Int64.random(in: 0 ..< .max)).mp4"
|
||||||
|
let tempFile = EngineTempBox.shared.tempFile(fileName: "video.mp4")
|
||||||
|
let videoExport = MediaEditorVideoExport(postbox: context.account.postbox, subject: exportSubject, configuration: configuration, outputPath: tempFile.path, textScale: 2.0)
|
||||||
|
|
||||||
|
let _ = (videoExport.status
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] status in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch status {
|
||||||
|
case .completed:
|
||||||
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: tempFile.path), options: .mappedIfSafe) {
|
||||||
|
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||||
|
account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||||
|
subscriber.putNext(resource)
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}
|
||||||
|
EngineTempBox.shared.dispose(tempFile)
|
||||||
|
case let .progress(progress):
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
self.controllerNode.state = self.controllerNode.state.withAvatarUploadProgress(.value(CGFloat(progress * 0.45)))
|
||||||
|
self.requestLayout(transition: .immediate)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return EmptyDisposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
videoResource = .single(nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
videoResource = .single(nil)
|
videoResource = .single(nil)
|
||||||
|
|||||||
@ -1236,7 +1236,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
controller.videoCompletion = { [weak self] image, url, values, markup, commit in
|
controller.videoCompletion = { [weak self] image, url, values, markup, commit in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
|
if let rootController = strongSelf.effectiveNavigationController as? TelegramRootController, let settingsController = rootController.accountSettingsController as? PeerInfoScreenImpl {
|
||||||
settingsController.updateProfileVideo(image, asset: AVURLAsset(url: url), values: values, markup: markup, mode: .accept, uploadStatus: nil)
|
settingsController.updateProfileVideo(image, video: nil, values: nil, markup: markup, mode: .accept, uploadStatus: nil)
|
||||||
commit()
|
commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
|||||||
private let displayCallIcons: Bool
|
private let displayCallIcons: Bool
|
||||||
private let multipleSelection: Bool
|
private let multipleSelection: Bool
|
||||||
private let requirePhoneNumbers: Bool
|
private let requirePhoneNumbers: Bool
|
||||||
|
private let allowChannelsInSearch: Bool
|
||||||
|
|
||||||
private let openProfile: ((EnginePeer) -> Void)?
|
private let openProfile: ((EnginePeer) -> Void)?
|
||||||
private let sendMessage: ((EnginePeer) -> Void)?
|
private let sendMessage: ((EnginePeer) -> Void)?
|
||||||
@ -108,6 +109,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
|||||||
self.confirmation = params.confirmation
|
self.confirmation = params.confirmation
|
||||||
self.multipleSelection = params.multipleSelection
|
self.multipleSelection = params.multipleSelection
|
||||||
self.requirePhoneNumbers = params.requirePhoneNumbers
|
self.requirePhoneNumbers = params.requirePhoneNumbers
|
||||||
|
self.allowChannelsInSearch = params.allowChannelsInSearch
|
||||||
|
|
||||||
self.openProfile = params.openProfile
|
self.openProfile = params.openProfile
|
||||||
self.sendMessage = params.sendMessage
|
self.sendMessage = params.sendMessage
|
||||||
@ -216,7 +218,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func loadDisplayNode() {
|
override func loadDisplayNode() {
|
||||||
self.displayNode = ContactSelectionControllerNode(context: self.context, mode: self.mode, presentationData: self.presentationData, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection, requirePhoneNumbers: self.requirePhoneNumbers)
|
self.displayNode = ContactSelectionControllerNode(context: self.context, mode: self.mode, presentationData: self.presentationData, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection, requirePhoneNumbers: self.requirePhoneNumbers, allowChannelsInSearch: self.allowChannelsInSearch)
|
||||||
self._ready.set(self.contactsNode.contactListNode.ready)
|
self._ready.set(self.contactsNode.contactListNode.ready)
|
||||||
|
|
||||||
self.contactsNode.navigationBar = self.navigationBar
|
self.contactsNode.navigationBar = self.navigationBar
|
||||||
|
|||||||
@ -23,6 +23,7 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
private let displayDeviceContacts: Bool
|
private let displayDeviceContacts: Bool
|
||||||
private let displayCallIcons: Bool
|
private let displayCallIcons: Bool
|
||||||
|
private let allowChannelsInSearch: Bool
|
||||||
private let filters: [ContactListFilter]
|
private let filters: [ContactListFilter]
|
||||||
|
|
||||||
let contactListNode: ContactListNode
|
let contactListNode: ContactListNode
|
||||||
@ -56,11 +57,12 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
var searchContainerNode: ContactsSearchContainerNode?
|
var searchContainerNode: ContactsSearchContainerNode?
|
||||||
|
|
||||||
init(context: AccountContext, mode: ContactSelectionControllerMode, presentationData: PresentationData, options: Signal<[ContactListAdditionalOption], NoError>, displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool, requirePhoneNumbers: Bool) {
|
init(context: AccountContext, mode: ContactSelectionControllerMode, presentationData: PresentationData, options: Signal<[ContactListAdditionalOption], NoError>, displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool, requirePhoneNumbers: Bool, allowChannelsInSearch: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.displayDeviceContacts = displayDeviceContacts
|
self.displayDeviceContacts = displayDeviceContacts
|
||||||
self.displayCallIcons = displayCallIcons
|
self.displayCallIcons = displayCallIcons
|
||||||
|
self.allowChannelsInSearch = allowChannelsInSearch
|
||||||
|
|
||||||
var excludeSelf = true
|
var excludeSelf = true
|
||||||
|
|
||||||
@ -247,6 +249,9 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
categories.insert(.global)
|
categories.insert(.global)
|
||||||
}
|
}
|
||||||
|
if self.allowChannelsInSearch {
|
||||||
|
categories.insert(.channels)
|
||||||
|
}
|
||||||
|
|
||||||
let searchContainerNode = ContactsSearchContainerNode(context: self.context, updatedPresentationData: (self.presentationData, self.presentationDataPromise.get()), onlyWriteable: false, categories: categories, filters: self.filters, addContact: nil, openPeer: { [weak self] peer in
|
let searchContainerNode = ContactsSearchContainerNode(context: self.context, updatedPresentationData: (self.presentationData, self.presentationDataPromise.get()), onlyWriteable: false, categories: categories, filters: self.filters, addContact: nil, openPeer: { [weak self] peer in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -316,6 +321,10 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
categories.insert(.global)
|
categories.insert(.global)
|
||||||
}
|
}
|
||||||
|
if self.allowChannelsInSearch {
|
||||||
|
categories.insert(.channels)
|
||||||
|
}
|
||||||
|
|
||||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ContactsSearchContainerNode(context: self.context, updatedPresentationData: (self.presentationData, self.presentationDataPromise.get()), onlyWriteable: false, categories: categories, filters: self.filters, addContact: nil, openPeer: { [weak self] peer in
|
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ContactsSearchContainerNode(context: self.context, updatedPresentationData: (self.presentationData, self.presentationDataPromise.get()), onlyWriteable: false, categories: categories, filters: self.filters, addContact: nil, openPeer: { [weak self] peer in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
var updated = false
|
var updated = false
|
||||||
|
|||||||
@ -2302,8 +2302,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
mode = .starsGifting(birthdays: nil, hasActions: true, showSelf: false)
|
mode = .starsGifting(birthdays: nil, hasActions: true, showSelf: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var allowChannelsInSearch = false
|
||||||
let contactOptions: Signal<[ContactListAdditionalOption], NoError>
|
let contactOptions: Signal<[ContactListAdditionalOption], NoError>
|
||||||
if case let .starGiftTransfer(_, _, _, _, canExportDate) = source {
|
if case let .starGiftTransfer(_, _, _, _, canExportDate) = source {
|
||||||
|
allowChannelsInSearch = true
|
||||||
var subtitle: String?
|
var subtitle: String?
|
||||||
if let canExportDate {
|
if let canExportDate {
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
@ -2369,6 +2371,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
autoDismiss: false,
|
autoDismiss: false,
|
||||||
title: { _ in return title },
|
title: { _ in return title },
|
||||||
options: contactOptions,
|
options: contactOptions,
|
||||||
|
allowChannelsInSearch: allowChannelsInSearch,
|
||||||
openProfile: { peer in
|
openProfile: { peer in
|
||||||
openProfileImpl?(peer)
|
openProfileImpl?(peer)
|
||||||
},
|
},
|
||||||
@ -2454,7 +2457,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
if currentTime > canExportDate || "".isEmpty {
|
if currentTime > canExportDate {
|
||||||
let alertController = giftWithdrawAlertController(context: context, gift: gift, commit: {
|
let alertController = giftWithdrawAlertController(context: context, gift: gift, commit: {
|
||||||
let _ = (context.engine.payments.checkStarGiftWithdrawalAvailability(reference: reference)
|
let _ = (context.engine.payments.checkStarGiftWithdrawalAvailability(reference: reference)
|
||||||
|> deliverOnMainQueue).start(error: { [weak controller] error in
|
|> deliverOnMainQueue).start(error: { [weak controller] error in
|
||||||
|
|||||||
@ -338,7 +338,7 @@ func presentLegacyWebSearchGallery(context: AccountContext, peer: EnginePeer?, t
|
|||||||
|
|
||||||
let (items, focusItem) = galleryItems(account: context.account, results: results, current: current, selectionContext: selectionContext, editingContext: editingContext)
|
let (items, focusItem) = galleryItems(account: context.account, results: results, current: current, selectionContext: selectionContext, editingContext: editingContext)
|
||||||
|
|
||||||
let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: false, allowCaptionEntities: true, hasTimer: false, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: false, hasCamera: false, recipientName: recipientName, isScheduledMessages: false)!
|
let model = TGMediaPickerGalleryModel(context: legacyController.context, items: items, focus: focusItem, selectionContext: selectionContext, editingContext: editingContext, hasCaptions: false, allowCaptionEntities: true, hasTimer: false, onlyCrop: false, inhibitDocumentCaptions: false, hasSelectionPanel: false, hasCamera: false, recipientName: recipientName, isScheduledMessages: false, hasCoverButton: false)!
|
||||||
model.stickersContext = paintStickersContext
|
model.stickersContext = paintStickersContext
|
||||||
controller.model = model
|
controller.model = model
|
||||||
model.controller = controller
|
model.controller = controller
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user