mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
ab9bc3e655
commit
aeb924b5ff
@ -8733,3 +8733,10 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Premium.Emoji.Description" = "Unlock this emoji and many more by subscribing to Telegram Premium.";
|
||||
"Premium.Emoji.Proceed" = "Unlock Premium Emoji";
|
||||
|
||||
"Localization.TranslateEntireChat" = "Translate Entire Chat";
|
||||
|
||||
"Premium.Translation" = "Real-Time Translation";
|
||||
"Premium.TranslationInfo" = "Real-time translation of channels and chats into other languages.";
|
||||
"Premium.TranslationStandaloneInfo" = "Subscribe to **Telegram Premium** to be able to translate all messages in a chat at once.";
|
||||
"Premium.Translation.Proceed" = "About Telegram Premium";
|
||||
|
@ -859,6 +859,7 @@ public enum PremiumIntroSource {
|
||||
case emojiStatus(PeerId, Int64, TelegramMediaFile?, LoadedStickerPack?)
|
||||
case voiceToText
|
||||
case fasterDownload
|
||||
case translation
|
||||
}
|
||||
|
||||
public enum PremiumDemoSubject {
|
||||
@ -875,6 +876,7 @@ public enum PremiumDemoSubject {
|
||||
case appIcons
|
||||
case animatedEmoji
|
||||
case emojiStatus
|
||||
case translation
|
||||
}
|
||||
|
||||
public protocol ComposeController: ViewController {
|
||||
|
@ -522,7 +522,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
@objc private func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if let item = self.item, let switchView = self.switchNode.view as? UISwitch, case .ended = recognizer.state {
|
||||
if item.enabled {
|
||||
if item.enabled && !item.displayLocked {
|
||||
let value = switchView.isOn
|
||||
item.updated(!value)
|
||||
} else {
|
||||
|
@ -37,6 +37,35 @@ private var phoneBorderImage = {
|
||||
})
|
||||
}()
|
||||
|
||||
private var phoneBorderImage14 = {
|
||||
return generateImage(phoneSize, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
|
||||
context.setFillColor(UIColor(rgb: 0x000000, alpha: 0.5).cgColor)
|
||||
try? drawSvgPath(context, path: "M203.506,7.0 C211.281,0.0 217.844,0.0 223.221,0.439253 C228.851,0.899605 234.245,1.90219 239.377,4.51905 C247.173,8.49411 253.512,14.8369 257.484,22.6384 C260.099,27.7743 261.101,33.1718 261.561,38.8062 C262.0,44.1865 262.0,50.754 262.0,58.5351 V480.465 C262.0,488.246 262.0,494.813 261.561,500.194 C261.101,505.828 260.099,511.226 257.484,516.362 C253.512,524.163 247.173,530.506 239.377,534.481 C234.245,537.098 228.851,538.1 223.221,538.561 C217.844,539.0 211.281,539.0 203.506,539.0 H58.4942 C50.7185,539 44.1556,539.0 38.7791,538.561 C33.1486,538.1 27.7549,537.098 22.6226,534.481 C14.8265,530.506 8.48817,524.163 4.51589,516.362 C1.90086,511.226 0.898976,505.828 0.438946,500.194 C0.0,494.813 0.0,488.246 7.0,480.465 V58.5354 C0.0,50.7541 0.0,44.1866 0.438946,38.8062 C0.898976,33.1718 1.90086,27.7743 4.51589,22.6384 C8.48817,14.8369 14.8265,8.49411 22.6226,4.51905 C27.7549,1.90219 33.1486,0.899605 38.7791,0.439253 C44.1557,-0.0 50.7187,0.0 58.4945,7.0 H203.506 Z ")
|
||||
context.setBlendMode(.copy)
|
||||
context.fill(CGRect(origin: CGPoint(x: 43.0, y: UIScreenPixel), size: CGSize(width: 175.0, height: 8.0)))
|
||||
context.fill(CGRect(origin: CGPoint(x: UIScreenPixel, y: 43.0), size: CGSize(width: 8.0, height: 452.0)))
|
||||
|
||||
context.setBlendMode(.clear)
|
||||
try? drawSvgPath(context, path: "M15.3737,28.1746 C12.1861,34.4352 12.1861,42.6307 12.1861,59.0217 V479.978 C12.1861,496.369 12.1861,504.565 15.3737,510.825 C18.1777,516.332 22.6518,520.81 28.1549,523.615 C34.4111,526.805 42.6009,526.805 58.9805,526.805 H203.02 C219.399,526.805 227.589,526.805 233.845,523.615 C239.348,520.81 243.822,516.332 246.626,510.825 C249.814,504.565 249.814,496.369 249.814,479.978 V59.0217 C249.814,42.6307 249.814,34.4352 246.626,28.1746 C243.822,22.6677 239.348,18.1904 233.845,15.3845 C227.589,12.1946 219.399,12.1946 203.02,12.1946 H58.9805 C42.6009,12.1946 34.4111,12.1946 28.1549,15.3845 C22.6518,18.1904 18.1777,22.6677 15.3737,28.1746 Z ")
|
||||
|
||||
context.setBlendMode(.copy)
|
||||
context.setFillColor(UIColor.black.cgColor)
|
||||
try? drawSvgPath(context, path: "M222.923,4.08542 C217.697,3.65815 211.263,3.65823 203.378,3.65833 H58.6219 C50.7366,3.65823 44.3026,3.65815 39.0768,4.08542 C33.6724,4.52729 28.8133,5.46834 24.2823,7.77863 C17.1741,11.4029 11.395,17.1861 7.77325,24.2992 C5.46457,28.8334 4.52418,33.6959 4.08262,39.1041 C3.65565,44.3336 3.65573,50.7721 3.65583,58.6628 V480.337 C3.65573,488.228 3.65565,494.666 4.08262,499.896 C4.52418,505.304 5.46457,510.167 7.77325,514.701 C11.395,521.814 17.1741,527.597 24.2823,531.221 C28.8133,533.532 33.6724,534.473 39.0768,534.915 C44.3028,535.342 50.737,535.342 58.6226,535.342 H203.377 C211.263,535.342 217.697,535.342 222.923,534.915 C228.328,534.473 233.187,533.532 237.718,531.221 C244.826,527.597 250.605,521.814 254.227,514.701 C256.535,510.167 257.476,505.304 257.917,499.896 C258.344,494.667 258.344,488.228 258.344,480.338 V58.6617 C258.344,50.7714 258.344,44.3333 257.917,39.1041 C257.476,33.6959 256.535,28.8334 254.227,24.2992 C250.605,17.1861 244.826,11.4029 237.718,7.77863 C233.187,5.46834 228.328,4.52729 222.923,4.08542 Z ")
|
||||
|
||||
context.setBlendMode(.clear)
|
||||
try? drawSvgPath(context, path: "M12.1861,59.0217 C12.1861,42.6306 12.1861,34.4351 15.3737,28.1746 C18.1777,22.6676 22.6519,18.1904 28.1549,15.3844 C34.4111,12.1945 42.6009,12.1945 58.9805,12.1945 H76.6868 H162.561 L185.316,12.1945 H203.02 C219.399,12.1945 227.589,12.1945 233.845,15.3844 C239.348,18.1904 243.822,22.6676 246.626,28.1746 C249.814,34.4351 249.814,42.6306 249.814,59.0217 V479.978 C249.814,496.369 249.814,504.565 246.626,510.825 C243.822,516.332 239.348,520.81 233.845,523.615 C227.589,526.805 219.399,526.805 203.02,526.805 H58.9805 C42.6009,526.805 34.4111,526.805 28.1549,523.615 C22.6519,520.81 18.1777,516.332 15.3737,510.825 C12.1861,504.565 12.1861,496.369 12.1861,479.978 V59.0217 Z ")
|
||||
|
||||
context.setBlendMode(.copy)
|
||||
|
||||
let islandSize = CGSize(width: 76.0, height: 23.0)
|
||||
let island = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: floor((size.width - islandSize.width) / 2.0), y: 17.0), size: islandSize), cornerRadius: islandSize.height / 2.0)
|
||||
context.addPath(island.cgPath)
|
||||
context.fillPath()
|
||||
})
|
||||
}()
|
||||
|
||||
private var phoneBorderMaskImage = {
|
||||
generateImage(phoneSize, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
@ -50,6 +79,19 @@ private var phoneBorderMaskImage = {
|
||||
})
|
||||
}()
|
||||
|
||||
private var phoneBorderMaskImage14 = {
|
||||
generateImage(phoneSize, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
|
||||
context.setStrokeColor(UIColor.white.cgColor)
|
||||
context.setLineWidth(2.0)
|
||||
|
||||
context.translateBy(x: 12.0, y: 12.0 - UIScreenPixel)
|
||||
|
||||
try? drawSvgPath(context, path: " M1.17188,47.3156 C1.17188,39.1084 1.17265,33.013 1.56706,28.1857 C1.96052,23.3701 2.74071,19.9044 4.25094,16.9404 C6.95936,11.6248 11.2811,7.30311 16.5966,4.59469 C19.5606,3.08446 23.0263,2.30427 27.842,1.91081 C32.6693,1.5164 38.7646,1.51562 46.9719,1.51562 H64.6745 H64.6803 L64.8409,1.51754 L173.322,1.51562 H173.328 H191.028 C199.235,1.51562 205.331,1.5164 210.158,1.91081 C214.974,2.30427 218.439,3.08446 221.403,4.59469 C226.719,7.30311 231.041,11.6248 233.749,16.9404 C235.259,19.9044 236.039,23.3701 236.433,28.1857 C236.827,33.013 236.828,39.1084 236.828,47.3156 V468.028 C236.828,476.235 236.827,482.331 236.433,487.158 C236.039,491.974 235.259,495.439 233.749,498.403 C231.041,503.719 226.719,508.041 221.403,510.749 C218.439,512.259 214.974,513.039 210.158,513.433 C205.331,513.827 199.235,513.828 191.028,513.828 H46.9719 C38.7646,513.828 32.6693,513.827 27.842,513.433 C23.0263,513.039 19.5606,512.259 16.5966,510.749 C11.2811,508.041 6.95936,503.719 4.25094,498.403 C2.74071,495.439 1.96052,491.974 1.56706,487.158 C1.17265,482.331 1.17188,476.235 1.17188,468.028 V47.3156 S ")
|
||||
})
|
||||
}()
|
||||
|
||||
private var starMaskImage = {
|
||||
return generateImage(CGSize(width: 88.0, height: 84.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
|
@ -904,6 +904,23 @@ private final class DemoSheetContent: CombinedComponent {
|
||||
)
|
||||
)
|
||||
|
||||
availableItems[.translation] = DemoPagerComponent.Item(
|
||||
AnyComponentWithIdentity(
|
||||
id: PremiumDemoScreen.Subject.translation,
|
||||
component: AnyComponent(
|
||||
PageComponent(
|
||||
content: AnyComponent(AppIconsDemoComponent(
|
||||
context: component.context,
|
||||
appIcons: appIcons
|
||||
)),
|
||||
title: strings.Premium_Translation,
|
||||
text: isStandalone ? strings.Premium_TranslationStandaloneInfo : strings.Premium_TranslationInfo,
|
||||
textColor: textColor
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
var items: [DemoPagerComponent.Item] = component.order.compactMap { availableItems[$0] }
|
||||
let index: Int
|
||||
switch component.source {
|
||||
@ -990,6 +1007,8 @@ private final class DemoSheetContent: CombinedComponent {
|
||||
case .animatedEmoji:
|
||||
buttonText = strings.Premium_AnimatedEmoji_Proceed
|
||||
buttonAnimationName = "premium_unlock"
|
||||
case .translation:
|
||||
buttonText = strings.Premium_Translation_Proceed
|
||||
default:
|
||||
buttonText = strings.Common_OK
|
||||
}
|
||||
@ -1170,6 +1189,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
|
||||
case appIcons
|
||||
case animatedEmoji
|
||||
case emojiStatus
|
||||
case translation
|
||||
}
|
||||
|
||||
public enum Source: Equatable {
|
||||
|
@ -386,6 +386,8 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
||||
demoSubject = .animatedEmoji
|
||||
case .emojiStatus:
|
||||
demoSubject = .emojiStatus
|
||||
case .translation:
|
||||
demoSubject = .translation
|
||||
}
|
||||
|
||||
var dismissImpl: (() -> Void)?
|
||||
|
@ -165,6 +165,12 @@ public enum PremiumSource: Equatable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .translation:
|
||||
if case .translation = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,6 +197,7 @@ public enum PremiumSource: Equatable {
|
||||
case giftTerms
|
||||
case voiceToText
|
||||
case fasterDownload
|
||||
case translation
|
||||
|
||||
var identifier: String? {
|
||||
switch self {
|
||||
@ -242,6 +249,8 @@ public enum PremiumSource: Equatable {
|
||||
} else {
|
||||
return "deeplink"
|
||||
}
|
||||
case .translation:
|
||||
return "translation"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,6 +269,7 @@ enum PremiumPerk: CaseIterable {
|
||||
case appIcons
|
||||
case animatedEmoji
|
||||
case emojiStatus
|
||||
case translation
|
||||
|
||||
static var allCases: [PremiumPerk] {
|
||||
return [
|
||||
@ -275,7 +285,8 @@ enum PremiumPerk: CaseIterable {
|
||||
.animatedUserpics,
|
||||
.appIcons,
|
||||
.animatedEmoji,
|
||||
.emojiStatus
|
||||
.emojiStatus,
|
||||
.translation
|
||||
]
|
||||
}
|
||||
|
||||
@ -317,6 +328,8 @@ enum PremiumPerk: CaseIterable {
|
||||
return "animated_emoji"
|
||||
case .emojiStatus:
|
||||
return "emoji_status"
|
||||
case .translation:
|
||||
return "translation"
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,6 +361,8 @@ enum PremiumPerk: CaseIterable {
|
||||
return strings.Premium_AnimatedEmoji
|
||||
case .emojiStatus:
|
||||
return strings.Premium_EmojiStatus
|
||||
case .translation:
|
||||
return strings.Premium_Translation
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,6 +394,8 @@ enum PremiumPerk: CaseIterable {
|
||||
return strings.Premium_AnimatedEmojiInfo
|
||||
case .emojiStatus:
|
||||
return strings.Premium_EmojiStatusInfo
|
||||
case .translation:
|
||||
return strings.Premium_TranslationInfo
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,6 +427,8 @@ enum PremiumPerk: CaseIterable {
|
||||
return "Premium/Perk/Emoji"
|
||||
case .emojiStatus:
|
||||
return "Premium/Perk/Status"
|
||||
case .translation:
|
||||
return "Premium/Perk/Status"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1646,6 +1665,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
||||
demoSubject = .animatedEmoji
|
||||
case .emojiStatus:
|
||||
demoSubject = .emojiStatus
|
||||
case .translation:
|
||||
demoSubject = .translation
|
||||
}
|
||||
|
||||
let isPremium = state?.isPremium == true
|
||||
|
@ -16,6 +16,7 @@ import SearchUI
|
||||
import UndoUI
|
||||
import TelegramUIPreferences
|
||||
import TranslateUI
|
||||
import PremiumUI
|
||||
|
||||
private enum LanguageListSection: ItemListSectionId {
|
||||
case translate
|
||||
@ -38,6 +39,7 @@ private enum LanguageListEntryType {
|
||||
private enum LanguageListEntry: Comparable, Identifiable {
|
||||
case translateTitle(text: String)
|
||||
case translate(text: String, value: Bool)
|
||||
case translateEntire(text: String, value: Bool, locked: Bool)
|
||||
case doNotTranslate(text: String, value: String)
|
||||
case translateInfo(text: String)
|
||||
|
||||
@ -50,10 +52,12 @@ private enum LanguageListEntry: Comparable, Identifiable {
|
||||
return .translate(0)
|
||||
case .translate:
|
||||
return .translate(1)
|
||||
case .doNotTranslate:
|
||||
case .translateEntire:
|
||||
return .translate(2)
|
||||
case .translateInfo:
|
||||
case .doNotTranslate:
|
||||
return .translate(3)
|
||||
case .translateInfo:
|
||||
return .translate(4)
|
||||
case .localizationTitle:
|
||||
return .localizationTitle
|
||||
case let .localization(index, info, _, _, _, _, _):
|
||||
@ -67,10 +71,12 @@ private enum LanguageListEntry: Comparable, Identifiable {
|
||||
return 0
|
||||
case .translate:
|
||||
return 1
|
||||
case .doNotTranslate:
|
||||
case .translateEntire:
|
||||
return 2
|
||||
case .translateInfo:
|
||||
case .doNotTranslate:
|
||||
return 3
|
||||
case .translateInfo:
|
||||
return 4
|
||||
case .localizationTitle:
|
||||
return 1000
|
||||
case let .localization(index, _, _, _, _, _, _):
|
||||
@ -82,7 +88,7 @@ private enum LanguageListEntry: Comparable, Identifiable {
|
||||
return lhs.index() < rhs.index()
|
||||
}
|
||||
|
||||
func item(presentationData: PresentationData, searchMode: Bool, openSearch: @escaping () -> Void, toggleShowTranslate: @escaping (Bool) -> Void, openDoNotTranslate: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void) -> ListViewItem {
|
||||
func item(presentationData: PresentationData, searchMode: Bool, openSearch: @escaping () -> Void, toggleShowTranslate: @escaping (Bool) -> Void, openDoNotTranslate: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void, showPremiumInfo: @escaping () -> Void) -> ListViewItem {
|
||||
switch self {
|
||||
case let .translateTitle(text):
|
||||
return ItemListSectionHeaderItem(presentationData: ItemListPresentationData(presentationData), text: text, sectionId: LanguageListSection.translate.rawValue)
|
||||
@ -90,6 +96,14 @@ private enum LanguageListEntry: Comparable, Identifiable {
|
||||
return ItemListSwitchItem(presentationData: ItemListPresentationData(presentationData), title: text, value: value, sectionId: LanguageListSection.translate.rawValue, style: .blocks, updated: { value in
|
||||
toggleShowTranslate(value)
|
||||
})
|
||||
case let .translateEntire(text, value, locked):
|
||||
return ItemListSwitchItem(presentationData: ItemListPresentationData(presentationData), title: text, value: value, enableInteractiveChanges: !locked, displayLocked: locked, sectionId: LanguageListSection.translate.rawValue, style: .blocks, updated: { value in
|
||||
if !locked {
|
||||
toggleShowTranslate(value)
|
||||
}
|
||||
}, activatedWhileDisabled: {
|
||||
showPremiumInfo()
|
||||
})
|
||||
case let .doNotTranslate(text, value):
|
||||
return ItemListDisclosureItem(presentationData: ItemListPresentationData(presentationData), title: text, label: value, sectionId: LanguageListSection.translate.rawValue, style: .blocks, action: {
|
||||
openDoNotTranslate()
|
||||
@ -119,8 +133,8 @@ private func preparedLanguageListSearchContainerTransition(presentationData: Pre
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: true, openSearch: {}, toggleShowTranslate: { _ in }, openDoNotTranslate: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: true, openSearch: {}, toggleShowTranslate: { _ in }, openDoNotTranslate: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: true, openSearch: {}, toggleShowTranslate: { _ in }, openDoNotTranslate: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }, showPremiumInfo: {}), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: true, openSearch: {}, toggleShowTranslate: { _ in }, openDoNotTranslate: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }, showPremiumInfo: {}), directionHint: nil) }
|
||||
|
||||
return LocalizationListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching)
|
||||
}
|
||||
@ -307,12 +321,12 @@ private struct LanguageListNodeTransition {
|
||||
let crossfade: Bool
|
||||
}
|
||||
|
||||
private func preparedLanguageListNodeTransition(presentationData: PresentationData, from fromEntries: [LanguageListEntry], to toEntries: [LanguageListEntry], openSearch: @escaping () -> Void, toggleShowTranslate: @escaping (Bool) -> Void, openDoNotTranslate: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void, firstTime: Bool, isLoading: Bool, forceUpdate: Bool, animated: Bool, crossfade: Bool) -> LanguageListNodeTransition {
|
||||
private func preparedLanguageListNodeTransition(presentationData: PresentationData, from fromEntries: [LanguageListEntry], to toEntries: [LanguageListEntry], openSearch: @escaping () -> Void, toggleShowTranslate: @escaping (Bool) -> Void, openDoNotTranslate: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void, showPremiumInfo: @escaping () -> Void, firstTime: Bool, isLoading: Bool, forceUpdate: Bool, animated: Bool, crossfade: Bool) -> LanguageListNodeTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: false, openSearch: openSearch, toggleShowTranslate: toggleShowTranslate, openDoNotTranslate: openDoNotTranslate, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: false, openSearch: openSearch, toggleShowTranslate: toggleShowTranslate, openDoNotTranslate: openDoNotTranslate, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: false, openSearch: openSearch, toggleShowTranslate: toggleShowTranslate, openDoNotTranslate: openDoNotTranslate, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, showPremiumInfo: showPremiumInfo), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: false, openSearch: openSearch, toggleShowTranslate: toggleShowTranslate, openDoNotTranslate: openDoNotTranslate, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, showPremiumInfo: showPremiumInfo), directionHint: nil) }
|
||||
|
||||
return LanguageListNodeTransition(deletions: deletions, insertions: insertions, updates: updates, firstTime: firstTime, isLoading: isLoading, animated: animated, crossfade: crossfade)
|
||||
}
|
||||
@ -461,19 +475,24 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
|
||||
|
||||
if #available(iOS 12.0, *) {
|
||||
entries.append(.translateTitle(text: presentationData.strings.Localization_TranslateMessages.uppercased()))
|
||||
|
||||
entries.append(.translate(text: presentationData.strings.Localization_ShowTranslate, value: showTranslate))
|
||||
if showTranslate {
|
||||
var value = ""
|
||||
if ignoredLanguages.count > 1 {
|
||||
value = ignoredLanguages.joined(separator: ", ")
|
||||
} else if let code = ignoredLanguages.first {
|
||||
let enLocale = Locale(identifier: "en")
|
||||
if let title = enLocale.localizedString(forLanguageCode: code) {
|
||||
value = title
|
||||
}
|
||||
|
||||
entries.append(.translateEntire(text: presentationData.strings.Localization_TranslateEntireChat, value: false, locked: true))
|
||||
|
||||
var value = ""
|
||||
if ignoredLanguages.count > 1 {
|
||||
value = ignoredLanguages.joined(separator: ", ")
|
||||
} else if let code = ignoredLanguages.first {
|
||||
let enLocale = Locale(identifier: "en")
|
||||
if let title = enLocale.localizedString(forLanguageCode: code) {
|
||||
value = title
|
||||
}
|
||||
|
||||
entries.append(.doNotTranslate(text: presentationData.strings.Localization_DoNotTranslate, value: value))
|
||||
}
|
||||
|
||||
entries.append(.doNotTranslate(text: presentationData.strings.Localization_DoNotTranslate, value: value))
|
||||
|
||||
if showTranslate {
|
||||
entries.append(.translateInfo(text: ignoredLanguages.count > 1 ? presentationData.strings.Localization_DoNotTranslateManyInfo : presentationData.strings.Localization_DoNotTranslateInfo))
|
||||
} else {
|
||||
entries.append(.translateInfo(text: presentationData.strings.Localization_ShowTranslateInfoExtended))
|
||||
@ -526,7 +545,17 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
|
||||
if let strongSelf = self {
|
||||
strongSelf.push(translationSettingsController(context: strongSelf.context))
|
||||
}
|
||||
}, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: (previousEntriesAndPresentationData?.0.count ?? 0) != entries.count, crossfade: (previousState == nil || previousState!.availableOfficialLocalizations.isEmpty) != localizationListState.availableOfficialLocalizations.isEmpty)
|
||||
}, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, showPremiumInfo: {
|
||||
var replaceImpl: ((ViewController) -> Void)?
|
||||
let controller = PremiumDemoScreen(context: context, subject: .appIcons, action: {
|
||||
let controller = PremiumIntroScreen(context: context, source: .appIcons)
|
||||
replaceImpl?(controller)
|
||||
})
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
}, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: (previousEntriesAndPresentationData?.0.count ?? 0) != entries.count, crossfade: (previousState == nil || previousState!.availableOfficialLocalizations.isEmpty) != localizationListState.availableOfficialLocalizations.isEmpty)
|
||||
strongSelf.enqueueTransition(transition)
|
||||
})
|
||||
self.updatedDisposable = context.engine.localization.synchronizedLocalizationListState().start()
|
||||
|
@ -6698,7 +6698,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
}
|
||||
|
||||
let searchCategories: Signal<EmojiSearchCategories?, NoError>
|
||||
if isEmojiSelection || isReactionSelection {
|
||||
if isEmojiSelection || isReactionSelection || isProfilePhotoEmojiSelection || isGroupPhotoEmojiSelection {
|
||||
searchCategories = context.engine.stickers.emojiSearchCategories(kind: .emoji)
|
||||
} else if isStatusSelection {
|
||||
searchCategories = context.engine.stickers.emojiSearchCategories(kind: .status)
|
||||
|
@ -1507,6 +1507,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
mappedSource = .voiceToText
|
||||
case .fasterDownload:
|
||||
mappedSource = .fasterDownload
|
||||
case .translation:
|
||||
mappedSource = .translation
|
||||
}
|
||||
return PremiumIntroScreen(context: context, source: mappedSource)
|
||||
}
|
||||
@ -1540,6 +1542,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
mappedSubject = .animatedEmoji
|
||||
case .emojiStatus:
|
||||
mappedSubject = .emojiStatus
|
||||
case .translation:
|
||||
mappedSubject = .translation
|
||||
}
|
||||
return PremiumDemoScreen(context: context, subject: mappedSubject, action: action)
|
||||
}
|
||||
|
@ -5,14 +5,16 @@ import SwiftSignalKit
|
||||
|
||||
public struct TranslationSettings: Codable, Equatable {
|
||||
public var showTranslate: Bool
|
||||
public var translateChats: Bool
|
||||
public var ignoredLanguages: [String]?
|
||||
|
||||
public static var defaultSettings: TranslationSettings {
|
||||
return TranslationSettings(showTranslate: false, ignoredLanguages: nil)
|
||||
return TranslationSettings(showTranslate: false, translateChats: true, ignoredLanguages: nil)
|
||||
}
|
||||
|
||||
init(showTranslate: Bool, ignoredLanguages: [String]?) {
|
||||
init(showTranslate: Bool, translateChats: Bool, ignoredLanguages: [String]?) {
|
||||
self.showTranslate = showTranslate
|
||||
self.translateChats = translateChats
|
||||
self.ignoredLanguages = ignoredLanguages
|
||||
}
|
||||
|
||||
@ -20,6 +22,7 @@ public struct TranslationSettings: Codable, Equatable {
|
||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
self.showTranslate = try container.decodeIfPresent(Bool.self, forKey: "showTranslate") ?? false
|
||||
self.translateChats = try container.decodeIfPresent(Bool.self, forKey: "translateChats") ?? true
|
||||
self.ignoredLanguages = try container.decodeIfPresent([String].self, forKey: "ignoredLanguages")
|
||||
}
|
||||
|
||||
@ -27,19 +30,24 @@ public struct TranslationSettings: Codable, Equatable {
|
||||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
try container.encode(self.showTranslate, forKey: "showTranslate")
|
||||
try container.encode(self.translateChats, forKey: "translateChats")
|
||||
try container.encodeIfPresent(self.ignoredLanguages, forKey: "ignoredLanguages")
|
||||
}
|
||||
|
||||
public static func ==(lhs: TranslationSettings, rhs: TranslationSettings) -> Bool {
|
||||
return lhs.showTranslate == rhs.showTranslate && lhs.ignoredLanguages == rhs.ignoredLanguages
|
||||
return lhs.showTranslate == rhs.showTranslate && lhs.translateChats == rhs.translateChats && lhs.ignoredLanguages == rhs.ignoredLanguages
|
||||
}
|
||||
|
||||
public func withUpdatedShowTranslate(_ showTranslate: Bool) -> TranslationSettings {
|
||||
return TranslationSettings(showTranslate: showTranslate, ignoredLanguages: self.ignoredLanguages)
|
||||
return TranslationSettings(showTranslate: showTranslate, translateChats: self.translateChats, ignoredLanguages: self.ignoredLanguages)
|
||||
}
|
||||
|
||||
public func withUpdatedTranslateChats(_ translateChats: Bool) -> TranslationSettings {
|
||||
return TranslationSettings(showTranslate: self.showTranslate, translateChats: translateChats, ignoredLanguages: self.ignoredLanguages)
|
||||
}
|
||||
|
||||
public func withUpdatedIgnoredLanguages(_ ignoredLanguages: [String]?) -> TranslationSettings {
|
||||
return TranslationSettings(showTranslate: self.showTranslate, ignoredLanguages: ignoredLanguages)
|
||||
return TranslationSettings(showTranslate: self.showTranslate, translateChats: self.translateChats, ignoredLanguages: ignoredLanguages)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user