Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2026-03-28 15:55:56 +01:00
commit 0fc60571fe
10 changed files with 60 additions and 55 deletions

View file

@ -1562,7 +1562,6 @@ public protocol SharedAccountContext: AnyObject {
context: AccountContext,
theme: PresentationTheme?,
mode: TextProcessingScreenMode,
ignoredTranslationLanguages: [String],
inputText: TextWithEntities,
copyResult: ((TextWithEntities) -> Void)?,
translateChat: ((String) -> Void)?

View file

@ -762,14 +762,6 @@ public class AttachmentController: ViewController, MinimizableController {
return
}
let sharedDataEntries = await controller.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]).get()
let translationSettings: TranslationSettings
if let value = sharedDataEntries.entries[ApplicationSpecificSharedDataKeys.translationSettings], let parsedValue = value.get(TranslationSettings.self) {
translationSettings = parsedValue
} else {
translationSettings = .defaultSettings
}
let textProcessingScreen = await controller.context.sharedContext.makeTextProcessingScreen(
context: controller.context,
theme: self.presentationData.theme,
@ -791,7 +783,6 @@ public class AttachmentController: ViewController, MinimizableController {
},
sendContextActions: nil
),
ignoredTranslationLanguages: translationSettings.ignoredLanguages ?? [],
inputText: TextWithEntities(text: caption.string, entities: []),
copyResult: nil,
translateChat: nil

View file

