Various fixes

This commit is contained in:
Ilya Laktyushin 2025-05-02 17:03:23 +04:00
parent 751e20043f
commit da164c2332
9 changed files with 58 additions and 37 deletions

View File

@ -713,7 +713,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
return .single(message.flatMap { ($0, false) })
}
}
translateToLanguage = chatTranslationState(context: context, peerId: messageId.peerId)
translateToLanguage = chatTranslationState(context: context, peerId: messageId.peerId, threadId: threadIdValue)
|> map { translationState in
if let translationState, translationState.isEnabled {
let translateToLanguage = translationState.toLang ?? baseLanguageCode

View File

@ -780,7 +780,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
let overlayColor = item.presentationData.theme.theme.overallDarkAppearance && uniquePatternFile == nil ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12)
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - giftSize.width) / 2.0), y: hasServiceMessage ? labelLayout.size.height + 12.0 : 0.0), size: giftSize)
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - giftSize.width) / 2.0), y: hasServiceMessage ? labelLayout.size.height + 12.0 : 0.0), size: giftSize)
let mediaBackgroundFrame = imageFrame.insetBy(dx: -2.0, dy: -2.0)
var iconSize = CGSize(width: 160.0, height: 160.0)
@ -852,7 +852,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
let _ = ribbonTextApply()
let _ = moreApply()
let labelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - labelLayout.size.width) / 2.0), y: 2.0), size: labelLayout.size)
let labelFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - labelLayout.size.width) / 2.0), y: 2.0), size: labelLayout.size)
strongSelf.labelNode.frame = labelFrame
let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 151.0), size: titleLayout.size)

View File

@ -325,6 +325,8 @@ public class ChatMessagePaymentAlertController: AlertController {
private let balance = ComponentView<Empty>()
private var didAppear = false
public init(context: AccountContext?, presentationData: PresentationData, contentNode: AlertContentNode, navigationController: NavigationController?, showBalance: Bool = true) {
self.context = context
self.presentationData = presentationData
@ -361,6 +363,15 @@ public class ChatMessagePaymentAlertController: AlertController {
public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
if !self.didAppear {
self.didAppear = true
if !layout.metrics.isTablet && layout.size.width > layout.size.height {
Queue.mainQueue().after(0.1) {
self.view.window?.endEditing(true)
}
}
}
if let context = self.context, let _ = self.parentNavigationController, self.showBalance {
let insets = layout.insets(options: .statusBar)
let balanceSize = self.balance.update(

View File

@ -334,8 +334,8 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode
strongSelf.buttonNode.isHidden = fromYou || isGroupOrChannel
strongSelf.buttonTitleNode.isHidden = fromYou || isGroupOrChannel
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
if let media, mediaUpdated {
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - imageSize.width) / 2.0), y: 13.0), size: imageSize)
if let media, mediaUpdated {
let boundingSize = imageSize
var imageSize = boundingSize
let updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
@ -440,7 +440,7 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode
}
}
let mediaBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize)
let mediaBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((boundingWidth - width) / 2.0), y: 0.0), size: backgroundSize)
strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame
strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)

View File

