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

This commit is contained in:
Ilya Laktyushin 2022-04-21 00:59:25 +04:00
commit 2c7c60ffee
14 changed files with 190 additions and 33 deletions

View File

@ -204,7 +204,7 @@ public class ItemListCheckboxItemNode: ItemListRevealOptionsItemNode {
titleColor = item.presentationData.theme.list.itemAccentColor
}
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 28.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let separatorHeight = UIScreenPixel

View File

@ -262,7 +262,7 @@ private final class AudioPlayerWrapper: NSObject, AVAudioPlayerDelegate {
super.init()
self.player = try? AVAudioPlayer(contentsOf: url, fileTypeHint: "m4a")
self.player = try? AVAudioPlayer(contentsOf: url, fileTypeHint: "mp3")
self.player?.delegate = self
}
@ -304,7 +304,7 @@ public func fileNameForNotificationSound(account: Account, notificationSoundList
}
for sound in notificationSoundList.sounds {
if sound.file.fileId.id == fileId {
if let path = account.postbox.mediaBox.completedResourcePath(sound.file.resource, pathExtension: "mp3") {
if let path = account.postbox.mediaBox.completedResourcePath(sound.file.resource, pathExtension: nil) {
return path
}
}
@ -329,7 +329,7 @@ public func playSound(context: AccountContext, notificationSoundList: Notificati
deactivateImpl?()
})
currentPlayer?.play()
} else {
} else if !filePath.isEmpty {
if let url = getAppBundle().url(forResource: filePath, withExtension: "m4a") {
currentPlayer = AudioPlayerWrapper(url: url, completed: {
deactivateImpl?()

View File

@ -68,7 +68,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1071145937] = { return Api.BotCommandScope.parse_botCommandScopePeerAdmins($0) }
dict[169026035] = { return Api.BotCommandScope.parse_botCommandScopePeerUser($0) }
dict[1011811544] = { return Api.BotCommandScope.parse_botCommandScopeUsers($0) }
dict[-863263529] = { return Api.BotInfo.parse_botInfo($0) }
dict[-1892676777] = { return Api.BotInfo.parse_botInfo($0) }
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
dict[416402882] = { return Api.BotInlineMessage.parse_botInlineMessageMediaContact($0) }
dict[85477117] = { return Api.BotInlineMessage.parse_botInlineMessageMediaGeo($0) }

View File

@ -856,18 +856,19 @@ public extension Api {
}
public extension Api {
enum BotInfo: TypeConstructorDescription {
case botInfo(flags: Int32, userId: Int64?, description: String?, descriptionPhoto: Api.Photo?, commands: [Api.BotCommand]?, menuButton: Api.BotMenuButton?)
case botInfo(flags: Int32, userId: Int64?, description: String?, descriptionPhoto: Api.Photo?, descriptionDocument: Api.Document?, commands: [Api.BotCommand]?, menuButton: Api.BotMenuButton?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .botInfo(let flags, let userId, let description, let descriptionPhoto, let commands, let menuButton):
case .botInfo(let flags, let userId, let description, let descriptionPhoto, let descriptionDocument, let commands, let menuButton):
if boxed {
buffer.appendInt32(-863263529)
buffer.appendInt32(-1892676777)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(userId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {descriptionPhoto!.serialize(buffer, true)}
if Int(flags) & Int(1 << 5) != 0 {descriptionDocument!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(commands!.count))
for item in commands! {
@ -880,8 +881,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .botInfo(let flags, let userId, let description, let descriptionPhoto, let commands, let menuButton):
return ("botInfo", [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("description", String(describing: description)), ("descriptionPhoto", String(describing: descriptionPhoto)), ("commands", String(describing: commands)), ("menuButton", String(describing: menuButton))])
case .botInfo(let flags, let userId, let description, let descriptionPhoto, let descriptionDocument, let commands, let menuButton):
return ("botInfo", [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("description", String(describing: description)), ("descriptionPhoto", String(describing: descriptionPhoto)), ("descriptionDocument", String(describing: descriptionDocument)), ("commands", String(describing: commands)), ("menuButton", String(describing: menuButton))])
}
}
@ -896,22 +897,27 @@ public extension Api {
if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Photo
} }
var _5: [Api.BotCommand]?
if Int(_1!) & Int(1 << 2) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotCommand.self)
var _5: Api.Document?
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Document
} }
var _6: Api.BotMenuButton?
var _6: [Api.BotCommand]?
if Int(_1!) & Int(1 << 2) != 0 {if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotCommand.self)
} }
var _7: Api.BotMenuButton?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.BotMenuButton
_7 = Api.parse(reader, signature: signature) as? Api.BotMenuButton
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.BotInfo.botInfo(flags: _1!, userId: _2, description: _3, descriptionPhoto: _4, commands: _5, menuButton: _6)
let _c5 = (Int(_1!) & Int(1 << 5) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.BotInfo.botInfo(flags: _1!, userId: _2, description: _3, descriptionPhoto: _4, descriptionDocument: _5, commands: _6, menuButton: _7)
}
else {
return nil

View File

@ -6697,6 +6697,22 @@ public extension Api.functions.phone {
})
}
}
public extension Api.functions.phone {
static func saveCallLog(peer: Api.InputPhoneCall, file: Api.InputFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(1092913030)
peer.serialize(buffer, true)
file.serialize(buffer, true)
return (FunctionDescription(name: "phone.saveCallLog", parameters: [("peer", String(describing: peer)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
}
public extension Api.functions.phone {
static func saveDefaultGroupCallJoinAs(peer: Api.InputPeer, joinAs: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()

View File

@ -16,7 +16,7 @@ extension BotMenuButton {
extension BotInfo {
convenience init(apiBotInfo: Api.BotInfo) {
switch apiBotInfo {
case let .botInfo(_, _, description, descriptionPhoto, apiCommands, apiMenuButton):
case let .botInfo(_, _, description, descriptionPhoto, _, apiCommands, apiMenuButton):
let photo: TelegramMediaImage? = descriptionPhoto.flatMap(telegramMediaImageFromApiPhoto)
var commands: [BotCommand] = []
if let apiCommands = apiCommands {

View File

@ -226,6 +226,7 @@ private enum MediaReferenceRevalidationKey: Hashable {
case themes
case peerAvatars(peer: PeerReference)
case attachBot(peer: PeerReference)
case notificationSoundList
}
private final class MediaReferenceRevalidationItemContext {
@ -556,6 +557,24 @@ final class MediaReferenceRevalidationContext {
}
}
}
func notificationSoundList(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> {
return self.genericItem(key: .notificationSoundList, background: background, request: { next, error in
return (requestNotificationSoundList(network: network, hash: 0)
|> map { result -> [TelegramMediaFile] in
guard let result = result else {
return []
}
return result.sounds.map(\.file)
}).start(next: next)
}) |> mapToSignal { next -> Signal<[TelegramMediaFile], RevalidateMediaReferenceError> in
if let next = next as? [TelegramMediaFile] {
return .single(next)
} else {
return .fail(.generic)
}
}
}
}
struct RevalidatedMediaResource {
@ -799,6 +818,16 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
}
return .fail(.generic)
}
case let .soundList(resource):
return revalidationContext.notificationSoundList(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation)
|> mapToSignal { files -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
for file in files {
if file.resource.id == resource.id {
return .single(RevalidatedMediaResource(updatedResource: file.resource, updatedReference: nil))
}
}
return .fail(.generic)
}
case .standalone:
return .fail(.generic)
}

View File

@ -627,7 +627,7 @@ private final class CallSessionManagerContext {
if let strongSelf = self {
if let context = strongSelf.contexts[internalId] {
context.state = .terminated(id: id, accessHash: accessHash, reason: .ended(.hungUp), reportRating: reportRating, sendDebugLogs: sendDebugLogs)
if sendDebugLogs {
/*if sendDebugLogs {
let network = strongSelf.network
let _ = (debugLog
|> timeout(5.0, queue: strongSelf.queue, alternate: .single(nil))
@ -636,7 +636,7 @@ private final class CallSessionManagerContext {
let _ = _internal_saveCallDebugLog(network: network, callId: CallId(id: id, accessHash: accessHash), log: debugLog).start()
}
})
}
}*/
strongSelf.contextUpdated(internalId: internalId)
if context.isEmpty {
strongSelf.contexts.removeValue(forKey: internalId)

View File

@ -569,6 +569,7 @@ public enum MediaResourceReference: Equatable {
case wallpaper(wallpaper: WallpaperReference?, resource: MediaResource)
case stickerPackThumbnail(stickerPack: StickerPackReference, resource: MediaResource)
case theme(theme: ThemeReference, resource: MediaResource)
case soundList(resource: MediaResource)
public var resource: MediaResource {
switch self {
@ -588,6 +589,8 @@ public enum MediaResourceReference: Equatable {
return resource
case let .theme(_, resource):
return resource
case let .soundList(resource):
return resource
}
}
@ -641,6 +644,12 @@ public enum MediaResourceReference: Equatable {
} else {
return false
}
case let .soundList(lhsResource):
if case let .soundList(rhsResource) = rhs, lhsResource.isEqual(to: rhsResource) {
return true
} else {
return false
}
}
}
}

View File

@ -14,13 +14,74 @@ func _internal_rateCall(account: Account, callId: CallId, starsCount: Int32, com
|> map { _ in }
}
func _internal_saveCallDebugLog(network: Network, callId: CallId, log: String) -> Signal<Void, NoError> {
public enum SaveCallDebugLogResult {
case done
case sendFullLog
}
func _internal_saveCallDebugLog(network: Network, callId: CallId, log: String) -> Signal<SaveCallDebugLogResult, NoError> {
if log.count > 1024 * 16 {
return .complete()
}
return network.request(Api.functions.phone.saveCallDebug(peer: Api.InputPhoneCall.inputPhoneCall(id: callId.id, accessHash: callId.accessHash), debug: .dataJSON(data: log)))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
return .single(.boolTrue)
}
|> map { result -> SaveCallDebugLogResult in
switch result {
case .boolFalse:
return .sendFullLog
case .boolTrue:
return .done
}
}
}
func _internal_saveCompleteCallDebugLog(account: Account, callId: CallId, logPath: String) -> Signal<Never, NoError> {
let tempFile = TempBox.shared.tempFile(fileName: "log.txt.gz")
do {
guard let data = try? Data(contentsOf: URL(fileURLWithPath: logPath), options: .mappedIfSafe) else {
Logger.shared.log("saveCompleteCallDebugLog", "Failed to open log file")
return .complete()
}
guard let gzippedData = MTGzip.compress(data) else {
Logger.shared.log("saveCompleteCallDebugLog", "Failed to compress log file")
return .complete()
}
guard let _ = try? gzippedData.write(to: URL(fileURLWithPath: tempFile.path), options: .atomic) else {
Logger.shared.log("saveCompleteCallDebugLog", "Failed to write compressed log file")
return .complete()
}
}
guard let size = fileSize(tempFile.path) else {
Logger.shared.log("saveCompleteCallDebugLog", "Could not get log file size")
return .complete()
}
return multipartUpload(network: account.network, postbox: account.postbox, source: .tempFile(tempFile), encrypt: false, tag: nil, hintFileSize: size, hintFileIsLarge: false, forceNoBigParts: true, useLargerParts: false)
|> mapToSignal { value -> Signal<Never, MultipartUploadError> in
switch value {
case .progress:
return .complete()
case let .inputFile(inputFile):
return account.network.request(Api.functions.phone.saveCallLog(peer: Api.InputPhoneCall.inputPhoneCall(id: callId.id, accessHash: callId.accessHash), file: inputFile))
|> mapError { _ -> MultipartUploadError in
return .generic
}
|> ignoreValues
case .inputSecretFile:
return .fail(.generic)
}
}
|> `catch` { _ -> Signal<Never, NoError> in
return .complete()
}
|> map { _ in }
}

View File

@ -25,9 +25,13 @@ public extension TelegramEngine {
return _internal_rateCall(account: self.account, callId: callId, starsCount: starsCount, comment: comment, userInitiated: userInitiated)
}
public func saveCallDebugLog(callId: CallId, log: String) -> Signal<Void, NoError> {
public func saveCallDebugLog(callId: CallId, log: String) -> Signal<SaveCallDebugLogResult, NoError> {
return _internal_saveCallDebugLog(network: self.account.network, callId: callId, log: log)
}
public func saveCompleteCallDebugLog(callId: CallId, logPath: String) -> Signal<Never, NoError> {
return _internal_saveCompleteCallDebugLog(account: self.account, callId: callId, logPath: logPath)
}
public func getCurrentGroupCall(callId: Int64, accessHash: Int64, peerId: PeerId? = nil) -> Signal<GroupCallSummary?, GetCurrentGroupCallError> {
return _internal_getCurrentGroupCall(account: self.account, callId: callId, accessHash: accessHash, peerId: peerId)

View File

@ -152,7 +152,7 @@ public func ensureDownloadedNotificationSoundList(postbox: Postbox) -> Signal<Ne
for resource in resources {
signals.append(
fetchedMediaResource(mediaBox: postbox.mediaBox, reference: .standalone(resource: resource))
fetchedMediaResource(mediaBox: postbox.mediaBox, reference: .soundList(resource: resource))
|> ignoreValues
|> `catch` { _ -> Signal<Never, NoError> in
return .complete()
@ -168,6 +168,30 @@ public func ensureDownloadedNotificationSoundList(postbox: Postbox) -> Signal<Ne
|> ignoreValues
}
func requestNotificationSoundList(network: Network, hash: Int64) -> Signal<NotificationSoundList?, NoError> {
return network.request(Api.functions.account.getSavedRingtones(hash: hash))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.account.SavedRingtones?, NoError> in
return .single(nil)
}
|> map { result -> NotificationSoundList? in
guard let result = result else {
return nil
}
switch result {
case let .savedRingtones(hash, ringtones):
let notificationSoundList = NotificationSoundList(
hash: hash,
sounds: ringtones.compactMap(NotificationSoundList.NotificationSound.init(apiDocument:))
)
return notificationSoundList
case .savedRingtonesNotModified:
return nil
}
}
}
private func pollNotificationSoundList(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
return Signal<Never, NoError> { subscriber in
let signal: Signal<Never, NoError> = _internal_cachedNotificationSoundList(postbox: postbox)
@ -204,7 +228,7 @@ private func pollNotificationSoundList(postbox: Postbox, network: Network) -> Si
for resource in resources {
signals.append(
fetchedMediaResource(mediaBox: postbox.mediaBox, reference: .standalone(resource: resource))
fetchedMediaResource(mediaBox: postbox.mediaBox, reference: .soundList(resource: resource))
|> ignoreValues
|> `catch` { _ -> Signal<Never, NoError> in
return .complete()

View File

@ -278,7 +278,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
var botInfos: [CachedPeerBotInfo] = []
for botInfo in chatFullBotInfo ?? [] {
switch botInfo {
case let .botInfo(_, userId, _, _, _, _):
case let .botInfo(_, userId, _, _, _, _, _):
if let userId = userId {
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
let parsedBotInfo = BotInfo(apiBotInfo: botInfo)
@ -451,7 +451,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
var botInfos: [CachedPeerBotInfo] = []
for botInfo in apiBotInfos {
switch botInfo {
case let .botInfo(_, userId, _, _, _, _):
case let .botInfo(_, userId, _, _, _, _, _):
if let userId = userId {
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
let parsedBotInfo = BotInfo(apiBotInfo: botInfo)

View File

@ -943,9 +943,17 @@ public final class OngoingCallContext {
if let callId = callId, !statsLogPath.isEmpty, let data = try? Data(contentsOf: URL(fileURLWithPath: statsLogPath)), let dataString = String(data: data, encoding: .utf8) {
debugLogValue.set(.single(dataString))
if sendDebugLogs {
let _ = TelegramEngine(account: self.account).calls.saveCallDebugLog(callId: callId, log: dataString).start()
}
let engine = TelegramEngine(account: self.account)
let _ = engine.calls.saveCallDebugLog(callId: callId, log: dataString).start(next: { result in
switch result {
case .sendFullLog:
if !logPath.isEmpty {
let _ = engine.calls.saveCompleteCallDebugLog(callId: callId, logPath: logPath).start()
}
case .done:
break
}
})
}
}
let derivedState = context.nativeGetDerivedState()