Various improvements

This commit is contained in:
Ilya Laktyushin 2026-04-18 08:41:08 +02:00
parent 1fa0c7991c
commit d88a29b378
44 changed files with 477 additions and 226 deletions

View file

@ -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 >]()";

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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)
}

View file

@ -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

View file

@ -792,9 +792,10 @@ public final class ResizableSheetComponent<ChildEnvironmentType: Sendable & Equa
let scrollContentHeight = max(topInset + contentHeight + containerInset, availableSize.height - containerInset)
self.scrollContentClippingView.layer.cornerRadius = 38.0
self.itemLayout = ItemLayout(containerSize: availableSize, containerInset: containerInset, containerCornerRadius: sheetEnvironment.deviceMetrics.screenCornerRadius, bottomInset: sheetEnvironment.safeInsets.bottom, topInset: topInset, fillingSize: fillingSize, isTablet: sheetEnvironment.metrics.isTablet)
let containerCornerRadius = max(22.0, sheetEnvironment.deviceMetrics.screenCornerRadius)
self.itemLayout = ItemLayout(containerSize: availableSize, containerInset: containerInset, containerCornerRadius: containerCornerRadius, bottomInset: sheetEnvironment.safeInsets.bottom, topInset: topInset, fillingSize: fillingSize, isTablet: sheetEnvironment.metrics.isTablet)
transition.setFrame(view: self.scrollContentView, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset + containerInset), size: CGSize(width: availableSize.width, height: contentHeight)))
transition.setPosition(layer: self.backgroundLayer, position: CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0))

View file

@ -403,7 +403,8 @@ public final class SheetComponent<ChildEnvironmentType: Sendable & Equatable>: 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

View file

@ -7,12 +7,20 @@
#import <LegacyComponents/TGMediaEditingContext.h>
#import <LegacyComponents/TGMediaSelectionContext.h>
@class TGModernGalleryController;
typedef void (^ _Nonnull TGPhotoVideoEditorSchedulePickerCompletion)(int32_t time);
typedef void (^ _Nonnull TGPhotoVideoEditorSchedulePicker)(bool media, TGPhotoVideoEditorSchedulePickerCompletion _Nonnull done);
typedef void (^ _Nonnull TGPhotoVideoEditorCompletion)(id<TGMediaEditableItem> _Nonnull item, TGMediaEditingContext * _Nonnull editingContext, bool silentPosting, int32_t scheduleTime);
@interface TGPhotoVideoEditor : NSObject
+ (void)presentWithContext:(id<LegacyComponentsContext>)context parentController:(TGViewController *)parentController image:(UIImage *)image video:(NSURL *)video stickersContext:(id<TGPhotoPaintStickersContext>)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<LegacyComponentsContext> _Nonnull)context parentController:(TGViewController * _Nonnull)parentController image:(UIImage * _Nullable)image video:(NSURL * _Nullable)video stickersContext:(id<TGPhotoPaintStickersContext> _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<LegacyComponentsContext>)context controller:(TGViewController *)controller caption:(NSAttributedString *)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem>)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString *)recipientName stickersContext:(id<TGPhotoPaintStickersContext>)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<TGMediaEditableItem>, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed;
+ (TGModernGalleryController * _Nonnull)controllerWithContext:(id<LegacyComponentsContext> _Nonnull)context caption:(NSAttributedString * _Nonnull)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem> _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id<TGPhotoPaintStickersContext> _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<LegacyComponentsContext>)context controller:(TGViewController *)controller withItem:(id<TGMediaEditableItem>)item cropRect:(CGRect)cropRect adjustments:(id<TGMediaEditAdjustments>)adjustments referenceView:(UIView *)referenceView completion:(void (^)(UIImage *, id<TGMediaEditAdjustments>))completion fullSizeCompletion:(void (^)(UIImage *))fullSizeCompletion beginTransitionOut:(void (^)(bool))beginTransitionOut finishTransitionOut:(void (^)())finishTransitionOut;
+ (void)presentWithContext:(id<LegacyComponentsContext> _Nonnull)context controller:(TGViewController * _Nonnull)controller caption:(NSAttributedString * _Nonnull)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem> _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id<TGPhotoPaintStickersContext> _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<LegacyComponentsContext> _Nonnull)context controller:(TGViewController * _Nonnull)controller withItem:(id<TGMediaEditableItem> _Nonnull)item cropRect:(CGRect)cropRect adjustments:(id<TGMediaEditAdjustments> _Nullable)adjustments referenceView:(UIView * _Nonnull)referenceView completion:(void (^ _Nonnull)(UIImage * _Nonnull image, id<TGMediaEditAdjustments> _Nullable adjustments))completion fullSizeCompletion:(void (^ _Nonnull)(UIImage * _Nonnull image))fullSizeCompletion beginTransitionOut:(void (^ _Nullable)(bool saving))beginTransitionOut finishTransitionOut:(void (^ _Nullable)(void))finishTransitionOut;
@end