@ -4978,7 +4978,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
self.refreshMessageTagStatsDisposable = context.engine.messages.refreshMessageTagStats(peerId: peerId, threadId: chatLocation.threadId, tags: [.video, .photo, .gif, .music, .voiceOrInstantVideo, .webPage, .file]).startStrict()
if peerId.namespace == Namespaces.Peer.CloudChannel {
self.translationStateDisposable = (chatTranslationState(context: context, peerId: peerId)
self.translationStateDisposable = (chatTranslationState(context: context, peerId: peerId, threadId: nil)
|> deliverOnMainQueue).startStrict(next: { [weak self] translationState in
self?.translationState = translationState
})
@ -6507,7 +6507,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
f(.dismissWithoutContent)
if let strongSelf = self {
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, { current in
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, threadId: nil, { current in
return current?.withIsEnabled(true)
}).startStandalone()
@ -6698,7 +6698,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
f(.dismissWithoutContent)
if let strongSelf = self {
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, { current in
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, threadId: nil, { current in
return current?.withIsEnabled(true)
}).startStandalone()
@ -6957,7 +6957,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
f(.dismissWithoutContent)
if let strongSelf = self {
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, { current in
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: strongSelf.peerId, threadId: nil, { current in
return current?.withIsEnabled(true)
}).startStandalone()

View File

@ -681,6 +681,7 @@ extension ChatControllerImpl {
let hasAutoTranslate = self.context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.AutoTranslateEnabled(id: peerId))
|> distinctUntilChanged
let chatLocation = self.chatLocation
self.translationStateDisposable = (combineLatest(
queue: .concurrentDefaultQueue(),
isPremium,
@ -693,7 +694,7 @@ extension ChatControllerImpl {
maybeSuggestPremium = true
}
if (isPremium || maybeSuggestPremium || hasAutoTranslate) && !isHidden {
return chatTranslationState(context: context, peerId: peerId)
return chatTranslationState(context: context, peerId: peerId, threadId: chatLocation.threadId)
|> map { translationState -> ChatPresentationTranslationState? in
if let translationState, !translationState.fromLang.isEmpty && (translationState.fromLang != baseLanguageCode || translationState.isEnabled) {
return ChatPresentationTranslationState(isEnabled: translationState.isEnabled, fromLang: translationState.fromLang, toLang: translationState.toLang ?? baseLanguageCode)
@ -4357,32 +4358,32 @@ extension ChatControllerImpl {
}
let _ = strongSelf.context.engine.peers.setForumChannelTopicClosed(id: peerId, threadId: threadId, isClosed: false).startStandalone()
}, toggleTranslation: { [weak self] type in
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else {
guard let self, let peerId = self.chatLocation.peerId else {
return
}
let _ = (updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: peerId, { current in
let _ = (updateChatTranslationStateInteractively(engine: self.context.engine, peerId: peerId, threadId: self.chatLocation.threadId, { current in
return current?.withIsEnabled(type == .translated)
})
|> deliverOnMainQueue).startStandalone(completed: { [weak self] in
if let strongSelf = self, type == .translated {
if let self, type == .translated {
Queue.mainQueue().after(0.15) {
strongSelf.chatDisplayNode.historyNode.refreshPollActionsForVisibleMessages()
self.chatDisplayNode.historyNode.refreshPollActionsForVisibleMessages()
}
}
})
}, changeTranslationLanguage: { [weak self] langCode in
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else {
guard let self, let peerId = self.chatLocation.peerId else {
return
}
let langCode = normalizeTranslationLanguage(langCode)
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: peerId, { current in
let _ = updateChatTranslationStateInteractively(engine: self.context.engine, peerId: peerId, threadId: self.chatLocation.threadId, { current in
return current?.withToLang(langCode).withIsEnabled(true)
}).startStandalone()
}, addDoNotTranslateLanguage: { [weak self] langCode in
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else {
guard let self, let peerId = self.chatLocation.peerId else {
return
}
let _ = updateTranslationSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { current in
let _ = updateTranslationSettingsInteractively(accountManager: self.context.sharedContext.accountManager, { current in
var updated = current
if var ignoredLanguages = updated.ignoredLanguages {
if !ignoredLanguages.contains(langCode) {
@ -4391,7 +4392,7 @@ extension ChatControllerImpl {
updated.ignoredLanguages = ignoredLanguages
} else {
var ignoredLanguages = Set<String>()
ignoredLanguages.insert(strongSelf.presentationData.strings.baseLanguageCode)
ignoredLanguages.insert(self.presentationData.strings.baseLanguageCode)
for language in systemLanguageCodes() {
ignoredLanguages.insert(language)
}
@ -4400,11 +4401,11 @@ extension ChatControllerImpl {
}
return updated
}).startStandalone()
let _ = updateChatTranslationStateInteractively(engine: strongSelf.context.engine, peerId: peerId, { current in
let _ = updateChatTranslationStateInteractively(engine: self.context.engine, peerId: peerId, threadId: self.chatLocation.threadId, { current in
return nil
}).startStandalone()
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
var languageCode = presentationData.strings.baseLanguageCode
let rawSuffix = "-raw"
if languageCode.hasSuffix(rawSuffix) {
@ -4413,11 +4414,11 @@ extension ChatControllerImpl {
let locale = Locale(identifier: languageCode)
let fromLanguage: String = locale.localizedString(forLanguageCode: langCode) ?? ""
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_AddedToDoNotTranslateText(fromLanguage).string, round: false, undoText: presentationData.strings.Conversation_Translation_Settings), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in
if case .undo = action, let strongSelf = self {
let controller = translationSettingsController(context: strongSelf.context)
self.present(UndoOverlayController(presentationData: presentationData, content: .image(image: generateTintedImage(image: UIImage(bundleImageName: "Chat/Title Panels/Translate"), color: .white)!, title: nil, text: presentationData.strings.Conversation_Translation_AddedToDoNotTranslateText(fromLanguage).string, round: false, undoText: presentationData.strings.Conversation_Translation_Settings), elevatedLayout: false, animateInAsReplacement: false, action: { [weak self] action in
if case .undo = action, let self {
let controller = translationSettingsController(context: self.context)
controller.navigationPresentation = .modal
strongSelf.push(controller)
self.push(controller)
}
return true
}), in: .current)

View File

@ -1655,7 +1655,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
let translationState: Signal<ChatTranslationState?, NoError>
if let peerId = chatLocation.peerId, peerId.namespace != Namespaces.Peer.SecretChat && peerId != context.account.peerId && subject != .scheduledMessages {
translationState = chatTranslationState(context: context, peerId: peerId)
translationState = chatTranslationState(context: context, peerId: peerId, threadId: self.chatLocation.threadId)
} else {
translationState = .single(nil)
}

View File

@ -115,7 +115,7 @@ final class ChatPremiumRequiredInputPanelNode: ChatInputPanelNode {
}
}
let size = CGSize(width: params.width - params.additionalSideInsets.left * 2.0 - params.leftInset * 2.0, height: height)
let size = CGSize(width: params.width - params.additionalSideInsets.left * 2.0 - params.leftInset * 2.0 - 32.0, height: height)
let buttonSize = self.button.update(
transition: .immediate,
component: AnyComponent(PlainButtonComponent(
@ -136,7 +136,7 @@ final class ChatPremiumRequiredInputPanelNode: ChatInputPanelNode {
if buttonView.superview == nil {
self.view.addSubview(buttonView)
}
transition.setFrame(view: buttonView, frame: CGRect(origin: CGPoint(), size: buttonSize))
transition.setFrame(view: buttonView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((params.width - buttonSize.width) / 2.0), y: 0.0), size: buttonSize))
}
return height

View File

@ -75,9 +75,12 @@ public struct ChatTranslationState: Codable {
}
}
private func cachedChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id) -> Signal<ChatTranslationState?, NoError> {
private func cachedChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id, threadId: Int64?) -> Signal<ChatTranslationState?, NoError> {
let key = EngineDataBuffer(length: 8)
key.setInt64(0, value: peerId.id._internalGetInt64Value())
if let threadId {
key.setInt64(8, value: threadId)
}
return engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key))
|> map { entry -> ChatTranslationState? in
@ -85,9 +88,12 @@ private func cachedChatTranslationState(engine: TelegramEngine, peerId: EnginePe
}
}
private func updateChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id, state: ChatTranslationState?) -> Signal<Never, NoError> {
private func updateChatTranslationState(engine: TelegramEngine, peerId: EnginePeer.Id, threadId: Int64?, state: ChatTranslationState?) -> Signal<Never, NoError> {
let key = EngineDataBuffer(length: 8)
key.setInt64(0, value: peerId.id._internalGetInt64Value())
if let threadId {
key.setInt64(8, value: threadId)
}
if let state {
return engine.itemCache.put(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key, item: state)
@ -96,9 +102,12 @@ private func updateChatTranslationState(engine: TelegramEngine, peerId: EnginePe
}
}
public func updateChatTranslationStateInteractively(engine: TelegramEngine, peerId: EnginePeer.Id, _ f: @escaping (ChatTranslationState?) -> ChatTranslationState?) -> Signal<Never, NoError> {
public func updateChatTranslationStateInteractively(engine: TelegramEngine, peerId: EnginePeer.Id, threadId: Int64?, _ f: @escaping (ChatTranslationState?) -> ChatTranslationState?) -> Signal<Never, NoError> {
let key = EngineDataBuffer(length: 8)
key.setInt64(0, value: peerId.id._internalGetInt64Value())
if let threadId {
key.setInt64(8, value: threadId)
}
return engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: ApplicationSpecificItemCacheCollectionId.translationState, id: key))
|> map { entry -> ChatTranslationState? in
@ -106,7 +115,7 @@ public func updateChatTranslationStateInteractively(engine: TelegramEngine, peer
}
|> mapToSignal { current -> Signal<Never, NoError> in
if let current {
return updateChatTranslationState(engine: engine, peerId: peerId, state: f(current))
return updateChatTranslationState(engine: engine, peerId: peerId, threadId: threadId, state: f(current))
} else {
return .never()
}
@ -166,7 +175,7 @@ public func translateMessageIds(context: AccountContext, messageIds: [EngineMess
} |> switchToLatest
}
public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) -> Signal<ChatTranslationState?, NoError> {
public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64?) -> Signal<ChatTranslationState?, NoError> {
if peerId.id == EnginePeer.Id.Id._internalFromInt64Value(777000) {
return .single(nil)
}
@ -202,7 +211,7 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id)
}
}
return cachedChatTranslationState(engine: context.engine, peerId: peerId)
return cachedChatTranslationState(engine: context.engine, peerId: peerId, threadId: threadId)
|> mapToSignal { cached in
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
if let cached, let timestamp = cached.timestamp, cached.baseLang == baseLang && currentTime - timestamp < 60 * 60 {
@ -214,7 +223,7 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id)
} else {
return .single(nil)
|> then(
context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId: peerId, threadId: nil), index: .upperBound, anchorIndex: .upperBound, count: 32, fixedCombinedReadStates: nil)
context.account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId: peerId, threadId: threadId), index: .upperBound, anchorIndex: .upperBound, count: 32, fixedCombinedReadStates: nil)
|> filter { messageHistoryView -> Bool in
return messageHistoryView.0.entries.count > 1
}
@ -308,7 +317,7 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id)
toLang: cached?.toLang,
isEnabled: isEnabled
)
let _ = updateChatTranslationState(engine: context.engine, peerId: peerId, state: state).start()
let _ = updateChatTranslationState(engine: context.engine, peerId: peerId, threadId: threadId, state: state).start()
if !dontTranslateLanguages.contains(fromLang) {
return state
} else {