@ -817,7 +817,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
case let .reference(reference):
if let transitionInfo = reference.transitionInfo() {
if let referenceView = transitionInfo.referenceView as? ContextExtractableContainer {
if #available(iOS 26.0, *) {
if #available(iOS 26.2, *) {
if transitionInfo.referenceView.bounds.width == transitionInfo.referenceView.bounds.height {
contextExtractableContainer = (referenceView, convertFrame(transitionInfo.referenceView.bounds.inset(by: transitionInfo.insets), from: transitionInfo.referenceView, to: self.view))
}

View file

@ -357,14 +357,6 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
entities = generateTextEntities(inputText.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(inputText, maxAnimatedEmojisInText: 0))
}
let sharedDataEntries = await self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]).get()
let translationSettings: TranslationSettings
if let value = sharedDataEntries.entries[ApplicationSpecificSharedDataKeys.translationSettings], let parsedValue = value.get(TranslationSettings.self) {
translationSettings = parsedValue
} else {
translationSettings = .defaultSettings
}
self.pushViewController(await self.context.sharedContext.makeTextProcessingScreen(
context: self.context,
theme: defaultDarkColorPresentationTheme,
@ -379,7 +371,6 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
send: nil,
sendContextActions: nil
),
ignoredTranslationLanguages: translationSettings.ignoredLanguages ?? [],
inputText: TextWithEntities(text: inputText.string, entities: entities),
copyResult: { [weak self] text in
guard let self else {

View file

@ -30,7 +30,6 @@ final class TextProcessingLanguageSelectionComponent: Component {
let sourceView: UIView
let topLanguages: [Language]
let selectedLanguageCode: String
let ignoredTranslationLanguages: [String]
let currentStyle: TelegramComposeAIMessageMode.StyleId
let displayStyles: [TextProcessingScreen.Style]?
let completion: (String, TelegramComposeAIMessageMode.StyleId) -> Void
@ -44,7 +43,6 @@ final class TextProcessingLanguageSelectionComponent: Component {
sourceView: UIView,
topLanguages: [Language],
selectedLanguageCode: String,
ignoredTranslationLanguages: [String],
currentStyle: TelegramComposeAIMessageMode.StyleId,
displayStyles: [TextProcessingScreen.Style]?,
completion: @escaping (String, TelegramComposeAIMessageMode.StyleId) -> Void,
@ -57,7 +55,6 @@ final class TextProcessingLanguageSelectionComponent: Component {
self.sourceView = sourceView
self.topLanguages = topLanguages
self.selectedLanguageCode = selectedLanguageCode
self.ignoredTranslationLanguages = ignoredTranslationLanguages
self.currentStyle = currentStyle
self.displayStyles = displayStyles
self.completion = completion
@ -78,9 +75,6 @@ final class TextProcessingLanguageSelectionComponent: Component {
if lhs.selectedLanguageCode != rhs.selectedLanguageCode {
return false
}
if lhs.ignoredTranslationLanguages != rhs.ignoredTranslationLanguages {
return false
}
if lhs.currentStyle != rhs.currentStyle {
return false
}
@ -407,9 +401,6 @@ final class TextProcessingLanguageSelectionComponent: Component {
if self.mainItems.isEmpty {
self.mainItems = supportedTranslationLanguages.compactMap { item in
if component.ignoredTranslationLanguages.contains(item) {
return nil
}
return Language(id: item, languageCode: item, name: localizedLanguageName(strings: component.strings, language: item, kind: .neutral))
}
var topIds: [String] = []

View file

@ -43,6 +43,7 @@ final class TextProcessingContentComponent: Component {
let styles: [TextProcessingScreen.Style]
let inputText: TextWithEntities
let initialEditState: TextProcessingScreen.EditState?
let ignoredTranslationLanguages: [String]
let shouldDisplayStyleNotice: Bool
let copyCurrentResult: (() -> Void)?
let translateChat: ((String) -> Void)?
@ -55,6 +56,7 @@ final class TextProcessingContentComponent: Component {
styles: [TextProcessingScreen.Style],
inputText: TextWithEntities,
initialEditState: TextProcessingScreen.EditState?,
ignoredTranslationLanguages: [String],
shouldDisplayStyleNotice: Bool,
copyCurrentResult: (() -> Void)?,
translateChat: ((String) -> Void)?,
@ -66,6 +68,7 @@ final class TextProcessingContentComponent: Component {
self.mode = mode
self.inputText = inputText
self.initialEditState = initialEditState
self.ignoredTranslationLanguages = ignoredTranslationLanguages
self.shouldDisplayStyleNotice = shouldDisplayStyleNotice
self.copyCurrentResult = copyCurrentResult
self.translateChat = translateChat
@ -351,7 +354,7 @@ final class TextProcessingContentComponent: Component {
styles: component.styles,
externalState: self.translateState,
inputText: component.inputText,
mode: .translate,
mode: .translate(ignoredLanguages: component.ignoredTranslationLanguages),
copyAction: component.copyCurrentResult,
displayLanguageSelectionMenu: component.displayLanguageSelectionMenu,
present: { [weak self] c, a in
@ -816,6 +819,7 @@ private final class TextProcessingSheetComponent: Component {
styles: component.styles,
inputText: component.inputText,
initialEditState: component.initialEditState,
ignoredTranslationLanguages: component.ignoredTranslationLanguages,
shouldDisplayStyleNotice: component.shouldDisplayStyleNotice,
copyCurrentResult: component.copyCurrentResult != nil ? {
copyCurrentResultImpl()
@ -1012,7 +1016,6 @@ private final class TextProcessingSheetComponent: Component {
sourceView: languageSelectionMenuDataValue.sourceView,
topLanguages: [],
selectedLanguageCode: languageSelectionMenuDataValue.currentLanguage,
ignoredTranslationLanguages: component.ignoredTranslationLanguages,
currentStyle: languageSelectionMenuDataValue.currentStyle,
displayStyles: languageSelectionMenuDataValue.displayStyle ? component.styles : nil,
completion: languageSelectionMenuDataValue.completion,
@ -1088,7 +1091,6 @@ public class TextProcessingScreen: ViewControllerComponentContainer {
context: AccountContext,
theme: PresentationTheme? = nil,
mode: Mode,
ignoredTranslationLanguages: [String],
inputText: TextWithEntities,
copyResult: ((TextWithEntities) -> Void)?,
translateChat: ((String) -> Void)?
@ -1115,13 +1117,21 @@ public class TextProcessingScreen: ViewControllerComponentContainer {
TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: ApplicationSpecificPreferencesKeys.textProcessingEditingState(peerId: saveRestoreStateId))
).get()?.get(EditState.self)
}
let sharedDataEntries = await context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]).get()
let translationSettings: TranslationSettings
if let value = sharedDataEntries.entries[ApplicationSpecificSharedDataKeys.translationSettings], let parsedValue = value.get(TranslationSettings.self) {
translationSettings = parsedValue
} else {
translationSettings = .defaultSettings
}
super.init(
context: context,
component: TextProcessingSheetComponent(
context: context,
mode: mode,
ignoredTranslationLanguages: ignoredTranslationLanguages,
ignoredTranslationLanguages: translationSettings.ignoredLanguages ?? [],
styles: styles,
inputText: inputText,
initialEditState: initialEditState,

View file

@ -50,8 +50,8 @@ func localizedLanguageName(strings: PresentationStrings, language: String, kind:
}
final class TextProcessingTranslateContentComponent: Component {
enum Mode {
case translate
enum Mode: Equatable {
case translate(ignoredLanguages: [String])
case stylize
case fix
}
@ -280,13 +280,38 @@ final class TextProcessingTranslateContentComponent: Component {
if component.externalState.result == nil {
switch component.mode {
case .translate:
var languageCode = component.strings.baseLanguageCode
case let .translate(ignoredLanguages):
var baseLang = component.strings.baseLanguageCode
let rawSuffix = "-raw"
if languageCode.hasSuffix(rawSuffix) {
languageCode = String(languageCode.dropLast(rawSuffix.count))
if baseLang.hasSuffix(rawSuffix) {
baseLang = String(baseLang.dropLast(rawSuffix.count))
}
component.externalState.result = (languageCode, nil, [])
var toLanguage = baseLang
let fromLanguage = component.externalState.sourceLanguage ?? ""
if toLanguage == fromLanguage {
if fromLanguage == "en" {
var dontTranslateLanguages = Set<String>()
if !ignoredLanguages.isEmpty {
dontTranslateLanguages = Set(ignoredLanguages)
} else {
dontTranslateLanguages.insert(baseLang)
for language in systemLanguageCodes() {
dontTranslateLanguages.insert(language)
}
}
toLanguage = dontTranslateLanguages.first(where: { $0 != "en" }) ?? "en"
} else {
toLanguage = "en"
}
if toLanguage == "en" && fromLanguage == "en" {
if let anyOtherLanguage = NSLocale.preferredLanguages.first(where: { !$0.hasPrefix("en-") }) {
toLanguage = anyOtherLanguage
}
}
}
component.externalState.result = (toLanguage, nil, [])
self.beginTranslationIfNecessary(reset: false)
case .stylize:
component.externalState.result = ("", component.inputText, [])
@ -303,6 +328,9 @@ final class TextProcessingTranslateContentComponent: Component {
let bottomInset: CGFloat = 14.0
let blockSpacing: CGFloat = 30.0
let fromLanguage = component.externalState.sourceLanguage ?? ""
let fromTitle = localizedLanguageName(strings: component.strings, language: fromLanguage, kind: .translateFrom)
let fromFormat: String
let toFormat: String
var toTitle: String
@ -377,7 +405,7 @@ final class TextProcessingTranslateContentComponent: Component {
theme: component.theme,
strings: component.strings,
titleFormat: fromFormat,
title: localizedLanguageName(strings: component.strings, language: component.externalState.sourceLanguage ?? "", kind: .translateFrom),
title: fromTitle,
titleAction: nil,
isExpanded: (
component.externalState.isSourceTextExpanded,
@ -415,6 +443,13 @@ final class TextProcessingTranslateContentComponent: Component {
}
}
let isTranslate: Bool
if case .translate = component.mode {
isTranslate = true
} else {
isTranslate = false
}
let targetTextSize = self.targetText.update(
transition: transition,
component: AnyComponent(TextProcessingTextAreaComponent(
@ -423,7 +458,7 @@ final class TextProcessingTranslateContentComponent: Component {
strings: component.strings,
titleFormat: toFormat,
title: toTitle,
titleAction: component.mode == .translate ? { [weak self] sourceView in
titleAction: isTranslate ? { [weak self] sourceView in
guard let self, let component = self.component, let result = component.externalState.result else {
return
}
@ -450,7 +485,7 @@ final class TextProcessingTranslateContentComponent: Component {
}
component.copyAction?()
} : nil,
emojify: (component.mode == .translate || component.mode == .stylize) ? (
emojify: (isTranslate || component.mode == .stylize) ? (
component.externalState.emojify,
{ [weak self] in
guard let self, let component = self.component else {

View file

@ -4085,7 +4085,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.push(await TextProcessingScreen(
context: self.context,
mode: .translate(fromLanguage: language),
ignoredTranslationLanguages: translationSettings.ignoredLanguages ?? [],
inputText: TextWithEntities(text: text.string, entities: entities ?? []),
copyResult: canCopy ? { [weak self] text in
guard let self else {

View file

@ -4500,14 +4500,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
}
let sharedDataEntries = await self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]).get()
let translationSettings: TranslationSettings
if let value = sharedDataEntries.entries[ApplicationSpecificSharedDataKeys.translationSettings], let parsedValue = value.get(TranslationSettings.self) {
translationSettings = parsedValue
} else {
translationSettings = .defaultSettings
}
self.controller?.push(await TextProcessingScreen(
context: self.context,
mode: .edit(
@ -4575,7 +4567,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
)
}
),
ignoredTranslationLanguages: translationSettings.ignoredLanguages ?? [],
inputText: TextWithEntities(text: inputText.string, entities: entities),
copyResult: { [weak self] text in
guard let self, let controller = self.controller else {

View file

@ -4375,7 +4375,6 @@ public final class SharedAccountContextImpl: SharedAccountContext {
context: AccountContext,
theme: PresentationTheme?,
mode: TextProcessingScreenMode,
ignoredTranslationLanguages: [String],
inputText: TextWithEntities,
copyResult: ((TextWithEntities) -> Void)?,
translateChat: ((String) -> Void)?
@ -4384,7 +4383,6 @@ public final class SharedAccountContextImpl: SharedAccountContext {
context: context,
theme: theme,
mode: mode,
ignoredTranslationLanguages: ignoredTranslationLanguages,
inputText: inputText,
copyResult: copyResult,
translateChat: translateChat