mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge commit '77cc01f0d9'
This commit is contained in:
commit
e6ce004498
34 changed files with 402 additions and 142 deletions
|
|
@ -15982,6 +15982,9 @@ Error: %8$@";
|
|||
"Notification.PollAddedOption" = "%1$@ added the option \"%2$@\" to the poll";
|
||||
"Notification.PollAddedOptionYou" = "You added the option \"%1$@\" to the poll";
|
||||
|
||||
"Notification.PollDeletedOption" = "%1$@ deleted the option \"%2$@\" from the poll";
|
||||
"Notification.PollDeletedOptionYou" = "You deleted the option \"%1$@\" to the poll";
|
||||
|
||||
"Notification.ManagedBotCreated" = "%@ bot created";
|
||||
|
||||
"Chat.PolOptionAddedTimestamp.Date" = "Added by %1$@ %2$@";
|
||||
|
|
@ -15999,3 +16002,6 @@ Error: %8$@";
|
|||
"MessagePoll.ResultsIn" = "results in %@";
|
||||
"MessagePoll.ResultsInDays_1" = "results in %@ day";
|
||||
"MessagePoll.ResultsInDays_any" = "results in %@ days";
|
||||
|
||||
"Premium.AiTools" = "AI Tools";
|
||||
"Premium.AiToolsInfo" = "Transform your messages and entire chats in your preferred style and language.";
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public enum PremiumIntroSource {
|
|||
case messageEffects
|
||||
case todo
|
||||
case copyProtection
|
||||
case aiTools
|
||||
case auth(String)
|
||||
case premiumGift(TelegramMediaFile)
|
||||
}
|
||||
|
|
@ -85,6 +86,7 @@ public enum PremiumDemoSubject {
|
|||
case messageEffects
|
||||
case todo
|
||||
case copyProtection
|
||||
case aiTools
|
||||
|
||||
case businessLocation
|
||||
case businessHours
|
||||
|
|
|
|||
|
|
@ -3580,8 +3580,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
}
|
||||
|
||||
interaction.messageContextAction(EngineMessage(message), node, rect, gesture, key, fetchResourceId)
|
||||
}, toggleMediaPlayback: { _ in
|
||||
}, toggleMessagesSelection: { messageId, selected in
|
||||
}, toggleMediaPlayback: nil, toggleMessagesSelection: { messageId, selected in
|
||||
if let messageId = messageId.first {
|
||||
interaction.toggleMessageSelection(messageId, selected)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ class ChatImageGalleryItem: GalleryItem {
|
|||
for media in self.message.media {
|
||||
if let poll = media as? TelegramMediaPoll, let image = poll.attachedMedia as? TelegramMediaImage {
|
||||
node.setImage(userLocation: .peer(self.message.id.peerId), imageReference: .message(message: MessageReference(self.message), media: image))
|
||||
} else if let poll = media as? TelegramMediaPoll, let file = poll.attachedMedia as? TelegramMediaFile, file.mimeType.hasPrefix("image/") {
|
||||
node.setFile(context: self.context, userLocation: .peer(self.message.id.peerId), fileReference: .message(message: MessageReference(self.message), media: file))
|
||||
} else if let paidContent = media as? TelegramMediaPaidContent {
|
||||
let mediaIndex = self.mediaIndex ?? 0
|
||||
if case let .full(fullMedia) = paidContent.extendedMedia[Int(mediaIndex)], let image = fullMedia as? TelegramMediaImage {
|
||||
|
|
|
|||
|
|
@ -976,9 +976,11 @@
|
|||
if (adjustments.paintingData.hasAnimation) {
|
||||
grouping = false;
|
||||
}
|
||||
// if ([editingContext livePhotoModeForItem:asset] != TGMediaLivePhotoModeOff) {
|
||||
// grouping = false;
|
||||
// }
|
||||
|
||||
TGMediaLivePhotoMode livePhotoMode = [editingContext livePhotoModeForItem:asset];
|
||||
if (livePhotoMode == TGMediaLivePhotoModeLoop || livePhotoMode == TGMediaLivePhotoModeBounce) {
|
||||
grouping = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1544,9 +1546,10 @@
|
|||
if (adjustments.paintingData.hasAnimation) {
|
||||
grouping = false;
|
||||
}
|
||||
// if ([editingContext livePhotoModeForItem:asset] != TGMediaLivePhotoModeOff) {
|
||||
// grouping = false;
|
||||
// }
|
||||
TGMediaLivePhotoMode livePhotoMode = [editingContext livePhotoModeForItem:asset];
|
||||
if (livePhotoMode == TGMediaLivePhotoModeLoop || livePhotoMode == TGMediaLivePhotoModeBounce) {
|
||||
grouping = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1771,21 +1774,6 @@
|
|||
- (UIBarButtonItem *)rightBarButtonItem
|
||||
{
|
||||
return nil;
|
||||
// if (_intent == TGMediaAssetsControllerSendFileIntent)
|
||||
// return nil;
|
||||
// if (self.requestSearchController == nil) {
|
||||
// return nil;
|
||||
// }
|
||||
//
|
||||
// if (iosMajorVersion() < 7)
|
||||
// {
|
||||
// TGModernBarButton *searchButton = [[TGModernBarButton alloc] initWithImage:TGComponentsImageNamed(@"NavigationSearchIcon.png")];
|
||||
// searchButton.portraitAdjustment = CGPointMake(-7, -5);
|
||||
// [searchButton addTarget:self action:@selector(searchButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
||||
// return [[UIBarButtonItem alloc] initWithCustomView:searchButton];
|
||||
// }
|
||||
//
|
||||
// return [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSearch target:self action:@selector(searchButtonPressed)];
|
||||
}
|
||||
|
||||
- (void)cancelButtonPressed
|
||||
|
|
|
|||
|
|
@ -754,6 +754,14 @@
|
|||
hasLivePhotoButton = true;
|
||||
}
|
||||
}
|
||||
} else if ([item isKindOfClass:[TGMediaPickerGalleryPhotoItem class]]) {
|
||||
TGMediaPickerGalleryPhotoItem *photoGalleryItem = (TGMediaPickerGalleryPhotoItem *)item;
|
||||
if ([photoGalleryItem.asset isKindOfClass:[TGMediaAsset class]]) {
|
||||
TGMediaAsset *asset = (TGMediaAsset *)photoGalleryItem.asset;
|
||||
if (asset.subtypes & TGMediaAssetSubtypePhotoLive) {
|
||||
hasLivePhotoButton = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
[_muteButton setImage:muteIcon forState:UIControlStateNormal];
|
||||
[_muteButton setImage:muteActiveIcon forState:UIControlStateSelected];
|
||||
|
|
|
|||
|
|
@ -338,7 +338,13 @@
|
|||
backgroundHeight += _keyboardHeight - edgeInsets.bottom;
|
||||
}
|
||||
|
||||
CGRect livePhotoButtonFrame = CGRectMake(edgeInsets.left + 16.0, edgeInsets.top + 80.0 + 32.0 - _keyboardHeight, 160.0, 18.0);
|
||||
CGFloat livePhotoY = 0.0;
|
||||
if (frame.size.width > frame.size.height && !TGIsPad()) {
|
||||
livePhotoY = 48.0;
|
||||
} else {
|
||||
livePhotoY = edgeInsets.top + 145.0 - _keyboardHeight;
|
||||
}
|
||||
CGRect livePhotoButtonFrame = CGRectMake(_safeAreaInset.left + edgeInsets.left + 16.0, livePhotoY, 160.0, 18.0);
|
||||
_livePhotoButtonView.frame = livePhotoButtonFrame;
|
||||
|
||||
CGRect panelFrame = CGRectMake(edgeInsets.left, panelY, frame.size.width, panelHeight);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,16 @@ import LegacyMediaPickerUI
|
|||
import Photos
|
||||
import MediaAssetsContext
|
||||
|
||||
private func galleryFetchResultItems(fetchResult: PHFetchResult<PHAsset>, index: Int, reversed: Bool, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, stickersContext: TGPhotoPaintStickersContext, immediateThumbnail: UIImage?) -> ([TGModernGalleryItem], TGModernGalleryItem?) {
|
||||
private func galleryFetchResultItems(
|
||||
fetchResult: PHFetchResult<PHAsset>,
|
||||
index: Int,
|
||||
reversed: Bool,
|
||||
selectionContext: TGMediaSelectionContext?,
|
||||
editingContext: TGMediaEditingContext,
|
||||
stickersContext: TGPhotoPaintStickersContext,
|
||||
immediateThumbnail: UIImage?,
|
||||
asFile: Bool
|
||||
) -> ([TGModernGalleryItem], TGModernGalleryItem?) {
|
||||
var focusItem: TGModernGalleryItem?
|
||||
var galleryItems: [TGModernGalleryItem] = []
|
||||
|
||||
|
|
@ -24,6 +33,7 @@ private func galleryFetchResultItems(fetchResult: PHFetchResult<PHAsset>, index:
|
|||
galleryItem.selectionContext = selectionContext
|
||||
galleryItem.editingContext = editingContext
|
||||
galleryItem.stickersContext = stickersContext
|
||||
galleryItem.asFile = asFile
|
||||
galleryItems.append(galleryItem)
|
||||
|
||||
if i == index {
|
||||
|
|
@ -112,6 +122,7 @@ func presentLegacyMediaPickerGallery(
|
|||
immediateThumbnail: UIImage?,
|
||||
selectionContext: TGMediaSelectionContext?,
|
||||
editingContext: TGMediaEditingContext,
|
||||
asFile: Bool,
|
||||
hasSilentPosting: Bool,
|
||||
hasSchedule: Bool,
|
||||
hasTimer: Bool,
|
||||
|
|
@ -166,10 +177,10 @@ func presentLegacyMediaPickerGallery(
|
|||
|
||||
let (items, focusItem): ([TGModernGalleryItem], TGModernGalleryItem?)
|
||||
switch source {
|
||||
case let .fetchResult(fetchResult, index, reversed):
|
||||
(items, focusItem) = galleryFetchResultItems(fetchResult: fetchResult, index: index, reversed: reversed, selectionContext: selectionContext, editingContext: editingContext, stickersContext: paintStickersContext, immediateThumbnail: immediateThumbnail)
|
||||
case let .selection(item):
|
||||
(items, focusItem) = gallerySelectionItems(item: item, selectionContext: selectionContext, editingContext: editingContext, stickersContext: paintStickersContext, immediateThumbnail: immediateThumbnail)
|
||||
case let .fetchResult(fetchResult, index, reversed):
|
||||
(items, focusItem) = galleryFetchResultItems(fetchResult: fetchResult, index: index, reversed: reversed, selectionContext: selectionContext, editingContext: editingContext, stickersContext: paintStickersContext, immediateThumbnail: immediateThumbnail, asFile: asFile)
|
||||
case let .selection(item):
|
||||
(items, focusItem) = gallerySelectionItems(item: item, selectionContext: selectionContext, editingContext: editingContext, stickersContext: paintStickersContext, immediateThumbnail: immediateThumbnail)
|
||||
}
|
||||
|
||||
let recipientName: String?
|
||||
|
|
@ -183,7 +194,23 @@ func presentLegacyMediaPickerGallery(
|
|||
}
|
||||
}
|
||||
|
||||
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)!
|
||||
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
|
||||
controller.model = model
|
||||
model.controller = controller
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||
}
|
||||
duration = stringForDuration(Int32(asset.duration))
|
||||
} else {
|
||||
if asset.mediaSubtypes.contains(.photoLive) {
|
||||
if asset.mediaSubtypes.contains(.photoLive) && interaction.displayLivePhotoIcon {
|
||||
typeIcon = UIImage(bundleImageName: "Chat/Message/LivePhoto")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,8 +47,20 @@ final class MediaPickerInteraction {
|
|||
let selectionState: TGMediaSelectionContext?
|
||||
let editingState: TGMediaEditingContext
|
||||
var hiddenMediaId: String?
|
||||
var displayLivePhotoIcon: Bool = false
|
||||
|
||||
init(downloadManager: AssetDownloadManager, openMedia: @escaping (PHFetchResult<PHAsset>, Int, UIImage?) -> Void, openSelectedMedia: @escaping (TGMediaSelectableItem, UIImage?) -> Void, openDraft: @escaping (MediaEditorDraft, UIImage?) -> Void, toggleSelection: @escaping (TGMediaSelectableItem, Bool, Bool) -> Bool, sendSelected: @escaping (TGMediaSelectableItem?, Bool, Int32?, Bool, ChatSendMessageActionSheetController.SendParameters?, @escaping () -> Void) -> Void, schedule: @escaping (ChatSendMessageActionSheetController.SendParameters?) -> Void, dismissInput: @escaping () -> Void, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext) {
|
||||
init(
|
||||
downloadManager: AssetDownloadManager,
|
||||
openMedia: @escaping (PHFetchResult<PHAsset>, Int, UIImage?) -> Void,
|
||||
openSelectedMedia: @escaping (TGMediaSelectableItem, UIImage?) -> Void,
|
||||
openDraft: @escaping (MediaEditorDraft, UIImage?) -> Void,
|
||||
toggleSelection: @escaping (TGMediaSelectableItem, Bool, Bool) -> Bool,
|
||||
sendSelected: @escaping (TGMediaSelectableItem?, Bool, Int32?, Bool, ChatSendMessageActionSheetController.SendParameters?, @escaping () -> Void) -> Void,
|
||||
schedule: @escaping (ChatSendMessageActionSheetController.SendParameters?) -> Void,
|
||||
dismissInput: @escaping () -> Void,
|
||||
selectionState: TGMediaSelectionContext?,
|
||||
editingState: TGMediaEditingContext
|
||||
) {
|
||||
self.downloadManager = downloadManager
|
||||
self.openMedia = openMedia
|
||||
self.openSelectedMedia = openSelectedMedia
|
||||
|
|
@ -185,6 +197,18 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
|
||||
case assets(PHAssetCollection?, AssetsMode)
|
||||
case media([Media])
|
||||
|
||||
var asFile: Bool {
|
||||
switch self {
|
||||
case let .assets(_, mode):
|
||||
if case let .poll(_, asFile) = mode {
|
||||
return asFile
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
|
|
@ -607,11 +631,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
self.gridNode.scrollView.alwaysBounceVertical = true
|
||||
self.gridNode.scrollView.showsVerticalScrollIndicator = false
|
||||
|
||||
if case let .assets(_, mode) = controller.subject, [.wallpaper, .story, .addImage, .cover, .createSticker, .createAvatar].contains(mode) {
|
||||
|
||||
} else {
|
||||
self.setupSelectionGesture()
|
||||
}
|
||||
self.setupSelectionGesture()
|
||||
|
||||
if let controller = self.controller, case let .assets(collection, _) = controller.subject, collection != nil {
|
||||
self.gridNode.view.interactiveTransitionGestureRecognizerTest = { point -> Bool in
|
||||
|
|
@ -808,10 +828,20 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
}
|
||||
}
|
||||
|
||||
func setupSelectionGesture() {
|
||||
guard self.selectionGesture == nil else {
|
||||
func setupSelectionGesture(force: Bool = false) {
|
||||
guard self.selectionGesture == nil, let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
|
||||
if !force, case let .assets(_, mode) = controller.subject {
|
||||
switch mode {
|
||||
case .default:
|
||||
break
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
let selectionGesture = MediaPickerGridSelectionGesture<TGMediaSelectableItem>()
|
||||
selectionGesture.delegate = self.wrappedGestureRecognizerDelegate
|
||||
selectionGesture.began = { [weak self] in
|
||||
|
|
@ -1296,7 +1326,6 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
self.openingMedia = true
|
||||
|
||||
let asset = fetchResult[index]
|
||||
|
||||
let _ = (checkIfAssetIsLocal(asset)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] isLocallyAvailable in
|
||||
guard let self else {
|
||||
|
|
@ -1333,7 +1362,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
|
||||
self.openingMedia = true
|
||||
|
||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState?.selectionLimit == 1 ? nil : interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState?.selectionLimit == 1 ? nil : interaction.selectionState, editingContext: interaction.editingState, asFile: controller.subject.asFile, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||
self?.hiddenMediaId.set(.single(id))
|
||||
}, initialLayout: layout, transitionHostView: { [weak self] in
|
||||
return self?.gridNode.view
|
||||
|
|
@ -1346,7 +1375,11 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
}, presentSchedulePicker: controller.presentSchedulePicker, presentTimerPicker: controller.presentTimerPicker, getCaptionPanelView: controller.getCaptionPanelView, present: { [weak self] c, a in
|
||||
self?.currentGalleryParentController = c
|
||||
c.navigationPresentation = .flatModal
|
||||
self?.controller?.parentController()?.push(c)
|
||||
if let parentController = self?.controller?.parentController() {
|
||||
parentController.push(c)
|
||||
} else {
|
||||
self?.controller?.push(c)
|
||||
}
|
||||
//self?.controller?.present(c, in: .window(.root), with: a)
|
||||
}, finishedTransitionIn: { [weak self] in
|
||||
self?.openingMedia = false
|
||||
|
|
@ -1376,7 +1409,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
}
|
||||
|
||||
self.openingMedia = true
|
||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, presentationData: self.presentationData, source: .selection(item: item), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, presentationData: self.presentationData, source: .selection(item: item), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, asFile: controller.subject.asFile, hasSilentPosting: true, hasSchedule: true, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||
self?.hiddenMediaId.set(.single(id))
|
||||
}, initialLayout: layout, transitionHostView: { [weak self] in
|
||||
return self?.selectionNode?.view
|
||||
|
|
@ -2021,6 +2054,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
self.secondaryButtonAction = secondaryButtonAction
|
||||
|
||||
let selectionContext = selectionContext ?? TGMediaSelectionContext(groupingAllowed: false, selectionLimit: enableMultiselection ? 100 : 1)!
|
||||
let editingContext = editingContext ?? (subject.asFile ? TGMediaEditingContext.forCaptionsOnly() : TGMediaEditingContext())!
|
||||
|
||||
self.titleView = MediaPickerTitleView(theme: self.presentationData.theme, glass: style == .glass, segments: [self.presentationData.strings.Attachment_AllMedia, self.presentationData.strings.Attachment_SelectedMedia(1)], selectedIndex: 0)
|
||||
|
||||
|
|
@ -2260,7 +2294,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
if let currentItem = currentItem {
|
||||
selectionState.setItem(currentItem, selected: true)
|
||||
}
|
||||
strongSelf.controllerNode.send(fromGallery: currentItem != nil, silently: silently, scheduleTime: scheduleTime, animated: animated, parameters: parameters, completion: completion)
|
||||
strongSelf.controllerNode.send(fromGallery: currentItem != nil, asFile: strongSelf.subject.asFile, silently: silently, scheduleTime: scheduleTime, animated: animated, parameters: parameters, completion: completion)
|
||||
}
|
||||
}, schedule: { [weak self] parameters in
|
||||
if let strongSelf = self {
|
||||
|
|
@ -2272,7 +2306,16 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
if let strongSelf = self {
|
||||
strongSelf.controllerNode.dismissInput()
|
||||
}
|
||||
}, selectionState: selectionContext, editingState: editingContext ?? TGMediaEditingContext())
|
||||
}, selectionState: selectionContext, editingState: editingContext)
|
||||
|
||||
var displayLivePhotoIcon = false
|
||||
if case let .assets(_, mode) = subject, case .default = mode {
|
||||
if let peer = self.peer, case .secretChat = peer {
|
||||
} else {
|
||||
displayLivePhotoIcon = true
|
||||
}
|
||||
}
|
||||
self.interaction?.displayLivePhotoIcon = displayLivePhotoIcon
|
||||
|
||||
let highQualityPhoto = UserDefaults.standard.bool(forKey: "TG_photoHighQuality_v0")
|
||||
if highQualityPhoto {
|
||||
|
|
@ -2575,13 +2618,8 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
|
||||
let selectedSize = self.selectedButtonNode.update(count: count)
|
||||
|
||||
var safeInset: CGFloat = 0.0
|
||||
if layout.safeInsets.right > 0.0 {
|
||||
safeInset += layout.safeInsets.right + 16.0
|
||||
}
|
||||
let selectedButtonInset: CGFloat = self._hasGlassStyle ? 68.0 : 54.0
|
||||
let navigationHeight = navigationLayout(layout: layout).navigationFrame.height
|
||||
self.selectedButtonNode.frame = CGRect(origin: CGPoint(x: self.view.bounds.width - selectedButtonInset - selectedSize.width - safeInset, y: self._hasGlassStyle ? 16.0 : floorToScreenPixels((navigationHeight - selectedSize.height) / 2.0) + 1.0), size: selectedSize)
|
||||
self.selectedButtonNode.frame = CGRect(origin: CGPoint(x: 16.0 + 44.0 + 12.0, y: self._hasGlassStyle ? 16.0 : floorToScreenPixels((navigationHeight - selectedSize.height) / 2.0) + 1.0), size: selectedSize)
|
||||
|
||||
let isSelectionButtonVisible = count > 0 && self.controllerNode.currentDisplayMode == .all
|
||||
transition.updateAlpha(node: self.selectedButtonNode, alpha: isSelectionButtonVisible ? 1.0 : 0.0)
|
||||
|
|
@ -2973,7 +3011,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
}
|
||||
|
||||
self.explicitMultipleSelection = true
|
||||
self.controllerNode.setupSelectionGesture()
|
||||
self.controllerNode.setupSelectionGesture(force: true)
|
||||
self.requestAttachmentMenuExpansion()
|
||||
|
||||
if let state = self.controllerNode.state {
|
||||
|
|
@ -3202,14 +3240,8 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||
self.validLayout = layout
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
|
||||
|
||||
var safeInset: CGFloat = 0.0
|
||||
if layout.safeInsets.right > 0.0 {
|
||||
safeInset += layout.safeInsets.right + 16.0
|
||||
}
|
||||
let navigationHeight = navigationLayout(layout: layout).navigationFrame.height
|
||||
|
||||
let selectedButtonInset: CGFloat = self._hasGlassStyle ? 68.0 : 54.0
|
||||
self.selectedButtonNode.frame = CGRect(origin: CGPoint(x: self.view.bounds.width - selectedButtonInset - self.selectedButtonNode.frame.width - safeInset, y: self._hasGlassStyle ? 16.0 : floorToScreenPixels((navigationHeight - self.selectedButtonNode.frame.height) / 2.0) + 1.0), size: self.selectedButtonNode.frame.size)
|
||||
self.selectedButtonNode.frame = CGRect(origin: CGPoint(x: 16.0 + 44.0 + 12.0, y: self._hasGlassStyle ? 16.0 : floorToScreenPixels((navigationHeight - self.selectedButtonNode.frame.height) / 2.0) + 1.0), size: self.selectedButtonNode.frame.size)
|
||||
}
|
||||
|
||||
public func dismissAnimated() {
|
||||
|
|
|
|||
|
|
@ -1129,6 +1129,26 @@ private final class DemoSheetContent: CombinedComponent {
|
|||
)
|
||||
)
|
||||
|
||||
availableItems[.aiTools] = DemoPagerComponent.Item(
|
||||
AnyComponentWithIdentity(
|
||||
id: PremiumDemoScreen.Subject.aiTools,
|
||||
component: AnyComponent(
|
||||
PageComponent(
|
||||
content: AnyComponent(PhoneDemoComponent(
|
||||
context: component.context,
|
||||
position: .top,
|
||||
model: .island,
|
||||
videoFile: configuration.videos["ai_compose"],
|
||||
decoration: .badgeStars
|
||||
)),
|
||||
title: strings.Premium_AiTools,
|
||||
text: strings.Premium_AiToolsInfo,
|
||||
textColor: textColor
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
let index: Int = 0
|
||||
var items: [DemoPagerComponent.Item] = []
|
||||
if let item = availableItems.first(where: { $0.value.content.id == component.subject as AnyHashable }) {
|
||||
|
|
@ -1221,6 +1241,8 @@ private final class DemoSheetContent: CombinedComponent {
|
|||
text = strings.Premium_TodoInfo
|
||||
case .copyProtection:
|
||||
text = strings.Premium_CopyProtectionInfo
|
||||
case .aiTools:
|
||||
text = "Transform your messages and entire chats in your preferred style and language."
|
||||
default:
|
||||
text = ""
|
||||
}
|
||||
|
|
@ -1309,6 +1331,8 @@ private final class DemoSheetContent: CombinedComponent {
|
|||
buttonText = strings.Premium_PaidMessages_Proceed
|
||||
case .copyProtection:
|
||||
buttonText = strings.Premium_PaidMessages_Proceed
|
||||
case .aiTools:
|
||||
buttonText = strings.Premium_PaidMessages_Proceed
|
||||
default:
|
||||
buttonText = strings.Common_OK
|
||||
}
|
||||
|
|
@ -1498,6 +1522,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
|
|||
case messageEffects
|
||||
case todo
|
||||
case copyProtection
|
||||
case aiTools
|
||||
|
||||
case businessLocation
|
||||
case businessHours
|
||||
|
|
@ -1560,6 +1585,8 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
|
|||
return .todo
|
||||
case .copyProtection:
|
||||
return .copyProtection
|
||||
case .aiTools:
|
||||
return .aiTools
|
||||
case .businessLocation:
|
||||
return .businessLocation
|
||||
case .businessHours:
|
||||
|
|
|
|||
|
|
@ -443,6 +443,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||
UIColor(rgb: 0x676bff),
|
||||
UIColor(rgb: 0x6172ff),
|
||||
UIColor(rgb: 0x5b79ff),
|
||||
UIColor(rgb: 0x5b79ff),
|
||||
UIColor(rgb: 0x4492ff),
|
||||
UIColor(rgb: 0x429bd5),
|
||||
UIColor(rgb: 0x41a6a5),
|
||||
|
|
|
|||
|
|
@ -323,6 +323,12 @@ public enum PremiumSource: Equatable {
|
|||
} else {
|
||||
return false
|
||||
}
|
||||
case .aiTools:
|
||||
if case .aiTools = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .auth(lhsPrice):
|
||||
if case let .auth(rhsPrice) = rhs, lhsPrice == rhsPrice {
|
||||
return true
|
||||
|
|
@ -384,6 +390,7 @@ public enum PremiumSource: Equatable {
|
|||
case messageEffects
|
||||
case todo
|
||||
case copyProtection
|
||||
case aiTools
|
||||
case auth(String)
|
||||
case premiumGift(TelegramMediaFile)
|
||||
|
||||
|
|
@ -483,6 +490,8 @@ public enum PremiumSource: Equatable {
|
|||
return "todo"
|
||||
case .copyProtection:
|
||||
return "pm_noforwards"
|
||||
case .aiTools:
|
||||
return "ai_compose"
|
||||
case .auth:
|
||||
return "auth"
|
||||
case .premiumGift:
|
||||
|
|
@ -517,6 +526,7 @@ public enum PremiumPerk: CaseIterable {
|
|||
case messageEffects
|
||||
case todo
|
||||
case copyProtection
|
||||
case aiTools
|
||||
|
||||
case businessLocation
|
||||
case businessHours
|
||||
|
|
@ -553,7 +563,8 @@ public enum PremiumPerk: CaseIterable {
|
|||
.business,
|
||||
.messageEffects,
|
||||
.todo,
|
||||
.copyProtection
|
||||
.copyProtection,
|
||||
.aiTools
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -631,6 +642,8 @@ public enum PremiumPerk: CaseIterable {
|
|||
return "todo"
|
||||
case .copyProtection:
|
||||
return "pm_noforwards"
|
||||
case .aiTools:
|
||||
return "ai_compose"
|
||||
case .business:
|
||||
return "business"
|
||||
case .businessLocation:
|
||||
|
|
@ -704,6 +717,8 @@ public enum PremiumPerk: CaseIterable {
|
|||
return strings.Premium_Todo
|
||||
case .copyProtection:
|
||||
return strings.Premium_CopyProtection
|
||||
case .aiTools:
|
||||
return strings.Premium_AiTools
|
||||
case .businessLocation:
|
||||
return strings.Business_Location
|
||||
case .businessHours:
|
||||
|
|
@ -775,6 +790,8 @@ public enum PremiumPerk: CaseIterable {
|
|||
return strings.Premium_TodoInfo
|
||||
case .copyProtection:
|
||||
return strings.Premium_CopyProtectionInfo
|
||||
case .aiTools:
|
||||
return strings.Premium_AiToolsInfo
|
||||
case .businessLocation:
|
||||
return strings.Business_LocationInfo
|
||||
case .businessHours:
|
||||
|
|
@ -846,6 +863,8 @@ public enum PremiumPerk: CaseIterable {
|
|||
return "Item List/Icons/Checkbox"
|
||||
case .copyProtection:
|
||||
return "Item List/Icons/NoForward"
|
||||
case .aiTools:
|
||||
return "Item List/Icons/AITools"
|
||||
case .businessLocation:
|
||||
return "Item List/Icons/Location"
|
||||
case .businessHours:
|
||||
|
|
@ -870,6 +889,7 @@ struct PremiumIntroConfiguration {
|
|||
static var defaultValue: PremiumIntroConfiguration {
|
||||
return PremiumIntroConfiguration(perks: [
|
||||
.stories,
|
||||
.aiTools,
|
||||
.moreUpload,
|
||||
.doubleLimits,
|
||||
.lastSeen,
|
||||
|
|
@ -932,6 +952,12 @@ struct PremiumIntroConfiguration {
|
|||
if perks.count < 4 {
|
||||
perks = PremiumIntroConfiguration.defaultValue.perks
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
if !perks.contains(.aiTools) {
|
||||
perks.insert(.aiTools, at: 1)
|
||||
}
|
||||
#endif
|
||||
|
||||
var businessPerks: [PremiumPerk] = []
|
||||
if let values = data["business_promo_order"] as? [String] {
|
||||
|
|
@ -1635,7 +1661,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||
|
||||
super.init()
|
||||
|
||||
self.newPerks = [PremiumPerk.copyProtection.identifier]
|
||||
self.newPerks = [PremiumPerk.aiTools.identifier, PremiumPerk.copyProtection.identifier]
|
||||
|
||||
let premiumIntroConfiguration: Signal<PremiumIntroConfiguration, NoError>
|
||||
let accountPeer: Signal<EnginePeer?, NoError>
|
||||
|
|
@ -1970,6 +1996,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||
UIColor(rgb: 0x676bff),
|
||||
UIColor(rgb: 0x6172ff),
|
||||
UIColor(rgb: 0x5b79ff),
|
||||
UIColor(rgb: 0x5b79ff),
|
||||
UIColor(rgb: 0x4492ff),
|
||||
UIColor(rgb: 0x429bd5),
|
||||
UIColor(rgb: 0x41a6a5),
|
||||
|
|
@ -2220,6 +2247,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
|||
demoSubject = .todo
|
||||
case .copyProtection:
|
||||
demoSubject = .copyProtection
|
||||
case .aiTools:
|
||||
demoSubject = .aiTools
|
||||
case .business:
|
||||
demoSubject = .business
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -884,6 +884,26 @@ public class PremiumLimitsListScreen: ViewController {
|
|||
)
|
||||
)
|
||||
|
||||
availableItems[.aiTools] = DemoPagerComponent.Item(
|
||||
AnyComponentWithIdentity(
|
||||
id: PremiumDemoScreen.Subject.aiTools,
|
||||
component: AnyComponent(
|
||||
PageComponent(
|
||||
content: AnyComponent(PhoneDemoComponent(
|
||||
context: context,
|
||||
position: .top,
|
||||
model: .island,
|
||||
videoFile: videos["ai_compose"],
|
||||
decoration: .badgeStars
|
||||
)),
|
||||
title: strings.Premium_AiTools,
|
||||
text: strings.Premium_AiToolsInfo,
|
||||
textColor: textColor
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
availableItems[.business] = DemoPagerComponent.Item(
|
||||
AnyComponentWithIdentity(
|
||||
id: PremiumDemoScreen.Subject.business,
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-207944868] = { return Api.FileHash.parse_fileHash($0) }
|
||||
dict[-11252123] = { return Api.Folder.parse_folder($0) }
|
||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||
dict[-838922550] = { return Api.ForumTopic.parse_forumTopic($0) }
|
||||
dict[-52766699] = { return Api.ForumTopic.parse_forumTopic($0) }
|
||||
dict[37687451] = { return Api.ForumTopic.parse_forumTopicDeleted($0) }
|
||||
dict[-394605632] = { return Api.FoundStory.parse_foundStory($0) }
|
||||
dict[-1107729093] = { return Api.Game.parse_game($0) }
|
||||
|
|
@ -623,6 +623,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($0) }
|
||||
dict[-1799538451] = { return Api.MessageAction.parse_messageActionPinMessage($0) }
|
||||
dict[-1650340500] = { return Api.MessageAction.parse_messageActionPollAppendAnswer($0) }
|
||||
dict[966161628] = { return Api.MessageAction.parse_messageActionPollDeleteAnswer($0) }
|
||||
dict[-1341372510] = { return Api.MessageAction.parse_messageActionPrizeStars($0) }
|
||||
dict[827428507] = { return Api.MessageAction.parse_messageActionRequestedPeer($0) }
|
||||
dict[-1816979384] = { return Api.MessageAction.parse_messageActionRequestedPeerSentMe($0) }
|
||||
|
|
@ -1174,7 +1175,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-710666460] = { return Api.Update.parse_updateMessageExtendedMedia($0) }
|
||||
dict[1318109142] = { return Api.Update.parse_updateMessageID($0) }
|
||||
dict[-699641301] = { return Api.Update.parse_updateMessagePoll($0) }
|
||||
dict[619974263] = { return Api.Update.parse_updateMessagePollVote($0) }
|
||||
dict[1989799956] = { return Api.Update.parse_updateMessagePollVote($0) }
|
||||
dict[506035194] = { return Api.Update.parse_updateMessageReactions($0) }
|
||||
dict[-1618924792] = { return Api.Update.parse_updateMonoForumNoPaidException($0) }
|
||||
dict[-2030252155] = { return Api.Update.parse_updateMoveStickerSetToTop($0) }
|
||||
|
|
@ -1258,7 +1259,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-484987010] = { return Api.Updates.parse_updatesTooLong($0) }
|
||||
dict[1648005024] = { return Api.UrlAuthResult.parse_urlAuthResultAccepted($0) }
|
||||
dict[-1445536993] = { return Api.UrlAuthResult.parse_urlAuthResultDefault($0) }
|
||||
dict[-117904610] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
|
||||
dict[1020666860] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
|
||||
dict[829899656] = { return Api.User.parse_user($0) }
|
||||
dict[-742634630] = { return Api.User.parse_userEmpty($0) }
|
||||
dict[114026053] = { return Api.UserFull.parse_userFull($0) }
|
||||
|
|
|
|||
|
|
@ -2080,6 +2080,15 @@ public extension Api {
|
|||
return ("messageActionPollAppendAnswer", [("answer", self.answer as Any)])
|
||||
}
|
||||
}
|
||||
public class Cons_messageActionPollDeleteAnswer: TypeConstructorDescription {
|
||||
public var answer: Api.PollAnswer
|
||||
public init(answer: Api.PollAnswer) {
|
||||
self.answer = answer
|
||||
}
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
return ("messageActionPollDeleteAnswer", [("answer", self.answer as Any)])
|
||||
}
|
||||
}
|
||||
public class Cons_messageActionPrizeStars: TypeConstructorDescription {
|
||||
public var flags: Int32
|
||||
public var stars: Int64
|
||||
|
|
@ -2429,6 +2438,7 @@ public extension Api {
|
|||
case messageActionPhoneCall(Cons_messageActionPhoneCall)
|
||||
case messageActionPinMessage
|
||||
case messageActionPollAppendAnswer(Cons_messageActionPollAppendAnswer)
|
||||
case messageActionPollDeleteAnswer(Cons_messageActionPollDeleteAnswer)
|
||||
case messageActionPrizeStars(Cons_messageActionPrizeStars)
|
||||
case messageActionRequestedPeer(Cons_messageActionRequestedPeer)
|
||||
case messageActionRequestedPeerSentMe(Cons_messageActionRequestedPeerSentMe)
|
||||
|
|
@ -2838,6 +2848,12 @@ public extension Api {
|
|||
}
|
||||
_data.answer.serialize(buffer, true)
|
||||
break
|
||||
case .messageActionPollDeleteAnswer(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(966161628)
|
||||
}
|
||||
_data.answer.serialize(buffer, true)
|
||||
break
|
||||
case .messageActionPrizeStars(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1341372510)
|
||||
|
|
@ -3208,6 +3224,8 @@ public extension Api {
|
|||
return ("messageActionPinMessage", [])
|
||||
case .messageActionPollAppendAnswer(let _data):
|
||||
return ("messageActionPollAppendAnswer", [("answer", _data.answer as Any)])
|
||||
case .messageActionPollDeleteAnswer(let _data):
|
||||
return ("messageActionPollDeleteAnswer", [("answer", _data.answer as Any)])
|
||||
case .messageActionPrizeStars(let _data):
|
||||
return ("messageActionPrizeStars", [("flags", _data.flags as Any), ("stars", _data.stars as Any), ("transactionId", _data.transactionId as Any), ("boostPeer", _data.boostPeer as Any), ("giveawayMsgId", _data.giveawayMsgId as Any)])
|
||||
case .messageActionRequestedPeer(let _data):
|
||||
|
|
@ -3973,6 +3991,19 @@ public extension Api {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_messageActionPollDeleteAnswer(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: Api.PollAnswer?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.PollAnswer
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.MessageAction.messageActionPollDeleteAnswer(Cons_messageActionPollDeleteAnswer(answer: _1!))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_messageActionPrizeStars(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
|
|
|
|||
|
|
@ -1690,15 +1690,17 @@ public extension Api {
|
|||
public var pollId: Int64
|
||||
public var peer: Api.Peer
|
||||
public var options: [Buffer]
|
||||
public var positions: [Int32]
|
||||
public var qts: Int32
|
||||
public init(pollId: Int64, peer: Api.Peer, options: [Buffer], qts: Int32) {
|
||||
public init(pollId: Int64, peer: Api.Peer, options: [Buffer], positions: [Int32], qts: Int32) {
|
||||
self.pollId = pollId
|
||||
self.peer = peer
|
||||
self.options = options
|
||||
self.positions = positions
|
||||
self.qts = qts
|
||||
}
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
return ("updateMessagePollVote", [("pollId", self.pollId as Any), ("peer", self.peer as Any), ("options", self.options as Any), ("qts", self.qts as Any)])
|
||||
return ("updateMessagePollVote", [("pollId", self.pollId as Any), ("peer", self.peer as Any), ("options", self.options as Any), ("positions", self.positions as Any), ("qts", self.qts as Any)])
|
||||
}
|
||||
}
|
||||
public class Cons_updateMessageReactions: TypeConstructorDescription {
|
||||
|
|
@ -3440,7 +3442,7 @@ public extension Api {
|
|||
break
|
||||
case .updateMessagePollVote(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(619974263)
|
||||
buffer.appendInt32(1989799956)
|
||||
}
|
||||
serializeInt64(_data.pollId, buffer: buffer, boxed: false)
|
||||
_data.peer.serialize(buffer, true)
|
||||
|
|
@ -3449,6 +3451,11 @@ public extension Api {
|
|||
for item in _data.options {
|
||||
serializeBytes(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(_data.positions.count))
|
||||
for item in _data.positions {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
serializeInt32(_data.qts, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updateMessageReactions(let _data):
|
||||
|
|
@ -4245,7 +4252,7 @@ public extension Api {
|
|||
case .updateMessagePoll(let _data):
|
||||
return ("updateMessagePoll", [("flags", _data.flags as Any), ("peer", _data.peer as Any), ("msgId", _data.msgId as Any), ("topMsgId", _data.topMsgId as Any), ("pollId", _data.pollId as Any), ("poll", _data.poll as Any), ("results", _data.results as Any)])
|
||||
case .updateMessagePollVote(let _data):
|
||||
return ("updateMessagePollVote", [("pollId", _data.pollId as Any), ("peer", _data.peer as Any), ("options", _data.options as Any), ("qts", _data.qts as Any)])
|
||||
return ("updateMessagePollVote", [("pollId", _data.pollId as Any), ("peer", _data.peer as Any), ("options", _data.options as Any), ("positions", _data.positions as Any), ("qts", _data.qts as Any)])
|
||||
case .updateMessageReactions(let _data):
|
||||
return ("updateMessageReactions", [("flags", _data.flags as Any), ("peer", _data.peer as Any), ("msgId", _data.msgId as Any), ("topMsgId", _data.topMsgId as Any), ("savedPeerId", _data.savedPeerId as Any), ("reactions", _data.reactions as Any)])
|
||||
case .updateMonoForumNoPaidException(let _data):
|
||||
|
|
@ -6022,14 +6029,19 @@ public extension Api {
|
|||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self)
|
||||
}
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _4: [Int32]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
|
||||
}
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.Update.updateMessagePollVote(Cons_updateMessagePollVote(pollId: _1!, peer: _2!, options: _3!, qts: _4!))
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.Update.updateMessagePollVote(Cons_updateMessagePollVote(pollId: _1!, peer: _2!, options: _3!, positions: _4!, qts: _5!))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -579,7 +579,8 @@ public extension Api {
|
|||
public var region: String?
|
||||
public var matchCodes: [String]?
|
||||
public var userIdHint: Int64?
|
||||
public init(flags: Int32, bot: Api.User, domain: String, browser: String?, platform: String?, ip: String?, region: String?, matchCodes: [String]?, userIdHint: Int64?) {
|
||||
public var verifiedAppName: String?
|
||||
public init(flags: Int32, bot: Api.User, domain: String, browser: String?, platform: String?, ip: String?, region: String?, matchCodes: [String]?, userIdHint: Int64?, verifiedAppName: String?) {
|
||||
self.flags = flags
|
||||
self.bot = bot
|
||||
self.domain = domain
|
||||
|
|
@ -589,9 +590,10 @@ public extension Api {
|
|||
self.region = region
|
||||
self.matchCodes = matchCodes
|
||||
self.userIdHint = userIdHint
|
||||
self.verifiedAppName = verifiedAppName
|
||||
}
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
return ("urlAuthResultRequest", [("flags", self.flags as Any), ("bot", self.bot as Any), ("domain", self.domain as Any), ("browser", self.browser as Any), ("platform", self.platform as Any), ("ip", self.ip as Any), ("region", self.region as Any), ("matchCodes", self.matchCodes as Any), ("userIdHint", self.userIdHint as Any)])
|
||||
return ("urlAuthResultRequest", [("flags", self.flags as Any), ("bot", self.bot as Any), ("domain", self.domain as Any), ("browser", self.browser as Any), ("platform", self.platform as Any), ("ip", self.ip as Any), ("region", self.region as Any), ("matchCodes", self.matchCodes as Any), ("userIdHint", self.userIdHint as Any), ("verifiedAppName", self.verifiedAppName as Any)])
|
||||
}
|
||||
}
|
||||
case urlAuthResultAccepted(Cons_urlAuthResultAccepted)
|
||||
|
|
@ -616,7 +618,7 @@ public extension Api {
|
|||
break
|
||||
case .urlAuthResultRequest(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-117904610)
|
||||
buffer.appendInt32(1020666860)
|
||||
}
|
||||
serializeInt32(_data.flags, buffer: buffer, boxed: false)
|
||||
_data.bot.serialize(buffer, true)
|
||||
|
|
@ -643,6 +645,9 @@ public extension Api {
|
|||
if Int(_data.flags) & Int(1 << 4) != 0 {
|
||||
serializeInt64(_data.userIdHint!, buffer: buffer, boxed: false)
|
||||
}
|
||||
if Int(_data.flags) & Int(1 << 7) != 0 {
|
||||
serializeString(_data.verifiedAppName!, buffer: buffer, boxed: false)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -654,7 +659,7 @@ public extension Api {
|
|||
case .urlAuthResultDefault:
|
||||
return ("urlAuthResultDefault", [])
|
||||
case .urlAuthResultRequest(let _data):
|
||||
return ("urlAuthResultRequest", [("flags", _data.flags as Any), ("bot", _data.bot as Any), ("domain", _data.domain as Any), ("browser", _data.browser as Any), ("platform", _data.platform as Any), ("ip", _data.ip as Any), ("region", _data.region as Any), ("matchCodes", _data.matchCodes as Any), ("userIdHint", _data.userIdHint as Any)])
|
||||
return ("urlAuthResultRequest", [("flags", _data.flags as Any), ("bot", _data.bot as Any), ("domain", _data.domain as Any), ("browser", _data.browser as Any), ("platform", _data.platform as Any), ("ip", _data.ip as Any), ("region", _data.region as Any), ("matchCodes", _data.matchCodes as Any), ("userIdHint", _data.userIdHint as Any), ("verifiedAppName", _data.verifiedAppName as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -712,6 +717,10 @@ public extension Api {
|
|||
if Int(_1!) & Int(1 << 4) != 0 {
|
||||
_9 = reader.readInt64()
|
||||
}
|
||||
var _10: String?
|
||||
if Int(_1!) & Int(1 << 7) != 0 {
|
||||
_10 = parseString(reader)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
|
|
@ -721,8 +730,9 @@ public extension Api {
|
|||
let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 4) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.UrlAuthResult.urlAuthResultRequest(Cons_urlAuthResultRequest(flags: _1!, bot: _2!, domain: _3!, browser: _4, platform: _5, ip: _6, region: _7, matchCodes: _8, userIdHint: _9))
|
||||
let _c10 = (Int(_1!) & Int(1 << 7) == 0) || _10 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
||||
return Api.UrlAuthResult.urlAuthResultRequest(Cons_urlAuthResultRequest(flags: _1!, bot: _2!, domain: _3!, browser: _4, platform: _5, ip: _6, region: _7, matchCodes: _8, userIdHint: _9, verifiedAppName: _10))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1141,10 +1141,11 @@ public extension Api {
|
|||
public var unreadCount: Int32
|
||||
public var unreadMentionsCount: Int32
|
||||
public var unreadReactionsCount: Int32
|
||||
public var unreadPollVotesCount: Int32
|
||||
public var fromId: Api.Peer
|
||||
public var notifySettings: Api.PeerNotifySettings
|
||||
public var draft: Api.DraftMessage?
|
||||
public init(flags: Int32, id: Int32, date: Int32, peer: Api.Peer, title: String, iconColor: Int32, iconEmojiId: Int64?, topMessage: Int32, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, unreadMentionsCount: Int32, unreadReactionsCount: Int32, fromId: Api.Peer, notifySettings: Api.PeerNotifySettings, draft: Api.DraftMessage?) {
|
||||
public init(flags: Int32, id: Int32, date: Int32, peer: Api.Peer, title: String, iconColor: Int32, iconEmojiId: Int64?, topMessage: Int32, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, unreadMentionsCount: Int32, unreadReactionsCount: Int32, unreadPollVotesCount: Int32, fromId: Api.Peer, notifySettings: Api.PeerNotifySettings, draft: Api.DraftMessage?) {
|
||||
self.flags = flags
|
||||
self.id = id
|
||||
self.date = date
|
||||
|
|
@ -1158,12 +1159,13 @@ public extension Api {
|
|||
self.unreadCount = unreadCount
|
||||
self.unreadMentionsCount = unreadMentionsCount
|
||||
self.unreadReactionsCount = unreadReactionsCount
|
||||
self.unreadPollVotesCount = unreadPollVotesCount
|
||||
self.fromId = fromId
|
||||
self.notifySettings = notifySettings
|
||||
self.draft = draft
|
||||
}
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
return ("forumTopic", [("flags", self.flags as Any), ("id", self.id as Any), ("date", self.date as Any), ("peer", self.peer as Any), ("title", self.title as Any), ("iconColor", self.iconColor as Any), ("iconEmojiId", self.iconEmojiId as Any), ("topMessage", self.topMessage as Any), ("readInboxMaxId", self.readInboxMaxId as Any), ("readOutboxMaxId", self.readOutboxMaxId as Any), ("unreadCount", self.unreadCount as Any), ("unreadMentionsCount", self.unreadMentionsCount as Any), ("unreadReactionsCount", self.unreadReactionsCount as Any), ("fromId", self.fromId as Any), ("notifySettings", self.notifySettings as Any), ("draft", self.draft as Any)])
|
||||
return ("forumTopic", [("flags", self.flags as Any), ("id", self.id as Any), ("date", self.date as Any), ("peer", self.peer as Any), ("title", self.title as Any), ("iconColor", self.iconColor as Any), ("iconEmojiId", self.iconEmojiId as Any), ("topMessage", self.topMessage as Any), ("readInboxMaxId", self.readInboxMaxId as Any), ("readOutboxMaxId", self.readOutboxMaxId as Any), ("unreadCount", self.unreadCount as Any), ("unreadMentionsCount", self.unreadMentionsCount as Any), ("unreadReactionsCount", self.unreadReactionsCount as Any), ("unreadPollVotesCount", self.unreadPollVotesCount as Any), ("fromId", self.fromId as Any), ("notifySettings", self.notifySettings as Any), ("draft", self.draft as Any)])
|
||||
}
|
||||
}
|
||||
public class Cons_forumTopicDeleted: TypeConstructorDescription {
|
||||
|
|
@ -1182,7 +1184,7 @@ public extension Api {
|
|||
switch self {
|
||||
case .forumTopic(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-838922550)
|
||||
buffer.appendInt32(-52766699)
|
||||
}
|
||||
serializeInt32(_data.flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(_data.id, buffer: buffer, boxed: false)
|
||||
|
|
@ -1199,6 +1201,7 @@ public extension Api {
|
|||
serializeInt32(_data.unreadCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(_data.unreadMentionsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(_data.unreadReactionsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(_data.unreadPollVotesCount, buffer: buffer, boxed: false)
|
||||
_data.fromId.serialize(buffer, true)
|
||||
_data.notifySettings.serialize(buffer, true)
|
||||
if Int(_data.flags) & Int(1 << 4) != 0 {
|
||||
|
|
@ -1217,7 +1220,7 @@ public extension Api {
|
|||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .forumTopic(let _data):
|
||||
return ("forumTopic", [("flags", _data.flags as Any), ("id", _data.id as Any), ("date", _data.date as Any), ("peer", _data.peer as Any), ("title", _data.title as Any), ("iconColor", _data.iconColor as Any), ("iconEmojiId", _data.iconEmojiId as Any), ("topMessage", _data.topMessage as Any), ("readInboxMaxId", _data.readInboxMaxId as Any), ("readOutboxMaxId", _data.readOutboxMaxId as Any), ("unreadCount", _data.unreadCount as Any), ("unreadMentionsCount", _data.unreadMentionsCount as Any), ("unreadReactionsCount", _data.unreadReactionsCount as Any), ("fromId", _data.fromId as Any), ("notifySettings", _data.notifySettings as Any), ("draft", _data.draft as Any)])
|
||||
return ("forumTopic", [("flags", _data.flags as Any), ("id", _data.id as Any), ("date", _data.date as Any), ("peer", _data.peer as Any), ("title", _data.title as Any), ("iconColor", _data.iconColor as Any), ("iconEmojiId", _data.iconEmojiId as Any), ("topMessage", _data.topMessage as Any), ("readInboxMaxId", _data.readInboxMaxId as Any), ("readOutboxMaxId", _data.readOutboxMaxId as Any), ("unreadCount", _data.unreadCount as Any), ("unreadMentionsCount", _data.unreadMentionsCount as Any), ("unreadReactionsCount", _data.unreadReactionsCount as Any), ("unreadPollVotesCount", _data.unreadPollVotesCount as Any), ("fromId", _data.fromId as Any), ("notifySettings", _data.notifySettings as Any), ("draft", _data.draft as Any)])
|
||||
case .forumTopicDeleted(let _data):
|
||||
return ("forumTopicDeleted", [("id", _data.id as Any)])
|
||||
}
|
||||
|
|
@ -1254,18 +1257,20 @@ public extension Api {
|
|||
_12 = reader.readInt32()
|
||||
var _13: Int32?
|
||||
_13 = reader.readInt32()
|
||||
var _14: Api.Peer?
|
||||
var _14: Int32?
|
||||
_14 = reader.readInt32()
|
||||
var _15: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
_14 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
_15 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _15: Api.PeerNotifySettings?
|
||||
var _16: Api.PeerNotifySettings?
|
||||
if let signature = reader.readInt32() {
|
||||
_15 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
|
||||
_16 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
|
||||
}
|
||||
var _16: Api.DraftMessage?
|
||||
var _17: Api.DraftMessage?
|
||||
if Int(_1!) & Int(1 << 4) != 0 {
|
||||
if let signature = reader.readInt32() {
|
||||
_16 = Api.parse(reader, signature: signature) as? Api.DraftMessage
|
||||
_17 = Api.parse(reader, signature: signature) as? Api.DraftMessage
|
||||
}
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
|
|
@ -1283,9 +1288,10 @@ public extension Api {
|
|||
let _c13 = _13 != nil
|
||||
let _c14 = _14 != nil
|
||||
let _c15 = _15 != nil
|
||||
let _c16 = (Int(_1!) & Int(1 << 4) == 0) || _16 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 {
|
||||
return Api.ForumTopic.forumTopic(Cons_forumTopic(flags: _1!, id: _2!, date: _3!, peer: _4!, title: _5!, iconColor: _6!, iconEmojiId: _7, topMessage: _8!, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, unreadMentionsCount: _12!, unreadReactionsCount: _13!, fromId: _14!, notifySettings: _15!, draft: _16))
|
||||
let _c16 = _16 != nil
|
||||
let _c17 = (Int(_1!) & Int(1 << 4) == 0) || _17 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
|
||||
return Api.ForumTopic.forumTopic(Cons_forumTopic(flags: _1!, id: _2!, date: _3!, peer: _4!, title: _5!, iconColor: _6!, iconEmojiId: _7, topMessage: _8!, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, unreadMentionsCount: _12!, unreadReactionsCount: _13!, unreadPollVotesCount: _14!, fromId: _15!, notifySettings: _16!, draft: _17))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||
}
|
||||
|
||||
switch action {
|
||||
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday, .messageActionStarGiftPurchaseOffer, .messageActionStarGiftPurchaseOfferDeclined, .messageActionNoForwardsToggle, .messageActionNoForwardsRequest, .messageActionPollAppendAnswer:
|
||||
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday, .messageActionStarGiftPurchaseOffer, .messageActionStarGiftPurchaseOfferDeclined, .messageActionNoForwardsToggle, .messageActionNoForwardsRequest, .messageActionPollAppendAnswer, .messageActionPollDeleteAnswer:
|
||||
break
|
||||
case let .messageActionManagedBotCreated(messageActionManagedBotCreated):
|
||||
let botId = messageActionManagedBotCreated.botId
|
||||
|
|
|
|||
|
|
@ -367,6 +367,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||
return TelegramMediaAction(action: .managedBotCreated(botId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionManagedBotCreatedData.botId))))
|
||||
case let .messageActionPollAppendAnswer(messageActionPollAppendAnswerData):
|
||||
return TelegramMediaAction(action: .pollOptionAppended(TelegramMediaPollOption(apiOption: messageActionPollAppendAnswerData.answer)))
|
||||
case let .messageActionPollDeleteAnswer(messageActionPollDeleteAnswerData):
|
||||
return TelegramMediaAction(action: .pollOptionDeleted(TelegramMediaPollOption(apiOption: messageActionPollDeleteAnswerData.answer)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -306,6 +306,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
case copyProtectionRequest(hasExpired: Bool, previousValue: Bool, newValue: Bool)
|
||||
case managedBotCreated(botId: PeerId)
|
||||
case pollOptionAppended(TelegramMediaPollOption)
|
||||
case pollOptionDeleted(TelegramMediaPollOption)
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||
|
|
@ -487,6 +488,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
self = .managedBotCreated(botId: PeerId(decoder.decodeInt64ForKey("botId", orElse: 0)))
|
||||
case 63:
|
||||
self = .pollOptionAppended(decoder.decodeObjectForKey("option", decoder: { TelegramMediaPollOption(decoder: $0) }) as! TelegramMediaPollOption)
|
||||
case 64:
|
||||
self = .pollOptionDeleted(decoder.decodeObjectForKey("option", decoder: { TelegramMediaPollOption(decoder: $0) }) as! TelegramMediaPollOption)
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
|
|
@ -996,6 +999,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
case let .pollOptionAppended(option):
|
||||
encoder.encodeInt32(63, forKey: "_rawValue")
|
||||
encoder.encodeObject(option, forKey: "option")
|
||||
case let .pollOptionDeleted(option):
|
||||
encoder.encodeInt32(64, forKey: "_rawValue")
|
||||
encoder.encodeObject(option, forKey: "option")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ public func stringForMediaKind(_ kind: MessageContentKind, strings: Presentation
|
|||
|
||||
public func descriptionStringForMessage(contentSettings: ContentSettings, message: EngineMessage, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id) -> (NSAttributedString, Bool, Bool) {
|
||||
let contentKind = messageContentKind(contentSettings: contentSettings, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId)
|
||||
if !message.text.isEmpty && ![.expiredImage, .expiredVideo].contains(contentKind.key) {
|
||||
if !message.text.isEmpty && ![.expiredImage, .expiredVideo, .poll].contains(contentKind.key) {
|
||||
return (foldLineBreaks(messageTextWithAttributes(message: message)), false, true)
|
||||
}
|
||||
let result = stringForMediaKind(contentKind, strings: strings)
|
||||
|
|
|
|||
|
|
@ -1822,19 +1822,6 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ManagedBotCreated(peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)
|
||||
case let .pollOptionAppended(option):
|
||||
var optionTitle = "DELETED"
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute, let message = message.associatedMessages[attribute.messageId] {
|
||||
for media in message.media {
|
||||
if let todo = media as? TelegramMediaTodo {
|
||||
optionTitle = todo.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if optionTitle.count > 20 {
|
||||
optionTitle = optionTitle.prefix(20) + "…"
|
||||
}
|
||||
let optionEntities = option.entities.filter { entity in
|
||||
switch entity.type {
|
||||
case .Spoiler, .CustomEmoji:
|
||||
|
|
@ -1872,6 +1859,44 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||
}
|
||||
attributedString = resultAttributedString
|
||||
}
|
||||
case let .pollOptionDeleted(option):
|
||||
let optionEntities = option.entities.filter { entity in
|
||||
switch entity.type {
|
||||
case .Spoiler, .CustomEmoji:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
if message.author?.id == accountPeerId {
|
||||
var optionText = option.text
|
||||
if optionText.count > 20 {
|
||||
optionText = optionText.prefix(20) + "…"
|
||||
}
|
||||
let resultString = strings.Notification_PollDeletedOptionYou(optionText)
|
||||
let stringWithRanges = resultString._tuple
|
||||
let resultAttributedString = NSMutableAttributedString(attributedString: addAttributesToStringWithRanges(stringWithRanges, body: bodyAttributes, argumentAttributes: [0: boldAttributes, 1: boldAttributes]))
|
||||
if let optionRange = serviceMessageArgumentRange(index: 0, value: optionText, in: stringWithRanges) {
|
||||
addServiceMessageTextEntities(optionEntities, to: resultAttributedString, text: optionText, range: optionRange, associatedMedia: message.associatedMedia)
|
||||
}
|
||||
attributedString = resultAttributedString
|
||||
} else {
|
||||
let peerName = message.author?.compactDisplayTitle ?? ""
|
||||
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])
|
||||
attributes[1] = boldAttributes
|
||||
|
||||
var optionText = option.text
|
||||
if optionText.count > 20 {
|
||||
optionText = optionText.prefix(20) + "…"
|
||||
}
|
||||
let resultString = strings.Notification_PollDeletedOption(peerName, optionText)
|
||||
let stringWithRanges = resultString._tuple
|
||||
let resultAttributedString = NSMutableAttributedString(attributedString: addAttributesToStringWithRanges(stringWithRanges, body: bodyAttributes, argumentAttributes: attributes))
|
||||
if let optionRange = serviceMessageArgumentRange(index: 1, value: optionText, in: stringWithRanges) {
|
||||
addServiceMessageTextEntities(optionEntities, to: resultAttributedString, text: optionText, range: optionRange, associatedMedia: message.associatedMedia)
|
||||
}
|
||||
attributedString = resultAttributedString
|
||||
}
|
||||
case .unknown:
|
||||
attributedString = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
|
|||
var index: Int32 = 0
|
||||
|
||||
if let savedMusic, !savedMusic.isEmpty {
|
||||
entries.append(.header(title: "SAVED MUSIC", section: section))
|
||||
entries.append(.header(title: "PROFILE MUSIC", section: section))
|
||||
|
||||
var savedMusic = savedMusic
|
||||
var hasShowMore = false
|
||||
|
|
@ -652,7 +652,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
|
|||
section += 1
|
||||
|
||||
if !messages.isEmpty {
|
||||
entries.append(.header(title: "SHARED AUDIO", section: section))
|
||||
entries.append(.header(title: "YOUR CHATS", section: section))
|
||||
var messages = messages
|
||||
var hasShowMore = false
|
||||
if messages.count > 4 && !expandedSections.contains(section) {
|
||||
|
|
@ -672,7 +672,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
|
|||
index = 0
|
||||
section += 1
|
||||
|
||||
entries.append(.header(title: "GLOBAL SEARCH", section: section))
|
||||
entries.append(.header(title: "PUBLIC CHATS", section: section))
|
||||
for message in globalMusic {
|
||||
entries.append(.file(index: index, message: message, section: section))
|
||||
index += 1
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ private extension ListMessageItemInteraction {
|
|||
return controllerInteraction.openMessage(message, OpenMessageParams(mode: mode))
|
||||
}, openMessageContextMenu: { message, bool, node, rect, gesture in
|
||||
controllerInteraction.openMessageContextMenu(message, bool, node, rect, gesture, nil)
|
||||
}, toggleMediaPlayback: { _ in
|
||||
}, toggleMessagesSelection: { messageId, selected in
|
||||
}, toggleMediaPlayback: nil, toggleMessagesSelection: { messageId, selected in
|
||||
controllerInteraction.toggleMessagesSelection(messageId, selected)
|
||||
}, openUrl: { url, param1, param2, message in
|
||||
controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: param1, external: param2, message: message))
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ swift_library(
|
|||
],
|
||||
deps = [
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/Crc32",
|
||||
"//submodules/Display",
|
||||
"//submodules/TelegramCore",
|
||||
"//submodules/Postbox",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Crc32
|
||||
import Display
|
||||
import TelegramCore
|
||||
import Postbox
|
||||
|
|
@ -3654,11 +3655,6 @@ public class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
private struct ArbitraryRandomNumberGenerator : RandomNumberGenerator {
|
||||
init(seed: Int) { srand48(seed) }
|
||||
func next() -> UInt64 { return UInt64(drand48() * Double(UInt64.max)) }
|
||||
}
|
||||
|
||||
private func stringForRemainingTime(_ duration: Int32, strings: PresentationStrings, results: Bool) -> String {
|
||||
let days = duration / (3600 * 24)
|
||||
let hours = duration / 3600
|
||||
|
|
@ -3739,26 +3735,31 @@ private func resolvedOptionOrder(for item: ChatMessageBubbleContentItem) -> [(In
|
|||
return defaultOrderedOptions
|
||||
}
|
||||
|
||||
let currentOpaqueIdentifiers = poll.options.map(\.opaqueIdentifier)
|
||||
let messageSeed = UInt64(bitPattern: Int64(item.message.stableId))
|
||||
let peerSeed = UInt64(bitPattern: item.context.account.peerId.toInt64())
|
||||
let seed = Int(truncatingIfNeeded: (messageSeed &* 6364136223846793005) ^ peerSeed)
|
||||
let userId = item.context.account.peerId.id._internalGetInt64Value()
|
||||
let pollId = poll.pollId.id
|
||||
|
||||
var resolvedOpaqueIdentifiers = currentOpaqueIdentifiers
|
||||
var randomNumberGenerator = ArbitraryRandomNumberGenerator(seed: seed)
|
||||
resolvedOpaqueIdentifiers.shuffle(using: &randomNumberGenerator)
|
||||
return defaultOrderedOptions
|
||||
.map { index, option in
|
||||
var hashValue = Data()
|
||||
hashValue.append(contentsOf: String(userId).utf8)
|
||||
hashValue.append(option.opaqueIdentifier)
|
||||
hashValue.append(contentsOf: String(pollId).utf8)
|
||||
|
||||
let indicesByOpaqueIdentifier = Dictionary(uniqueKeysWithValues: poll.options.enumerated().map { ($0.element.opaqueIdentifier, $0.offset) })
|
||||
let orderedOptions = resolvedOpaqueIdentifiers.compactMap { opaqueIdentifier -> (Int, TelegramMediaPollOption)? in
|
||||
guard let index = indicesByOpaqueIdentifier[opaqueIdentifier] else {
|
||||
return nil
|
||||
let sortValue: UInt32 = hashValue.withUnsafeBytes { bytes in
|
||||
guard let baseAddress = bytes.baseAddress else {
|
||||
return 0
|
||||
}
|
||||
return Crc32(baseAddress, Int32(bytes.count))
|
||||
}
|
||||
|
||||
return (index, option, sortValue)
|
||||
}
|
||||
return (index, poll.options[index])
|
||||
}
|
||||
|
||||
if orderedOptions.count == poll.options.count {
|
||||
return orderedOptions
|
||||
} else {
|
||||
return defaultOrderedOptions
|
||||
}
|
||||
.sorted(by: { lhs, rhs in
|
||||
if lhs.2 != rhs.2 {
|
||||
return lhs.2 < rhs.2
|
||||
} else {
|
||||
return lhs.0 < rhs.0
|
||||
}
|
||||
})
|
||||
.map { ($0.0, $0.1) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3239,7 +3239,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||
var hasDescriptionButton = false
|
||||
if let uniqueGift {
|
||||
titleString = uniqueGift.title + " **#\(formatCollectibleNumber(uniqueGift.number, dateTimeFormat: environment.dateTimeFormat))**"
|
||||
descriptionText = "\(strings.Gift_Unique_Collectible) #\(formatCollectibleNumber(uniqueGift.number, dateTimeFormat: environment.dateTimeFormat))"
|
||||
descriptionText = "\(strings.Gift_Unique_Collectible)"
|
||||
for attribute in uniqueGift.attributes {
|
||||
if case let .model(name, _, _, _) = attribute {
|
||||
descriptionText = name
|
||||
|
|
@ -3520,7 +3520,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||
}
|
||||
|
||||
var descriptionSize = CGSize()
|
||||
if state.justUpgraded {
|
||||
if !"".isEmpty, state.justUpgraded {
|
||||
var items: [AnyComponentWithIdentity<Empty>] = [
|
||||
AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: "\(strings.Gift_Unique_Collectible) #", font: textFont, color: .white, tintColor: textColor)))
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1103,9 +1103,13 @@ public final class ListComposePollOptionComponent: Component {
|
|||
|
||||
let cornerRadius: CGFloat = 10.0
|
||||
let makeLayout = imageNode.asyncLayout()
|
||||
let apply = makeLayout(TransformImageArguments(corners: ImageCorners(radius: cornerRadius), imageSize: imageSize, boundingSize: imageNodeSize, intrinsicInsets: UIEdgeInsets(), emptyColor: component.theme.list.mediaPlaceholderColor))
|
||||
apply()
|
||||
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
let apply = makeLayout(TransformImageArguments(corners: ImageCorners(radius: cornerRadius), imageSize: imageSize, boundingSize: imageNodeSize, intrinsicInsets: UIEdgeInsets(), emptyColor: component.theme.list.mediaPlaceholderColor))
|
||||
Queue.mainQueue().async {
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
if self.imageButton.superview == nil {
|
||||
self.imageButton.addTarget(self, action: #selector(self.imageButtonPressed), for: .touchUpInside)
|
||||
self.addSubview(self.imageButton)
|
||||
|
|
|
|||
12
submodules/TelegramUI/Images.xcassets/Item List/Icons/AITools.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Item List/Icons/AITools.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ai.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
submodules/TelegramUI/Images.xcassets/Item List/Icons/AITools.imageset/ai.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Item List/Icons/AITools.imageset/ai.pdf
vendored
Normal file
Binary file not shown.
|
|
@ -202,8 +202,7 @@ extension ListMessageItemInteraction {
|
|||
return controllerInteraction.openMessage(message, OpenMessageParams(mode: mode))
|
||||
}, openMessageContextMenu: { message, bool, node, rect, gesture in
|
||||
controllerInteraction.openMessageContextMenu(message, bool, node, rect, gesture, nil)
|
||||
}, toggleMediaPlayback: { _ in
|
||||
}, toggleMessagesSelection: { messageId, selected in
|
||||
}, toggleMediaPlayback: nil, toggleMessagesSelection: { messageId, selected in
|
||||
controllerInteraction.toggleMessagesSelection(messageId, selected)
|
||||
}, openUrl: { url, param1, param2, message in
|
||||
controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: param1, external: param2, message: message, progress: Promise()))
|
||||
|
|
|
|||
|
|
@ -2970,6 +2970,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
mappedSource = .todo
|
||||
case .copyProtection:
|
||||
mappedSource = .copyProtection
|
||||
case .aiTools:
|
||||
mappedSource = .aiTools
|
||||
case let .auth(price):
|
||||
mappedSource = .auth(price)
|
||||
case let .premiumGift(file):
|
||||
|
|
@ -3052,6 +3054,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
mappedSubject = .todo
|
||||
case .copyProtection:
|
||||
mappedSubject = .copyProtection
|
||||
case .aiTools:
|
||||
mappedSubject = .aiTools
|
||||
case .business:
|
||||
mappedSubject = .business
|
||||
buttonText = presentationData.strings.Chat_EmptyStateIntroFooterPremiumActionButton
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue