Various fixes

This commit is contained in:
Ilya Laktyushin 2023-09-23 20:16:34 +04:00
parent 2973d7ce06
commit 4e4d02aefc
9 changed files with 144 additions and 79 deletions

View File

@ -781,6 +781,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.storyProgressDisposable?.dispose() self.storyProgressDisposable?.dispose()
self.storiesPostingAvailabilityDisposable?.dispose() self.storiesPostingAvailabilityDisposable?.dispose()
self.sharedOpenStoryProgressDisposable.dispose() self.sharedOpenStoryProgressDisposable.dispose()
for (_, disposable) in self.preloadStoryResourceDisposables {
disposable.dispose()
}
} }
private func updateNavigationMetadata() { private func updateNavigationMetadata() {

View File

@ -351,6 +351,8 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
self.scrollNode.view.contentInsetAdjustmentBehavior = .never self.scrollNode.view.contentInsetAdjustmentBehavior = .never
} }
self.effectView.effect = makeCustomZoomBlurEffect(isLight: self.presentationData.theme.rootController.keyboardColor == .light)
if let snapshotView = self.sourceSendButton.view.snapshotView(afterScreenUpdates: false) { if let snapshotView = self.sourceSendButton.view.snapshotView(afterScreenUpdates: false) {
self.sendButtonNode.view.addSubview(snapshotView) self.sendButtonNode.view.addSubview(snapshotView)
} }
@ -446,10 +448,8 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
self.textInputNode.textView.setContentOffset(self.textInputNode.textView.contentOffset, animated: false) self.textInputNode.textView.setContentOffset(self.textInputNode.textView.contentOffset, animated: false)
UIView.animate(withDuration: 0.2, animations: { self.effectView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.effectView.effect = makeCustomZoomBlurEffect(isLight: self.presentationData.theme.rootController.keyboardColor == .light)
}, completion: { _ in })
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.messageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) self.messageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
@ -533,24 +533,32 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
var completedBubble = false var completedBubble = false
var completedAlpha = false var completedAlpha = false
var completed = false
let intermediateCompletion: () -> Void = { [weak self] in let intermediateCompletion: () -> Void = { [weak self] in
if completedEffect && completedButton && completedBubble && completedAlpha { if completedEffect && completedButton && completedBubble && completedAlpha && !completed {
completed = true
self?.textInputNode.isHidden = false self?.textInputNode.isHidden = false
self?.sourceSendButton.isHidden = false self?.sourceSendButton.isHidden = false
completion() completion()
} }
} }
UIView.animate(withDuration: 0.2, animations: { self.effectView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
self.effectView.effect = nil
}, completion: { _ in
completedEffect = true completedEffect = true
intermediateCompletion() intermediateCompletion()
}) })
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in }) self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in })
Queue.mainQueue().after(0.45) {
if !completed {
completed = true
self.textInputNode.isHidden = false
self.sourceSendButton.isHidden = false
completion()
}
}
if self.animateInputField { if self.animateInputField {
if cancel { if cancel {
self.fromMessageTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, delay: 0.15, removeOnCompletion: false) self.fromMessageTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, delay: 0.15, removeOnCompletion: false)
@ -561,7 +569,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
}) })
} else { } else {
self.textInputNode.isHidden = false self.textInputNode.isHidden = false
self.messageClipNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in self.messageClipNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
completedAlpha = true completedAlpha = true
intermediateCompletion() intermediateCompletion()
}) })

View File

@ -1676,6 +1676,7 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
private let context: AccountContext private let context: AccountContext
private var action: (() -> Bool)? private var action: (() -> Bool)?
private let openPeer: (EnginePeer) -> Void private let openPeer: (EnginePeer) -> Void
public var disposed: () -> Void = {}
private let hapticFeedback = HapticFeedback() private let hapticFeedback = HapticFeedback()
@ -1707,6 +1708,10 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit {
self.disposed()
}
public override func viewDidLoad() { public override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()

View File

@ -230,7 +230,7 @@ class StatsOverviewItemNode: ListViewItemNode {
if let stats = item.stats as? ChannelBoostStatus { if let stats = item.stats as? ChannelBoostStatus {
topLeftValueLabelLayoutAndApply = makeTopLeftValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "\(stats.level)", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) topLeftValueLabelLayoutAndApply = makeTopLeftValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "\(stats.level)", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
topRightValueLabelLayoutAndApply = makeTopRightValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "\(Int(stats.premiumAudience?.value ?? 0))", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) topRightValueLabelLayoutAndApply = makeTopRightValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "\(Int(stats.premiumAudience?.value ?? 0))", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
bottomLeftValueLabelLayoutAndApply = makeBottomLeftValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "\(stats.boosts)", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) bottomLeftValueLabelLayoutAndApply = makeBottomLeftValueLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "\(stats.boosts)", font: valueFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))

View File

