Various fixes

This commit is contained in:
Ilya Laktyushin 2023-01-28 00:03:52 +04:00
parent b1ca18df4e
commit 6000760416
11 changed files with 169 additions and 66 deletions

View File

@ -8844,3 +8844,5 @@ Sorry for the inconvenience.";
"EmojiInput.TrendingEmoji" = "TRENDING EMOJI"; "EmojiInput.TrendingEmoji" = "TRENDING EMOJI";
"Chat.PlaceholderTextNotAllowed" = "Text not allowed"; "Chat.PlaceholderTextNotAllowed" = "Text not allowed";
"CallList.DeleteAll" = "Delete All";

View File

@ -39,7 +39,7 @@ private final class DeleteAllButtonNode: ASDisplayNode {
self.buttonNode.addSubnode(self.titleNode) self.buttonNode.addSubnode(self.titleNode)
self.contentNode.contentNode.addSubnode(self.buttonNode) self.contentNode.contentNode.addSubnode(self.buttonNode)
self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.Notification_Exceptions_DeleteAll, font: Font.regular(17.0), textColor: presentationData.theme.rootController.navigationBar.accentTextColor) self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.CallList_DeleteAll, font: Font.regular(17.0), textColor: presentationData.theme.rootController.navigationBar.accentTextColor)
//self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) //self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
} }

View File

@ -183,7 +183,7 @@ private final class LegacyComponentsGlobalsProviderImpl: NSObject, LegacyCompone
switch type { switch type {
case TGAudioSessionTypePlayAndRecord, TGAudioSessionTypePlayAndRecordHeadphones: case TGAudioSessionTypePlayAndRecord, TGAudioSessionTypePlayAndRecordHeadphones:
if legacyContext.sharedContext.currentMediaInputSettings.with({ $0 }).pauseMusicOnRecording { if legacyContext.sharedContext.currentMediaInputSettings.with({ $0 }).pauseMusicOnRecording {
convertedType = .record(speaker: false) convertedType = .record(speaker: false, withOthers: false)
} else { } else {
convertedType = .recordWithOthers convertedType = .recordWithOthers
} }

View File

@ -333,7 +333,8 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
UIColor(rgb: 0x5A6EEE), UIColor(rgb: 0x5A6EEE),
UIColor(rgb: 0x548DFF), UIColor(rgb: 0x548DFF),
UIColor(rgb: 0x54A3FF), UIColor(rgb: 0x54A3FF),
UIColor(rgb: 0x54bdff) UIColor(rgb: 0x54bdff),
UIColor(rgb: 0x71c8ff)
] ]
i = 0 i = 0

View File

