From 97f8c538146e6c575d956f73def573f43fdfae02 Mon Sep 17 00:00:00 2001 From: isaac <> Date: Fri, 24 Apr 2026 11:18:31 +0400 Subject: [PATCH] Various improvements --- .../Sources/ChatListController.swift | 17 +-- .../ChatListFilterPresetController.swift | 4 +- .../ChatListFilterPresetListController.swift | 2 +- .../Sources/ChatScheduleTimeScreen.swift | 137 +++++++++--------- ...UpdateChatPresentationInterfaceState.swift | 2 +- .../TelegramUI/Sources/ChatController.swift | 8 + .../Sources/ChatControllerNode.swift | 4 + 7 files changed, 91 insertions(+), 83 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 330cedc81e..5ffc762e5a 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -3951,13 +3951,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController resolvedItems = [] } - var wasEmpty = false - if let tabContainerData = strongSelf.tabContainerData { - wasEmpty = tabContainerData.0.count <= 1 || tabContainerData.1 - } else { - wasEmpty = true - } - let firstItem = countAndFilterItems.1.first?.0 ?? .allChats let firstItemEntryId: ChatListFilterTabEntryId switch firstItem { @@ -4026,17 +4019,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController strongSelf.initializedFilters = true } - let isEmpty = resolvedItems.count <= 1 - let animated = strongSelf.didSetupTabs strongSelf.didSetupTabs = true if let layout = strongSelf.validLayout { - if wasEmpty != isEmpty { - let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.2, curve: .easeInOut) : .immediate - strongSelf.containerLayoutUpdated(layout, transition: transition) - (strongSelf.parent as? TabBarController)?.updateLayout(transition: transition) - } + let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.2, curve: .easeInOut) : .immediate + strongSelf.containerLayoutUpdated(layout, transition: transition) + (strongSelf.parent as? TabBarController)?.updateLayout(transition: transition) } if !notifiedFirstUpdate { diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index d85f03cf88..c43fcd9375 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -2076,7 +2076,7 @@ public func chatListFilterPresetController(context: AccountContext, currentPrese let isPremium = peerView.peers[peerView.peerId]?.isPremium ?? false - let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { + let leftNavigationButton = ItemListNavigationButton(content: .text("___close"), style: .regular, enabled: true, action: { if let attemptNavigationImpl { attemptNavigationImpl({ value in if value { @@ -2087,7 +2087,7 @@ public func chatListFilterPresetController(context: AccountContext, currentPrese dismissImpl?() } }) - let rightNavigationButton = ItemListNavigationButton(content: .text(currentPreset == nil ? presentationData.strings.Common_Create : presentationData.strings.Common_Done), style: .bold, enabled: state.isComplete, action: { + let rightNavigationButton = ItemListNavigationButton(content: .text("___done"), style: .bold, enabled: state.isComplete, action: { applyImpl?(false, { dismissImpl?() }) diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index bf072d9898..0d90835b6f 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -622,7 +622,7 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch case .default: leftNavigationButton = nil case .modal: - leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Close), style: .regular, enabled: true, action: { + leftNavigationButton = ItemListNavigationButton(content: .text("___close"), style: .regular, enabled: true, action: { dismissImpl?() }) } diff --git a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift index 782a1ff862..b485152126 100644 --- a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift +++ b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift @@ -318,75 +318,82 @@ private final class ChatScheduleTimeSheetContentComponent: Component { contentHeight += pickerHeight } - transition.setFrame(layer: self.topSeparator, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: CGSize(width: availableSize.width - sideInset * 2.0, height: UIScreenPixel))) - self.topSeparator.backgroundColor = environment.theme.list.itemBlocksSeparatorColor.cgColor - if self.topSeparator.superlayer == nil { - self.layer.addSublayer(self.topSeparator) - } - - let timeTitleSize = self.timeTitle.update( - transition: transition, - component: AnyComponent( - Text(text: strings.ScheduleMessage_Time, font: Font.regular(17.0), color: environment.theme.actionSheet.primaryTextColor) - ), - environment: {}, - containerSize: availableSize - ) - let timeTitleFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight + 16.0), size: timeTitleSize) - if let timeTitleView = self.timeTitle.view { - if timeTitleView.superview == nil { - self.addSubview(timeTitleView) - } - transition.setFrame(view: timeTitleView, frame: timeTitleFrame) - } - let date = self.date ?? Date() + var timeValueFrame: CGRect? - var t: time_t = Int(date.timeIntervalSince1970) - var timeinfo = tm() - localtime_r(&t, &timeinfo); - - let timeString = stringForShortTimestamp(hours: Int32(timeinfo.tm_hour), minutes: Int32(timeinfo.tm_min), dateTimeFormat: environment.dateTimeFormat) - let timeValueSize = self.timeValue.update( - transition: transition, - component: AnyComponent( - PlainButtonComponent( - content: AnyComponent( - ButtonContentComponent( - theme: environment.theme, - text: timeString, - isActive: self.isPickingTime, - isLocked: false - ) - ), - action: { [weak self] in - guard let self else { - return - } - if self.isPickingRepeatPeriod { - self.isPickingRepeatPeriod = false - } else { - self.isPickingTime = !self.isPickingTime - } - self.state?.updated() - }, - animateScale: false - ) - ), - environment: { - }, - containerSize: availableSize - ) - let timeValueFrame = CGRect(origin: CGPoint(x: availableSize.width - sideInset - timeValueSize.width, y: contentHeight + 10.0), size: timeValueSize) - if let timeValueView = self.timeValue.view { - if timeValueView.superview == nil { - self.addSubview(timeValueView) + switch component.mode { + case .search: + break + default: + transition.setFrame(layer: self.topSeparator, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: CGSize(width: availableSize.width - sideInset * 2.0, height: UIScreenPixel))) + self.topSeparator.backgroundColor = environment.theme.list.itemBlocksSeparatorColor.cgColor + if self.topSeparator.superlayer == nil { + self.layer.addSublayer(self.topSeparator) } - transition.setFrame(view: timeValueView, frame: timeValueFrame) + + let timeTitleSize = self.timeTitle.update( + transition: transition, + component: AnyComponent( + Text(text: strings.ScheduleMessage_Time, font: Font.regular(17.0), color: environment.theme.actionSheet.primaryTextColor) + ), + environment: {}, + containerSize: availableSize + ) + let timeTitleFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight + 16.0), size: timeTitleSize) + if let timeTitleView = self.timeTitle.view { + if timeTitleView.superview == nil { + self.addSubview(timeTitleView) + } + transition.setFrame(view: timeTitleView, frame: timeTitleFrame) + } + + var t: time_t = Int(date.timeIntervalSince1970) + var timeinfo = tm() + localtime_r(&t, &timeinfo); + + let timeString = stringForShortTimestamp(hours: Int32(timeinfo.tm_hour), minutes: Int32(timeinfo.tm_min), dateTimeFormat: environment.dateTimeFormat) + let timeValueSize = self.timeValue.update( + transition: transition, + component: AnyComponent( + PlainButtonComponent( + content: AnyComponent( + ButtonContentComponent( + theme: environment.theme, + text: timeString, + isActive: self.isPickingTime, + isLocked: false + ) + ), + action: { [weak self] in + guard let self else { + return + } + if self.isPickingRepeatPeriod { + self.isPickingRepeatPeriod = false + } else { + self.isPickingTime = !self.isPickingTime + } + self.state?.updated() + }, + animateScale: false + ) + ), + environment: { + }, + containerSize: availableSize + ) + let timeValueFrameValue = CGRect(origin: CGPoint(x: availableSize.width - sideInset - timeValueSize.width, y: contentHeight + 10.0), size: timeValueSize) + timeValueFrame = timeValueFrameValue + if let timeValueView = self.timeValue.view { + if timeValueView.superview == nil { + self.addSubview(timeValueView) + } + transition.setFrame(view: timeValueView, frame: timeValueFrameValue) + } + + contentHeight += 56.0 } - contentHeight += 56.0 - var repeatValueFrame = CGRect() if case .format = component.mode { contentHeight += 8.0 @@ -644,7 +651,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { let contentSize = CGSize(width: availableSize.width, height: contentHeight) - if self.isPickingTime { + if self.isPickingTime, let timeValueFrame { let _ = self.timePicker.update( transition: transition, component: AnyComponent( diff --git a/submodules/TelegramUI/Sources/Chat/UpdateChatPresentationInterfaceState.swift b/submodules/TelegramUI/Sources/Chat/UpdateChatPresentationInterfaceState.swift index acf7b004a7..2ae5bbd430 100644 --- a/submodules/TelegramUI/Sources/Chat/UpdateChatPresentationInterfaceState.swift +++ b/submodules/TelegramUI/Sources/Chat/UpdateChatPresentationInterfaceState.swift @@ -28,7 +28,7 @@ func updateChatPresentationInterfaceStateImpl( completion externalCompletion: @escaping (ContainedViewLayoutTransition) -> Void ) { var transition = transition - if !selfController.didAppear { + if !selfController.enableAnimations { transition = .immediate } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 12d3cf1c2d..2783f947c9 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -458,6 +458,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var willAppear = false var didAppear = false + var enableAnimations = false var scheduledActivateInput: ChatControllerActivateInput? var raiseToListen: RaiseToListenManager? @@ -7248,6 +7249,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } + DispatchQueue.main.async { [weak self] in + guard let self else { + return + } + self.enableAnimations = true + } + if case let .replyThread(message) = self.chatLocation, message.isForumPost { if self.keepMessageCountersSyncrhonizedDisposable == nil { self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: message.peerId, threadId: message.threadId).startStrict() diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 12beb7853f..04837a3094 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1682,6 +1682,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { } else if let headerPanelsView = self.headerPanelsView { self.headerPanelsView = nil if let headerPanelsComponentView = headerPanelsView.view { + transition.updateTransformScale(layer: headerPanelsComponentView.layer, scale: 0.001) transition.updateAlpha(layer: headerPanelsComponentView.layer, alpha: 0.0, completion: { [weak headerPanelsComponentView] _ in headerPanelsComponentView?.removeFromSuperview() }) @@ -2493,6 +2494,8 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { listInsets.left += floatingTopicsPanelInsets.left listInsets.bottom += floatingTopicsPanelInsets.top + childContentInsets.top = listInsets.bottom + var emptyNodeInsets = insets emptyNodeInsets.bottom += inputPanelsHeight self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets, listInsets.left, listInsets.right) @@ -2680,6 +2683,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { var headerPanelsTransition = ComponentTransition(transition) if headerPanelsComponentView.superview == nil { headerPanelsTransition.animateAlpha(view: headerPanelsComponentView, from: 0.0, to: 1.0) + headerPanelsTransition.animateScale(view: headerPanelsComponentView, from: 0.001, to: 1.0) headerPanelsTransition = headerPanelsTransition.withAnimation(.none) self.floatingTopicsPanelContainer.view.addSubview(headerPanelsComponentView) }