View file

@ -5,6 +5,7 @@
#import <LegacyComponents/TGMediaPickerGalleryModel.h>
#import <LegacyComponents/TGMediaPickerGalleryPhotoItem.h>
#import <LegacyComponents/TGMediaPickerSendActionSheetController.h>
#import <LegacyComponents/TGMediaPickerGalleryVideoItem.h>
#import <LegacyComponents/TGMediaPickerGalleryVideoItemView.h>
@ -156,21 +157,18 @@
}
}
+ (void)presentWithContext:(id<LegacyComponentsContext>)context controller:(TGViewController *)controller caption:(NSAttributedString *)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem>)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString *)recipientName stickersContext:(id<TGPhotoPaintStickersContext>)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<TGMediaEditableItem>, TGMediaEditingContext *))completion dismissed:(void (^)())dismissed
+ (TGModernGalleryController *)_configuredControllerWithContext:(id<LegacyComponentsContext> _Nonnull)context caption:(NSAttributedString * _Nonnull)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem> _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id<TGPhotoPaintStickersContext> _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<LegacyComponentsOverlayWindowManager> windowManager = [context makeOverlayWindowManager];
id<LegacyComponentsContext> 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<TGModernGalleryItem> item, TGModernGalleryItemView *itemView) {
appeared();
};
//galleryController.hasFadeOutTransition = true;
galleryController.customDismissBlock = customDismiss;
id<TGModernGalleryEditableItem> 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<LegacyComponentsContext>)context controller:(TGViewController *)controller withItem:(id<TGMediaEditableItem>)item cropRect:(CGRect)cropRect adjustments:(id<TGMediaEditAdjustments>)adjustments referenceView:(UIView *)referenceView completion:(void (^)(UIImage *, id<TGMediaEditAdjustments>))completion fullSizeCompletion:(void (^)(UIImage *))fullSizeCompletion beginTransitionOut:(void (^)(bool))beginTransitionOut finishTransitionOut:(void (^)())finishTransitionOut;
+ (TGModernGalleryController * _Nonnull)controllerWithContext:(id<LegacyComponentsContext> _Nonnull)context caption:(NSAttributedString * _Nonnull)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem> _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id<TGPhotoPaintStickersContext> _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<LegacyComponentsContext> _Nonnull)context controller:(TGViewController * _Nonnull)controller caption:(NSAttributedString * _Nonnull)caption withItem:(id<TGMediaEditableItem, TGMediaSelectableItem> _Nonnull)item paint:(bool)paint adjustments:(bool)adjustments recipientName:(NSString * _Nonnull)recipientName stickersContext:(id<TGPhotoPaintStickersContext> _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<LegacyComponentsContext> _Nonnull)context controller:(TGViewController * _Nonnull)controller withItem:(id<TGMediaEditableItem> _Nonnull)item cropRect:(CGRect)cropRect adjustments:(id<TGMediaEditAdjustments> _Nullable)adjustments referenceView:(UIView * _Nonnull)referenceView completion:(void (^ _Nonnull)(UIImage * _Nonnull image, id<TGMediaEditAdjustments> _Nullable adjustments))completion fullSizeCompletion:(void (^ _Nonnull)(UIImage * _Nonnull image))fullSizeCompletion beginTransitionOut:(void (^ _Nullable)(bool saving))beginTransitionOut finishTransitionOut:(void (^ _Nullable)(void))finishTransitionOut
{
id<LegacyComponentsOverlayWindowManager> windowManager = [context makeOverlayWindowManager];

View file

@ -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<StoryMediaEditorResult, NoError>
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)
})

View file

@ -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

View file

@ -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 {

View file

@ -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)

View file

@ -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 {

View file

@ -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
}

View file

@ -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)

View file

@ -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 {

View file

@ -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
)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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<EnginePeer?, NoError> 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<EnginePeer?, NoError>
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<EnginePeer?, NoError> 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
))
}
}

View file

@ -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
}
}

View file

@ -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))

View file

@ -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)))

View file

@ -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)
}))