@ -1382,6 +1382,9 @@ public final class StoryItemSetContainerComponent: Component {
if self.sendMessageContext.menuController != nil { if self.sendMessageContext.menuController != nil {
return .pause return .pause
} }
if self.sendMessageContext.progressPauseContext.hasExternalController {
return .pause
}
if let navigationController = component.controller()?.navigationController as? NavigationController { if let navigationController = component.controller()?.navigationController as? NavigationController {
let topViewController = navigationController.topViewController let topViewController = navigationController.topViewController
if !(topViewController is StoryContainerScreen) && !(topViewController is MediaEditorScreen) && !(topViewController is ShareWithPeersScreen) && !(topViewController is AttachmentController) { if !(topViewController is StoryContainerScreen) && !(topViewController is MediaEditorScreen) && !(topViewController is ShareWithPeersScreen) && !(topViewController is AttachmentController) {

View File

@ -69,6 +69,7 @@ final class StoryItemSetContainerSendMessage {
weak var statusController: ViewController? weak var statusController: ViewController?
weak var lookupController: UIViewController? weak var lookupController: UIViewController?
weak var menuController: ViewController? weak var menuController: ViewController?
var progressPauseContext = StoryProgressPauseContext()
var isViewingAttachedStickers = false var isViewingAttachedStickers = false
var currentTooltipUpdateTimer: Foundation.Timer? var currentTooltipUpdateTimer: Foundation.Timer?
@ -2617,78 +2618,96 @@ final class StoryItemSetContainerSendMessage {
guard let component = view.component, let navigationController = component.controller()?.navigationController as? NavigationController else { guard let component = view.component, let navigationController = component.controller()?.navigationController as? NavigationController else {
return return
} }
let peerId = component.slice.peer.id
component.context.sharedContext.openResolvedUrl(result, context: component.context, urlContext: .chat(peerId: peerId, updatedPresentationData: nil), navigationController: navigationController, forceExternal: forceExternal, openPeer: { [weak self, weak view] peerId, navigation in self.progressPauseContext.update = { [weak self, weak view] controller in
guard let self, let view, let component = view.component, let controller = component.controller() as? StoryContainerScreen else { guard let self, let view else {
return return
} }
self.progressPauseContext.externalController = controller
switch navigation { view.updateIsProgressPaused()
case let .chat(_, subject, peekData): }
if let navigationController = controller.navigationController as? NavigationController {
if case let .channel(channel) = peerId, channel.flags.contains(.isForum) { let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme)
controller.dismissWithoutTransitionOut() let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
component.context.sharedContext.navigateToForumChannel(context: component.context, peerId: peerId.id, navigationController: navigationController) let peerId = component.slice.peer.id
} else { component.context.sharedContext.openResolvedUrl(
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always, peekData: peekData, pushController: { [weak controller, weak navigationController] chatController, animated, completion in result,
guard let controller, let navigationController else { context: component.context,
return urlContext: .chat(peerId: peerId, updatedPresentationData: updatedPresentationData),
} navigationController: navigationController,
if "".isEmpty { forceExternal: forceExternal,
navigationController.pushViewController(chatController) openPeer: { [weak self, weak view] peerId, navigation in
} else { guard let self, let view, let component = view.component, let controller = component.controller() as? StoryContainerScreen else {
var viewControllers = navigationController.viewControllers return
if let index = viewControllers.firstIndex(where: { $0 === controller }) {
viewControllers.insert(chatController, at: index)
} else {
viewControllers.append(chatController)
}
navigationController.setViewControllers(viewControllers, animated: animated)
}
}))
}
} }
case .info:
self.navigationActionDisposable.set((component.context.account.postbox.loadedPeerWithId(peerId.id) switch navigation {
|> take(1) case let .chat(_, subject, peekData):
|> deliverOnMainQueue).start(next: { [weak view] peer in if let navigationController = controller.navigationController as? NavigationController {
guard let view, let component = view.component else { if case let .channel(channel) = peerId, channel.flags.contains(.isForum) {
return controller.dismissWithoutTransitionOut()
} component.context.sharedContext.navigateToForumChannel(context: component.context, peerId: peerId.id, navigationController: navigationController)
if peer.restrictionText(platform: "ios", contentSettings: component.context.currentContentSettings.with { $0 }) == nil { } else {
if let infoController = component.context.sharedContext.makePeerInfoController(context: component.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) { component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always, peekData: peekData, pushController: { [weak controller, weak navigationController] chatController, animated, completion in
component.controller()?.push(infoController) guard let controller, let navigationController else {
return
}
if "".isEmpty {
navigationController.pushViewController(chatController)
} else {
var viewControllers = navigationController.viewControllers
if let index = viewControllers.firstIndex(where: { $0 === controller }) {
viewControllers.insert(chatController, at: index)
} else {
viewControllers.append(chatController)
}
navigationController.setViewControllers(viewControllers, animated: animated)
}
}))
} }
} }
})) case .info:
case let .withBotStartPayload(startPayload): self.navigationActionDisposable.set((component.context.account.postbox.loadedPeerWithId(peerId.id)
if let navigationController = controller.navigationController as? NavigationController { |> take(1)
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peerId), botStart: startPayload, keepStack: .always)) |> deliverOnMainQueue).start(next: { [weak view] peer in
guard let view, let component = view.component else {
return
}
if peer.restrictionText(platform: "ios", contentSettings: component.context.currentContentSettings.with { $0 }) == nil {
if let infoController = component.context.sharedContext.makePeerInfoController(context: component.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
component.controller()?.push(infoController)
}
}
}))
case let .withBotStartPayload(startPayload):
if let navigationController = controller.navigationController as? NavigationController {
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peerId), botStart: startPayload, keepStack: .always))
}
case let .withAttachBot(attachBotStart):
if let navigationController = controller.navigationController as? NavigationController {
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peerId), attachBotStart: attachBotStart))
}
default:
break
} }
case let .withAttachBot(attachBotStart): },
if let navigationController = controller.navigationController as? NavigationController { sendFile: nil,
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peerId), attachBotStart: attachBotStart)) sendSticker: nil,
requestMessageActionUrlAuth: nil,
joinVoiceChat: nil,
present: { [weak view] c, a in
guard let view, let component = view.component, let controller = component.controller() else {
return
} }
default: controller.present(c, in: .window(.root), with: a)
break },
} dismissInput: { [weak view] in
}, guard let view else {
sendFile: nil, return
sendSticker: nil, }
requestMessageActionUrlAuth: nil, view.endEditing(true)
joinVoiceChat: nil, },
present: { [weak view] c, a in contentContext: self.progressPauseContext
guard let view, let component = view.component, let controller = component.controller() else {
return
}
controller.present(c, in: .window(.root), with: a)
}, dismissInput: { [weak view] in
guard let view else {
return
}
view.endEditing(true)
},
contentContext: nil
) )
} }
@ -3397,3 +3416,12 @@ final class StoryItemSetContainerSendMessage {
} }
} }
} }
public class StoryProgressPauseContext {
fileprivate weak var externalController: ViewController?
public fileprivate(set) var update: (ViewController?) -> Void = { _ in }
var hasExternalController: Bool {
return self.externalController != nil
}
}