@ -18,7 +18,7 @@ public enum ManagedAudioSessionType: Equatable {
case ambient case ambient
case play case play
case playWithPossiblePortOverride case playWithPossiblePortOverride
case record(speaker: Bool) case record(speaker: Bool, withOthers: Bool)
case voiceCall case voiceCall
case videoCall case videoCall
case recordWithOthers case recordWithOthers
@ -587,7 +587,14 @@ public final class ManagedAudioSession {
index += 1 index += 1
} }
let lastIsRecordWithOthers = self.holders.last?.audioSessionType == .recordWithOthers var lastIsRecordWithOthers = false
if let lastHolder = self.holders.last {
if case let .record(_, withOthers) = lastHolder.audioSessionType {
lastIsRecordWithOthers = withOthers
} else if case .recordWithOthers = lastHolder.audioSessionType {
lastIsRecordWithOthers = true
}
}
if !deactivating { if !deactivating {
if let activeIndex = activeIndex { if let activeIndex = activeIndex {
var deactivate = false var deactivate = false
@ -896,13 +903,13 @@ public final class ManagedAudioSession {
if resetToBuiltin { if resetToBuiltin {
var updatedType = type var updatedType = type
if case .record(false) = updatedType, self.isHeadsetPluggedInValue { if case .record(false, let withOthers) = updatedType, self.isHeadsetPluggedInValue {
updatedType = .record(speaker: true) updatedType = .record(speaker: true, withOthers: withOthers)
} }
switch updatedType { switch updatedType {
case .record(false): case .record(false, _):
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker) try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
case .voiceCall, .playWithPossiblePortOverride, .record(true): case .voiceCall, .playWithPossiblePortOverride, .record(true, _):
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none) try AVAudioSession.sharedInstance().overrideOutputAudioPort(.none)
if let routes = AVAudioSession.sharedInstance().availableInputs { if let routes = AVAudioSession.sharedInstance().availableInputs {
var alreadySet = false var alreadySet = false

View File

@ -356,11 +356,11 @@ public extension TelegramEngine {
return EngineMessageReactionListContext(account: self.account, message: message, reaction: reaction) return EngineMessageReactionListContext(account: self.account, message: message, reaction: reaction)
} }
public func translate(text: String, toLang: String) -> Signal<String?, NoError> { public func translate(text: String, toLang: String) -> Signal<String?, TranslationError> {
return _internal_translate(network: self.account.network, text: text, toLang: toLang) return _internal_translate(network: self.account.network, text: text, toLang: toLang)
} }
public func translateMessages(messageIds: [EngineMessage.Id], toLang: String) -> Signal<Void, NoError> { public func translateMessages(messageIds: [EngineMessage.Id], toLang: String) -> Signal<Void, TranslationError> {
return _internal_translateMessages(account: self.account, messageIds: messageIds, toLang: toLang) return _internal_translateMessages(account: self.account, messageIds: messageIds, toLang: toLang)
} }

View File

@ -4,19 +4,36 @@ import SwiftSignalKit
import TelegramApi import TelegramApi
import MtProtoKit import MtProtoKit
func _internal_translate(network: Network, text: String, toLang: String) -> Signal<String?, NoError> { public enum TranslationError {
case generic
case invalidMessageId
case textIsEmpty
case textTooLong
case invalidLanguage
case limitExceeded
}
func _internal_translate(network: Network, text: String, toLang: String) -> Signal<String?, TranslationError> {
var flags: Int32 = 0 var flags: Int32 = 0
flags |= (1 << 1) flags |= (1 << 1)
return network.request(Api.functions.messages.translateText(flags: flags, peer: nil, id: nil, text: [.textWithEntities(text: text, entities: [])], toLang: toLang)) return network.request(Api.functions.messages.translateText(flags: flags, peer: nil, id: nil, text: [.textWithEntities(text: text, entities: [])], toLang: toLang))
|> map(Optional.init) |> mapError { error -> TranslationError in
|> `catch` { _ -> Signal<Api.messages.TranslatedText?, NoError> in if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .single(nil) return .limitExceeded
} } else if error.errorDescription == "MSG_ID_INVALID" {
|> mapToSignal { result -> Signal<String?, NoError> in return .invalidMessageId
guard let result = result else { } else if error.errorDescription == "INPUT_TEXT_EMPTY" {
return .complete() return .textIsEmpty
} else if error.errorDescription == "INPUT_TEXT_TOO_LONG" {
return .textTooLong
} else if error.errorDescription == "TO_LANG_INVALID" {
return .invalidLanguage
} else {
return .generic
} }
}
|> mapToSignal { result -> Signal<String?, TranslationError> in
switch result { switch result {
case let .translateResult(results): case let .translateResult(results):
if case let .textWithEntities(text, _) = results.first { if case let .textWithEntities(text, _) = results.first {
@ -28,14 +45,15 @@ func _internal_translate(network: Network, text: String, toLang: String) -> Sign
} }
} }
func _internal_translateMessages(account: Account, messageIds: [EngineMessage.Id], toLang: String) -> Signal<Void, NoError> { func _internal_translateMessages(account: Account, messageIds: [EngineMessage.Id], toLang: String) -> Signal<Void, TranslationError> {
guard let peerId = messageIds.first?.peerId else { guard let peerId = messageIds.first?.peerId else {
return .never() return .never()
} }
return account.postbox.transaction { transaction -> Api.InputPeer? in return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(peerId).flatMap(apiInputPeer) return transaction.getPeer(peerId).flatMap(apiInputPeer)
} }
|> mapToSignal { inputPeer -> Signal<Void, NoError> in |> castError(TranslationError.self)
|> mapToSignal { inputPeer -> Signal<Void, TranslationError> in
guard let inputPeer = inputPeer else { guard let inputPeer = inputPeer else {
return .never() return .never()
} }
@ -45,12 +63,23 @@ func _internal_translateMessages(account: Account, messageIds: [EngineMessage.Id
let id: [Int32] = messageIds.map { $0.id } let id: [Int32] = messageIds.map { $0.id }
return account.network.request(Api.functions.messages.translateText(flags: flags, peer: inputPeer, id: id, text: nil, toLang: toLang)) return account.network.request(Api.functions.messages.translateText(flags: flags, peer: inputPeer, id: id, text: nil, toLang: toLang))
|> map(Optional.init) |> mapError { error -> TranslationError in
|> `catch` { _ -> Signal<Api.messages.TranslatedText?, NoError> in if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .single(nil) return .limitExceeded
} else if error.errorDescription == "MSG_ID_INVALID" {
return .invalidMessageId
} else if error.errorDescription == "INPUT_TEXT_EMPTY" {
return .textIsEmpty
} else if error.errorDescription == "INPUT_TEXT_TOO_LONG" {
return .textTooLong
} else if error.errorDescription == "TO_LANG_INVALID" {
return .invalidLanguage
} else {
return .generic
}
} }
|> mapToSignal { result -> Signal<Void, NoError> in |> mapToSignal { result -> Signal<Void, TranslationError> in
guard let result = result, case let .translateResult(results) = result else { guard case let .translateResult(results) = result else {
return .complete() return .complete()
} }
return account.postbox.transaction { transaction in return account.postbox.transaction { transaction in
@ -71,6 +100,7 @@ func _internal_translateMessages(account: Account, messageIds: [EngineMessage.Id
index += 1 index += 1
} }
} }
|> castError(TranslationError.self)
} }
} }
} }

View File

@ -34,6 +34,25 @@ enum AvatarBackground: Equatable {
} }
} }
var isLight: Bool {
switch self {
case let .gradient(colors):
if colors.count == 1 {
return UIColor(rgb: colors.first!).lightness > 0.99
} else if colors.count == 2 {
return UIColor(rgb: colors.first!).lightness > 0.99 || UIColor(rgb: colors.last!).lightness > 0.99
} else {
var lightCount = 0
for color in colors {
if UIColor(rgb: color).lightness > 0.99 {
lightCount += 1
}
}
return lightCount >= 2
}
}
}
func generateImage(size: CGSize) -> UIImage { func generateImage(size: CGSize) -> UIImage {
switch self { switch self {
case let .gradient(colors): case let .gradient(colors):
@ -313,31 +332,28 @@ final class AvatarEditorScreenComponent: Component {
) )
} }
} }
let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|> map { peer -> Bool in
guard case let .user(user) = peer else {
return false
}
return user.isPremium
}
|> distinctUntilChanged
let resultSignal = signal let resultSignal = signal
|> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in |> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
return combineLatest( return combineLatest(
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000) |> take(1),
context.engine.stickers.availableReactions(), combineLatest(keywords.map { context.engine.stickers.searchStickers(query: $0.emoticons)
hasPremium |> map { items -> [FoundStickerItem] in
return items.items
}
})
) )
|> take(1) |> map { view, stickers -> [EmojiPagerContentComponent.ItemGroup] in
|> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in let hasPremium = true
var result: [(String, TelegramMediaFile?, String)] = []
var emoji: [(String, TelegramMediaFile?, String)] = []
var existingEmoticons = Set<String>()
var allEmoticons: [String: String] = [:] var allEmoticons: [String: String] = [:]
for keyword in keywords { for keyword in keywords {
for emoticon in keyword.emoticons { for emoticon in keyword.emoticons {
allEmoticons[emoticon] = keyword.keyword allEmoticons[emoticon] = keyword.keyword
existingEmoticons.insert(emoticon)
} }
} }
@ -350,9 +366,9 @@ final class AvatarEditorScreenComponent: Component {
case let .CustomEmoji(_, _, alt, _): case let .CustomEmoji(_, _, alt, _):
if !item.file.isPremiumEmoji || hasPremium { if !item.file.isPremiumEmoji || hasPremium {
if !alt.isEmpty, let keyword = allEmoticons[alt] { if !alt.isEmpty, let keyword = allEmoticons[alt] {
result.append((alt, item.file, keyword)) emoji.append((alt, item.file, keyword))
} else if alt == query { } else if alt == query {
result.append((alt, item.file, alt)) emoji.append((alt, item.file, alt))
} }
} }
default: default:
@ -361,10 +377,10 @@ final class AvatarEditorScreenComponent: Component {
} }
} }
var items: [EmojiPagerContentComponent.Item] = [] var emojiItems: [EmojiPagerContentComponent.Item] = []
var existingIds = Set<MediaId>() var existingIds = Set<MediaId>()
for item in result { for item in emoji {
if let itemFile = item.1 { if let itemFile = item.1 {
if existingIds.contains(itemFile.fileId) { if existingIds.contains(itemFile.fileId) {
continue continue
@ -378,25 +394,71 @@ final class AvatarEditorScreenComponent: Component {
icon: .none, icon: .none,
tintMode: animationData.isTemplate ? .primary : .none tintMode: animationData.isTemplate ? .primary : .none
) )
items.append(item) emojiItems.append(item)
} }
} }
return [EmojiPagerContentComponent.ItemGroup( var stickerItems: [EmojiPagerContentComponent.Item] = []
supergroupId: "search", for stickerResult in stickers {
groupId: "search", for sticker in stickerResult {
title: nil, if existingIds.contains(sticker.file.fileId) {
subtitle: nil, continue
actionButtonTitle: nil, }
isFeatured: false,
isPremiumLocked: false, existingIds.insert(sticker.file.fileId)
isEmbedded: false, let animationData = EntityKeyboardAnimationData(file: sticker.file)
hasClear: false, let item = EmojiPagerContentComponent.Item(
collapsedLineCount: nil, animationData: animationData,
displayPremiumBadges: false, content: .animation(animationData),
headerItem: nil, itemFile: sticker.file,
items: items subgroupId: nil,
)] icon: .none,
tintMode: .none
)
stickerItems.append(item)
}
}
var result: [EmojiPagerContentComponent.ItemGroup] = []
if !emojiItems.isEmpty {
result.append(
EmojiPagerContentComponent.ItemGroup(
supergroupId: "search",
groupId: "emoji",
title: "Emoji",
subtitle: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
isEmbedded: false,
hasClear: false,
collapsedLineCount: nil,
displayPremiumBadges: false,
headerItem: nil,
items: emojiItems
)
)
}
if !stickerItems.isEmpty {
result.append(
EmojiPagerContentComponent.ItemGroup(
supergroupId: "search",
groupId: "stickers",
title: "Stickers",
subtitle: nil,
actionButtonTitle: nil,
isFeatured: false,
isPremiumLocked: false,
isEmbedded: false,
hasClear: false,
collapsedLineCount: nil,
displayPremiumBadges: false,
headerItem: nil,
items: stickerItems
)
)
}
return result
} }
} }

View File

@ -395,10 +395,10 @@ final class ManagedAudioRecorderContext {
} }
let _ = self.audioUnit.swap(audioUnit) let _ = self.audioUnit.swap(audioUnit)
if self.audioSessionDisposable == nil { if self.audioSessionDisposable == nil {
let queue = self.queue let queue = self.queue
self.audioSessionDisposable = self.mediaManager.audioSession.push(audioSessionType: .record(speaker: self.beginWithTone), activate: { [weak self] state in self.audioSessionDisposable = self.mediaManager.audioSession.push(audioSessionType: .record(speaker: self.beginWithTone, withOthers: false), activate: { [weak self] state in
queue.async { queue.async {
if let strongSelf = self, !strongSelf.paused { if let strongSelf = self, !strongSelf.paused {
strongSelf.hasAudioSession = true strongSelf.hasAudioSession = true

View File

@ -44,8 +44,6 @@ private struct GlobalControlOptions: OptionSet {
static let seek = GlobalControlOptions(rawValue: 1 << 5) static let seek = GlobalControlOptions(rawValue: 1 << 5)
} }
public var test: Double?
public final class MediaManagerImpl: NSObject, MediaManager { public final class MediaManagerImpl: NSObject, MediaManager {
public static var globalAudioSession: ManagedAudioSession { public static var globalAudioSession: ManagedAudioSession {
return sharedAudioSession return sharedAudioSession

View File

@ -144,6 +144,9 @@ public func translateMessageIds(context: AccountContext, messageIds: [EngineMess
} }
} }
return context.engine.messages.translateMessages(messageIds: messageIdsToTranslate, toLang: toLang) return context.engine.messages.translateMessages(messageIds: messageIdsToTranslate, toLang: toLang)
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
}
} |> switchToLatest } |> switchToLatest
} }