From d88a29b378f75ae2d6be8e9aae14a93c1e31c085 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 18 Apr 2026 08:41:08 +0200 Subject: [PATCH] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 5 + .../Sources/AttachmentContainer.swift | 4 +- .../Sources/AttachmentController.swift | 7 +- .../Sources/ChatListController.swift | 2 +- .../Sources/ChatListControllerNode.swift | 3 + .../Sources/ChatListSearchContainerNode.swift | 3 +- .../Sources/ResizableSheetComponent.swift | 7 +- .../Sources/SheetComponent.swift | 3 +- .../LegacyComponents/TGPhotoVideoEditor.h | 14 ++- .../Sources/TGPhotoVideoEditor.m | 114 ++++++++++++++---- .../Sources/LegacyAttachmentMenu.swift | 113 ++++++++++++----- .../Sources/LegacyAvatarPicker.swift | 6 +- .../Sources/SearchDisplayController.swift | 5 + .../PresentationResourcesSettings.swift | 47 +------- .../ChatChannelSubscriberInputPanelNode.swift | 21 ++-- .../Sources/ChatInputPanelNode.swift | 10 +- .../ChatMessageSelectionInputPanelNode.swift | 25 ++-- .../ChatRecordingPreviewInputPanelNode.swift | 2 +- .../Sources/ChatTextInputPanelComponent.swift | 1 + .../Sources/ChatTextInputPanelNode.swift | 35 +++--- .../Sources/ChatTitleComponent.swift | 8 +- .../ChatTitleView/Sources/ChatTitleView.swift | 21 ++-- .../PeerInfoScreen/Sources/PeerInfoData.swift | 65 ++++++++-- .../Sources/PeerInfoInteraction.swift | 3 + .../Sources/PeerInfoScreen.swift | 16 +++ .../Sources/PeerInfoSelectionPanelNode.swift | 2 +- .../Sources/PeerInfoSettingsItems.swift | 26 +++- .../Sources/ChatbotSetupScreen.swift | 14 +-- .../Icons/Cake.imageset/Contents.json | 12 ++ .../Icons/Cake.imageset/birthday.pdf | Bin 0 -> 5942 bytes .../Sources/Chat/ChatControllerEditGif.swift | 28 ++++- .../Sources/Chat/ChatControllerPaste.swift | 11 +- .../Sources/ChatControllerContentData.swift | 8 +- .../Sources/ChatControllerNode.swift | 10 +- .../Sources/ChatHistoryListNode.swift | 5 + .../ChatMessageReportInputPanelNode.swift | 2 +- .../ChatPremiumRequiredInputPanelNode.swift | 8 +- .../ChatRestrictedInputPanelNode.swift | 2 +- .../Sources/ChatTagSearchInputPanelNode.swift | 15 +-- .../Sources/ChatUnblockInputPanelNode.swift | 2 +- .../Sources/DeleteChatInputPanelNode.swift | 2 +- .../OverlayAudioPlayerControllerNode.swift | 4 +- ...retChatHandshakeStatusInputPanelNode.swift | 2 +- .../TelegramUI/Sources/TextLinkHandling.swift | 10 +- 44 files changed, 477 insertions(+), 226 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/birthday.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 75fb799b54..c6e9ae24b3 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -16199,3 +16199,8 @@ Error: %8$@"; "Chat.Poll.Restriction.Country.CountriesLastDelimiter" = " and "; "Conversation.MessageGuestChatForUser" = "for %@"; + +"Settings.About.PrivacyHelpEmpty" = "A few words about you."; +"Settings.About.PrivacyHelpEveryone" = "Everyone can see your bio. [Change >]()"; +"Settings.About.PrivacyHelpContacts" = "Only uour contacts can see your bio. [Change >]()"; +"Settings.About.PrivacyHelpNobody" = "Nobody can see your bio. [Change >]()"; diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index 88fd1b7b67..25d2bf0d7d 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -479,7 +479,9 @@ final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate { if self.isDismissed { return } - self.bottomClipNode.cornerRadius = layout.deviceMetrics.screenCornerRadius - 2.0 + + let containerCornerRadius = max(24.0, layout.deviceMetrics.screenCornerRadius) + self.bottomClipNode.cornerRadius = containerCornerRadius - 2.0 self.isUpdatingState = true diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index a7d9cc47c0..b7297c4666 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -1174,7 +1174,8 @@ public class AttachmentController: ViewController, MinimizableController { localGlassView.contentView.addSubview(buttonIcon) ComponentTransition(buttonTransition).animateBlur(layer: buttonIcon.layer, fromRadius: 0.0, toRadius: 10.0) - containerView.update(bounds: CGRect(origin: .zero, size: targetFrame.size), topCornerRadius: 38.0, bottomCornerRadius: layout.deviceMetrics.screenCornerRadius - 2.0, boundsTransition: scaleTransition, cornersTransition: cornersTransition) + let containerCornerRadius = max(24.0, layout.deviceMetrics.screenCornerRadius) + containerView.update(bounds: CGRect(origin: .zero, size: targetFrame.size), topCornerRadius: 38.0, bottomCornerRadius: containerCornerRadius - 2.0, boundsTransition: scaleTransition, cornersTransition: cornersTransition) scaleTransition.animateBounds(layer: containerView.layer, from: CGRect(origin: .zero, size: CGSize(width: targetFrame.width, height: targetFrame.width))) scaleTransition.animateTransformScale(view: containerView, from: sourceButtonScale) positionTransition.animatePosition(layer: containerView.layer, from: sourceButtonFrame.center, to: containerView.center, completion: { _ in @@ -1242,7 +1243,9 @@ public class AttachmentController: ViewController, MinimizableController { if let sourceGlassView = findParentGlassBackgroundView(attachmentButton), let glassParams = sourceGlassView.params { let containerView = ClipContainerView() containerView.frame = initialFrame - containerView.update(bounds: CGRect(origin: .zero, size: initialFrame.size), topCornerRadius: 38.0, bottomCornerRadius: layout.deviceMetrics.screenCornerRadius - 2.0, boundsTransition: .immediate, cornersTransition: .immediate) + + let containerCornerRadius = max(24.0, layout.deviceMetrics.screenCornerRadius) + containerView.update(bounds: CGRect(origin: .zero, size: initialFrame.size), topCornerRadius: 38.0, bottomCornerRadius: containerCornerRadius - 2.0, boundsTransition: .immediate, cornersTransition: .immediate) self.view.addSubview(containerView) let localGlassView = GlassBackgroundView() diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 3ce4e72602..6e2cbd0c81 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -7287,7 +7287,7 @@ private final class ChatListLocationContext { dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, displayBackground: false, - content: .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, customSubtitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: nil, customMessageCount: nil, isEnabled: true), + content: .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, customSubtitle: nil, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: nil, customMessageCount: nil, hidePeerStatus: false, isEnabled: true), activities: nil, networkState: nil, tapped: { [weak self] in diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 8281e29585..a036e41e04 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -1986,6 +1986,9 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate { contentNode.dismissSearch = { [weak self] in self?.dismissSearch?() } + contentNode.dismissSearchImmediately = { [weak self] in + self?.controller?.deactivateSearch(animated: false) + } contentNode.openAdInfo = { [weak self] node, adPeer in self?.controller?.openAdInfo(node: node, adPeer: adPeer) } diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index aef3f58aa0..3cdf4f11b5 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -110,6 +110,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private let navigationController: NavigationController? var dismissSearch: (() -> Void)? + var dismissSearchImmediately: (() -> Void)? var openAdInfo: ((ASDisplayNode, AdPeer) -> Void)? private let edgeEffectView: EdgeEffectView @@ -1657,7 +1658,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo if let strongSelf = self { let proceed: (ChatController) -> Void = { chatController in chatController.purposefulAction = { [weak self] in - self?.cancel?() + self?.dismissSearchImmediately?() } if let navigationController = strongSelf.navigationController { var viewControllers = navigationController.viewControllers diff --git a/submodules/Components/ResizableSheetComponent/Sources/ResizableSheetComponent.swift b/submodules/Components/ResizableSheetComponent/Sources/ResizableSheetComponent.swift index 852881033d..d5623abed6 100644 --- a/submodules/Components/ResizableSheetComponent/Sources/ResizableSheetComponent.swift +++ b/submodules/Components/ResizableSheetComponent/Sources/ResizableSheetComponent.swift @@ -792,9 +792,10 @@ public final class ResizableSheetComponent: C if availableSize.width < availableSize.height { glassInset = 6.0 } - bottomCornerRadius = sheetEnvironment.deviceMetrics.screenCornerRadius - glassInset + let containerCornerRadius = max(24.0, sheetEnvironment.deviceMetrics.screenCornerRadius) + bottomCornerRadius = containerCornerRadius - 2.0 case .legacy: topCornerRadius = 12.0 bottomCornerRadius = 12.0 diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h index ef21ecd0b6..97fa637d8d 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoVideoEditor.h @@ -7,12 +7,20 @@ #import #import +@class TGModernGalleryController; + +typedef void (^ _Nonnull TGPhotoVideoEditorSchedulePickerCompletion)(int32_t time); +typedef void (^ _Nonnull TGPhotoVideoEditorSchedulePicker)(bool media, TGPhotoVideoEditorSchedulePickerCompletion _Nonnull done); +typedef void (^ _Nonnull TGPhotoVideoEditorCompletion)(id _Nonnull item, TGMediaEditingContext * _Nonnull editingContext, bool silentPosting, int32_t scheduleTime); + @interface TGPhotoVideoEditor : NSObject -+ (void)presentWithContext:(id)context parentController:(TGViewController *)parentController image:(UIImage *)image video:(NSURL *)video stickersContext:(id)stickersContext transitionView:(UIView *)transitionView senderName:(NSString *)senderName didFinishWithImage:(void (^)(UIImage *image))didFinishWithImage didFinishWithVideo:(void (^)(UIImage *image, NSURL *url, TGVideoEditAdjustments *adjustments))didFinishWithVideo dismissed:(void (^)(void))dismissed; ++ (void)presentWithContext:(id _Nonnull)context parentController:(TGViewController * _Nonnull)parentController image:(UIImage * _Nullable)image video:(NSURL * _Nullable)video stickersContext:(id _Nullable)stickersContext transitionView:(UIView * _Nullable)transitionView senderName:(NSString * _Nullable)senderName didFinishWithImage:(void (^ _Nullable)(UIImage * _Nonnull image))didFinishWithImage didFinishWithVideo:(void (^ _Nullable)(UIImage * _Nonnull image, NSURL * _Nonnull url, TGVideoEditAdjustments * _Nullable adjustments))didFinishWithVideo dismissed:(void (^ _Nonnull)(void))dismissed; -+ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSAttributedString *)caption withItem:(id)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString *)recipientName stickersContext:(id)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView *)mainSnapshot snapshots:(NSArray *)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif appeared:(void (^)(void))appeared completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed; ++ (TGModernGalleryController * _Nonnull)controllerWithContext:(id _Nonnull)context caption:(NSAttributedString * _Nonnull)caption withItem:(id _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id _Nullable)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView * _Nullable)mainSnapshot snapshots:(NSArray * _Nonnull)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder presentSchedulePicker:(TGPhotoVideoEditorSchedulePicker _Nonnull)presentSchedulePicker appeared:(void (^ _Nonnull)(void))appeared completion:(TGPhotoVideoEditorCompletion _Nonnull)completion dismissed:(void (^ _Nonnull)(void))dismissed; -+ (void)presentEditorWithContext:(id)context controller:(TGViewController *)controller withItem:(id)item cropRect:(CGRect)cropRect adjustments:(id)adjustments referenceView:(UIView *)referenceView completion:(void (^)(UIImage *, id))completion fullSizeCompletion:(void (^)(UIImage *))fullSizeCompletion beginTransitionOut:(void (^)(bool))beginTransitionOut finishTransitionOut:(void (^)())finishTransitionOut; ++ (void)presentWithContext:(id _Nonnull)context controller:(TGViewController * _Nonnull)controller caption:(NSAttributedString * _Nonnull)caption withItem:(id _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id _Nullable)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView * _Nullable)mainSnapshot snapshots:(NSArray * _Nonnull)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder presentSchedulePicker:(TGPhotoVideoEditorSchedulePicker _Nonnull)presentSchedulePicker appeared:(void (^ _Nonnull)(void))appeared completion:(TGPhotoVideoEditorCompletion _Nonnull)completion dismissed:(void (^ _Nonnull)(void))dismissed; + ++ (void)presentEditorWithContext:(id _Nonnull)context controller:(TGViewController * _Nonnull)controller withItem:(id _Nonnull)item cropRect:(CGRect)cropRect adjustments:(id _Nullable)adjustments referenceView:(UIView * _Nonnull)referenceView completion:(void (^ _Nonnull)(UIImage * _Nonnull image, id _Nullable adjustments))completion fullSizeCompletion:(void (^ _Nonnull)(UIImage * _Nonnull image))fullSizeCompletion beginTransitionOut:(void (^ _Nullable)(bool saving))beginTransitionOut finishTransitionOut:(void (^ _Nullable)(void))finishTransitionOut; @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m b/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m index 4f81c2f1fe..5ebd25410c 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m +++ b/submodules/LegacyComponents/Sources/TGPhotoVideoEditor.m @@ -5,6 +5,7 @@ #import #import +#import #import #import @@ -156,21 +157,18 @@ } } -+ (void)presentWithContext:(id)context controller:(TGViewController *)controller caption:(NSAttributedString *)caption withItem:(id)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString *)recipientName stickersContext:(id)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView *)mainSnapshot snapshots:(NSArray *)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif appeared:(void (^)(void))appeared completion:(void (^)(id, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed ++ (TGModernGalleryController *)_configuredControllerWithContext:(id _Nonnull)context caption:(NSAttributedString * _Nonnull)caption withItem:(id _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id _Nullable)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView * _Nullable)__unused mainSnapshot snapshots:(NSArray * _Nonnull)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder presentSchedulePicker:(TGPhotoVideoEditorSchedulePicker _Nonnull)presentSchedulePicker appeared:(void (^ _Nonnull)(void))appeared completion:(TGPhotoVideoEditorCompletion _Nonnull)completion completedDismiss:(void (^ _Nullable)(void))completedDismiss customDismiss:(void (^ _Nullable)(void))customDismiss { - id windowManager = [context makeOverlayWindowManager]; - id windowContext = [windowManager context]; - TGMediaEditingContext *editingContext = [[TGMediaEditingContext alloc] init]; [editingContext setForcedCaption:caption]; - TGModernGalleryController *galleryController = [[TGModernGalleryController alloc] initWithContext:windowContext]; + TGModernGalleryController *galleryController = [[TGModernGalleryController alloc] initWithContext:context]; galleryController.adjustsStatusBarVisibility = true; galleryController.animateTransition = !immediate; galleryController.finishedTransitionIn = ^(id item, TGModernGalleryItemView *itemView) { appeared(); }; - //galleryController.hasFadeOutTransition = true; + galleryController.customDismissBlock = customDismiss; id galleryItem = nil; if (item.isVideo) { @@ -181,7 +179,7 @@ galleryItem.editingContext = editingContext; 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 hasCoverButton:false]; + TGMediaPickerGalleryModel *model = [[TGMediaPickerGalleryModel alloc] initWithContext:context 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.stickersContext = stickersContext; @@ -213,6 +211,7 @@ galleryController.model = model; __weak TGModernGalleryController *weakGalleryController = galleryController; + __weak TGMediaPickerGalleryModel *weakModel = model; [model.interfaceView updateSelectionInterface:1 counterVisible:false animated:false]; model.interfaceView.thumbnailSignalForItem = ^SSignal *(id item) @@ -233,10 +232,62 @@ } if (completion != nil) - completion(item.asset, editingContext); + completion(item.asset, editingContext, false, 0); [strongController dismissWhenReadyAnimated:true]; }; + model.interfaceView.doneLongPressed = ^(TGMediaPickerGalleryItem *item) + { + __strong TGModernGalleryController *strongController = weakGalleryController; + __strong TGMediaPickerGalleryModel *strongModel = weakModel; + if (strongController == nil || strongModel == nil || !(hasSilentPosting || hasSchedule)) + return; + + if (iosMajorVersion() >= 10) { + UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; + [generator impactOccurred]; + } + + TGMediaPickerSendActionSheetController *sendController = [[TGMediaPickerSendActionSheetController alloc] initWithContext:context isDark:true sendButtonFrame:strongModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting canSendWhenOnline:hasSchedule canSchedule:hasSchedule reminder:reminder hasTimer:false]; + sendController.modalPresentationStyle = UIModalPresentationOverFullScreen; + sendController.customDismissBlock = ^{ + __strong TGModernGalleryController *strongController = weakGalleryController; + [strongController dismissViewControllerAnimated:false completion:nil]; + }; + void (^complete)(bool, int32_t) = ^(bool silentPosting, int32_t scheduleTime) + { + __strong TGModernGalleryController *strongController = weakGalleryController; + if (strongController == nil) + return; + + if ([item isKindOfClass:[TGMediaPickerGalleryVideoItem class]]) + { + TGMediaPickerGalleryVideoItemView *itemView = (TGMediaPickerGalleryVideoItemView *)[strongController itemViewForItem:item]; + [itemView stop]; + [itemView setPlayButtonHidden:true animated:true]; + } + + if (completion != nil) + completion(item.asset, editingContext, silentPosting, scheduleTime); + + [strongController dismissWhenReadyAnimated:true]; + }; + sendController.send = ^{ + complete(false, 0); + }; + sendController.sendSilently = ^{ + complete(true, 0); + }; + sendController.sendWhenOnline = ^{ + complete(false, 0x7ffffffe); + }; + sendController.schedule = ^{ + presentSchedulePicker(true, ^(int32_t time) { + complete(false, time); + }); + }; + [strongController presentViewController:sendController animated:false completion:nil]; + }; galleryController.beginTransitionIn = ^UIView *(__unused TGMediaPickerGalleryItem *item, __unused TGModernGalleryItemView *itemView) { @@ -247,21 +298,12 @@ { return nil; }; - - galleryController.completedTransitionOut = ^ - { - TGModernGalleryController *strongGalleryController = weakGalleryController; - if (strongGalleryController != nil && strongGalleryController.overlayWindow == nil) + if (completedDismiss != nil) { + galleryController.completedTransitionOut = ^ { - TGNavigationController *navigationController = (TGNavigationController *)strongGalleryController.navigationController; - TGOverlayControllerWindow *window = (TGOverlayControllerWindow *)navigationController.view.window; - if ([window isKindOfClass:[TGOverlayControllerWindow class]]) - [window dismiss]; - } - if (dismissed) { - dismissed(); - } - }; + completedDismiss(); + }; + } if (paint || adjustments) { [model.interfaceView immediateEditorTransitionIn]; @@ -271,8 +313,6 @@ [galleryController.view addSubview:view]; } - TGOverlayControllerWindow *controllerWindow = [[TGOverlayControllerWindow alloc] initWithManager:windowManager parentController:controller contentController:galleryController]; - controllerWindow.hidden = false; galleryController.view.clipsToBounds = true; if (isGif) { @@ -292,9 +332,33 @@ [model beginEditingCaption]; }); } + + return galleryController; } -+ (void)presentEditorWithContext:(id)context controller:(TGViewController *)controller withItem:(id)item cropRect:(CGRect)cropRect adjustments:(id)adjustments referenceView:(UIView *)referenceView completion:(void (^)(UIImage *, id))completion fullSizeCompletion:(void (^)(UIImage *))fullSizeCompletion beginTransitionOut:(void (^)(bool))beginTransitionOut finishTransitionOut:(void (^)())finishTransitionOut; ++ (TGModernGalleryController * _Nonnull)controllerWithContext:(id _Nonnull)context caption:(NSAttributedString * _Nonnull)caption withItem:(id _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id _Nullable)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView * _Nullable)mainSnapshot snapshots:(NSArray * _Nonnull)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder presentSchedulePicker:(TGPhotoVideoEditorSchedulePicker _Nonnull)presentSchedulePicker appeared:(void (^ _Nonnull)(void))appeared completion:(TGPhotoVideoEditorCompletion _Nonnull)completion dismissed:(void (^ _Nonnull)(void))dismissed +{ + TGModernGalleryController *galleryController = [self _configuredControllerWithContext:context caption:caption withItem:item paint:paint adjustments:adjustments recipientName:recipientName stickersContext:stickersContext fromRect:fromRect mainSnapshot:mainSnapshot snapshots:snapshots immediate:immediate activateInput:activateInput isGif:isGif hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder presentSchedulePicker:presentSchedulePicker appeared:appeared completion:completion completedDismiss:dismissed customDismiss:nil]; + galleryController.asyncTransitionIn = true; + return galleryController; +} + ++ (void)presentWithContext:(id _Nonnull)context controller:(TGViewController * _Nonnull)controller caption:(NSAttributedString * _Nonnull)caption withItem:(id _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id _Nullable)stickersContext fromRect:(CGRect)fromRect mainSnapshot:(UIView * _Nullable)mainSnapshot snapshots:(NSArray * _Nonnull)snapshots immediate:(bool)immediate activateInput:(bool)activateInput isGif:(bool)isGif hasSilentPosting:(bool)hasSilentPosting hasSchedule:(bool)hasSchedule reminder:(bool)reminder presentSchedulePicker:(TGPhotoVideoEditorSchedulePicker _Nonnull)presentSchedulePicker appeared:(void (^ _Nonnull)(void))appeared completion:(TGPhotoVideoEditorCompletion _Nonnull)completion dismissed:(void (^ _Nonnull)(void))dismissed +{ + __weak TGViewController *weakController = controller; + TGModernGalleryController *galleryController = [self _configuredControllerWithContext:context caption:caption withItem:item paint:paint adjustments:adjustments recipientName:recipientName stickersContext:stickersContext fromRect:fromRect mainSnapshot:mainSnapshot snapshots:snapshots immediate:immediate activateInput:activateInput isGif:isGif hasSilentPosting:hasSilentPosting hasSchedule:hasSchedule reminder:reminder presentSchedulePicker:presentSchedulePicker appeared:appeared completion:completion completedDismiss:nil customDismiss:^{ + __strong TGViewController *strongController = weakController; + [strongController dismissViewControllerAnimated:false completion:^{ + if (dismissed) { + dismissed(); + } + }]; + }]; + galleryController.modalPresentationStyle = UIModalPresentationFullScreen; + [controller presentViewController:galleryController animated:false completion:nil]; +} + ++ (void)presentEditorWithContext:(id _Nonnull)context controller:(TGViewController * _Nonnull)controller withItem:(id _Nonnull)item cropRect:(CGRect)cropRect adjustments:(id _Nullable)adjustments referenceView:(UIView * _Nonnull)referenceView completion:(void (^ _Nonnull)(UIImage * _Nonnull image, id _Nullable adjustments))completion fullSizeCompletion:(void (^ _Nonnull)(UIImage * _Nonnull image))fullSizeCompletion beginTransitionOut:(void (^ _Nullable)(bool saving))beginTransitionOut finishTransitionOut:(void (^ _Nullable)(void))finishTransitionOut { id windowManager = [context makeOverlayWindowManager]; diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift index acc28dacf4..fe4a830aed 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAttachmentMenu.swift @@ -131,12 +131,12 @@ public func legacyStoryMediaEditor(context: AccountContext, item: TGMediaEditabl present(legacyController, nil) - TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: NSAttributedString(), withItem: item, paint: false, adjustments: false, recipientName: "", stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: [] as [Any], immediate: true, activateInput: false, isGif: false, appeared: { + TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: NSAttributedString(), withItem: item, paint: false, adjustments: false, recipientName: "", stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: [] as [Any], immediate: true, activateInput: false, isGif: false, hasSilentPosting: false, hasSchedule: false, reminder: false, presentSchedulePicker: { _, _ in }, appeared: { - }, completion: { result, editingContext in + }, completion: { result, editingContext, _, _ in var completionResult: Signal if let photo = result as? TGCameraCapturedPhoto { - if let _ = editingContext?.adjustments(for: result) { + if let _ = editingContext.adjustments(for: result) { completionResult = .single(.image(photo.existingImage)) } else { completionResult = .single(.image(photo.existingImage)) @@ -167,6 +167,10 @@ public func legacyMediaEditor( snapshots: [UIView], transitionCompletion: (() -> Void)?, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, + hasSilentPosting: Bool = false, + hasSchedule: Bool = false, + reminder: Bool = false, + presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void = { _, _ in }, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, Bool) -> Void, present: @escaping (ViewController, Any?) -> Void ) { @@ -209,32 +213,87 @@ public func legacyMediaEditor( legacyController?.view.disablesInteractiveTransitionGestureRecognizer = true } - let emptyController = LegacyEmptyController(context: legacyController.context)! - emptyController.navigationBarShouldBeHidden = true - let navigationController = makeLegacyNavigationController(rootController: emptyController) - navigationController.setNavigationBarHidden(true, animated: false) - legacyController.bind(controller: navigationController) - - legacyController.enableSizeClassSignal = true - - present(legacyController, nil) - - TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: initialCaption, withItem: item, paint: mode == .draw, adjustments: mode == .adjustments, recipientName: recipientName, stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: snapshots as [Any], immediate: transitionCompletion != nil, activateInput: mode == .caption, isGif: isGif, appeared: { + let schedulePicker: (Bool, @escaping (Int32) -> Void) -> Void = { media, done in + presentSchedulePicker(media, done) + } + let appeared: () -> Void = { transitionCompletion?() - }, completion: { result, editingContext in + } + let completion: (TGMediaEditableItem, TGMediaEditingContext, Bool, Int32) -> Void = { result, editingContext, silentPosting, scheduleTime in let nativeGenerator = legacyAssetPickerItemGenerator() var selectableResult: TGMediaSelectableItem? - if let result = result { - selectableResult = unsafeDowncast(result, to: TGMediaSelectableItem.self) - } + selectableResult = unsafeDowncast(result, to: TGMediaSelectableItem.self) + let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: selectableResult, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: { _1, _2, _3 in nativeGenerator(_1, _2, _3, nil) }) - let isCaptionAbove = editingContext?.isCaptionAbove() ?? false - sendMessagesWithSignals(signals, false, 0, isCaptionAbove) - }, dismissed: { [weak legacyController] in + let isCaptionAbove = editingContext.isCaptionAbove() + sendMessagesWithSignals(signals, silentPosting, scheduleTime, isCaptionAbove) + } + let dismissed: () -> Void = { [weak legacyController] in legacyController?.dismiss() - }) + } + + legacyController.enableSizeClassSignal = true + + if isGif { + let galleryController = TGPhotoVideoEditor.controller( + with: legacyController.context, + caption: initialCaption, + withItem: item, + paint: mode == .draw, + adjustments: mode == .adjustments, + recipientName: recipientName, + stickersContext: paintStickersContext, + from: .zero, + mainSnapshot: nil, + snapshots: snapshots as [Any], + immediate: transitionCompletion != nil, + activateInput: mode == .caption, + isGif: true, + hasSilentPosting: hasSilentPosting, + hasSchedule: hasSchedule, + reminder: reminder, + presentSchedulePicker: schedulePicker, + appeared: appeared, + completion: completion, + dismissed: dismissed + ) + legacyController.bind(controller: galleryController) + present(legacyController, nil) + } else { + let emptyController = LegacyEmptyController(context: legacyController.context)! + emptyController.navigationBarShouldBeHidden = true + let navigationController = makeLegacyNavigationController(rootController: emptyController) + navigationController.setNavigationBarHidden(true, animated: false) + legacyController.bind(controller: navigationController) + + present(legacyController, nil) + + TGPhotoVideoEditor.present( + with: legacyController.context, + controller: emptyController, + caption: initialCaption, + withItem: item, + paint: mode == .draw, + adjustments: mode == .adjustments, + recipientName: recipientName, + stickersContext: paintStickersContext, + from: .zero, + mainSnapshot: nil, + snapshots: snapshots as [Any], + immediate: transitionCompletion != nil, + activateInput: mode == .caption, + isGif: false, + hasSilentPosting: hasSilentPosting, + hasSchedule: hasSchedule, + reminder: reminder, + presentSchedulePicker: schedulePicker, + appeared: appeared, + completion: completion, + dismissed: dismissed + ) + } }) } @@ -530,13 +589,11 @@ public func legacyAttachmentMenu( present(legacyController, nil) - TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: initialCaption, withItem: item, paint: false, adjustments: false, recipientName: recipientName, stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: [], immediate: false, activateInput: false, isGif: false, appeared: { - }, completion: { result, editingContext in + TGPhotoVideoEditor.present(with: legacyController.context, controller: emptyController, caption: initialCaption, withItem: item, paint: false, adjustments: false, recipientName: recipientName, stickersContext: paintStickersContext, from: .zero, mainSnapshot: nil, snapshots: [], immediate: false, activateInput: false, isGif: false, hasSilentPosting: false, hasSchedule: false, reminder: false, presentSchedulePicker: { _, _ in }, appeared: { + }, completion: { result, editingContext, _, _ in let nativeGenerator = legacyAssetPickerItemGenerator() - var selectableResult: TGMediaSelectableItem? - if let result = result { - selectableResult = unsafeDowncast(result, to: TGMediaSelectableItem.self) - } + let selectableResult: TGMediaSelectableItem? = unsafeDowncast(result, to: TGMediaSelectableItem.self) + let signals = TGCameraController.resultSignals(for: nil, editingContext: editingContext, currentItem: selectableResult, storeAssets: false, saveEditedPhotos: false, descriptionGenerator: { _1, _2, _3 in nativeGenerator(_1, _2, _3, nil) }) diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift index d367e03a9d..35a7c4da0c 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyAvatarPicker.swift @@ -108,11 +108,9 @@ public func legacyAvatarEditor(context: AccountContext, media: AnyMediaReference present(legacyController, nil) TGPhotoVideoEditor.present(with: legacyController.context, parentController: emptyController, image: image.0, video: video.0, stickersContext: paintStickersContext, transitionView: transitionView, senderName: senderName, didFinishWithImage: { image in - if let image = image { - imageCompletion(image) - } + imageCompletion(image) }, didFinishWithVideo: { image, url, adjustments in - if let image = image, let url = url, let adjustments = adjustments { + if let adjustments = adjustments { videoCompletion(image, url, adjustments) } }, dismissed: { [weak legacyController] in diff --git a/submodules/SearchUI/Sources/SearchDisplayController.swift b/submodules/SearchUI/Sources/SearchDisplayController.swift index 53cdd002ce..518b730a05 100644 --- a/submodules/SearchUI/Sources/SearchDisplayController.swift +++ b/submodules/SearchUI/Sources/SearchDisplayController.swift @@ -312,6 +312,11 @@ public final class SearchDisplayController { if let searchBar = self.searchBar { searchBar.deactivate(clear: false) } + if !self.searchBarIsExternal, let searchBar = self.searchBar { + searchBar.isUserInteractionEnabled = false + } + self.backgroundNode.isUserInteractionEnabled = false + self.contentNode.isUserInteractionEnabled = false if !self.searchBarIsExternal, let searchBar = self.searchBar { if let placeholder = placeholder { diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift index 944b7a2ee4..2cd47b82f8 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift @@ -132,6 +132,10 @@ public struct PresentationResourcesSettings { public static let business = renderSettingsIcon(name: "Item List/Icons/Business", backgroundColors: [UIColor(rgb: 0xA95CE3), UIColor(rgb: 0xF16B80)]) public static let myProfile = renderSettingsIcon(name: "Item List/Icons/Profile", backgroundColors: [colorRed]) + public static let birthday = renderSettingsIcon(name: "Item List/Icons/Cake", backgroundColors: [colorBlue]) + public static let aiTools = renderSettingsIcon(name: "Item List/Icons/AITools", backgroundColors: [colorPurple]) + public static let yourColor = renderSettingsIcon(name: "Item List/Icons/Brush", backgroundColors: [colorLightBlue]) + public static let storageUsage = renderSettingsIcon(name: "Item List/Icons/Pie", backgroundColors: [colorOrange]) public static let dataUsage = renderSettingsIcon(name: "Item List/Icons/Stats", backgroundColors: [colorPurple]) @@ -213,48 +217,7 @@ public struct PresentationResourcesSettings { }) public static let ton = renderSettingsIcon(name: "Ads/TonAbout", backgroundColors: [UIColor(rgb: 0x32ade6)]) - -// generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in -// let bounds = CGRect(origin: CGPoint(), size: size) -// context.clear(bounds) -// -// context.setFillColor(UIColor(rgb: 0x32ade6).cgColor) -// context.fill(bounds) -// -// if let gradientImage, let cgImage = gradientImage.cgImage { -// context.saveGState() -// context.setBlendMode(.plusLighter) -// context.draw(cgImage, in: CGRect(origin: .zero, size: size)) -// context.restoreGState() -// } -// -// if let backdropImage, let cgImage = backdropImage.cgImage { -// context.saveGState() -// context.setBlendMode(.overlay) -// context.draw(cgImage, in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)) -// context.restoreGState() -// } -// -// context.setBlendMode(.normal) -// -// if let image = generateTintedImage(image: UIImage(bundleImageName: "Ads/TonAbout"), color: UIColor(rgb: 0xffffff)), let cgImage = image.cgImage { -// context.draw(cgImage, in: CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - image.size.width) / 2.0), y: floorToScreenPixels((bounds.height - image.size.height) / 2.0)), size: image.size)) -// } -// -// let outerPath = UIBezierPath(rect: CGRect(origin: .zero, size: size)) -// let innerPath = UIBezierPath(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: 8.0) -// outerPath.append(innerPath) -// -// context.saveGState() -// outerPath.usesEvenOddFillRule = true -// context.addPath(outerPath.cgPath) -// context.clip(using: .evenOdd) -// -// context.setBlendMode(.clear) -// context.fill(CGRect(origin: .zero, size: size)) -// context.restoreGState() -// }) - + public static let stars = generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) context.clear(bounds) diff --git a/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift index 6c92a201d3..053026ef6c 100644 --- a/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatChannelSubscriberInputPanelNode/Sources/ChatChannelSubscriberInputPanelNode.swift @@ -174,7 +174,7 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { private var presentationInterfaceState: ChatPresentationInterfaceState? - private var layoutData: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, CGFloat, Bool, LayoutMetrics)? + private var layoutData: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, CGFloat, Bool, LayoutMetrics, DeviceMetrics)? public override init() { super.init() @@ -214,8 +214,8 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { switch action { case .join, .joinGroup, .applyToJoin: self.isJoining = true - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, isSecondary, metrics) = self.layoutData, let presentationInterfaceState = self.presentationInterfaceState { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, force: true) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, isSecondary, metrics, deviceMetrics) = self.layoutData, let presentationInterfaceState = self.presentationInterfaceState { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, deviceMetrics: deviceMetrics, force: true) } self.actionDisposable.set((context.peerChannelMemberCategoriesContextsManager.join(engine: context.engine, peerId: peer.id, hash: nil) |> afterDisposed { [weak self] in @@ -292,8 +292,8 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { } } - override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { - return self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: transition, interfaceState: interfaceState, metrics: metrics, force: false) + override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { + return self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: transition, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, force: false) } private var displayedGiftOrSuggestTooltip = false @@ -389,9 +389,9 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { }) } - private func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, force: Bool) -> CGFloat { + private func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, force: Bool) -> CGFloat { let isFirstTime = self.layoutData == nil - self.layoutData = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, isSecondary, metrics) + self.layoutData = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, isSecondary, metrics, deviceMetrics) var transition = transition if !isFirstTime && !transition.isAnimated { @@ -433,10 +433,9 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { var leftInset = leftInset + 8.0 var rightInset = rightInset + 8.0 - if bottomInset <= 32.0 { - leftInset += 18.0 - rightInset += 18.0 - } + let compactBottomSideInset = self.compactBottomSideInset(bottomInset: bottomInset, deviceMetrics: deviceMetrics) + leftInset += compactBottomSideInset + rightInset += compactBottomSideInset var leftPanelItems: [GlassControlGroupComponent.Item] = [] if displaySuggestPost { diff --git a/submodules/TelegramUI/Components/Chat/ChatInputPanelNode/Sources/ChatInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatInputPanelNode/Sources/ChatInputPanelNode.swift index 25a2afaf63..c092290429 100644 --- a/submodules/TelegramUI/Components/Chat/ChatInputPanelNode/Sources/ChatInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatInputPanelNode/Sources/ChatInputPanelNode.swift @@ -23,7 +23,15 @@ open class ChatInputPanelNode: ASDisplayNode { open func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition) { } - open func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + public final func compactBottomSideInset(bottomInset: CGFloat, deviceMetrics: DeviceMetrics) -> CGFloat { + if bottomInset <= 32.0 && deviceMetrics.screenCornerRadius > 0.0 { + return 18.0 + } else { + return 0.0 + } + } + + open func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { return 0.0 } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageSelectionInputPanelNode/Sources/ChatMessageSelectionInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageSelectionInputPanelNode/Sources/ChatMessageSelectionInputPanelNode.swift index 6047a3099b..5a90c21e7f 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageSelectionInputPanelNode/Sources/ChatMessageSelectionInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageSelectionInputPanelNode/Sources/ChatMessageSelectionInputPanelNode.swift @@ -202,7 +202,7 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { private let reactionOverlayContainer: ChatMessageSelectionInputPanelNodeViewForOverlayContent - private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, metrics: LayoutMetrics, isSecondary: Bool, isMediaInputExpanded: Bool)? + private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, metrics: LayoutMetrics, isSecondary: Bool, isMediaInputExpanded: Bool, deviceMetrics: DeviceMetrics)? private var presentationInterfaceState: ChatPresentationInterfaceState? private var actions: ChatAvailableMessageActions? @@ -288,8 +288,8 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { if self.selectedMessages.isEmpty { self.actions = nil - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) = self.validLayout, let interfaceState = self.presentationInterfaceState { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) = self.validLayout, let interfaceState = self.presentationInterfaceState { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) } self.canDeleteMessagesDisposable.set(nil) } else if let context = self.context { @@ -297,8 +297,8 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { |> deliverOnMainQueue).startStrict(next: { [weak self] actions in if let strongSelf = self { strongSelf.actions = actions - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight: maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout, let interfaceState = strongSelf.presentationInterfaceState { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight: maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) = strongSelf.validLayout, let interfaceState = strongSelf.presentationInterfaceState { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) } } })) @@ -456,21 +456,20 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { } private func update(transition: ContainedViewLayoutTransition) { - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) = self.validLayout, let interfaceState = self.presentationInterfaceState { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: transition, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) = self.validLayout, let interfaceState = self.presentationInterfaceState { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: transition, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) } } - override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { - self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) + override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { + self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) var leftInset = leftInset + 8.0 var rightInset = rightInset + 8.0 - if bottomInset <= 32.0 { - leftInset += 18.0 - rightInset += 18.0 - } + let compactBottomSideInset = self.compactBottomSideInset(bottomInset: bottomInset, deviceMetrics: deviceMetrics) + leftInset += compactBottomSideInset + rightInset += compactBottomSideInset let panelHeight = defaultHeight(metrics: metrics) diff --git a/submodules/TelegramUI/Components/Chat/ChatRecordingPreviewInputPanelNode/Sources/ChatRecordingPreviewInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecordingPreviewInputPanelNode/Sources/ChatRecordingPreviewInputPanelNode.swift index f8c3ce8074..3004117e1e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecordingPreviewInputPanelNode/Sources/ChatRecordingPreviewInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecordingPreviewInputPanelNode/Sources/ChatRecordingPreviewInputPanelNode.swift @@ -392,7 +392,7 @@ public final class ChatRecordingPreviewInputPanelNodeImpl: ChatInputPanelNode { })*/ } - override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { let waveformBackgroundFrame = CGRect(origin: CGPoint(x: 3.0, y: 3.0), size: CGSize(width: width - 3.0 * 2.0, height: 40.0 - 3.0 * 2.0)) if self.presentationInterfaceState != interfaceState { diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelComponent.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelComponent.swift index a9434330d9..3baa7ab194 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelComponent.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelComponent.swift @@ -1052,6 +1052,7 @@ public final class ChatTextInputPanelComponent: Component { transition: transition.containedViewLayoutTransition, interfaceState: presentationInterfaceState, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact, orientation: nil), + deviceMetrics: DeviceMetrics.iPhone16Pro, isMediaInputExpanded: false ) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index f349894a89..8edb6af71b 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -300,7 +300,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg private var accessoryItemButtons: [(ChatTextInputAccessoryItem, AccessoryItemIconButton)] = [] - private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, CGFloat, LayoutMetrics, Bool, Bool)? + private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, CGFloat, LayoutMetrics, Bool, Bool, DeviceMetrics)? private var leftMenuInset: CGFloat = 0.0 private var rightSlowModeInset: CGFloat = 0.0 private var currentTextInputBackgroundWidthOffset: CGFloat = 0.0 @@ -872,15 +872,15 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } self.mediaActionButtons.micButton.offsetRecordingControls = { [weak self] in if let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState { - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) = strongSelf.validLayout { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) } } } self.mediaActionButtons.micButton.updateCancelTranslation = { [weak self] in if let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState { - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) = strongSelf.validLayout { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) } } } @@ -1412,10 +1412,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } public func requestLayout(transition: ContainedViewLayoutTransition = .immediate) { - guard let presentationInterfaceState = self.presentationInterfaceState, let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) = self.validLayout else { + guard let presentationInterfaceState = self.presentationInterfaceState, let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) = self.validLayout else { return } - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: transition, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, transition: transition, interfaceState: presentationInterfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) } override public func updateLayout( @@ -1430,12 +1430,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, + deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool ) -> CGFloat { let isFirstTime = self.validLayout == nil let previousAdditionalSideInsets = self.validLayout?.4 - self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded) + self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, maxOverlayHeight, metrics, isSecondary, isMediaInputExpanded, deviceMetrics) let defaultGlassTintColor: GlassBackgroundView.TintColor let defaultGlassTintWithInnerColor: GlassBackgroundView.TintColor @@ -1450,10 +1451,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg var leftInset = leftInset var rightInset = rightInset - if bottomInset <= 32.0 { - leftInset += 18.0 - rightInset += 18.0 - } + let compactBottomSideInset = self.compactBottomSideInset(bottomInset: bottomInset, deviceMetrics: deviceMetrics) + leftInset += compactBottomSideInset + rightInset += compactBottomSideInset let placeholderColor: UIColor = interfaceState.theme.chat.inputPanel.inputPlaceholderColor @@ -2897,7 +2897,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg transition.updateAlpha(layer: mediaPreviewPanelNode.tintMaskView.layer, alpha: 1.0) transition.updateFrame(view: mediaPreviewPanelNode.tintMaskView, frame: mediaPreviewPanelFrame) - let _ = mediaPreviewPanelNode.updateLayout(width: mediaPreviewPanelFrame.width, leftInset: 0.0, rightInset: 0.0, bottomInset: 0.0, additionalSideInsets: UIEdgeInsets(), maxHeight: 40.0, maxOverlayHeight: 40.0, isSecondary: false, transition: mediaPreviewPanelTransition, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: false) + let _ = mediaPreviewPanelNode.updateLayout(width: mediaPreviewPanelFrame.width, leftInset: 0.0, rightInset: 0.0, bottomInset: 0.0, additionalSideInsets: UIEdgeInsets(), maxHeight: 40.0, maxOverlayHeight: 40.0, isSecondary: false, transition: mediaPreviewPanelTransition, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: false) } else if let mediaPreviewPanelNode = self.mediaPreviewPanelNode { self.mediaPreviewPanelNode = nil let mediaPreviewPanelView = mediaPreviewPanelNode.view @@ -4653,13 +4653,12 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } private func updateTextHeight(animated: Bool) { - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, _, metrics, _, _) = self.validLayout, let interfaceState = self.presentationInterfaceState { + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, _, metrics, _, _, deviceMetrics) = self.validLayout, let interfaceState = self.presentationInterfaceState { var leftInset = leftInset var rightInset = rightInset - if bottomInset <= 32.0 { - leftInset += 18.0 - rightInset += 18.0 - } + let compactBottomSideInset = self.compactBottomSideInset(bottomInset: bottomInset, deviceMetrics: deviceMetrics) + leftInset += compactBottomSideInset + rightInset += compactBottomSideInset let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset + self.currentTextInputBackgroundWidthOffset - additionalSideInsets.right let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth, sendActionControlsWidth: self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleComponent.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleComponent.swift index 64ed2c7941..c2c1e04a57 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleComponent.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleComponent.swift @@ -376,7 +376,7 @@ public final class ChatTitleComponent: Component { var titleStatusIcon: ChatTitleCredibilityIcon = .none var isEnabled = true switch component.content { - case let .peer(peerView, customTitle, _, _, isScheduledMessages, isMuted, _, isEnabledValue): + case let .peer(peerView, customTitle, _, _, isScheduledMessages, isMuted, _, hidePeerStatus, isEnabledValue): if peerView.peerId.isReplies { titleSegments = [AnimatedTextComponent.Item( id: AnyHashable(0), @@ -448,7 +448,7 @@ public final class ChatTitleComponent: Component { titleCredibilityIcon = .fake } else if peer.isScam { titleCredibilityIcon = .scam - } else if let emojiStatus = peer.emojiStatus { + } else if !hidePeerStatus, let emojiStatus = peer.emojiStatus { titleStatusIcon = .emojiStatus(emojiStatus) } else if peer.isPremium && !premiumConfiguration.isPremiumDisabled { titleCredibilityIcon = .premium @@ -612,7 +612,7 @@ public final class ChatTitleComponent: Component { var inputActivitiesAllowed = true switch component.content { - case let .peer(peerView, _, _, _, isScheduledMessages, _, _, _): + case let .peer(peerView, _, _, _, isScheduledMessages, _, _, _, _): if let peer = peerView.peer { if peer.id == component.context.account.peerId || isScheduledMessages || peer.id.isRepliesOrVerificationCodes { inputActivitiesAllowed = false @@ -710,7 +710,7 @@ public final class ChatTitleComponent: Component { } } else { switch component.content { - case let .peer(peerView, customTitle, customSubtitle, onlineMemberCount, isScheduledMessages, _, customMessageCount, _): + case let .peer(peerView, customTitle, customSubtitle, onlineMemberCount, isScheduledMessages, _, customMessageCount, _, _): if let customSubtitle { let string = NSAttributedString(string: customSubtitle, font: subtitleFont, textColor: component.theme.chat.inputPanel.inputControlColor) state = .info(string, .generic) diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift index 58fffdcb90..283fc51bd4 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift @@ -110,14 +110,14 @@ public enum ChatTitleContent: Equatable { } } - case peer(peerView: PeerData, customTitle: String?, customSubtitle: String?, onlineMemberCount: (total: Int32?, recent: Int32?), isScheduledMessages: Bool, isMuted: Bool?, customMessageCount: Int?, isEnabled: Bool) + case peer(peerView: PeerData, customTitle: String?, customSubtitle: String?, onlineMemberCount: (total: Int32?, recent: Int32?), isScheduledMessages: Bool, isMuted: Bool?, customMessageCount: Int?, hidePeerStatus: Bool, isEnabled: Bool) case replyThread(type: ReplyThreadType, count: Int) case custom(title: [TitleTextItem], subtitle: String?, isEnabled: Bool) public static func ==(lhs: ChatTitleContent, rhs: ChatTitleContent) -> Bool { switch lhs { - case let .peer(peerView, customTitle, customSubtitle, onlineMemberCount, isScheduledMessages, isMuted, customMessageCount, isEnabled): - if case let .peer(rhsPeerView, rhsCustomTitle, rhsCustomSubtitle, rhsOnlineMemberCount, rhsIsScheduledMessages, rhsIsMuted, rhsCustomMessageCount, rhsIsEnabled) = rhs { + case let .peer(peerView, customTitle, customSubtitle, onlineMemberCount, isScheduledMessages, isMuted, customMessageCount, hidePeerStatus, isEnabled): + if case let .peer(rhsPeerView, rhsCustomTitle, rhsCustomSubtitle, rhsOnlineMemberCount, rhsIsScheduledMessages, rhsIsMuted, rhsCustomMessageCount, rhsHidePeerStatus, rhsIsEnabled) = rhs { if peerView != rhsPeerView { return false } @@ -139,6 +139,9 @@ public enum ChatTitleContent: Equatable { if customMessageCount != rhsCustomMessageCount { return false } + if hidePeerStatus != rhsHidePeerStatus { + return false + } if isEnabled != rhsIsEnabled { return false } @@ -269,7 +272,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { var titleStatusIcon: ChatTitleCredibilityIcon = .none var isEnabled = true switch titleContent { - case let .peer(peerView, customTitle, _, _, isScheduledMessages, isMuted, _, isEnabledValue): + case let .peer(peerView, customTitle, _, _, isScheduledMessages, isMuted, _, hidePeerStatus, isEnabledValue): if peerView.peerId.isReplies { let typeText: String = self.strings.DialogList_Replies segments = [.text(0, NSAttributedString(string: typeText, font: titleFont, textColor: titleTheme.rootController.navigationBar.primaryTextColor))] @@ -306,7 +309,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { titleCredibilityIcon = .fake } else if peer.isScam { titleCredibilityIcon = .scam - } else if let emojiStatus = peer.emojiStatus { + } else if !hidePeerStatus, let emojiStatus = peer.emojiStatus { titleStatusIcon = .emojiStatus(emojiStatus) } else if peer.isPremium && !premiumConfiguration.isPremiumDisabled { titleCredibilityIcon = .premium @@ -476,8 +479,8 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { var enableAnimation = false switch titleContent { - case let .peer(_, customTitle, _, _, _, _, _, _): - if case let .peer(_, previousCustomTitle, _, _, _, _, _, _) = oldValue { + case let .peer(_, customTitle, _, _, _, _, _, _, _): + if case let .peer(_, previousCustomTitle, _, _, _, _, _, _, _) = oldValue { if customTitle != previousCustomTitle { enableAnimation = false } @@ -503,7 +506,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { var inputActivitiesAllowed = true if let titleContent = self.titleContent { switch titleContent { - case let .peer(peerView, _, _, _, isScheduledMessages, _, _, _): + case let .peer(peerView, _, _, _, isScheduledMessages, _, _, _, _): if let peer = peerView.peer { if peer.id == self.context.account.peerId || isScheduledMessages || peer.id.isRepliesOrVerificationCodes { inputActivitiesAllowed = false @@ -604,7 +607,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { } else { if let titleContent = self.titleContent { switch titleContent { - case let .peer(peerView, customTitle, customSubtitle, onlineMemberCount, isScheduledMessages, _, customMessageCount, _): + case let .peer(peerView, customTitle, customSubtitle, onlineMemberCount, isScheduledMessages, _, customMessageCount, _, _): if let customSubtitle { let string = NSAttributedString(string: customSubtitle, font: subtitleFont, textColor: titleTheme.rootController.navigationBar.secondaryTextColor) state = .info(string, .generic) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index 2a2a73c008..46ff447e9f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -425,6 +425,7 @@ final class PeerInfoScreenData { let savedMusicContext: ProfileSavedMusicContext? let savedMusicState: ProfileSavedMusicContext.State? let managedByBot: EnginePeer? + let businessConnectedBot: EnginePeer? let _isContact: Bool var forceIsContact: Bool = false @@ -480,7 +481,8 @@ final class PeerInfoScreenData { webAppPermissions: WebAppPermissionsState?, savedMusicContext: ProfileSavedMusicContext?, savedMusicState: ProfileSavedMusicContext.State?, - managedByBot: EnginePeer? + managedByBot: EnginePeer?, + businessConnectedBot: EnginePeer? ) { self.peer = peer self.chatPeer = chatPeer @@ -525,6 +527,7 @@ final class PeerInfoScreenData { self.savedMusicContext = savedMusicContext self.savedMusicState = savedMusicState self.managedByBot = managedByBot + self.businessConnectedBot = businessConnectedBot } } @@ -931,6 +934,20 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, let profileGiftsContext = ProfileGiftsContext(account: context.account, peerId: peerId) + let businessConnectedBot = context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Peer.BusinessConnectedBot(id: context.account.peerId) + ) + |> map { bot -> EnginePeer.Id? in + return bot?.id + } + |> distinctUntilChanged + |> mapToSignal { botPeerId -> Signal in + guard let botPeerId else { + return .single(nil) + } + return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: botPeerId)) + } + return combineLatest( context.account.viewTracker.peerView(peerId, updateData: true), accountsAndPeers, @@ -956,9 +973,10 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, bots, peerInfoPersonalOrLinkedChannel(context: context, peerId: peerId, isSettings: true), starsState, - tonState + tonState, + businessConnectedBot ) - |> map { peerView, accountsAndPeers, accountSessions, privacySettings, sharedPreferences, notifications, stickerPacks, hasPassport, accountPreferences, suggestions, limits, hasPassword, isPowerSavingEnabled, hasStories, bots, personalChannel, starsState, tonState -> PeerInfoScreenData in + |> map { peerView, accountsAndPeers, accountSessions, privacySettings, sharedPreferences, notifications, stickerPacks, hasPassport, accountPreferences, suggestions, limits, hasPassword, isPowerSavingEnabled, hasStories, bots, personalChannel, starsState, tonState, businessConnectedBot -> PeerInfoScreenData in let (notificationExceptions, notificationsAuthorizationStatus, notificationsWarningSuppressed) = notifications let (featuredStickerPacks, archivedStickerPacks) = stickerPacks @@ -1048,7 +1066,8 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, webAppPermissions: nil, savedMusicContext: nil, savedMusicState: nil, - managedByBot: nil + managedByBot: nil, + businessConnectedBot: businessConnectedBot ) } } @@ -1120,7 +1139,8 @@ func peerInfoScreenData( webAppPermissions: nil, savedMusicContext: nil, savedMusicState: nil, - managedByBot: nil + managedByBot: nil, + businessConnectedBot: nil )) case let .user(userPeerId, secretChatId, kind): let groupsInCommon: GroupsInCommonContext? @@ -1446,7 +1466,26 @@ func peerInfoScreenData( } let savedMusicContext = ProfileSavedMusicContext(account: context.account, peerId: peerId) - + + let businessConnectedBot: Signal + if isMyProfile { + businessConnectedBot = context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Peer.BusinessConnectedBot(id: context.account.peerId) + ) + |> map { bot -> EnginePeer.Id? in + return bot?.id + } + |> distinctUntilChanged + |> mapToSignal { botPeerId -> Signal in + guard let botPeerId else { + return .single(nil) + } + return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: botPeerId)) + } + } else { + businessConnectedBot = .single(nil) + } + return combineLatest( context.account.viewTracker.peerView(peerId, updateData: true), peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, isMyProfile: isMyProfile, chatLocationContextHolder: chatLocationContextHolder, sharedMediaFromForumTopic: sharedMediaFromForumTopic), @@ -1468,9 +1507,10 @@ func peerInfoScreenData( revenueContextAndState, premiumGiftOptions, webAppPermissions, - savedMusicContext.state + savedMusicContext.state, + businessConnectedBot ) - |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, recommendedBots, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, hasBotPreviewItems, personalChannel, privacySettings, starsRevenueContextAndState, revenueContextAndState, premiumGiftOptions, webAppPermissions, savedMusicState -> PeerInfoScreenData in + |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, recommendedBots, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, hasBotPreviewItems, personalChannel, privacySettings, starsRevenueContextAndState, revenueContextAndState, premiumGiftOptions, webAppPermissions, savedMusicState, businessConnectedBot -> PeerInfoScreenData in var availablePanes = availablePanes if isMyProfile { availablePanes?.insert(.stories, at: 0) @@ -1616,7 +1656,8 @@ func peerInfoScreenData( webAppPermissions: webAppPermissions, savedMusicContext: savedMusicContext, savedMusicState: savedMusicState, - managedByBot: managedByBot + managedByBot: managedByBot, + businessConnectedBot: businessConnectedBot ) } case .channel: @@ -1862,7 +1903,8 @@ func peerInfoScreenData( webAppPermissions: nil, savedMusicContext: nil, savedMusicState: nil, - managedByBot: nil + managedByBot: nil, + businessConnectedBot: nil ) } case let .group(groupId): @@ -2199,7 +2241,8 @@ func peerInfoScreenData( webAppPermissions: nil, savedMusicContext: nil, savedMusicState: nil, - managedByBot: nil + managedByBot: nil, + businessConnectedBot: nil )) } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoInteraction.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoInteraction.swift index 0d0bdf5c72..a9a1d9c92f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoInteraction.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoInteraction.swift @@ -83,6 +83,7 @@ final class PeerInfoInteraction { let editingOpenVerifyAccounts: () -> Void let editingToggleAutoTranslate: (Bool) -> Void let displayAutoTranslateLocked: () -> Void + let editingOpenBusinessChatBots: () -> Void let getController: () -> ViewController? init( @@ -160,6 +161,7 @@ final class PeerInfoInteraction { editingOpenVerifyAccounts: @escaping () -> Void, editingToggleAutoTranslate: @escaping (Bool) -> Void, displayAutoTranslateLocked: @escaping () -> Void, + editingOpenBusinessChatBots: @escaping () -> Void, getController: @escaping () -> ViewController? ) { self.openUsername = openUsername @@ -236,6 +238,7 @@ final class PeerInfoInteraction { self.editingOpenVerifyAccounts = editingOpenVerifyAccounts self.editingToggleAutoTranslate = editingToggleAutoTranslate self.displayAutoTranslateLocked = displayAutoTranslateLocked + self.editingOpenBusinessChatBots = editingOpenBusinessChatBots self.getController = getController } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index eb882686f9..4ac7ec63bc 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -682,6 +682,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro return } self.displayAutoTranslateLocked() + }, editingOpenBusinessChatBots: { [weak self] in + guard let self else { + return + } + self.editingOpenBusinessChatBots() }, getController: { [weak self] in return self?.controller @@ -3986,6 +3991,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro })) }) } + + private func editingOpenBusinessChatBots() { + let _ = (self.context.sharedContext.makeChatbotSetupScreenInitialData(context: self.context) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] initialData in + guard let self else { + return + } + self.controller?.push(self.context.sharedContext.makeChatbotSetupScreen(context: self.context, initialData: initialData)) + }) + } private func editingOpenInviteLinksSetup() { self.controller?.push(inviteLinkListController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId, admin: nil)) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSelectionPanelNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSelectionPanelNode.swift index 78af5c091e..a07cfeaf60 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSelectionPanelNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSelectionPanelNode.swift @@ -199,7 +199,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, preferredGlassType: .default, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(.default), chatLocation: .peer(id: self.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil, businessIntro: nil) - let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height, maxOverlayHeight: layout.size.height, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics, isMediaInputExpanded: false) + let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height, maxOverlayHeight: layout.size.height, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, isMediaInputExpanded: false) transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeight))) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift index d4554dfec9..18b22f5d2d 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift @@ -370,6 +370,8 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte let ItemBirthdayRemove = 11 let ItemBirthdayHelp = 12 let ItemPeerPersonalChannel = 13 + let ItemPeerChatAutomation = 14 + let ItemPeerChatAutomationHelp = 15 items[.help]!.append(PeerInfoScreenCommentItem(id: ItemNameHelp, text: presentationData.strings.EditProfile_NameAndPhotoOrVideoHelp)) @@ -400,7 +402,7 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte } let isEditingBirthDate = state.isEditingBirthDate - items[.birthday]!.append(PeerInfoScreenDisclosureItem(id: ItemBirthday, label: .coloredText(birthDateString, isEditingBirthDate ? .accent : .generic), text: presentationData.strings.Settings_Birthday, icon: nil, hasArrow: false, action: { + items[.birthday]!.append(PeerInfoScreenDisclosureItem(id: ItemBirthday, label: .coloredText(birthDateString, isEditingBirthDate ? .accent : .generic), text: presentationData.strings.Settings_Birthday, icon: PresentationResourcesSettings.birthday, hasArrow: false, action: { interaction.updateIsEditingBirthdate(!isEditingBirthDate) })) if isEditingBirthDate, let birthday { @@ -423,7 +425,7 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte })) if let user = data.peer as? TelegramUser { - items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPhoneNumber, label: .text(user.phone.flatMap({ formatPhoneNumber(context: context, number: $0) }) ?? ""), text: presentationData.strings.Settings_PhoneNumber, action: { + items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPhoneNumber, label: .text(user.phone.flatMap({ formatPhoneNumber(context: context, number: $0) }) ?? ""), text: presentationData.strings.Settings_PhoneNumber, icon: PresentationResourcesSettings.recentCalls, action: { interaction.openSettings(.phoneNumber) })) } @@ -431,7 +433,7 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte if let addressName = data.peer?.addressName, !addressName.isEmpty { username = "@\(addressName)" } - items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text(username), text: presentationData.strings.Settings_Username, action: { + items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text(username), text: presentationData.strings.Settings_Username, icon: PresentationResourcesSettings.email, action: { interaction.openSettings(.username) })) @@ -452,7 +454,7 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte } let colorImage = generateSettingsMenuPeerColorsLabelIcon(colors: colors) - items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerColor, label: .image(colorImage, colorImage.size), text: presentationData.strings.Settings_YourColor, icon: nil, action: { + items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerColor, label: .image(colorImage, colorImage.size), text: presentationData.strings.Settings_YourColor, icon: PresentationResourcesSettings.yourColor, action: { interaction.editingOpenNameColorSetup() })) @@ -468,12 +470,26 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte personalChannelTitle = peer.compactDisplayTitle } - items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerPersonalChannel, label: .text(personalChannelTitle ?? presentationData.strings.Settings_PersonalChannelEmptyValue), text: presentationData.strings.Settings_PersonalChannelItem, icon: nil, action: { + items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerPersonalChannel, label: .text(personalChannelTitle ?? presentationData.strings.Settings_PersonalChannelEmptyValue), text: presentationData.strings.Settings_PersonalChannelItem, icon: PresentationResourcesSettings.channels, action: { interaction.editingOpenPersonalChannel() })) } } + if "".isEmpty { + //TODO:localize + let automationBotTitle: String + if let botPeer = data.businessConnectedBot { + automationBotTitle = "@\(botPeer.compactDisplayTitle)" + } else { + automationBotTitle = "Off" + } + items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerChatAutomation, label: .text(automationBotTitle), text: "Chat Automation", icon: PresentationResourcesSettings.aiTools, action: { + interaction.editingOpenBusinessChatBots() + })) + items[.info]!.append(PeerInfoScreenCommentItem(id: ItemPeerChatAutomationHelp, text: "Add a bot to reply to messages on your behalf.")) + } + items[.account]!.append(PeerInfoScreenActionItem(id: ItemAddAccount, text: presentationData.strings.Settings_AddAnotherAccount, alignment: .center, action: { interaction.openSettings(.addAccount) })) diff --git a/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift b/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift index f6807785f5..f507350f5a 100644 --- a/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/ChatbotSetupScreen/Sources/ChatbotSetupScreen.swift @@ -645,13 +645,13 @@ final class ChatbotSetupScreenComponent: Component { let navigationTitleSize = self.navigationTitle.update( transition: transition, component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: environment.strings.ChatbotSetup_TitleItem, font: Font.semibold(17.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)), + text: .plain(NSAttributedString(string: environment.strings.ChatbotSetup_TitleItem, font: Font.bold(24.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)), horizontalAlignment: .center )), environment: {}, containerSize: CGSize(width: availableSize.width, height: 100.0) ) - let navigationTitleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - navigationTitleSize.width) / 2.0), y: environment.statusBarHeight + floor((environment.navigationHeight - environment.statusBarHeight - navigationTitleSize.height) / 2.0)), size: navigationTitleSize) + let navigationTitleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - navigationTitleSize.width) / 2.0), y: environment.navigationHeight + 76.0), size: navigationTitleSize) if let navigationTitleView = self.navigationTitle.view { if navigationTitleView.superview == nil { if let controller = self.environment?.controller(), let navigationBar = controller.navigationBar { @@ -681,7 +681,7 @@ final class ChatbotSetupScreenComponent: Component { environment: {}, containerSize: CGSize(width: 100.0, height: 100.0) ) - let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) * 0.5), y: contentHeight + 8.0), size: iconSize) + let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) * 0.5), y: contentHeight - 30.0), size: iconSize) if let iconView = self.icon.view as? LottieComponent.View { if iconView.superview == nil { self.scrollView.addSubview(iconView) @@ -691,11 +691,11 @@ final class ChatbotSetupScreenComponent: Component { iconView.bounds = CGRect(origin: CGPoint(), size: iconFrame.size) } - contentHeight += 129.0 + contentHeight += 115.0 let subtitleString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.ChatbotSetup_Text, attributes: MarkdownAttributes( - body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.freeTextColor), - bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: environment.theme.list.freeTextColor), + body: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor), + bold: MarkdownAttributeSet(font: Font.semibold(15.0), textColor: environment.theme.list.itemPrimaryTextColor), link: MarkdownAttributeSet(font: Font.regular(15.0), textColor: environment.theme.list.itemAccentColor), linkAttribute: { attributes in return ("URL", "") @@ -732,7 +732,7 @@ final class ChatbotSetupScreenComponent: Component { } )), environment: {}, - containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0) + containerSize: CGSize(width: availableSize.width - sideInset * 2.0 - 64.0, height: 1000.0) ) let subtitleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - subtitleSize.width) * 0.5), y: contentHeight), size: subtitleSize) if let subtitleView = self.subtitle.view { diff --git a/submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/Contents.json new file mode 100644 index 0000000000..2cc650de69 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "birthday.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/birthday.pdf b/submodules/TelegramUI/Images.xcassets/Item List/Icons/Cake.imageset/birthday.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c77d724ac19b24a2691f489b1f1a1be1ab96c728 GIT binary patch literal 5942 zcma)Ac|4R~)VI?_TBJp4B1vHkW*A%c$TpUWkY;%>jF~Y@CJ|CmN=0@N5=r?{WKSqW zSxVWXw5TX43h_SA45Huf{k-q<$9(QR_uTJU?m2hvIdWKIQzfLb223s({9s793Y?1f zg2CZBI&g#~K=ELD!c{?{9Y_K{ggpz-JW2!L2uCZ+Ig$fsZUr!LL>v)hzBU15z7C45;2pK&{Jvz}{%g)$zjtQLU%6KxFG%WMJ?LG5w#SVtIi^?bKyBA zFQU#lo;dbhLGOyOXeIG|ECIEA{bL( z5F!?$5S%OoF+c(J@Pnch9L+;bZGj5qlQqkS0e6P0EF3fE zu$^5O&*vrxZdPG&bTGUe=l}rnfO$2KtG)ymJX(NG!7;(KGzN~42!P!lLoO!5lmxB8 z5vF8t*%%;Di4YR_EhIMztuaTjhO2R<%$decE{r8%*K|tOQT@ixEAjF=Rac(2isdOd zt#tK7Fgbm76c29M%GFh_t87D7nHUSW=nI)_qA?wbD_7a}2nh;0xSSA$J=WAbE44F^ ze+%=YRr}2Yd42bD%7OwvCU?J2nM#}Gxk%wRR-tE#JWN0AX5(*6l#refSk@4V@h#p! z>VG8|SmPHuM)g}?P!`dXP$xFEg6U8zH7>c@sbUs8RUyHi7F8}tURT}YIQT{+RX<)* zYGadOu{4hkW=2~wu&!KUvp7%nzHLDs(=JL#v;9em=BwaM(Y~+4Nr+F-!JgNQsuxPn}eZO>k2wX(i7QXYE5XngB;szo=a_fP5se^oiMwhUn65`9YF1yRyCA3!m zAr|8x*lw`f=>64*7F4!)srY&QH7#x}^6LeoaT{}&Nma+HtQimH@5i#&ZW7O``PA>i z)^HIzP?Oc~{!=D^e{*o=R}1z=LF~56u)V?$^^vxU4)C3@wPCB%&}rXnGqb%M_;bYC zLrX)W(zn}gX?0XzYqdwM<*DcH?=basS0ejPDjUaT*j!C&?fszrVbynu$z7*Uv{uFA zl2yo-0^2u7pK7SNjQ2uX#W%+DHm!drEg7-z!A6|)KgT=F$TCNCi&h>J=?)*R9mnm- zf2O&~TFm1#=)U3sN7G^$=6HOAFI!cb(4478MJ>UcKRBh!2@haW|eKnHEbHq z8fS((cqzy8*81%DbjNJA-Du+L;?>p-*aqh_S(k4zEr+7ocC0mN&nU=t`H1!s`=QD@ zcRF)JYsX#VgS^A?2N6DdoyP_gJeAe+&|B~qH*7v< zX{t-8HGGIaV-jf+@o<+#VB?O)idfxPw_Bfcqi%WSp1u{6`}-Cnw>x*X09iQD<z6Y{U3FrP1-w!^Vq!~c9Ln8JTKj3}V~lS*sx3-`@tuE)2<8#Ecd z+qdUjM%Ekmx+8TLtjDeKS!&inT58GB$u?RS5a@$VZZ3D&&rM#QdSmxihLu_NsCY9g zrgW&-walqCHvi;r?6;)13g5`z0-EV~A0o>?tvsOOTZMl`O!)zJ z+_Bx`tv}98+?YuCRygMRrF$rBbotlrPa3r^h>T9wXN4f)+4D2Kyo13PgTDo5Sy;w} z$KF*s6*r0Kz4v`UH58}@ltSParHc_?Z7(#wq2#wgEi?jAFKPqj-6T;W+AI6i#F{Eceo&7Tx2?sUY+ihas7aQ zUeA5HVwbWO!k-q?n)7+z%l$X=tPceqKR>u%A- z)o#@m)IR2?)WxE`d>L?P<_F)+6KyA&PxVxP+U+=t9k2O3Qruf%GHwz!ad<*xLUe@H zeJtHEpY1yOp)zwS(c**LFFEQ&UT4s)=SAP^d0+E3@RB;C3SNXx3QugBc1gkNVF#RA z9dFo{-2C=?YhT(-%}AJ3q~~S@&2K~5{U0iJzRG#$Rr9fp&_PJ3OKCsZ{(ZWBI{)_m zilVFIjlKiELudNe^s-j4Sn?=q$@ZEbQIluvTeB#$gFo!O`7_dTY%}xw)isqczhA$P zPZe$!NFLH^)am{j@c|vV9oOx<{p^tM zpYM&7u*L!%}18+94)tM|p- z9DbR6`%2l<@;-XajOmzFS(4TL&fhPdd%x-qXdKx8$)~Q{Cop14YqEC|(KlMkc&j`$ zay|s$4-DNU^hL}>-2BVv$oW?`m9vuu??Mv>l*EzZV_Ot-b_V8-7EhjOh&H`Z@qIe{ zW&M+^tu|qMN-_{Z%|CySIgY43zSH);tNGI-pGV#D0oy6}9e?3J16_>?4duHfX0ro; z>5p-{duPirYmun&gWvtf^QtwxsFC*z1G`bu>c4-wJ}yg`__gJ^Uh>cS>5egl>1SgJ zxy{ARfSYCI-9WLQlQcANWL#Su|6ts`b@-O_@bCt-sCVhQ-I229lFxvrkuizMJ6E+D zwQ0KOT``DDh?z~YIioA0-*|+_VM{>7R#;+C)3E}KL4T@X&;h^oCB#GCb@v>-P&`c} z9_%qyfl&r>KW)eFGK|WJU%mmW+``Ey%c|zpB5yAJUVfA>AHL6Qoybs-)U(;jvHPE# zQ(u+m$EPZ#d{RUC+%j943cr5m6u#1|{t~O!JVjgjQf}Qjhf9udb7YpRb=!*IbHyfT zhJ^vKR+f;`^t2Kwz;l4FDlWaVGa;w56H%{-t>Izroe?}Q(klBOk6qNl^HUXiKF+^N z(F$PmW>h;ZnwY6o{+;L=#&g5JbNR5F!r4_1i)r{pw3!XXqp@Ugr2y{oxo z&;R+T#Xt~C-?F?wj76lBwy4Sb!n0jf_R+6xHdU&tHo@y*eEbG{*Z2qT1PwmEef@d3 ze5_5(&x&iQDZc_{m^uTW#;4emvoBMrZhEg~lE3KbY}qYNVa_Ih_y3t^{ln6EN9EAn z*z50(_8ofhBuM-|b@vLNF4yX(WrYt*d6q=w14@)pq}UI9WY zf=kl6FFmom_T}r8kaX6-OzJ5Kj(;OA8g*%uHpG%rM#vSO})7ffM-6H zb+vwEUTYWZqHx1TVyESan`Y4+I|e^LcZ}A~U71cd3GjPF4!^unw5FoN-a;f?38OA1a95i6rU?Lu=Cz?=1I4eW-RRYCmRb#bOIFB+3L)s)*97bIha=2oH9k5U_MDywdA!cx z>=SHI@A|X9ALs0oGTLJ=ad1RTD-wCJqy30PVkurSqH5-TRKng9rSGFwl6Bp;i;N12 z8YRRR;p6+JgoTax{Z8zAudHR?5icivIzy55AwqZc;I{(;X%*KU$QJe+w|C?41vkl3 zHLGsbysH{`AYmW;(%tW>-w&tAn^q)iNC#Tdo2P0}JxYKDrjR-@Wk zZyMX$a9g)EFiQE$3gOuGP9If^p1X-0SgS2nMq4f>qL(ETTbNj4Sp3my&xaMr2Q6|k zow@DT)>ZGbd`gg)FkTKDsi@u}7Q23QMgB7dAY565=*mZF=?&9A;-GbKWms5Gu(Ee% z!`s4^%l&eBc>6)O$SrksZ**tg&GHF!UR?7ZDGjB}T>Yx4x{#|#l?5`CtQI69RKOyk zHW8H4+)C1j%Azpg$hp~k;pzb}xEVNqJ8*V!ML<{v6bh9IqRpdlOIom&I27`Qw26Wrd@An^WAWoSPq-fd3ZY83520ZfMPS z72%wSn{Gx T!5ros3ks#G0+W+7u`&H0 CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState diff --git a/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift index 9cd52cba92..5dbb475afd 100644 --- a/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPremiumRequiredInputPanelNode.swift @@ -30,9 +30,10 @@ final class ChatPremiumRequiredInputPanelNode: ChatInputPanelNode { var isSecondary: Bool var interfaceState: ChatPresentationInterfaceState var metrics: LayoutMetrics + var deviceMetrics: DeviceMetrics var isMediaInputExpanded: Bool - init(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) { + init(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) { self.width = width self.leftInset = leftInset self.rightInset = rightInset @@ -43,6 +44,7 @@ final class ChatPremiumRequiredInputPanelNode: ChatInputPanelNode { self.isSecondary = isSecondary self.interfaceState = interfaceState self.metrics = metrics + self.deviceMetrics = deviceMetrics self.isMediaInputExpanded = isMediaInputExpanded } } @@ -74,8 +76,8 @@ final class ChatPremiumRequiredInputPanelNode: ChatInputPanelNode { deinit { } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { - let params = Params(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { + let params = Params(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) if let currentLayout = self.currentLayout, currentLayout.params == params { return currentLayout.height } diff --git a/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift index 9f76e4bc68..54fe6be26d 100644 --- a/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift @@ -81,7 +81,7 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.openBoostToUnrestrict() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState } diff --git a/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift index 3aa6cd9d48..7ad89bff3d 100644 --- a/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTagSearchInputPanelNode.swift @@ -32,9 +32,10 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode { var isSecondary: Bool var interfaceState: ChatPresentationInterfaceState var metrics: LayoutMetrics + var deviceMetrics: DeviceMetrics var isMediaInputExpanded: Bool - init(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) { + init(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) { self.width = width self.leftInset = leftInset self.rightInset = rightInset @@ -45,6 +46,7 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode { self.isSecondary = isSecondary self.interfaceState = interfaceState self.metrics = metrics + self.deviceMetrics = deviceMetrics self.isMediaInputExpanded = isMediaInputExpanded } } @@ -110,16 +112,15 @@ final class ChatTagSearchInputPanelNode: ChatInputPanelNode { self.totalMessageCountDisposable?.dispose() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { var leftInset = leftInset + 8.0 var rightInset = rightInset + 8.0 - if bottomInset <= 32.0 { - leftInset += 18.0 - rightInset += 18.0 - } + let compactBottomSideInset = self.compactBottomSideInset(bottomInset: bottomInset, deviceMetrics: deviceMetrics) + leftInset += compactBottomSideInset + rightInset += compactBottomSideInset - let params = Params(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + let params = Params(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, maxOverlayHeight: maxOverlayHeight, isSecondary: isSecondary, interfaceState: interfaceState, metrics: metrics, deviceMetrics: deviceMetrics, isMediaInputExpanded: isMediaInputExpanded) if let currentLayout = self.currentLayout, currentLayout.params == params { return currentLayout.height } diff --git a/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift index a344369297..6cf9fa6767 100644 --- a/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift @@ -91,7 +91,7 @@ final class ChatUnblockInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.unblockPeer() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState } diff --git a/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift b/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift index f40a2c3a50..91071281f8 100644 --- a/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift @@ -36,7 +36,7 @@ final class DeleteChatInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.deleteChat() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 9c050cddf5..3ff655d255 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -840,7 +840,9 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu containerTransform = CATransform3DScale(containerTransform, scale, scale, scale) transition.updateTransform(layer: self.containerContainingNode.layer, transform: containerTransform) - transition.updateCornerRadius(node: self.containerContainingNode, cornerRadius: layout.deviceMetrics.screenCornerRadius) + + let containerCornerRadius = max(22.0, layout.deviceMetrics.screenCornerRadius) + transition.updateCornerRadius(node: self.containerContainingNode, cornerRadius: containerCornerRadius) } private var effectiveHeaderHeight: CGFloat { diff --git a/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift b/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift index b8ae461975..bc6d4e0115 100644 --- a/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift @@ -53,7 +53,7 @@ final class SecretChatHandshakeStatusInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.unblockPeer() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, maxOverlayHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isMediaInputExpanded: Bool) -> CGFloat { self.presentationInterfaceState = interfaceState var text: String? diff --git a/submodules/TelegramUI/Sources/TextLinkHandling.swift b/submodules/TelegramUI/Sources/TextLinkHandling.swift index b6e53647a7..703227e606 100644 --- a/submodules/TelegramUI/Sources/TextLinkHandling.swift +++ b/submodules/TelegramUI/Sources/TextLinkHandling.swift @@ -18,12 +18,15 @@ import UndoUI import BrowserUI func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, navigateDisposable: MetaDisposable, controller: ViewController, action: TextLinkItemActionType, itemLink: TextLinkItem) { + let presentationData = context.sharedContext.currentPresentationData.with({ $0 }) + let presentImpl: (ViewController, Any?) -> Void = { controllerToPresent, _ in controller.present(controllerToPresent, in: .window(.root)) } let openResolvedPeerImpl: (EnginePeer?, ChatControllerInteractionNavigateToPeer) -> Void = { [weak controller] peer, navigation in - guard let peer = peer else { + guard let peer else { + controller?.present(textAlertController(context: context, updatedPresentationData: nil, title: nil, text: presentationData.strings.Resolve_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) return } context.sharedContext.openResolvedUrl(.peer(peer._asPeer(), navigation), context: context, urlContext: .generic, navigationController: (controller?.navigationController as? NavigationController), forceExternal: false, forceUpdate: false, openPeer: { (peer, navigation) in @@ -73,7 +76,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n if let controller = controller { switch result { case let .externalUrl(url): - context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: false, presentationData: context.sharedContext.currentPresentationData.with({ $0 }), navigationController: controller.navigationController as? NavigationController, dismissInput: { + context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: false, presentationData: presentationData, navigationController: controller.navigationController as? NavigationController, dismissInput: { }) case let .peer(peer, navigation): openResolvedPeerImpl(peer.flatMap(EnginePeer.init), navigation) @@ -100,7 +103,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n let sourceLocation = InstantPageSourceLocation(userLocation: peerId.flatMap(MediaResourceUserLocation.peer) ?? .other, peerType: .group) let browserController = context.sharedContext.makeInstantPageController(context: context, webPage: webPage, anchor: anchor, sourceLocation: sourceLocation) (controller.navigationController as? NavigationController)?.pushViewController(browserController, animated: true) - case .boost, .chatFolder, .join, .invoice: + case .boost, .chatFolder, .join, .invoice, .proxy: if let navigationController = controller.navigationController as? NavigationController { openResolvedUrlImpl(result, context: context, urlContext: peerId.flatMap { .chat(peerId: $0, message: nil, updatedPresentationData: nil) } ?? .generic, navigationController: navigationController, forceExternal: false, forceUpdate: false, openPeer: { peer, navigateToPeer in openResolvedPeerImpl(peer, navigateToPeer) @@ -128,7 +131,6 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n })) } - let presentationData = context.sharedContext.currentPresentationData.with { $0 } switch action { case .tap: switch itemLink {