View File

@ -103,6 +103,7 @@ final class ChatTextInputAudioRecordingTimeNode: ASDisplayNode {
deinit { deinit {
self.stateDisposable.dispose() self.stateDisposable.dispose()
self.durationDisposable?.dispose()
} }
func updateTheme(theme: PresentationTheme) { func updateTheme(theme: PresentationTheme) {

View File

@ -836,6 +836,10 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
} }
}) })
case let .boost(peerId, status, canApplyStatus): case let .boost(peerId, status, canApplyStatus):
var forceDark = false
if let updatedPresentationData, updatedPresentationData.initial.theme.overallDarkAppearance {
forceDark = true
}
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> deliverOnMainQueue).startStandalone(next: { peer in |> deliverOnMainQueue).startStandalone(next: { peer in
guard let peer, let status else { guard let peer, let status else {
@ -868,7 +872,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
var updateImpl: (() -> Void)? var updateImpl: (() -> Void)?
var dismissImpl: (() -> Void)? var dismissImpl: (() -> Void)?
let controller = PremiumLimitScreen(context: context, subject: subject, count: Int32(status.boosts), action: { let controller = PremiumLimitScreen(context: context, subject: subject, count: Int32(status.boosts), forceDark: forceDark, action: {
if isBoosted { if isBoosted {
return true return true
} }
@ -918,7 +922,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
return true return true
} }
let controller = textAlertController(sharedContext: context.sharedContext, title: title, text: text, actions: actions, parseMarkdown: true) let controller = textAlertController(sharedContext: context.sharedContext, updatedPresentationData: updatedPresentationData, title: title, text: text, actions: actions, parseMarkdown: true)
present(controller, nil) present(controller, nil)
} }
return dismiss return dismiss
@ -928,12 +932,21 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
}) })
navigationController?.pushViewController(controller) navigationController?.pushViewController(controller)
if let storyProgressPauseContext = contentContext as? StoryProgressPauseContext {
storyProgressPauseContext.update(controller)
let updateExternalController = storyProgressPauseContext.update
controller.disposed = {
updateExternalController(nil)
}
}
updateImpl = { [weak controller] in updateImpl = { [weak controller] in
if let _ = status.nextLevelBoosts { if let _ = status.nextLevelBoosts {
let _ = context.engine.peers.applyChannelBoost(peerId: peerId).startStandalone() let _ = context.engine.peers.applyChannelBoost(peerId: peerId).startStandalone()
controller?.updateSubject(nextSubject, count: nextCount) controller?.updateSubject(nextSubject, count: nextCount)
} else { } else {
controller?.dismiss() dismissImpl?()
} }
} }
dismissImpl = { [weak controller] in dismissImpl = { [weak controller] in

View File

@ -90,6 +90,10 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n
controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peer, peekData in controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peer, peekData in
openResolvedPeerImpl(peer, .chat(textInputState: nil, subject: nil, peekData: peekData)) openResolvedPeerImpl(peer, .chat(textInputState: nil, subject: nil, peekData: peekData))
}, parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root)) }, parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root))
case .boost:
if let navigationController = controller.navigationController as? NavigationController {
openResolvedUrlImpl(result, context: context, urlContext: peerId.flatMap { .chat(peerId: $0, updatedPresentationData: nil) } ?? .generic, navigationController: navigationController, forceExternal: false, openPeer: { _, _ in }, sendFile: nil, sendSticker: nil, joinVoiceChat: nil, present: { c, a in }, dismissInput: {}, contentContext: nil)
}
default: default:
break break
} }