View file

@ -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 {

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "birthday.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -14,6 +14,8 @@ extension ChatControllerImpl {
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
return
}
let hasSilentPosting = peer.id != self.context.account.peerId
let hasSchedule = self.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat && self.presentationInterfaceState.sendPaidMessageStars == nil
legacyMediaEditor(
context: self.context,
peer: peer,
@ -27,7 +29,24 @@ extension ChatControllerImpl {
getCaptionPanelView: { [weak self] in
return self?.getCaptionPanelView(isFile: false, hasTimer: false)
},
sendMessagesWithSignals: { [weak self] signals, _, _, isCaptionAbove in
hasSilentPosting: hasSilentPosting,
hasSchedule: hasSchedule,
reminder: peer.id == self.context.account.peerId,
presentSchedulePicker: { [weak self] _, done in
guard let self else {
return
}
self.presentScheduleTimePicker(style: .media, completion: { [weak self] time, _ in
guard let self else {
return
}
done(time)
if self.presentationInterfaceState.subject != .scheduledMessages && time != scheduleWhenOnlineTimestamp {
self.openScheduledMessages()
}
})
},
sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime, isCaptionAbove in
guard let self else {
return
}
@ -39,8 +58,8 @@ extension ChatControllerImpl {
fromGallery: false,
signals: signals,
originalMediaReference: file.abstract,
silentPosting: false,
scheduleTime: nil,
silentPosting: silentPosting,
scheduleTime: scheduleTime == 0 ? nil : scheduleTime,
replyToSubject: nil,
parameters: parameters,
getAnimatedTransitionSource: nil,
@ -48,7 +67,8 @@ extension ChatControllerImpl {
)
},
present: { [weak self] c, a in
self?.present(c, in: .window(.root), with: a)
c.navigationPresentation = .flatModal
self?.push(c)
}
)
}

View file

@ -23,6 +23,7 @@ extension ChatControllerImpl {
if strongSelf.presentationInterfaceState.interfaceState.postSuggestionState != nil {
enableMultiselection = false
}
let inputText = strongSelf.presentationInterfaceState.interfaceState.effectiveInputState.inputText
strongSelf.chatDisplayNode.dismissInput()
let controller = mediaPasteboardScreen(
@ -32,7 +33,15 @@ extension ChatControllerImpl {
subjects: subjects,
presentMediaPicker: { [weak self] subject, saveEditedPhotos, bannedSendPhotos, bannedSendVideos, present in
if let strongSelf = self {
strongSelf.presentMediaPicker(subject: subject, saveEditedPhotos: saveEditedPhotos, bannedSendPhotos: bannedSendPhotos, bannedSendVideos: bannedSendVideos, enableMultiselection: enableMultiselection, present: present, updateMediaPickerContext: { _ in }, completion: { [weak self] fromGallery, signals, silentPosting, scheduleTime, parameters, getAnimatedTransitionSource, completion in
strongSelf.presentMediaPicker(subject: subject, saveEditedPhotos: saveEditedPhotos, bannedSendPhotos: bannedSendPhotos, bannedSendVideos: bannedSendVideos, enableMultiselection: enableMultiselection, present: { controller, mediaPickerContext in
if !inputText.string.isEmpty {
mediaPickerContext?.setCaption(inputText)
}
present(controller, mediaPickerContext)
}, updateMediaPickerContext: { _ in }, completion: { [weak self] fromGallery, signals, silentPosting, scheduleTime, parameters, getAnimatedTransitionSource, completion in
if !inputText.string.isEmpty {
self?.clearInputText()
}
self?.enqueueMediaMessages(fromGallery: fromGallery, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime, parameters: parameters, getAnimatedTransitionSource: getAnimatedTransitionSource, completion: completion)
})
}

View file

@ -602,7 +602,7 @@ extension ChatControllerImpl {
notificationSettings: nil,
peerPresences: [:],
cachedData: nil
), customTitle: nil, customSubtitle: strings.Chat_Monoforum_Subtitle, onlineMemberCount: (nil, nil), isScheduledMessages: false, isMuted: nil, customMessageCount: nil, isEnabled: true)
), customTitle: nil, customSubtitle: strings.Chat_Monoforum_Subtitle, onlineMemberCount: (nil, nil), isScheduledMessages: false, isMuted: nil, customMessageCount: nil, hidePeerStatus: false, isEnabled: true)
} else {
strongSelf.state.chatTitleContent = .custom(title: [ChatTitleContent.TitleTextItem(id: AnyHashable(0), content: .text(channel.debugDisplayTitle))], subtitle: nil, isEnabled: true)
}
@ -613,7 +613,7 @@ extension ChatControllerImpl {
customSubtitle = "Tap to view as chats"
}
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, customSubtitle: customSubtitle, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil, isEnabled: hasPeerInfo)
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: nil, customSubtitle: customSubtitle, onlineMemberCount: onlineMemberCount, isScheduledMessages: isScheduledMessages, isMuted: nil, customMessageCount: nil, hidePeerStatus: false, isEnabled: hasPeerInfo)
let imageOverride: AvatarNodeImageOverride?
if context.account.peerId == peer.id {
@ -1519,7 +1519,7 @@ extension ChatControllerImpl {
customMessageCount = savedMessagesPeer?.messageCount ?? 0
}
strongSelf.state.chatTitleContent = .peer(peerView: mappedPeerData, customTitle: nil, customSubtitle: customSubtitle, onlineMemberCount: (nil, nil), isScheduledMessages: false, isMuted: false, customMessageCount: customMessageCount, isEnabled: true)
strongSelf.state.chatTitleContent = .peer(peerView: mappedPeerData, customTitle: nil, customSubtitle: customSubtitle, onlineMemberCount: (nil, nil), isScheduledMessages: false, isMuted: false, customMessageCount: customMessageCount, hidePeerStatus: false, isEnabled: true)
strongSelf.state.peerView = peerView
@ -1613,7 +1613,7 @@ extension ChatControllerImpl {
}
}
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: threadInfo.title, customSubtitle: customSubtitle, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: peerIsMuted, customMessageCount: messageAndTopic.messageCount == 0 ? nil : messageAndTopic.messageCount, isEnabled: true)
strongSelf.state.chatTitleContent = .peer(peerView: ChatTitleContent.PeerData(peerView: peerView), customTitle: threadInfo.title, customSubtitle: customSubtitle, onlineMemberCount: onlineMemberCount, isScheduledMessages: false, isMuted: peerIsMuted, customMessageCount: messageAndTopic.messageCount == 0 ? nil : messageAndTopic.messageCount, hidePeerStatus: true, isEnabled: true)
let avatarContent: EmojiStatusComponent.Content
if chatLocation.threadId == 1 {

View file

@ -1763,7 +1763,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
if inputTextPanelNode.isFocused {
self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring))
}
let _ = inputTextPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
let _ = inputTextPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
}
if let prevInputPanelNode = self.inputPanelNode, inputPanelNode.canHandleTransition(from: prevInputPanelNode) {
inputPanelNodeHandlesTransition = true
@ -1775,7 +1775,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
} else {
dismissedInputPanelNode = self.inputPanelNode
}
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: inputPanelNode.supernode !== self ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: inputPanelNode.supernode !== self ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
self.inputPanelNode = inputPanelNode
if inputPanelNode.supernode !== self {
@ -1786,7 +1786,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.inputPanelOverlayNode.view.addSubview(viewForOverlayContent)
}
} else {
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset - 120.0, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset - 120.0, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
}
} else {
@ -1797,7 +1797,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
if let secondaryInputPanelNode = inputPanelNodes.secondary, !previewing {
if secondaryInputPanelNode !== self.secondaryInputPanelNode {
dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: true, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: true, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
self.secondaryInputPanelNode = secondaryInputPanelNode
if secondaryInputPanelNode.supernode == nil {
@ -1808,7 +1808,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.inputPanelOverlayNode.view.addSubview(viewForOverlayContent)
}
} else {
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: inputPanelBottomInset, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, maxOverlayHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0)
secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight)
}
} else {

View file

@ -3362,6 +3362,11 @@ public final class ChatHistoryListNodeImpl: ListViewImpl, ChatHistoryNode, ChatH
if self.chatHistoryLocationValue?.content != locationInput {
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())
}
} else if historyView.originalView.holeEarlier, case let .custom(_, _, _, _, _, loadMore) = self.source, let loadMore {
if self.chatHistoryLocationValue?.content != locationInput {
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())
loadMore()
}
} else if case let .customChatContents(customChatContents) = self.subject, case .hashTagSearch = customChatContents.kind {
if self.chatHistoryLocationValue?.content != locationInput {
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())

View file

@ -72,7 +72,7 @@ final class ChatMessageReportInputPanelNode: ChatInputPanelNode {
}
}
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

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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 {

View file

@ -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?

View file

@ -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 {