Peer sound and message removal update

This commit is contained in:
Ali 2022-03-30 01:22:44 +04:00
parent 0e55dd7db7
commit 235302c7c4
63 changed files with 3906 additions and 1934 deletions

View file

@ -7419,3 +7419,9 @@ Sorry for the inconvenience.";
"WebApp.MessagePreview" = "Message Preview";
"WebApp.Send" = "Send";
"Notifications.SystemTones" = "SYSTEM TONES";
"Notifications.TelegramTones" = "TELEGRAM TONES";
"Notifications.UploadSound" = "Upload Sound";
"Notifications.MessageSoundInfo" = "Long tap on any short voice note or mp3 file in chat\nand select \"Save for Notifications\". It will appear here.";

View file

@ -464,6 +464,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, chatController: {
return nil
}, statuses: nil)
self.presentationDataDisposable = ((updatedPresentationData?.signal ?? context.sharedContext.presentationData)

View file

@ -142,6 +142,7 @@ public final class ChatPanelInterfaceInteraction {
public let openSendAsPeer: (ASDisplayNode, ContextGesture?) -> Void
public let presentChatRequestAdminInfo: () -> Void
public let displayCopyProtectionTip: (ASDisplayNode, Bool) -> Void
public let chatController: () -> ViewController?
public let statuses: ChatPanelInterfaceInteractionStatuses?
public init(
@ -233,6 +234,7 @@ public final class ChatPanelInterfaceInteraction {
openSendAsPeer: @escaping (ASDisplayNode, ContextGesture?) -> Void,
presentChatRequestAdminInfo: @escaping () -> Void,
displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void,
chatController: @escaping () -> ViewController?,
statuses: ChatPanelInterfaceInteractionStatuses?
) {
self.setupReplyMessage = setupReplyMessage
@ -323,6 +325,7 @@ public final class ChatPanelInterfaceInteraction {
self.openSendAsPeer = openSendAsPeer
self.presentChatRequestAdminInfo = presentChatRequestAdminInfo
self.displayCopyProtectionTip = displayCopyProtectionTip
self.chatController = chatController
self.statuses = statuses
}
@ -420,6 +423,8 @@ public final class ChatPanelInterfaceInteraction {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, chatController: {
return nil
}, statuses: nil)
}
}

View file

@ -94,6 +94,8 @@ private final class ContextControllerActionsListActionItemNode: HighlightTrackin
self.addSubnode(self.subtitleNode)
self.addSubnode(self.iconNode)
self.isEnabled = self.canBeHighlighted()
self.highligthedChanged = { [weak self] highlighted in
guard let strongSelf = self else {
return
@ -135,7 +137,7 @@ private final class ContextControllerActionsListActionItemNode: HighlightTrackin
}
func canBeHighlighted() -> Bool {
return true
return self.item.action != nil
}
func updateIsHighlighted(isHighlighted: Bool) {

View file

@ -225,7 +225,12 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
}
private func getActionsStackPositionLock() -> CGFloat? {
return self.actionsStackNode.view.convert(CGPoint(), to: self.view).y
switch self.source {
case .reference:
return nil
case .extracted:
return self.actionsStackNode.view.convert(CGPoint(), to: self.view).y
}
}
func update(

View file

@ -16,9 +16,15 @@ public enum ItemListCheckboxItemColor {
}
public class ItemListCheckboxItem: ListViewItem, ItemListItem {
public enum IconPlacement {
case `default`
case check
}
let presentationData: ItemListPresentationData
let icon: UIImage?
let iconSize: CGSize?
let iconPlacement: IconPlacement
let title: String
let style: ItemListCheckboxItemStyle
let color: ItemListCheckboxItemColor
@ -27,10 +33,11 @@ public class ItemListCheckboxItem: ListViewItem, ItemListItem {
public let sectionId: ItemListSectionId
let action: () -> Void
public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, iconSize: CGSize? = nil, title: String, style: ItemListCheckboxItemStyle, color: ItemListCheckboxItemColor = .accent, checked: Bool, zeroSeparatorInsets: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void) {
public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, iconSize: CGSize? = nil, iconPlacement: IconPlacement = .default, title: String, style: ItemListCheckboxItemStyle, color: ItemListCheckboxItemColor = .accent, checked: Bool, zeroSeparatorInsets: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void) {
self.presentationData = presentationData
self.icon = icon
self.iconSize = iconSize
self.iconPlacement = iconPlacement
self.title = title
self.style = style
self.color = color
@ -158,7 +165,12 @@ public class ItemListCheckboxItemNode: ListViewItemNode {
let iconInset: CGFloat = 44.0
if item.icon != nil {
leftInset += iconInset
switch item.iconPlacement {
case .default:
leftInset += iconInset
case .check:
break
}
}
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
@ -273,7 +285,15 @@ public class ItemListCheckboxItemNode: ListViewItemNode {
if let icon = item.icon {
let iconSize = item.iconSize ?? icon.size
strongSelf.imageNode.image = icon
strongSelf.imageNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0), y: floor((layout.contentSize.height - iconSize.height) / 2.0)), size: iconSize)
let iconFrame: CGRect
switch item.iconPlacement {
case .default:
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0), y: floor((layout.contentSize.height - iconSize.height) / 2.0)), size: iconSize)
case .check:
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0), y: floor((contentSize.height - iconSize.height) / 2.0)), size: iconSize)
}
strongSelf.imageNode.frame = iconFrame
}
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: strongSelf.backgroundNode.frame.height + UIScreenPixel + UIScreenPixel))

View file

@ -20,7 +20,7 @@ public struct NotificationSoundSettings {
}
}
public func notificationMuteSettingsController(presentationData: PresentationData, notificationSettings: MessageNotificationSettings, soundSettings: NotificationSoundSettings?, openSoundSettings: @escaping () -> Void, updateSettings: @escaping (Int32?) -> Void) -> ViewController {
public func notificationMuteSettingsController(presentationData: PresentationData, notificationSoundList: NotificationSoundList?, notificationSettings: MessageNotificationSettings, soundSettings: NotificationSoundSettings?, openSoundSettings: @escaping () -> Void, updateSettings: @escaping (Int32?) -> Void) -> ViewController {
let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
@ -81,7 +81,7 @@ public func notificationMuteSettingsController(presentationData: PresentationDat
items.append(item)
}
if let soundSettings = soundSettings {
items.append(ActionSheetButtonItem(title: soundSettings.value.flatMap({ presentationData.strings.Notification_Exceptions_Sound(localizedPeerNotificationSoundString(strings: presentationData.strings, sound: $0)).string }) ?? presentationData.strings.GroupInfo_SetSound, action: {
items.append(ActionSheetButtonItem(title: soundSettings.value.flatMap({ presentationData.strings.Notification_Exceptions_Sound(localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: $0)).string }) ?? presentationData.strings.GroupInfo_SetSound, action: {
dismissAction()
openSoundSettings()
}))

View file

@ -19,6 +19,8 @@ swift_library(
"//submodules/AccountContext:AccountContext",
"//submodules/TelegramStringFormatting:TelegramStringFormatting",
"//submodules/PresentationDataUtils:PresentationDataUtils",
"//submodules/LegacyMediaPickerUI:LegacyMediaPickerUI",
"//submodules/UndoUI:UndoUI",
],
visibility = [
"//visibility:public",

View file

@ -10,6 +10,9 @@ import PresentationDataUtils
import AccountContext
import TelegramStringFormatting
import AppBundle
import LegacyMediaPickerUI
import AVFoundation
import UndoUI
private struct NotificationSoundSelectionArguments {
let account: Account
@ -17,22 +20,24 @@ private struct NotificationSoundSelectionArguments {
let selectSound: (PeerMessageSound) -> Void
let complete: () -> Void
let cancel: () -> Void
let upload: () -> Void
}
private enum NotificationSoundSelectionSection: Int32 {
case cloud
case modern
case classic
}
private struct NotificationSoundSelectionState: Equatable {
let selectedSound: PeerMessageSound
static func ==(lhs: NotificationSoundSelectionState, rhs: NotificationSoundSelectionState) -> Bool {
return lhs.selectedSound == rhs.selectedSound
}
var selectedSound: PeerMessageSound
}
private enum NotificationSoundSelectionEntry: ItemListNodeEntry {
case cloudHeader(String)
case uploadSound(String)
case cloudInfo(String)
case modernHeader(PresentationTheme, String)
case classicHeader(PresentationTheme, String)
case none(section: NotificationSoundSelectionSection, theme: PresentationTheme, text: String, selected: Bool)
@ -41,6 +46,8 @@ private enum NotificationSoundSelectionEntry: ItemListNodeEntry {
var section: ItemListSectionId {
switch self {
case .cloudHeader, .uploadSound, .cloudInfo:
return NotificationSoundSelectionSection.cloud.rawValue
case .modernHeader:
return NotificationSoundSelectionSection.modern.rawValue
case .classicHeader:
@ -54,68 +61,102 @@ private enum NotificationSoundSelectionEntry: ItemListNodeEntry {
}
}
var stableId: Int32 {
var sortId: Int32 {
switch self {
case .modernHeader:
return 0
case .classicHeader:
return 1000
case let .none(section, _, _, _):
switch section {
case .modern:
return 2
case .classic:
return 1001
}
case let .default(section, _, _, _):
switch section {
case .modern:
return 1
case .classic:
return 1002
}
case let .sound(section, index, _, _, _, _):
switch section {
case .modern:
return 3 + index
case .classic:
return 1003 + index
}
case .cloudHeader:
return 0
case .uploadSound:
return 998
case .cloudInfo:
return 999
case .modernHeader:
return 1000
case .classicHeader:
return 2000
case let .none(section, _, _, _):
switch section {
case .cloud:
return 1
case .modern:
return 1001
case .classic:
return 2001
}
case let .default(section, _, _, _):
switch section {
case .cloud:
return 2
case .modern:
return 1002
case .classic:
return 2002
}
case let .sound(section, index, _, _, _, _):
switch section {
case .cloud:
return 3 + index
case .modern:
return 1003 + index
case .classic:
return 2003 + index
}
}
}
var stableId: Int32 {
return self.sortId
}
static func ==(lhs: NotificationSoundSelectionEntry, rhs: NotificationSoundSelectionEntry) -> Bool {
switch lhs {
case let .modernHeader(lhsTheme, lhsText):
if case let .modernHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .classicHeader(lhsTheme, lhsText):
if case let .classicHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .none(lhsSection, lhsTheme, lhsText, lhsSelected):
if case let .none(rhsSection, rhsTheme, rhsText, rhsSelected) = rhs, lhsSection == rhsSection, lhsTheme === rhsTheme, lhsText == rhsText, lhsSelected == rhsSelected {
return true
} else {
return false
}
case let .default(lhsSection, lhsTheme, lhsText, lhsSelected):
if case let .default(rhsSection, rhsTheme, rhsText, rhsSelected) = rhs, lhsSection == rhsSection, lhsTheme === rhsTheme, lhsText == rhsText, lhsSelected == rhsSelected {
return true
} else {
return false
}
case let .sound(lhsSection, lhsIndex, lhsTheme, lhsText, lhsSound, lhsSelected):
if case let .sound(rhsSection, rhsIndex, rhsTheme, rhsText, rhsSound, rhsSelected) = rhs, lhsSection == rhsSection, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsText == rhsText, lhsSound == rhsSound, lhsSelected == rhsSelected {
return true
} else {
return false
}
case let .cloudHeader(text):
if case .cloudHeader(text) = rhs {
return true
} else {
return false
}
case let .cloudInfo(text):
if case .cloudInfo(text) = rhs {
return true
} else {
return false
}
case let .uploadSound(text):
if case .uploadSound(text) = rhs {
return true
} else {
return false
}
case let .modernHeader(lhsTheme, lhsText):
if case let .modernHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .classicHeader(lhsTheme, lhsText):
if case let .classicHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .none(lhsSection, lhsTheme, lhsText, lhsSelected):
if case let .none(rhsSection, rhsTheme, rhsText, rhsSelected) = rhs, lhsSection == rhsSection, lhsTheme === rhsTheme, lhsText == rhsText, lhsSelected == rhsSelected {
return true
} else {
return false
}
case let .default(lhsSection, lhsTheme, lhsText, lhsSelected):
if case let .default(rhsSection, rhsTheme, rhsText, rhsSelected) = rhs, lhsSection == rhsSection, lhsTheme === rhsTheme, lhsText == rhsText, lhsSelected == rhsSelected {
return true
} else {
return false
}
case let .sound(lhsSection, lhsIndex, lhsTheme, lhsText, lhsSound, lhsSelected):
if case let .sound(rhsSection, rhsIndex, rhsTheme, rhsText, rhsSound, rhsSelected) = rhs, lhsSection == rhsSection, lhsIndex == rhsIndex, lhsTheme === rhsTheme, lhsText == rhsText, lhsSound == rhsSound, lhsSelected == rhsSelected {
return true
} else {
return false
}
}
}
@ -126,43 +167,63 @@ private enum NotificationSoundSelectionEntry: ItemListNodeEntry {
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
let arguments = arguments as! NotificationSoundSelectionArguments
switch self {
case let.modernHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .classicHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .none(_, _, text, selected):
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: true, sectionId: self.section, action: {
arguments.selectSound(.none)
})
case let .default(_, _, text, selected):
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.selectSound(.default)
})
case let .sound(_, _, _, text, sound, selected):
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.selectSound(sound)
})
case let .cloudHeader(text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .uploadSound(text):
let icon = PresentationResourcesItemList.uploadToneIcon(presentationData.theme)
return ItemListCheckboxItem(presentationData: presentationData, icon: icon, iconSize: nil, iconPlacement: .check, title: text, style: .left, checked: false, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.upload()
})
case let .cloudInfo(text):
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .modernHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .classicHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .none(_, _, text, selected):
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: true, sectionId: self.section, action: {
arguments.selectSound(.none)
})
case let .default(_, _, text, selected):
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.selectSound(.default)
})
case let .sound(_, _, _, text, sound, selected):
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
arguments.selectSound(sound)
})
}
}
}
private func notificationsAndSoundsEntries(presentationData: PresentationData, defaultSound: PeerMessageSound?, state: NotificationSoundSelectionState) -> [NotificationSoundSelectionEntry] {
private func notificationsAndSoundsEntries(presentationData: PresentationData, defaultSound: PeerMessageSound?, state: NotificationSoundSelectionState, notificationSoundList: NotificationSoundList?) -> [NotificationSoundSelectionEntry] {
var entries: [NotificationSoundSelectionEntry] = []
entries.append(.cloudHeader(presentationData.strings.Notifications_TelegramTones))
//entries.append(.none(section: .cloud, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: state.selectedSound == .none))
if let notificationSoundList = notificationSoundList {
for listSound in notificationSoundList.sounds {
let sound: PeerMessageSound = .cloud(fileId: listSound.file.fileId.id)
entries.append(.sound(section: .cloud, index: Int32(entries.count), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: state.selectedSound.id == sound.id))
}
}
entries.append(.uploadSound(presentationData.strings.Notifications_UploadSound))
entries.append(.cloudInfo(presentationData.strings.Notifications_MessageSoundInfo))
entries.append(.modernHeader(presentationData.theme, presentationData.strings.Notifications_AlertTones))
if let defaultSound = defaultSound {
entries.append(.default(section: .modern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: .default, default: defaultSound), selected: state.selectedSound == .default))
entries.append(.default(section: .modern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .default, default: defaultSound), selected: state.selectedSound.id == .default))
}
entries.append(.none(section: .modern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: .none), selected: state.selectedSound == .none))
entries.append(.none(section: .modern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: state.selectedSound.id == .none))
for i in 0 ..< 12 {
let sound: PeerMessageSound = .bundledModern(id: Int32(i))
entries.append(.sound(section: .modern, index: Int32(i), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: sound), sound: sound, selected: sound == state.selectedSound))
entries.append(.sound(section: .modern, index: Int32(i), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == state.selectedSound.id))
}
entries.append(.classicHeader(presentationData.theme, presentationData.strings.Notifications_ClassicTones))
for i in 0 ..< 8 {
let sound: PeerMessageSound = .bundledClassic(id: Int32(i))
entries.append(.sound(section: .classic, index: Int32(i), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: sound), sound: sound, selected: sound == state.selectedSound))
entries.append(.sound(section: .classic, index: Int32(i), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == state.selectedSound.id))
}
return entries
@ -195,28 +256,40 @@ private final class AudioPlayerWrapper: NSObject, AVAudioPlayerDelegate {
}
}
public func fileNameForNotificationSound(_ sound: PeerMessageSound, defaultSound: PeerMessageSound?) -> String {
public func fileNameForNotificationSound(account: Account, notificationSoundList: NotificationSoundList?, sound: PeerMessageSound, defaultSound: PeerMessageSound?) -> String {
switch sound {
case .none:
return ""
case .default:
if let defaultSound = defaultSound {
if case .default = defaultSound {
return "\(100)"
} else {
return fileNameForNotificationSound(defaultSound, defaultSound: nil)
}
} else {
case .none:
return ""
case .default:
if let defaultSound = defaultSound {
if case .default = defaultSound {
return "\(100)"
} else {
return fileNameForNotificationSound(account: account, notificationSoundList: notificationSoundList, sound: defaultSound, defaultSound: nil)
}
case let .bundledModern(id):
return "\(id + 100)"
case let .bundledClassic(id):
return "\(id + 2)"
} else {
return "\(100)"
}
case let .bundledModern(id):
return "\(id + 100)"
case let .bundledClassic(id):
return "\(id + 2)"
case let .cloud(fileId):
guard let notificationSoundList = notificationSoundList else {
return ""
}
for sound in notificationSoundList.sounds {
if sound.file.fileId.id == fileId {
if let path = account.postbox.mediaBox.completedResourcePath(sound.file.resource, pathExtension: "mp3") {
return path
}
}
}
return ""
}
}
public func playSound(context: AccountContext, sound: PeerMessageSound, defaultSound: PeerMessageSound?) -> Signal<Void, NoError> {
public func playSound(context: AccountContext, notificationSoundList: NotificationSoundList?, sound: PeerMessageSound, defaultSound: PeerMessageSound?) -> Signal<Void, NoError> {
if case .none = sound {
return .complete()
} else {
@ -225,11 +298,20 @@ public func playSound(context: AccountContext, sound: PeerMessageSound, defaultS
var deactivateImpl: (() -> Void)?
let session = context.sharedContext.mediaManager.audioSession.push(audioSessionType: .play, activate: { _ in
Queue.mainQueue().async {
if let url = getAppBundle().url(forResource: fileNameForNotificationSound(sound, defaultSound: defaultSound), withExtension: "m4a") {
currentPlayer = AudioPlayerWrapper(url: url, completed: {
let filePath = fileNameForNotificationSound(account: context.account, notificationSoundList: notificationSoundList, sound: sound, defaultSound: defaultSound)
if filePath.contains("/") {
currentPlayer = AudioPlayerWrapper(url: URL(fileURLWithPath: filePath), completed: {
deactivateImpl?()
})
currentPlayer?.play()
} else {
if let url = getAppBundle().url(forResource: filePath, withExtension: "m4a") {
currentPlayer = AudioPlayerWrapper(url: url, completed: {
deactivateImpl?()
})
currentPlayer?.play()
}
}
}
}, deactivate: { _ in
@ -266,25 +348,32 @@ public func notificationSoundSelectionController(context: AccountContext, update
var completeImpl: (() -> Void)?
var cancelImpl: (() -> Void)?
var presentFilePicker: (() -> Void)?
let playSoundDisposable = MetaDisposable()
let soundActionDisposable = MetaDisposable()
let arguments = NotificationSoundSelectionArguments(account: context.account, selectSound: { sound in
updateState { state in
return NotificationSoundSelectionState(selectedSound: sound)
}
playSoundDisposable.set(playSound(context: context, sound: sound, defaultSound: defaultSound).start())
let _ = (context.engine.peers.notificationSoundList()
|> take(1)
|> deliverOnMainQueue).start(next: { notificationSoundList in
playSoundDisposable.set(playSound(context: context, notificationSoundList: notificationSoundList, sound: sound, defaultSound: defaultSound).start())
})
}, complete: {
completeImpl?()
}, cancel: {
cancelImpl?()
}, upload: {
presentFilePicker?()
})
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
let signal = combineLatest(presentationData, statePromise.get())
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let signal = combineLatest(presentationData, statePromise.get(), context.engine.peers.notificationSoundList())
|> map { presentationData, state, notificationSoundList -> (ItemListControllerState, (ItemListNodeState, Any)) in
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
arguments.cancel()
})
@ -294,13 +383,14 @@ public func notificationSoundSelectionController(context: AccountContext, update
})
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Notifications_TextTone), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: notificationsAndSoundsEntries(presentationData: presentationData, defaultSound: defaultSound, state: state), style: .blocks)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: notificationsAndSoundsEntries(presentationData: presentationData, defaultSound: defaultSound, state: state, notificationSoundList: notificationSoundList), style: .blocks)
return (controllerState, (listState, arguments))
}
let controller = ItemListController(context: context, state: signal |> afterDisposed {
playSoundDisposable.dispose()
soundActionDisposable.dispose()
})
controller.enableInteractiveDismiss = true
if isModal {
@ -319,5 +409,57 @@ public func notificationSoundSelectionController(context: AccountContext, update
controller?.dismiss()
}
var presentUndo: ((UndoOverlayContent) -> Void)?
presentFilePicker = { [weak controller] in
guard let controller = controller else {
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controller.present(legacyICloudFilePicker(theme: presentationData.theme, documentTypes: ["public.mp3"], completion: { urls in
guard !urls.isEmpty, let url = urls.first else {
return
}
let coordinator = NSFileCoordinator(filePresenter: nil)
var error: NSError?
coordinator.coordinate(readingItemAt: url, options: .forUploading, error: &error, byAccessor: { url in
Queue.mainQueue().async {
let asset = AVAsset(url: url)
guard let data = try? Data(contentsOf: url) else {
return
}
if data.count > 200 * 1024 {
presentUndo?(.info(title: "Audio is too large", text: "The file is larger than 200 KB."))
return
}
asset.loadValuesAsynchronously(forKeys: ["duration"], completionHandler: {
let duration = asset.duration.seconds
if duration > 5.0 {
//TODO:localize
presentUndo?(.info(title: "Audio is too long", text: "The duration is longer than 5 seconds."))
} else {
soundActionDisposable.set((context.engine.peers.uploadNotificationSound(title: url.lastPathComponent, data: data)
|> deliverOnMainQueue).start(next: { _ in
}, error: { _ in
}))
}
})
}
})
}), in: .window(.root))
}
presentUndo = { [weak controller] content in
guard let controller = controller else {
return
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
controller.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
}
return controller
}

View file

@ -287,7 +287,7 @@ public enum NotificationExceptionMode : Equatable {
}
}
private func notificationsExceptionEntries(presentationData: PresentationData, state: NotificationExceptionState, query: String? = nil, foundPeers: [RenderedPeer] = []) -> [NotificationExceptionEntry] {
private func notificationsExceptionEntries(presentationData: PresentationData, notificationSoundList: NotificationSoundList?, state: NotificationExceptionState, query: String? = nil, foundPeers: [RenderedPeer] = []) -> [NotificationExceptionEntry] {
var entries: [NotificationExceptionEntry] = []
if !state.isSearchMode {
@ -361,7 +361,7 @@ private func notificationsExceptionEntries(presentationData: PresentationData, s
case .default:
break
default:
let soundName = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: value.settings.messageSound)
let soundName = localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: value.settings.messageSound)
title += (title.isEmpty ? presentationData.strings.Notification_Exceptions_Sound(soundName).string : ", \(presentationData.strings.Notification_Exceptions_Sound(soundName).string)")
}
switch value.settings.displayPreviews {
@ -975,8 +975,8 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
let previousEntriesHolder = Atomic<([NotificationExceptionEntry], PresentationTheme, PresentationStrings)?>(value: nil)
self.listDisposable = (combineLatest(context.sharedContext.presentationData, statePromise.get(), preferences) |> deliverOnMainQueue).start(next: { [weak self] (presentationData, state, prefs) in
let entries = notificationsExceptionEntries(presentationData: presentationData, state: state)
self.listDisposable = (combineLatest(context.sharedContext.presentationData, statePromise.get(), preferences, context.engine.peers.notificationSoundList()) |> deliverOnMainQueue).start(next: { [weak self] presentationData, state, prefs, notificationSoundList in
let entries = notificationsExceptionEntries(presentationData: presentationData, notificationSoundList: notificationSoundList, state: state)
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, presentationData.theme, presentationData.strings))
updateCanStartEditing(state.mode.peerIds.isEmpty ? nil : state.editing)
@ -1233,16 +1233,16 @@ private final class NotificationExceptionsSearchContainerNode: SearchDisplayCont
|> distinctUntilChanged
let searchSignal = stateQuery
|> mapToSignal { query -> Signal<(PresentationData, (NotificationExceptionState, String?), PreferencesView, [RenderedPeer]), NoError> in
|> mapToSignal { query -> Signal<(PresentationData, NotificationSoundList?, (NotificationExceptionState, String?), PreferencesView, [RenderedPeer]), NoError> in
var contactsSignal: Signal<[RenderedPeer], NoError> = .single([])
if let query = query {
contactsSignal = context.account.postbox.searchPeers(query: query)
}
return combineLatest(context.sharedContext.presentationData, stateAndPeers, preferences, contactsSignal)
return combineLatest(context.sharedContext.presentationData, context.engine.peers.notificationSoundList(), stateAndPeers, preferences, contactsSignal)
}
self.searchDisposable.set((searchSignal
|> deliverOnMainQueue).start(next: { [weak self] (presentationData, state, prefs, foundPeers) in
let entries = notificationsExceptionEntries(presentationData: presentationData, state: state.0, query: state.1, foundPeers: foundPeers)
|> deliverOnMainQueue).start(next: { [weak self] presentationData, notificationSoundList, state, prefs, foundPeers in
let entries = notificationsExceptionEntries(presentationData: presentationData, notificationSoundList: notificationSoundList, state: state.0, query: state.1, foundPeers: foundPeers)
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, presentationData.theme, presentationData.strings))
let transition = preparedNotificationExceptionsSearchContainerTransition(presentationData: ItemListPresentationData(presentationData), from: previousEntriesAndPresentationData?.0 ?? [], to: entries, arguments: arguments, isSearching: state.1 != nil && !state.1!.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings)

View file

@ -209,7 +209,7 @@ private enum NotificationPeerExceptionEntry: ItemListNodeEntry {
}
private func notificationPeerExceptionEntries(presentationData: PresentationData, state: NotificationExceptionPeerState) -> [NotificationPeerExceptionEntry] {
private func notificationPeerExceptionEntries(presentationData: PresentationData, notificationSoundList: NotificationSoundList?, state: NotificationExceptionPeerState) -> [NotificationPeerExceptionEntry] {
var entries:[NotificationPeerExceptionEntry] = []
var index: Int32 = 0
@ -239,15 +239,15 @@ private func notificationPeerExceptionEntries(presentationData: PresentationData
entries.append(.soundModernHeader(index: index, theme: presentationData.theme, title: presentationData.strings.Notifications_AlertTones))
index += 1
entries.append(.default(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: .default, default: state.defaultSound), selected: state.selectedSound == .default))
entries.append(.default(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .default, default: state.defaultSound), selected: state.selectedSound == .default))
index += 1
entries.append(.none(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: .none), selected: state.selectedSound == .none))
entries.append(.none(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: state.selectedSound == .none))
index += 1
for i in 0 ..< 12 {
let sound: PeerMessageSound = .bundledModern(id: Int32(i))
entries.append(.sound(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: sound), sound: sound, selected: sound == state.selectedSound))
entries.append(.sound(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound == state.selectedSound))
index += 1
}
@ -256,7 +256,7 @@ private func notificationPeerExceptionEntries(presentationData: PresentationData
for i in 0 ..< 8 {
let sound: PeerMessageSound = .bundledClassic(id: Int32(i))
entries.append(.sound(index: index, section: .soundClassic, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, sound: sound), sound: sound, selected: sound == state.selectedSound))
entries.append(.sound(index: index, section: .soundClassic, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound == state.selectedSound))
index += 1
}
}
@ -330,7 +330,12 @@ public func notificationPeerExceptionController(context: AccountContext, updated
let arguments = NotificationPeerExceptionArguments(account: context.account, selectSound: { sound in
updateState { state in
playSoundDisposable.set(playSound(context: context, sound: sound, defaultSound: state.defaultSound).start())
let _ = (context.engine.peers.notificationSoundList()
|> take(1)
|> deliverOnMainQueue).start(next: { notificationSoundList in
playSoundDisposable.set(playSound(context: context, notificationSoundList: notificationSoundList, sound: sound, defaultSound: state.defaultSound).start())
})
return state.withUpdatedSound(sound)
}
}, selectMode: { mode in
@ -365,8 +370,8 @@ public func notificationPeerExceptionController(context: AccountContext, updated
})
let signal = combineLatest(queue: .mainQueue(), (updatedPresentationData?.signal ?? context.sharedContext.presentationData), statePromise.get() |> distinctUntilChanged)
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let signal = combineLatest(queue: .mainQueue(), (updatedPresentationData?.signal ?? context.sharedContext.presentationData), context.engine.peers.notificationSoundList(), statePromise.get() |> distinctUntilChanged)
|> map { presentationData, notificationSoundList, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
arguments.cancel()
})
@ -376,7 +381,7 @@ public func notificationPeerExceptionController(context: AccountContext, updated
})
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: notificationPeerExceptionEntries(presentationData: presentationData, state: state), style: .blocks, animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: notificationPeerExceptionEntries(presentationData: presentationData, notificationSoundList: notificationSoundList, state: state), style: .blocks, animateChanges: false)
return (controllerState, (listState, arguments))
}

View file

@ -249,7 +249,7 @@ private func filteredGlobalSound(_ sound: PeerMessageSound) -> PeerMessageSound
}
}
private func notificationsPeerCategoryEntries(category: NotificationsPeerCategory, globalSettings: GlobalNotificationSettingsSet, state: NotificationExceptionState, presentationData: PresentationData) -> [NotificationsPeerCategoryEntry] {
private func notificationsPeerCategoryEntries(category: NotificationsPeerCategory, globalSettings: GlobalNotificationSettingsSet, state: NotificationExceptionState, presentationData: PresentationData, notificationSoundList: NotificationSoundList?) -> [NotificationsPeerCategoryEntry] {
var entries: [NotificationsPeerCategoryEntry] = []
let notificationSettings: MessageNotificationSettings
@ -268,7 +268,7 @@ private func notificationsPeerCategoryEntries(category: NotificationsPeerCategor
if notificationSettings.enabled || !notificationExceptions.isEmpty {
entries.append(.optionsHeader(presentationData.theme, presentationData.strings.Notifications_Options.uppercased()))
entries.append(.previews(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsPreview, notificationSettings.displayPreviews))
entries.append(.sound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, sound: filteredGlobalSound(notificationSettings.sound)), filteredGlobalSound(notificationSettings.sound)))
entries.append(.sound(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsSound, localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: filteredGlobalSound(notificationSettings.sound)), filteredGlobalSound(notificationSettings.sound)))
}
entries.append(.exceptionsHeader(presentationData.theme, presentationData.strings.Notifications_MessageNotificationsExceptions.uppercased()))
@ -338,7 +338,7 @@ private func notificationsPeerCategoryEntries(category: NotificationsPeerCategor
case .default:
break
default:
let soundName = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: value.settings.messageSound)
let soundName = localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: value.settings.messageSound)
title += (title.isEmpty ? presentationData.strings.Notification_Exceptions_Sound(soundName).string : ", \(presentationData.strings.Notification_Exceptions_Sound(soundName).string)")
}
switch value.settings.displayPreviews {
@ -687,8 +687,8 @@ public func notificationsPeerCategoryController(context: AccountContext, categor
let sharedData = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.inAppNotificationSettings])
let preferences = context.account.postbox.preferencesView(keys: [PreferencesKeys.globalNotifications])
let signal = combineLatest(context.sharedContext.presentationData, sharedData, preferences, statePromise.get())
|> map { presentationData, sharedData, view, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let signal = combineLatest(context.sharedContext.presentationData, context.engine.peers.notificationSoundList(), sharedData, preferences, statePromise.get())
|> map { presentationData, notificationSoundList, sharedData, view, state -> (ItemListControllerState, (ItemListNodeState, Any)) in
let viewSettings: GlobalNotificationSettingsSet
if let settings = view.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) {
viewSettings = settings.effective
@ -696,7 +696,7 @@ public func notificationsPeerCategoryController(context: AccountContext, categor
viewSettings = GlobalNotificationSettingsSet.defaultSettings
}
let entries = notificationsPeerCategoryEntries(category: category, globalSettings: viewSettings, state: state, presentationData: presentationData)
let entries = notificationsPeerCategoryEntries(category: category, globalSettings: viewSettings, state: state, presentationData: presentationData, notificationSoundList: notificationSoundList)
var index = 0
var scrollToItem: ListViewScrollToItem?

View file

@ -303,7 +303,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[2107670217] = { return Api.InputPeer.parse_inputPeerSelf($0) }
dict[-571955892] = { return Api.InputPeer.parse_inputPeerUser($0) }
dict[-1468331492] = { return Api.InputPeer.parse_inputPeerUserFromMessage($0) }
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
dict[-551616469] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
dict[506920429] = { return Api.InputPhoneCall.parse_inputPhoneCall($0) }
dict[1001634122] = { return Api.InputPhoto.parse_inputPhoto($0) }
dict[483901197] = { return Api.InputPhoto.parse_inputPhotoEmpty($0) }
@ -477,6 +477,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1614803355] = { return Api.MessagesFilter.parse_inputMessagesFilterVideo($0) }
dict[1358283666] = { return Api.MessagesFilter.parse_inputMessagesFilterVoice($0) }
dict[-1910892683] = { return Api.NearestDc.parse_nearestDc($0) }
dict[-1746354498] = { return Api.NotificationSound.parse_notificationSoundDefault($0) }
dict[-2096391452] = { return Api.NotificationSound.parse_notificationSoundLocal($0) }
dict[1863070943] = { return Api.NotificationSound.parse_notificationSoundNone($0) }
dict[-9666487] = { return Api.NotificationSound.parse_notificationSoundRingtone($0) }
dict[-703403793] = { return Api.NotifyPeer.parse_notifyBroadcasts($0) }
dict[-1073230141] = { return Api.NotifyPeer.parse_notifyChats($0) }
dict[-1613493288] = { return Api.NotifyPeer.parse_notifyPeer($0) }
@ -530,7 +534,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-386039788] = { return Api.PeerBlocked.parse_peerBlocked($0) }
dict[-901375139] = { return Api.PeerLocated.parse_peerLocated($0) }
dict[-118740917] = { return Api.PeerLocated.parse_peerSelfLocated($0) }
dict[-1353671392] = { return Api.PeerNotifySettings.parse_peerNotifySettings($0) }
dict[-1472527322] = { return Api.PeerNotifySettings.parse_peerNotifySettings($0) }
dict[-1525149427] = { return Api.PeerSettings.parse_peerSettings($0) }
dict[-1770029977] = { return Api.PhoneCall.parse_phoneCall($0) }
dict[912311057] = { return Api.PhoneCall.parse_phoneCallAccepted($0) }
@ -787,6 +791,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1757493555] = { return Api.Update.parse_updateReadMessagesContents($0) }
dict[-1706939360] = { return Api.Update.parse_updateRecentStickers($0) }
dict[-1821035490] = { return Api.Update.parse_updateSavedGifs($0) }
dict[1960361625] = { return Api.Update.parse_updateSavedRingtones($0) }
dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) }
dict[1135492588] = { return Api.Update.parse_updateStickerSets($0) }
dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) }
@ -845,6 +850,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-478701471] = { return Api.account.ResetPasswordResult.parse_resetPasswordFailedWait($0) }
dict[-383330754] = { return Api.account.ResetPasswordResult.parse_resetPasswordOk($0) }
dict[-370148227] = { return Api.account.ResetPasswordResult.parse_resetPasswordRequestedWait($0) }
dict[-1041683259] = { return Api.account.SavedRingtones.parse_savedRingtones($0) }
dict[-67704655] = { return Api.account.SavedRingtones.parse_savedRingtonesNotModified($0) }
dict[-2128640689] = { return Api.account.SentEmailCode.parse_sentEmailCode($0) }
dict[1304052993] = { return Api.account.Takeout.parse_takeout($0) }
dict[-1707242387] = { return Api.account.Themes.parse_themes($0) }
@ -1354,6 +1361,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.NearestDc:
_1.serialize(buffer, boxed)
case let _1 as Api.NotificationSound:
_1.serialize(buffer, boxed)
case let _1 as Api.NotifyPeer:
_1.serialize(buffer, boxed)
case let _1 as Api.Page:
@ -1550,6 +1559,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.account.ResetPasswordResult:
_1.serialize(buffer, boxed)
case let _1 as Api.account.SavedRingtones:
_1.serialize(buffer, boxed)
case let _1 as Api.account.SentEmailCode:
_1.serialize(buffer, boxed)
case let _1 as Api.account.Takeout:

View file

@ -680,6 +680,90 @@ public extension Api {
}
}
public extension Api {
enum NotificationSound: TypeConstructorDescription {
case notificationSoundDefault
case notificationSoundLocal(title: String, data: String)
case notificationSoundNone
case notificationSoundRingtone(id: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .notificationSoundDefault:
if boxed {
buffer.appendInt32(-1746354498)
}
break
case .notificationSoundLocal(let title, let data):
if boxed {
buffer.appendInt32(-2096391452)
}
serializeString(title, buffer: buffer, boxed: false)
serializeString(data, buffer: buffer, boxed: false)
break
case .notificationSoundNone:
if boxed {
buffer.appendInt32(1863070943)
}
break
case .notificationSoundRingtone(let id):
if boxed {
buffer.appendInt32(-9666487)
}
serializeInt64(id, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .notificationSoundDefault:
return ("notificationSoundDefault", [])
case .notificationSoundLocal(let title, let data):
return ("notificationSoundLocal", [("title", String(describing: title)), ("data", String(describing: data))])
case .notificationSoundNone:
return ("notificationSoundNone", [])
case .notificationSoundRingtone(let id):
return ("notificationSoundRingtone", [("id", String(describing: id))])
}
}
public static func parse_notificationSoundDefault(_ reader: BufferReader) -> NotificationSound? {
return Api.NotificationSound.notificationSoundDefault
}
public static func parse_notificationSoundLocal(_ reader: BufferReader) -> NotificationSound? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.NotificationSound.notificationSoundLocal(title: _1!, data: _2!)
}
else {
return nil
}
}
public static func parse_notificationSoundNone(_ reader: BufferReader) -> NotificationSound? {
return Api.NotificationSound.notificationSoundNone
}
public static func parse_notificationSoundRingtone(_ reader: BufferReader) -> NotificationSound? {
var _1: Int64?
_1 = reader.readInt64()
let _c1 = _1 != nil
if _c1 {
return Api.NotificationSound.notificationSoundRingtone(id: _1!)
}
else {
return nil
}
}
}
}
public extension Api {
enum NotifyPeer: TypeConstructorDescription {
case notifyBroadcasts
@ -754,77 +838,3 @@ public extension Api {
}
}
public extension Api {
enum Page: TypeConstructorDescription {
case page(flags: Int32, url: String, blocks: [Api.PageBlock], photos: [Api.Photo], documents: [Api.Document], views: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .page(let flags, let url, let blocks, let photos, let documents, let views):
if boxed {
buffer.appendInt32(-1738178803)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(blocks.count))
for item in blocks {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(photos.count))
for item in photos {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(documents.count))
for item in documents {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .page(let flags, let url, let blocks, let photos, let documents, let views):
return ("page", [("flags", String(describing: flags)), ("url", String(describing: url)), ("blocks", String(describing: blocks)), ("photos", String(describing: photos)), ("documents", String(describing: documents)), ("views", String(describing: views))])
}
}
public static func parse_page(_ reader: BufferReader) -> Page? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: [Api.PageBlock]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self)
}
var _4: [Api.Photo]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self)
}
var _5: [Api.Document]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self)
}
var _6: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.Page.page(flags: _1!, url: _2!, blocks: _3!, photos: _4!, documents: _5!, views: _6)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,77 @@
public extension Api {
enum Page: TypeConstructorDescription {
case page(flags: Int32, url: String, blocks: [Api.PageBlock], photos: [Api.Photo], documents: [Api.Document], views: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .page(let flags, let url, let blocks, let photos, let documents, let views):
if boxed {
buffer.appendInt32(-1738178803)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(blocks.count))
for item in blocks {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(photos.count))
for item in photos {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(documents.count))
for item in documents {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .page(let flags, let url, let blocks, let photos, let documents, let views):
return ("page", [("flags", String(describing: flags)), ("url", String(describing: url)), ("blocks", String(describing: blocks)), ("photos", String(describing: photos)), ("documents", String(describing: documents)), ("views", String(describing: views))])
}
}
public static func parse_page(_ reader: BufferReader) -> Page? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: [Api.PageBlock]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self)
}
var _4: [Api.Photo]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self)
}
var _5: [Api.Document]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self)
}
var _6: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.Page.page(flags: _1!, url: _2!, blocks: _3!, photos: _4!, documents: _5!, views: _6)
}
else {
return nil
}
}
}
}
public extension Api {
indirect enum PageBlock: TypeConstructorDescription {
case pageBlockAnchor(name: String)

View file

@ -606,27 +606,29 @@ public extension Api {
}
public extension Api {
enum PeerNotifySettings: TypeConstructorDescription {
case peerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, sound: String?)
case peerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, iosSound: Api.NotificationSound?, androidSound: Api.NotificationSound?, otherSound: Api.NotificationSound?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound):
case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let iosSound, let androidSound, let otherSound):
if boxed {
buffer.appendInt32(-1353671392)
buffer.appendInt32(-1472527322)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {showPreviews!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {silent!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(muteUntil!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(sound!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {iosSound!.serialize(buffer, true)}
if Int(flags) & Int(1 << 4) != 0 {androidSound!.serialize(buffer, true)}
if Int(flags) & Int(1 << 5) != 0 {otherSound!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound):
return ("peerNotifySettings", [("flags", String(describing: flags)), ("showPreviews", String(describing: showPreviews)), ("silent", String(describing: silent)), ("muteUntil", String(describing: muteUntil)), ("sound", String(describing: sound))])
case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let iosSound, let androidSound, let otherSound):
return ("peerNotifySettings", [("flags", String(describing: flags)), ("showPreviews", String(describing: showPreviews)), ("silent", String(describing: silent)), ("muteUntil", String(describing: muteUntil)), ("iosSound", String(describing: iosSound)), ("androidSound", String(describing: androidSound)), ("otherSound", String(describing: otherSound))])
}
}
@ -643,15 +645,27 @@ public extension Api {
} }
var _4: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
var _5: String?
if Int(_1!) & Int(1 << 3) != 0 {_5 = parseString(reader) }
var _5: Api.NotificationSound?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
var _6: Api.NotificationSound?
if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
var _7: Api.NotificationSound?
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
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 << 2) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.PeerNotifySettings.peerNotifySettings(flags: _1!, showPreviews: _2, silent: _3, muteUntil: _4, sound: _5)
let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 5) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.PeerNotifySettings.peerNotifySettings(flags: _1!, showPreviews: _2, silent: _3, muteUntil: _4, iosSound: _5, androidSound: _6, otherSound: _7)
}
else {
return nil

View file

@ -594,6 +594,7 @@ public extension Api {
case updateReadMessagesContents(messages: [Int32], pts: Int32, ptsCount: Int32)
case updateRecentStickers
case updateSavedGifs
case updateSavedRingtones
case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity])
case updateStickerSets
case updateStickerSetsOrder(flags: Int32, order: [Int64])
@ -1380,6 +1381,12 @@ public extension Api {
buffer.appendInt32(-1821035490)
}
break
case .updateSavedRingtones:
if boxed {
buffer.appendInt32(1960361625)
}
break
case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities):
if boxed {
@ -1655,6 +1662,8 @@ public extension Api {
return ("updateRecentStickers", [])
case .updateSavedGifs:
return ("updateSavedGifs", [])
case .updateSavedRingtones:
return ("updateSavedRingtones", [])
case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities):
return ("updateServiceNotification", [("flags", String(describing: flags)), ("inboxDate", String(describing: inboxDate)), ("type", String(describing: type)), ("message", String(describing: message)), ("media", String(describing: media)), ("entities", String(describing: entities))])
case .updateStickerSets:
@ -3265,6 +3274,9 @@ public extension Api {
public static func parse_updateSavedGifs(_ reader: BufferReader) -> Update? {
return Api.Update.updateSavedGifs
}
public static func parse_updateSavedRingtones(_ reader: BufferReader) -> Update? {
return Api.Update.updateSavedRingtones
}
public static func parse_updateServiceNotification(_ reader: BufferReader) -> Update? {
var _1: Int32?
_1 = reader.readInt32()

View file

@ -690,6 +690,64 @@ public extension Api.account {
}
}
public extension Api.account {
enum SavedRingtones: TypeConstructorDescription {
case savedRingtones(hash: Int64, ringtones: [Api.Document])
case savedRingtonesNotModified
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedRingtones(let hash, let ringtones):
if boxed {
buffer.appendInt32(-1041683259)
}
serializeInt64(hash, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(ringtones.count))
for item in ringtones {
item.serialize(buffer, true)
}
break
case .savedRingtonesNotModified:
if boxed {
buffer.appendInt32(-67704655)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedRingtones(let hash, let ringtones):
return ("savedRingtones", [("hash", String(describing: hash)), ("ringtones", String(describing: ringtones))])
case .savedRingtonesNotModified:
return ("savedRingtonesNotModified", [])
}
}
public static func parse_savedRingtones(_ reader: BufferReader) -> SavedRingtones? {
var _1: Int64?
_1 = reader.readInt64()
var _2: [Api.Document]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.account.SavedRingtones.savedRingtones(hash: _1!, ringtones: _2!)
}
else {
return nil
}
}
public static func parse_savedRingtonesNotModified(_ reader: BufferReader) -> SavedRingtones? {
return Api.account.SavedRingtones.savedRingtonesNotModified
}
}
}
public extension Api.account {
enum SentEmailCode: TypeConstructorDescription {
case sentEmailCode(emailPattern: String, length: Int32)
@ -1154,129 +1212,3 @@ public extension Api.auth {
}
}
public extension Api.auth {
enum LoggedOut: TypeConstructorDescription {
case loggedOut(flags: Int32, futureAuthToken: Buffer?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
if boxed {
buffer.appendInt32(-1012759713)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(futureAuthToken!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
return ("loggedOut", [("flags", String(describing: flags)), ("futureAuthToken", String(describing: futureAuthToken))])
}
}
public static func parse_loggedOut(_ reader: BufferReader) -> LoggedOut? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
if _c1 && _c2 {
return Api.auth.LoggedOut.loggedOut(flags: _1!, futureAuthToken: _2)
}
else {
return nil
}
}
}
}
public extension Api.auth {
enum LoginToken: TypeConstructorDescription {
case loginToken(expires: Int32, token: Buffer)
case loginTokenMigrateTo(dcId: Int32, token: Buffer)
case loginTokenSuccess(authorization: Api.auth.Authorization)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .loginToken(let expires, let token):
if boxed {
buffer.appendInt32(1654593920)
}
serializeInt32(expires, buffer: buffer, boxed: false)
serializeBytes(token, buffer: buffer, boxed: false)
break
case .loginTokenMigrateTo(let dcId, let token):
if boxed {
buffer.appendInt32(110008598)
}
serializeInt32(dcId, buffer: buffer, boxed: false)
serializeBytes(token, buffer: buffer, boxed: false)
break
case .loginTokenSuccess(let authorization):
if boxed {
buffer.appendInt32(957176926)
}
authorization.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .loginToken(let expires, let token):
return ("loginToken", [("expires", String(describing: expires)), ("token", String(describing: token))])
case .loginTokenMigrateTo(let dcId, let token):
return ("loginTokenMigrateTo", [("dcId", String(describing: dcId)), ("token", String(describing: token))])
case .loginTokenSuccess(let authorization):
return ("loginTokenSuccess", [("authorization", String(describing: authorization))])
}
}
public static func parse_loginToken(_ reader: BufferReader) -> LoginToken? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.auth.LoginToken.loginToken(expires: _1!, token: _2!)
}
else {
return nil
}
}
public static func parse_loginTokenMigrateTo(_ reader: BufferReader) -> LoginToken? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.auth.LoginToken.loginTokenMigrateTo(dcId: _1!, token: _2!)
}
else {
return nil
}
}
public static func parse_loginTokenSuccess(_ reader: BufferReader) -> LoginToken? {
var _1: Api.auth.Authorization?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.auth.Authorization
}
let _c1 = _1 != nil
if _c1 {
return Api.auth.LoginToken.loginTokenSuccess(authorization: _1!)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,129 @@
public extension Api.auth {
enum LoggedOut: TypeConstructorDescription {
case loggedOut(flags: Int32, futureAuthToken: Buffer?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
if boxed {
buffer.appendInt32(-1012759713)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeBytes(futureAuthToken!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .loggedOut(let flags, let futureAuthToken):
return ("loggedOut", [("flags", String(describing: flags)), ("futureAuthToken", String(describing: futureAuthToken))])
}
}
public static func parse_loggedOut(_ reader: BufferReader) -> LoggedOut? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
if _c1 && _c2 {
return Api.auth.LoggedOut.loggedOut(flags: _1!, futureAuthToken: _2)
}
else {
return nil
}
}
}
}
public extension Api.auth {
enum LoginToken: TypeConstructorDescription {
case loginToken(expires: Int32, token: Buffer)
case loginTokenMigrateTo(dcId: Int32, token: Buffer)
case loginTokenSuccess(authorization: Api.auth.Authorization)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .loginToken(let expires, let token):
if boxed {
buffer.appendInt32(1654593920)
}
serializeInt32(expires, buffer: buffer, boxed: false)
serializeBytes(token, buffer: buffer, boxed: false)
break
case .loginTokenMigrateTo(let dcId, let token):
if boxed {
buffer.appendInt32(110008598)
}
serializeInt32(dcId, buffer: buffer, boxed: false)
serializeBytes(token, buffer: buffer, boxed: false)
break
case .loginTokenSuccess(let authorization):
if boxed {
buffer.appendInt32(957176926)
}
authorization.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .loginToken(let expires, let token):
return ("loginToken", [("expires", String(describing: expires)), ("token", String(describing: token))])
case .loginTokenMigrateTo(let dcId, let token):
return ("loginTokenMigrateTo", [("dcId", String(describing: dcId)), ("token", String(describing: token))])
case .loginTokenSuccess(let authorization):
return ("loginTokenSuccess", [("authorization", String(describing: authorization))])
}
}
public static func parse_loginToken(_ reader: BufferReader) -> LoginToken? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.auth.LoginToken.loginToken(expires: _1!, token: _2!)
}
else {
return nil
}
}
public static func parse_loginTokenMigrateTo(_ reader: BufferReader) -> LoginToken? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.auth.LoginToken.loginTokenMigrateTo(dcId: _1!, token: _2!)
}
else {
return nil
}
}
public static func parse_loginTokenSuccess(_ reader: BufferReader) -> LoginToken? {
var _1: Api.auth.Authorization?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.auth.Authorization
}
let _c1 = _1 != nil
if _c1 {
return Api.auth.LoginToken.loginTokenSuccess(authorization: _1!)
}
else {
return nil
}
}
}
}
public extension Api.auth {
enum PasswordRecovery: TypeConstructorDescription {
case passwordRecovery(emailPattern: String)
@ -1178,183 +1304,3 @@ public extension Api.help {
}
}
public extension Api.help {
enum Country: TypeConstructorDescription {
case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
if boxed {
buffer.appendInt32(-1014526429)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(iso2, buffer: buffer, boxed: false)
serializeString(defaultName, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(countryCodes.count))
for item in countryCodes {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
return ("country", [("flags", String(describing: flags)), ("iso2", String(describing: iso2)), ("defaultName", String(describing: defaultName)), ("name", String(describing: name)), ("countryCodes", String(describing: countryCodes))])
}
}
public static func parse_country(_ reader: BufferReader) -> Country? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: [Api.help.CountryCode]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!)
}
else {
return nil
}
}
}
}
public extension Api.help {
enum CountryCode: TypeConstructorDescription {
case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .countryCode(let flags, let countryCode, let prefixes, let patterns):
if boxed {
buffer.appendInt32(1107543535)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(countryCode, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(prefixes!.count))
for item in prefixes! {
serializeString(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(patterns!.count))
for item in patterns! {
serializeString(item, buffer: buffer, boxed: false)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .countryCode(let flags, let countryCode, let prefixes, let patterns):
return ("countryCode", [("flags", String(describing: flags)), ("countryCode", String(describing: countryCode)), ("prefixes", String(describing: prefixes)), ("patterns", String(describing: patterns))])
}
}
public static func parse_countryCode(_ reader: BufferReader) -> CountryCode? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: [String]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
} }
var _4: [String]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.help.CountryCode.countryCode(flags: _1!, countryCode: _2!, prefixes: _3, patterns: _4)
}
else {
return nil
}
}
}
}
public extension Api.help {
enum DeepLinkInfo: TypeConstructorDescription {
case deepLinkInfo(flags: Int32, message: String, entities: [Api.MessageEntity]?)
case deepLinkInfoEmpty
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .deepLinkInfo(let flags, let message, let entities):
if boxed {
buffer.appendInt32(1783556146)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
break
case .deepLinkInfoEmpty:
if boxed {
buffer.appendInt32(1722786150)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .deepLinkInfo(let flags, let message, let entities):
return ("deepLinkInfo", [("flags", String(describing: flags)), ("message", String(describing: message)), ("entities", String(describing: entities))])
case .deepLinkInfoEmpty:
return ("deepLinkInfoEmpty", [])
}
}
public static func parse_deepLinkInfo(_ reader: BufferReader) -> DeepLinkInfo? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.help.DeepLinkInfo.deepLinkInfo(flags: _1!, message: _2!, entities: _3)
}
else {
return nil
}
}
public static func parse_deepLinkInfoEmpty(_ reader: BufferReader) -> DeepLinkInfo? {
return Api.help.DeepLinkInfo.deepLinkInfoEmpty
}
}
}

View file

@ -1,3 +1,183 @@
public extension Api.help {
enum Country: TypeConstructorDescription {
case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
if boxed {
buffer.appendInt32(-1014526429)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(iso2, buffer: buffer, boxed: false)
serializeString(defaultName, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(countryCodes.count))
for item in countryCodes {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .country(let flags, let iso2, let defaultName, let name, let countryCodes):
return ("country", [("flags", String(describing: flags)), ("iso2", String(describing: iso2)), ("defaultName", String(describing: defaultName)), ("name", String(describing: name)), ("countryCodes", String(describing: countryCodes))])
}
}
public static func parse_country(_ reader: BufferReader) -> Country? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: [Api.help.CountryCode]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!)
}
else {
return nil
}
}
}
}
public extension Api.help {
enum CountryCode: TypeConstructorDescription {
case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .countryCode(let flags, let countryCode, let prefixes, let patterns):
if boxed {
buffer.appendInt32(1107543535)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(countryCode, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(prefixes!.count))
for item in prefixes! {
serializeString(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(patterns!.count))
for item in patterns! {
serializeString(item, buffer: buffer, boxed: false)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .countryCode(let flags, let countryCode, let prefixes, let patterns):
return ("countryCode", [("flags", String(describing: flags)), ("countryCode", String(describing: countryCode)), ("prefixes", String(describing: prefixes)), ("patterns", String(describing: patterns))])
}
}
public static func parse_countryCode(_ reader: BufferReader) -> CountryCode? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: [String]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
} }
var _4: [String]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.help.CountryCode.countryCode(flags: _1!, countryCode: _2!, prefixes: _3, patterns: _4)
}
else {
return nil
}
}
}
}
public extension Api.help {
enum DeepLinkInfo: TypeConstructorDescription {
case deepLinkInfo(flags: Int32, message: String, entities: [Api.MessageEntity]?)
case deepLinkInfoEmpty
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .deepLinkInfo(let flags, let message, let entities):
if boxed {
buffer.appendInt32(1783556146)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
break
case .deepLinkInfoEmpty:
if boxed {
buffer.appendInt32(1722786150)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .deepLinkInfo(let flags, let message, let entities):
return ("deepLinkInfo", [("flags", String(describing: flags)), ("message", String(describing: message)), ("entities", String(describing: entities))])
case .deepLinkInfoEmpty:
return ("deepLinkInfoEmpty", [])
}
}
public static func parse_deepLinkInfo(_ reader: BufferReader) -> DeepLinkInfo? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.help.DeepLinkInfo.deepLinkInfo(flags: _1!, message: _2!, entities: _3)
}
else {
return nil
}
}
public static func parse_deepLinkInfoEmpty(_ reader: BufferReader) -> DeepLinkInfo? {
return Api.help.DeepLinkInfo.deepLinkInfoEmpty
}
}
}
public extension Api.help {
enum InviteText: TypeConstructorDescription {
case inviteText(message: String)
@ -1170,259 +1350,3 @@ public extension Api.messages {
}
}
public extension Api.messages {
enum CheckedHistoryImportPeer: TypeConstructorDescription {
case checkedHistoryImportPeer(confirmText: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
if boxed {
buffer.appendInt32(-1571952873)
}
serializeString(confirmText, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
return ("checkedHistoryImportPeer", [("confirmText", String(describing: confirmText))])
}
}
public static func parse_checkedHistoryImportPeer(_ reader: BufferReader) -> CheckedHistoryImportPeer? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.messages.CheckedHistoryImportPeer.checkedHistoryImportPeer(confirmText: _1!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum DhConfig: TypeConstructorDescription {
case dhConfig(g: Int32, p: Buffer, version: Int32, random: Buffer)
case dhConfigNotModified(random: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .dhConfig(let g, let p, let version, let random):
if boxed {
buffer.appendInt32(740433629)
}
serializeInt32(g, buffer: buffer, boxed: false)
serializeBytes(p, buffer: buffer, boxed: false)
serializeInt32(version, buffer: buffer, boxed: false)
serializeBytes(random, buffer: buffer, boxed: false)
break
case .dhConfigNotModified(let random):
if boxed {
buffer.appendInt32(-1058912715)
}
serializeBytes(random, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .dhConfig(let g, let p, let version, let random):
return ("dhConfig", [("g", String(describing: g)), ("p", String(describing: p)), ("version", String(describing: version)), ("random", String(describing: random))])
case .dhConfigNotModified(let random):
return ("dhConfigNotModified", [("random", String(describing: random))])
}
}
public static func parse_dhConfig(_ reader: BufferReader) -> DhConfig? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Int32?
_3 = reader.readInt32()
var _4: Buffer?
_4 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.messages.DhConfig.dhConfig(g: _1!, p: _2!, version: _3!, random: _4!)
}
else {
return nil
}
}
public static func parse_dhConfigNotModified(_ reader: BufferReader) -> DhConfig? {
var _1: Buffer?
_1 = parseBytes(reader)
let _c1 = _1 != nil
if _c1 {
return Api.messages.DhConfig.dhConfigNotModified(random: _1!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum Dialogs: TypeConstructorDescription {
case dialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
case dialogsNotModified(count: Int32)
case dialogsSlice(count: Int32, dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .dialogs(let dialogs, let messages, let chats, let users):
if boxed {
buffer.appendInt32(364538944)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(dialogs.count))
for item in dialogs {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messages.count))
for item in messages {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
case .dialogsNotModified(let count):
if boxed {
buffer.appendInt32(-253500010)
}
serializeInt32(count, buffer: buffer, boxed: false)
break
case .dialogsSlice(let count, let dialogs, let messages, let chats, let users):
if boxed {
buffer.appendInt32(1910543603)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(dialogs.count))
for item in dialogs {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messages.count))
for item in messages {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .dialogs(let dialogs, let messages, let chats, let users):
return ("dialogs", [("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))])
case .dialogsNotModified(let count):
return ("dialogsNotModified", [("count", String(describing: count))])
case .dialogsSlice(let count, let dialogs, let messages, let chats, let users):
return ("dialogsSlice", [("count", String(describing: count)), ("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))])
}
}
public static func parse_dialogs(_ reader: BufferReader) -> Dialogs? {
var _1: [Api.Dialog]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self)
}
var _2: [Api.Message]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
}
var _3: [Api.Chat]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _4: [Api.User]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.messages.Dialogs.dialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!)
}
else {
return nil
}
}
public static func parse_dialogsNotModified(_ reader: BufferReader) -> Dialogs? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.messages.Dialogs.dialogsNotModified(count: _1!)
}
else {
return nil
}
}
public static func parse_dialogsSlice(_ reader: BufferReader) -> Dialogs? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.Dialog]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self)
}
var _3: [Api.Message]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
}
var _4: [Api.Chat]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _5: [Api.User]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.messages.Dialogs.dialogsSlice(count: _1!, dialogs: _2!, messages: _3!, chats: _4!, users: _5!)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,259 @@
public extension Api.messages {
enum CheckedHistoryImportPeer: TypeConstructorDescription {
case checkedHistoryImportPeer(confirmText: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
if boxed {
buffer.appendInt32(-1571952873)
}
serializeString(confirmText, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .checkedHistoryImportPeer(let confirmText):
return ("checkedHistoryImportPeer", [("confirmText", String(describing: confirmText))])
}
}
public static func parse_checkedHistoryImportPeer(_ reader: BufferReader) -> CheckedHistoryImportPeer? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.messages.CheckedHistoryImportPeer.checkedHistoryImportPeer(confirmText: _1!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum DhConfig: TypeConstructorDescription {
case dhConfig(g: Int32, p: Buffer, version: Int32, random: Buffer)
case dhConfigNotModified(random: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .dhConfig(let g, let p, let version, let random):
if boxed {
buffer.appendInt32(740433629)
}
serializeInt32(g, buffer: buffer, boxed: false)
serializeBytes(p, buffer: buffer, boxed: false)
serializeInt32(version, buffer: buffer, boxed: false)
serializeBytes(random, buffer: buffer, boxed: false)
break
case .dhConfigNotModified(let random):
if boxed {
buffer.appendInt32(-1058912715)
}
serializeBytes(random, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .dhConfig(let g, let p, let version, let random):
return ("dhConfig", [("g", String(describing: g)), ("p", String(describing: p)), ("version", String(describing: version)), ("random", String(describing: random))])
case .dhConfigNotModified(let random):
return ("dhConfigNotModified", [("random", String(describing: random))])
}
}
public static func parse_dhConfig(_ reader: BufferReader) -> DhConfig? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Int32?
_3 = reader.readInt32()
var _4: Buffer?
_4 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.messages.DhConfig.dhConfig(g: _1!, p: _2!, version: _3!, random: _4!)
}
else {
return nil
}
}
public static func parse_dhConfigNotModified(_ reader: BufferReader) -> DhConfig? {
var _1: Buffer?
_1 = parseBytes(reader)
let _c1 = _1 != nil
if _c1 {
return Api.messages.DhConfig.dhConfigNotModified(random: _1!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum Dialogs: TypeConstructorDescription {
case dialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
case dialogsNotModified(count: Int32)
case dialogsSlice(count: Int32, dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .dialogs(let dialogs, let messages, let chats, let users):
if boxed {
buffer.appendInt32(364538944)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(dialogs.count))
for item in dialogs {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messages.count))
for item in messages {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
case .dialogsNotModified(let count):
if boxed {
buffer.appendInt32(-253500010)
}
serializeInt32(count, buffer: buffer, boxed: false)
break
case .dialogsSlice(let count, let dialogs, let messages, let chats, let users):
if boxed {
buffer.appendInt32(1910543603)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(dialogs.count))
for item in dialogs {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messages.count))
for item in messages {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .dialogs(let dialogs, let messages, let chats, let users):
return ("dialogs", [("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))])
case .dialogsNotModified(let count):
return ("dialogsNotModified", [("count", String(describing: count))])
case .dialogsSlice(let count, let dialogs, let messages, let chats, let users):
return ("dialogsSlice", [("count", String(describing: count)), ("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))])
}
}
public static func parse_dialogs(_ reader: BufferReader) -> Dialogs? {
var _1: [Api.Dialog]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self)
}
var _2: [Api.Message]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
}
var _3: [Api.Chat]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _4: [Api.User]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.messages.Dialogs.dialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!)
}
else {
return nil
}
}
public static func parse_dialogsNotModified(_ reader: BufferReader) -> Dialogs? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.messages.Dialogs.dialogsNotModified(count: _1!)
}
else {
return nil
}
}
public static func parse_dialogsSlice(_ reader: BufferReader) -> Dialogs? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.Dialog]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self)
}
var _3: [Api.Message]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
}
var _4: [Api.Chat]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _5: [Api.User]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.messages.Dialogs.dialogsSlice(count: _1!, dialogs: _2!, messages: _3!, chats: _4!, users: _5!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum DiscussionMessage: TypeConstructorDescription {
case discussionMessage(flags: Int32, messages: [Api.Message], maxId: Int32?, readInboxMaxId: Int32?, readOutboxMaxId: Int32?, unreadCount: Int32, chats: [Api.Chat], users: [Api.User])
@ -1268,249 +1524,3 @@ public extension Api.messages {
}
}
public extension Api.messages {
enum SearchCounter: TypeConstructorDescription {
case searchCounter(flags: Int32, filter: Api.MessagesFilter, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchCounter(let flags, let filter, let count):
if boxed {
buffer.appendInt32(-398136321)
}
serializeInt32(flags, buffer: buffer, boxed: false)
filter.serialize(buffer, true)
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchCounter(let flags, let filter, let count):
return ("searchCounter", [("flags", String(describing: flags)), ("filter", String(describing: filter)), ("count", String(describing: count))])
}
}
public static func parse_searchCounter(_ reader: BufferReader) -> SearchCounter? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.MessagesFilter?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.MessagesFilter
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.messages.SearchCounter.searchCounter(flags: _1!, filter: _2!, count: _3!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SearchResultsCalendar: TypeConstructorDescription {
case searchResultsCalendar(flags: Int32, count: Int32, minDate: Int32, minMsgId: Int32, offsetIdOffset: Int32?, periods: [Api.SearchResultsCalendarPeriod], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users):
if boxed {
buffer.appendInt32(343859772)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
serializeInt32(minDate, buffer: buffer, boxed: false)
serializeInt32(minMsgId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(periods.count))
for item in periods {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messages.count))
for item in messages {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users):
return ("searchResultsCalendar", [("flags", String(describing: flags)), ("count", String(describing: count)), ("minDate", String(describing: minDate)), ("minMsgId", String(describing: minMsgId)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("periods", String(describing: periods)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))])
}
}
public static func parse_searchResultsCalendar(_ reader: BufferReader) -> SearchResultsCalendar? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
var _6: [Api.SearchResultsCalendarPeriod]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsCalendarPeriod.self)
}
var _7: [Api.Message]?
if let _ = reader.readInt32() {
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
}
var _8: [Api.Chat]?
if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _9: [Api.User]?
if let _ = reader.readInt32() {
_9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.messages.SearchResultsCalendar.searchResultsCalendar(flags: _1!, count: _2!, minDate: _3!, minMsgId: _4!, offsetIdOffset: _5, periods: _6!, messages: _7!, chats: _8!, users: _9!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SearchResultsPositions: TypeConstructorDescription {
case searchResultsPositions(count: Int32, positions: [Api.SearchResultsPosition])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultsPositions(let count, let positions):
if boxed {
buffer.appendInt32(1404185519)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(positions.count))
for item in positions {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultsPositions(let count, let positions):
return ("searchResultsPositions", [("count", String(describing: count)), ("positions", String(describing: positions))])
}
}
public static func parse_searchResultsPositions(_ reader: BufferReader) -> SearchResultsPositions? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.SearchResultsPosition]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsPosition.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.messages.SearchResultsPositions.searchResultsPositions(count: _1!, positions: _2!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SentEncryptedMessage: TypeConstructorDescription {
case sentEncryptedFile(date: Int32, file: Api.EncryptedFile)
case sentEncryptedMessage(date: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .sentEncryptedFile(let date, let file):
if boxed {
buffer.appendInt32(-1802240206)
}
serializeInt32(date, buffer: buffer, boxed: false)
file.serialize(buffer, true)
break
case .sentEncryptedMessage(let date):
if boxed {
buffer.appendInt32(1443858741)
}
serializeInt32(date, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .sentEncryptedFile(let date, let file):
return ("sentEncryptedFile", [("date", String(describing: date)), ("file", String(describing: file))])
case .sentEncryptedMessage(let date):
return ("sentEncryptedMessage", [("date", String(describing: date))])
}
}
public static func parse_sentEncryptedFile(_ reader: BufferReader) -> SentEncryptedMessage? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.EncryptedFile?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.EncryptedFile
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.messages.SentEncryptedMessage.sentEncryptedFile(date: _1!, file: _2!)
}
else {
return nil
}
}
public static func parse_sentEncryptedMessage(_ reader: BufferReader) -> SentEncryptedMessage? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.messages.SentEncryptedMessage.sentEncryptedMessage(date: _1!)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,249 @@
public extension Api.messages {
enum SearchCounter: TypeConstructorDescription {
case searchCounter(flags: Int32, filter: Api.MessagesFilter, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchCounter(let flags, let filter, let count):
if boxed {
buffer.appendInt32(-398136321)
}
serializeInt32(flags, buffer: buffer, boxed: false)
filter.serialize(buffer, true)
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchCounter(let flags, let filter, let count):
return ("searchCounter", [("flags", String(describing: flags)), ("filter", String(describing: filter)), ("count", String(describing: count))])
}
}
public static func parse_searchCounter(_ reader: BufferReader) -> SearchCounter? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.MessagesFilter?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.MessagesFilter
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.messages.SearchCounter.searchCounter(flags: _1!, filter: _2!, count: _3!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SearchResultsCalendar: TypeConstructorDescription {
case searchResultsCalendar(flags: Int32, count: Int32, minDate: Int32, minMsgId: Int32, offsetIdOffset: Int32?, periods: [Api.SearchResultsCalendarPeriod], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users):
if boxed {
buffer.appendInt32(343859772)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
serializeInt32(minDate, buffer: buffer, boxed: false)
serializeInt32(minMsgId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(periods.count))
for item in periods {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(messages.count))
for item in messages {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users):
return ("searchResultsCalendar", [("flags", String(describing: flags)), ("count", String(describing: count)), ("minDate", String(describing: minDate)), ("minMsgId", String(describing: minMsgId)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("periods", String(describing: periods)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))])
}
}
public static func parse_searchResultsCalendar(_ reader: BufferReader) -> SearchResultsCalendar? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
var _6: [Api.SearchResultsCalendarPeriod]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsCalendarPeriod.self)
}
var _7: [Api.Message]?
if let _ = reader.readInt32() {
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
}
var _8: [Api.Chat]?
if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _9: [Api.User]?
if let _ = reader.readInt32() {
_9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.messages.SearchResultsCalendar.searchResultsCalendar(flags: _1!, count: _2!, minDate: _3!, minMsgId: _4!, offsetIdOffset: _5, periods: _6!, messages: _7!, chats: _8!, users: _9!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SearchResultsPositions: TypeConstructorDescription {
case searchResultsPositions(count: Int32, positions: [Api.SearchResultsPosition])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultsPositions(let count, let positions):
if boxed {
buffer.appendInt32(1404185519)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(positions.count))
for item in positions {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultsPositions(let count, let positions):
return ("searchResultsPositions", [("count", String(describing: count)), ("positions", String(describing: positions))])
}
}
public static func parse_searchResultsPositions(_ reader: BufferReader) -> SearchResultsPositions? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.SearchResultsPosition]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsPosition.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.messages.SearchResultsPositions.searchResultsPositions(count: _1!, positions: _2!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SentEncryptedMessage: TypeConstructorDescription {
case sentEncryptedFile(date: Int32, file: Api.EncryptedFile)
case sentEncryptedMessage(date: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .sentEncryptedFile(let date, let file):
if boxed {
buffer.appendInt32(-1802240206)
}
serializeInt32(date, buffer: buffer, boxed: false)
file.serialize(buffer, true)
break
case .sentEncryptedMessage(let date):
if boxed {
buffer.appendInt32(1443858741)
}
serializeInt32(date, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .sentEncryptedFile(let date, let file):
return ("sentEncryptedFile", [("date", String(describing: date)), ("file", String(describing: file))])
case .sentEncryptedMessage(let date):
return ("sentEncryptedMessage", [("date", String(describing: date))])
}
}
public static func parse_sentEncryptedFile(_ reader: BufferReader) -> SentEncryptedMessage? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.EncryptedFile?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.EncryptedFile
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.messages.SentEncryptedMessage.sentEncryptedFile(date: _1!, file: _2!)
}
else {
return nil
}
}
public static func parse_sentEncryptedMessage(_ reader: BufferReader) -> SentEncryptedMessage? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.messages.SentEncryptedMessage.sentEncryptedMessage(date: _1!)
}
else {
return nil
}
}
}
}
public extension Api.messages {
enum SponsoredMessages: TypeConstructorDescription {
case sponsoredMessages(messages: [Api.SponsoredMessage], chats: [Api.Chat], users: [Api.User])
@ -1260,489 +1506,3 @@ public extension Api.photos {
}
}
public extension Api.stats {
enum BroadcastStats: TypeConstructorDescription {
case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, ivInteractionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, recentMessageInteractions: [Api.MessageInteractionCounters])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions):
if boxed {
buffer.appendInt32(-1107852396)
}
period.serialize(buffer, true)
followers.serialize(buffer, true)
viewsPerPost.serialize(buffer, true)
sharesPerPost.serialize(buffer, true)
enabledNotifications.serialize(buffer, true)
growthGraph.serialize(buffer, true)
followersGraph.serialize(buffer, true)
muteGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
interactionsGraph.serialize(buffer, true)
ivInteractionsGraph.serialize(buffer, true)
viewsBySourceGraph.serialize(buffer, true)
newFollowersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(recentMessageInteractions.count))
for item in recentMessageInteractions {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions):
return ("broadcastStats", [("period", String(describing: period)), ("followers", String(describing: followers)), ("viewsPerPost", String(describing: viewsPerPost)), ("sharesPerPost", String(describing: sharesPerPost)), ("enabledNotifications", String(describing: enabledNotifications)), ("growthGraph", String(describing: growthGraph)), ("followersGraph", String(describing: followersGraph)), ("muteGraph", String(describing: muteGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("interactionsGraph", String(describing: interactionsGraph)), ("ivInteractionsGraph", String(describing: ivInteractionsGraph)), ("viewsBySourceGraph", String(describing: viewsBySourceGraph)), ("newFollowersBySourceGraph", String(describing: newFollowersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("recentMessageInteractions", String(describing: recentMessageInteractions))])
}
}
public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsPercentValue?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue
}
var _6: Api.StatsGraph?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _7: Api.StatsGraph?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _8: Api.StatsGraph?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _9: Api.StatsGraph?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: Api.StatsGraph?
if let signature = reader.readInt32() {
_14 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _15: [Api.MessageInteractionCounters]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageInteractionCounters.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 {
return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, growthGraph: _6!, followersGraph: _7!, muteGraph: _8!, topHoursGraph: _9!, interactionsGraph: _10!, ivInteractionsGraph: _11!, viewsBySourceGraph: _12!, newFollowersBySourceGraph: _13!, languagesGraph: _14!, recentMessageInteractions: _15!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MegagroupStats: TypeConstructorDescription {
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
if boxed {
buffer.appendInt32(-276825834)
}
period.serialize(buffer, true)
members.serialize(buffer, true)
messages.serialize(buffer, true)
viewers.serialize(buffer, true)
posters.serialize(buffer, true)
growthGraph.serialize(buffer, true)
membersGraph.serialize(buffer, true)
newMembersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
messagesGraph.serialize(buffer, true)
actionsGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
weekdaysGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topPosters.count))
for item in topPosters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topAdmins.count))
for item in topAdmins {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topInviters.count))
for item in topInviters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
return ("megagroupStats", [("period", String(describing: period)), ("members", String(describing: members)), ("messages", String(describing: messages)), ("viewers", String(describing: viewers)), ("posters", String(describing: posters)), ("growthGraph", String(describing: growthGraph)), ("membersGraph", String(describing: membersGraph)), ("newMembersBySourceGraph", String(describing: newMembersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("messagesGraph", String(describing: messagesGraph)), ("actionsGraph", String(describing: actionsGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("weekdaysGraph", String(describing: weekdaysGraph)), ("topPosters", String(describing: topPosters)), ("topAdmins", String(describing: topAdmins)), ("topInviters", String(describing: topInviters)), ("users", String(describing: users))])
}
}
public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _6: Api.StatsGraph?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _7: Api.StatsGraph?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _8: Api.StatsGraph?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _9: Api.StatsGraph?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: [Api.StatsGroupTopPoster]?
if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
}
var _15: [Api.StatsGroupTopAdmin]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
}
var _16: [Api.StatsGroupTopInviter]?
if let _ = reader.readInt32() {
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
}
var _17: [Api.User]?
if let _ = reader.readInt32() {
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = _16 != nil
let _c17 = _17 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MessageStats: TypeConstructorDescription {
case messageStats(viewsGraph: Api.StatsGraph)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageStats(let viewsGraph):
if boxed {
buffer.appendInt32(-1986399595)
}
viewsGraph.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageStats(let viewsGraph):
return ("messageStats", [("viewsGraph", String(describing: viewsGraph))])
}
}
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
var _1: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
let _c1 = _1 != nil
if _c1 {
return Api.stats.MessageStats.messageStats(viewsGraph: _1!)
}
else {
return nil
}
}
}
}
public extension Api.stickers {
enum SuggestedShortName: TypeConstructorDescription {
case suggestedShortName(shortName: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .suggestedShortName(let shortName):
if boxed {
buffer.appendInt32(-2046910401)
}
serializeString(shortName, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .suggestedShortName(let shortName):
return ("suggestedShortName", [("shortName", String(describing: shortName))])
}
}
public static func parse_suggestedShortName(_ reader: BufferReader) -> SuggestedShortName? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.stickers.SuggestedShortName.suggestedShortName(shortName: _1!)
}
else {
return nil
}
}
}
}
public extension Api.storage {
enum FileType: TypeConstructorDescription {
case fileGif
case fileJpeg
case fileMov
case fileMp3
case fileMp4
case filePartial
case filePdf
case filePng
case fileUnknown
case fileWebp
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .fileGif:
if boxed {
buffer.appendInt32(-891180321)
}
break
case .fileJpeg:
if boxed {
buffer.appendInt32(8322574)
}
break
case .fileMov:
if boxed {
buffer.appendInt32(1258941372)
}
break
case .fileMp3:
if boxed {
buffer.appendInt32(1384777335)
}
break
case .fileMp4:
if boxed {
buffer.appendInt32(-1278304028)
}
break
case .filePartial:
if boxed {
buffer.appendInt32(1086091090)
}
break
case .filePdf:
if boxed {
buffer.appendInt32(-1373745011)
}
break
case .filePng:
if boxed {
buffer.appendInt32(172975040)
}
break
case .fileUnknown:
if boxed {
buffer.appendInt32(-1432995067)
}
break
case .fileWebp:
if boxed {
buffer.appendInt32(276907596)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .fileGif:
return ("fileGif", [])
case .fileJpeg:
return ("fileJpeg", [])
case .fileMov:
return ("fileMov", [])
case .fileMp3:
return ("fileMp3", [])
case .fileMp4:
return ("fileMp4", [])
case .filePartial:
return ("filePartial", [])
case .filePdf:
return ("filePdf", [])
case .filePng:
return ("filePng", [])
case .fileUnknown:
return ("fileUnknown", [])
case .fileWebp:
return ("fileWebp", [])
}
}
public static func parse_fileGif(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileGif
}
public static func parse_fileJpeg(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileJpeg
}
public static func parse_fileMov(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileMov
}
public static func parse_fileMp3(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileMp3
}
public static func parse_fileMp4(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileMp4
}
public static func parse_filePartial(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.filePartial
}
public static func parse_filePdf(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.filePdf
}
public static func parse_filePng(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.filePng
}
public static func parse_fileUnknown(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileUnknown
}
public static func parse_fileWebp(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileWebp
}
}
}

View file

@ -1,3 +1,489 @@
public extension Api.stats {
enum BroadcastStats: TypeConstructorDescription {
case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, ivInteractionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, recentMessageInteractions: [Api.MessageInteractionCounters])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions):
if boxed {
buffer.appendInt32(-1107852396)
}
period.serialize(buffer, true)
followers.serialize(buffer, true)
viewsPerPost.serialize(buffer, true)
sharesPerPost.serialize(buffer, true)
enabledNotifications.serialize(buffer, true)
growthGraph.serialize(buffer, true)
followersGraph.serialize(buffer, true)
muteGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
interactionsGraph.serialize(buffer, true)
ivInteractionsGraph.serialize(buffer, true)
viewsBySourceGraph.serialize(buffer, true)
newFollowersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(recentMessageInteractions.count))
for item in recentMessageInteractions {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions):
return ("broadcastStats", [("period", String(describing: period)), ("followers", String(describing: followers)), ("viewsPerPost", String(describing: viewsPerPost)), ("sharesPerPost", String(describing: sharesPerPost)), ("enabledNotifications", String(describing: enabledNotifications)), ("growthGraph", String(describing: growthGraph)), ("followersGraph", String(describing: followersGraph)), ("muteGraph", String(describing: muteGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("interactionsGraph", String(describing: interactionsGraph)), ("ivInteractionsGraph", String(describing: ivInteractionsGraph)), ("viewsBySourceGraph", String(describing: viewsBySourceGraph)), ("newFollowersBySourceGraph", String(describing: newFollowersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("recentMessageInteractions", String(describing: recentMessageInteractions))])
}
}
public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsPercentValue?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue
}
var _6: Api.StatsGraph?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _7: Api.StatsGraph?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _8: Api.StatsGraph?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _9: Api.StatsGraph?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: Api.StatsGraph?
if let signature = reader.readInt32() {
_14 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _15: [Api.MessageInteractionCounters]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageInteractionCounters.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 {
return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, growthGraph: _6!, followersGraph: _7!, muteGraph: _8!, topHoursGraph: _9!, interactionsGraph: _10!, ivInteractionsGraph: _11!, viewsBySourceGraph: _12!, newFollowersBySourceGraph: _13!, languagesGraph: _14!, recentMessageInteractions: _15!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MegagroupStats: TypeConstructorDescription {
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
if boxed {
buffer.appendInt32(-276825834)
}
period.serialize(buffer, true)
members.serialize(buffer, true)
messages.serialize(buffer, true)
viewers.serialize(buffer, true)
posters.serialize(buffer, true)
growthGraph.serialize(buffer, true)
membersGraph.serialize(buffer, true)
newMembersBySourceGraph.serialize(buffer, true)
languagesGraph.serialize(buffer, true)
messagesGraph.serialize(buffer, true)
actionsGraph.serialize(buffer, true)
topHoursGraph.serialize(buffer, true)
weekdaysGraph.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topPosters.count))
for item in topPosters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topAdmins.count))
for item in topAdmins {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topInviters.count))
for item in topInviters {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
return ("megagroupStats", [("period", String(describing: period)), ("members", String(describing: members)), ("messages", String(describing: messages)), ("viewers", String(describing: viewers)), ("posters", String(describing: posters)), ("growthGraph", String(describing: growthGraph)), ("membersGraph", String(describing: membersGraph)), ("newMembersBySourceGraph", String(describing: newMembersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("messagesGraph", String(describing: messagesGraph)), ("actionsGraph", String(describing: actionsGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("weekdaysGraph", String(describing: weekdaysGraph)), ("topPosters", String(describing: topPosters)), ("topAdmins", String(describing: topAdmins)), ("topInviters", String(describing: topInviters)), ("users", String(describing: users))])
}
}
public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? {
var _1: Api.StatsDateRangeDays?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
}
var _2: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _3: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _4: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _5: Api.StatsAbsValueAndPrev?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
}
var _6: Api.StatsGraph?
if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _7: Api.StatsGraph?
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _8: Api.StatsGraph?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _9: Api.StatsGraph?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _10: Api.StatsGraph?
if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _11: Api.StatsGraph?
if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _12: Api.StatsGraph?
if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _13: Api.StatsGraph?
if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
var _14: [Api.StatsGroupTopPoster]?
if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
}
var _15: [Api.StatsGroupTopAdmin]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
}
var _16: [Api.StatsGroupTopInviter]?
if let _ = reader.readInt32() {
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
}
var _17: [Api.User]?
if let _ = reader.readInt32() {
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = _16 != nil
let _c17 = _17 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
}
else {
return nil
}
}
}
}
public extension Api.stats {
enum MessageStats: TypeConstructorDescription {
case messageStats(viewsGraph: Api.StatsGraph)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageStats(let viewsGraph):
if boxed {
buffer.appendInt32(-1986399595)
}
viewsGraph.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageStats(let viewsGraph):
return ("messageStats", [("viewsGraph", String(describing: viewsGraph))])
}
}
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
var _1: Api.StatsGraph?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
}
let _c1 = _1 != nil
if _c1 {
return Api.stats.MessageStats.messageStats(viewsGraph: _1!)
}
else {
return nil
}
}
}
}
public extension Api.stickers {
enum SuggestedShortName: TypeConstructorDescription {
case suggestedShortName(shortName: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .suggestedShortName(let shortName):
if boxed {
buffer.appendInt32(-2046910401)
}
serializeString(shortName, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .suggestedShortName(let shortName):
return ("suggestedShortName", [("shortName", String(describing: shortName))])
}
}
public static func parse_suggestedShortName(_ reader: BufferReader) -> SuggestedShortName? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.stickers.SuggestedShortName.suggestedShortName(shortName: _1!)
}
else {
return nil
}
}
}
}
public extension Api.storage {
enum FileType: TypeConstructorDescription {
case fileGif
case fileJpeg
case fileMov
case fileMp3
case fileMp4
case filePartial
case filePdf
case filePng
case fileUnknown
case fileWebp
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .fileGif:
if boxed {
buffer.appendInt32(-891180321)
}
break
case .fileJpeg:
if boxed {
buffer.appendInt32(8322574)
}
break
case .fileMov:
if boxed {
buffer.appendInt32(1258941372)
}
break
case .fileMp3:
if boxed {
buffer.appendInt32(1384777335)
}
break
case .fileMp4:
if boxed {
buffer.appendInt32(-1278304028)
}
break
case .filePartial:
if boxed {
buffer.appendInt32(1086091090)
}
break
case .filePdf:
if boxed {
buffer.appendInt32(-1373745011)
}
break
case .filePng:
if boxed {
buffer.appendInt32(172975040)
}
break
case .fileUnknown:
if boxed {
buffer.appendInt32(-1432995067)
}
break
case .fileWebp:
if boxed {
buffer.appendInt32(276907596)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .fileGif:
return ("fileGif", [])
case .fileJpeg:
return ("fileJpeg", [])
case .fileMov:
return ("fileMov", [])
case .fileMp3:
return ("fileMp3", [])
case .fileMp4:
return ("fileMp4", [])
case .filePartial:
return ("filePartial", [])
case .filePdf:
return ("filePdf", [])
case .filePng:
return ("filePng", [])
case .fileUnknown:
return ("fileUnknown", [])
case .fileWebp:
return ("fileWebp", [])
}
}
public static func parse_fileGif(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileGif
}
public static func parse_fileJpeg(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileJpeg
}
public static func parse_fileMov(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileMov
}
public static func parse_fileMp3(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileMp3
}
public static func parse_fileMp4(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileMp4
}
public static func parse_filePartial(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.filePartial
}
public static func parse_filePdf(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.filePdf
}
public static func parse_filePng(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.filePng
}
public static func parse_fileUnknown(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileUnknown
}
public static func parse_fileWebp(_ reader: BufferReader) -> FileType? {
return Api.storage.FileType.fileWebp
}
}
}
public extension Api.updates {
enum ChannelDifference: TypeConstructorDescription {
case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User])

View file

@ -436,6 +436,21 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func getSavedRingtones(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.SavedRingtones>) {
let buffer = Buffer()
buffer.appendInt32(-510647672)
serializeInt64(hash, buffer: buffer, boxed: false)
return (FunctionDescription(name: "account.getSavedRingtones", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SavedRingtones? in
let reader = BufferReader(buffer)
var result: Api.account.SavedRingtones?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.account.SavedRingtones
}
return result
})
}
}
public extension Api.functions.account {
static func getSecureValue(types: [Api.SecureValueType]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SecureValue]>) {
let buffer = Buffer()
@ -779,6 +794,22 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func saveRingtone(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-369618141)
id.serialize(buffer, true)
unsave.serialize(buffer, true)
return (FunctionDescription(name: "account.saveRingtone", parameters: [("id", String(describing: id)), ("unsave", String(describing: unsave))]), 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.account {
static func saveSecureValue(value: Api.InputSecureValue, secureSecretId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.SecureValue>) {
let buffer = Buffer()
@ -1127,6 +1158,23 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func uploadRingtone(file: Api.InputFile, fileName: String, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Document>) {
let buffer = Buffer()
buffer.appendInt32(-2095414366)
file.serialize(buffer, true)
serializeString(fileName, buffer: buffer, boxed: false)
serializeString(mimeType, buffer: buffer, boxed: false)
return (FunctionDescription(name: "account.uploadRingtone", parameters: [("file", String(describing: file)), ("fileName", String(describing: fileName)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in
let reader = BufferReader(buffer)
var result: Api.Document?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Document
}
return result
})
}
}
public extension Api.functions.account {
static func uploadTheme(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, fileName: String, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Document>) {
let buffer = Buffer()

View file

@ -444,19 +444,19 @@ public extension Api {
}
public extension Api {
enum InputPeerNotifySettings: TypeConstructorDescription {
case inputPeerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, sound: String?)
case inputPeerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, sound: Api.NotificationSound?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPeerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound):
if boxed {
buffer.appendInt32(-1673717362)
buffer.appendInt32(-551616469)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {showPreviews!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {silent!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(muteUntil!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeString(sound!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {sound!.serialize(buffer, true)}
break
}
}
@ -481,8 +481,10 @@ public extension Api {
} }
var _4: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
var _5: String?
if Int(_1!) & Int(1 << 3) != 0 {_5 = parseString(reader) }
var _5: Api.NotificationSound?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil

View file

@ -207,6 +207,8 @@ public final class ManagedAudioSession {
private let isActiveSubscribers = Bag<(Bool) -> Void>()
private let isPlaybackActiveSubscribers = Bag<(Bool) -> Void>()
private var callKitAudioSessionIsActive: Bool = false
public init() {
self.queue = Queue()
@ -899,18 +901,18 @@ public final class ManagedAudioSession {
}
public func callKitActivatedAudioSession() {
/*self.queue.async {
managedAudioSessionLog("ManagedAudioSession callKitDeactivatedAudioSession")
self.queue.async {
managedAudioSessionLog("ManagedAudioSession callKitDeactivatedAudioSession")
self.callKitAudioSessionIsActive = true
self.updateHolders()
}*/
}
}
public func callKitDeactivatedAudioSession() {
/*self.queue.async {
managedAudioSessionLog("ManagedAudioSession callKitDeactivatedAudioSession")
self.queue.async {
managedAudioSessionLog("ManagedAudioSession callKitDeactivatedAudioSession")
self.callKitAudioSessionIsActive = false
self.updateHolders()
}*/
}
}
}

View file

@ -1572,7 +1572,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
}).start()
}
strongSelf.presentUndoOverlay(content: .info(text: strongSelf.presentationData.strings.VoiceChat_EditBioSuccess), action: { _ in return false })
strongSelf.presentUndoOverlay(content: .info(title: nil, text: strongSelf.presentationData.strings.VoiceChat_EditBioSuccess), action: { _ in return false })
}
})
self?.controller?.present(controller, in: .window(.root))
@ -1593,7 +1593,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
if let strongSelf = self, let (firstName, lastName) = firstAndLastName {
let _ = context.engine.accountData.updateAccountPeerName(firstName: firstName, lastName: lastName).start()
strongSelf.presentUndoOverlay(content: .info(text: strongSelf.presentationData.strings.VoiceChat_EditNameSuccess), action: { _ in return false })
strongSelf.presentUndoOverlay(content: .info(title: nil, text: strongSelf.presentationData.strings.VoiceChat_EditNameSuccess), action: { _ in return false })
}
})
self?.controller?.present(controller, in: .window(.root))

View file

@ -1092,6 +1092,7 @@ public class Account {
self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
self.managedOperationsDisposable.add(managedSynchronizeAvailableReactions(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizeAttachMenuBots(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizeNotificationSoundList(postbox: self.postbox, network: self.network).start())
if !supplementary {
self.managedOperationsDisposable.add(managedChatListFilters(postbox: self.postbox, network: self.network, accountPeerId: self.peerId).start())

View file

@ -6,76 +6,91 @@ import TelegramApi
extension TelegramPeerNotificationSettings {
convenience init(apiSettings: Api.PeerNotifySettings) {
switch apiSettings {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, sound):
let muteState: PeerMuteState
if let muteUntil = muteUntil {
if muteUntil == 0 {
muteState = .unmuted
} else {
muteState = .muted(until: muteUntil)
}
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound):
let sound: Api.NotificationSound?
#if os(iOS)
sound = iosSound
#elseif os(macOS)
sound = desktopSound
#endif
let muteState: PeerMuteState
if let muteUntil = muteUntil {
if muteUntil == 0 {
muteState = .unmuted
} else {
muteState = .default
muteState = .muted(until: muteUntil)
}
let displayPreviews: PeerNotificationDisplayPreviews
if let showPreviews = showPreviews {
if case .boolTrue = showPreviews {
displayPreviews = .show
} else {
displayPreviews = .hide
}
} else {
muteState = .default
}
let displayPreviews: PeerNotificationDisplayPreviews
if let showPreviews = showPreviews {
if case .boolTrue = showPreviews {
displayPreviews = .show
} else {
displayPreviews = .default
displayPreviews = .hide
}
self.init(muteState: muteState, messageSound: PeerMessageSound(apiSound: sound), displayPreviews: displayPreviews)
} else {
displayPreviews = .default
}
self.init(muteState: muteState, messageSound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault), displayPreviews: displayPreviews)
}
}
}
extension PeerMessageSound {
init(apiSound: String?) {
guard let apiSound = apiSound else {
init(apiSound: Api.NotificationSound) {
switch apiSound {
case .notificationSoundDefault:
self = .default
return
}
var rawApiSound = apiSound
if let index = rawApiSound.firstIndex(of: ".") {
rawApiSound = String(rawApiSound[..<index])
}
let parsedSound: PeerMessageSound
if rawApiSound == "default" {
parsedSound = .default
} else if rawApiSound == "" || rawApiSound == "0" {
parsedSound = .none
} else {
let soundId: Int32
if let id = Int32(rawApiSound) {
soundId = id
} else {
soundId = 100
case .notificationSoundNone:
self = .none
case let .notificationSoundLocal(_, data):
var rawApiSound = data
if let index = rawApiSound.firstIndex(of: ".") {
rawApiSound = String(rawApiSound[..<index])
}
if soundId >= 100 && soundId <= 111 {
parsedSound = .bundledModern(id: soundId - 100)
} else if soundId >= 2 && soundId <= 9 {
parsedSound = .bundledClassic(id: soundId - 2)
let parsedSound: PeerMessageSound
if rawApiSound == "default" {
parsedSound = .default
} else if rawApiSound == "" || rawApiSound == "0" {
parsedSound = .none
} else {
parsedSound = .bundledModern(id: 0)
let soundId: Int32
if let id = Int32(rawApiSound) {
soundId = id
} else {
soundId = 100
}
if soundId >= 100 && soundId <= 111 {
parsedSound = .bundledModern(id: soundId - 100)
} else if soundId >= 2 && soundId <= 9 {
parsedSound = .bundledClassic(id: soundId - 2)
} else {
parsedSound = .bundledModern(id: 0)
}
}
self = parsedSound
case let .notificationSoundRingtone(id):
self = .cloud(fileId: id)
}
self = parsedSound
}
var apiSound: String? {
var apiSound: Api.NotificationSound {
switch self {
case .none:
return ""
case .default:
return nil
case let .bundledModern(id):
return "\(id + 100)"
case let .bundledClassic(id):
return "\(id + 2)"
case .none:
return .notificationSoundNone
case .default:
return .notificationSoundDefault
case let .bundledModern(id):
let string = "\(id + 100)"
return .notificationSoundLocal(title: string, data: string)
case let .bundledClassic(id):
let string = "\(id + 2)"
return .notificationSoundLocal(title: string, data: string)
case let .cloud(fileId):
return .notificationSoundRingtone(id: fileId)
}
}
}

View file

@ -6,14 +6,20 @@ import TelegramApi
extension MessageNotificationSettings {
init(apiSettings: Api.PeerNotifySettings) {
switch apiSettings {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, sound):
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
self = MessageNotificationSettings(enabled: muteUntil == 0, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound ?? "2"))
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound):
let sound: Api.NotificationSound?
#if os(iOS)
sound = iosSound
#elseif os(macOS)
sound = desktopSound
#endif
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
self = MessageNotificationSettings(enabled: muteUntil == 0, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault))
}
}
}

View file

@ -395,7 +395,10 @@ private func _internal_clearHistory(transaction: Transaction, postbox: Postbox,
if operation.minTimestamp != nil {
return .complete()
} else {
let flags: Int32 = 0
var flags: Int32 = 0
if operation.type == .forEveryone {
flags |= 1 << 0
}
return network.request(Api.functions.channels.deleteHistory(flags: flags, channel: inputChannel, maxId: operation.topMessageId.id))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in

View file

@ -116,56 +116,77 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
|> map { chats, users, channels, contactsJoinedMuted in
let chatsSettings: MessageNotificationSettings
switch chats {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, sound):
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
} else {
enabled = true
}
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
chatsSettings = MessageNotificationSettings(enabled: enabled, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound))
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound):
let sound: Api.NotificationSound?
#if os(iOS)
sound = iosSound
#elseif os(macOS)
sound = desktopSound
#endif
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
} else {
enabled = true
}
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
chatsSettings = MessageNotificationSettings(enabled: enabled, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault))
}
let userSettings: MessageNotificationSettings
switch users {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, sound):
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
} else {
enabled = true
}
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
userSettings = MessageNotificationSettings(enabled: enabled, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound))
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound):
let sound: Api.NotificationSound?
#if os(iOS)
sound = iosSound
#elseif os(macOS)
sound = desktopSound
#endif
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
} else {
enabled = true
}
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
userSettings = MessageNotificationSettings(enabled: enabled, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault))
}
let channelSettings: MessageNotificationSettings
switch channels {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, sound):
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
} else {
enabled = true
}
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
channelSettings = MessageNotificationSettings(enabled: enabled, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound))
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound):
let sound: Api.NotificationSound?
#if os(iOS)
sound = iosSound
#elseif os(macOS)
sound = desktopSound
#endif
let enabled: Bool
if muteUntil != nil && muteUntil != 0 {
enabled = false
} else {
enabled = true
}
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
channelSettings = MessageNotificationSettings(enabled: enabled, displayPreviews: displayPreviews, sound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault))
}
return GlobalNotificationSettingsSet(privateChats: userSettings, groupChats: chatsSettings, channels: channelSettings, contactsJoined: contactsJoinedMuted == .boolFalse)
@ -179,7 +200,7 @@ private func apiInputPeerNotifySettings(_ settings: MessageNotificationSettings)
} else {
muteUntil = Int32.max
}
let sound: String? = settings.sound.apiSound
let sound: Api.NotificationSound? = settings.sound.apiSound
var flags: Int32 = 0
flags |= (1 << 0)
if muteUntil != nil {

View file

@ -116,7 +116,7 @@ private func pushPeerNotificationSettings(postbox: Postbox, network: Network, pe
case .default:
muteUntil = nil
}
let sound: String? = settings.messageSound.apiSound
let sound: Api.NotificationSound? = settings.messageSound.apiSound
var flags: Int32 = 0
if showPreviews != nil {
flags |= (1 << 0)

View file

@ -84,6 +84,7 @@ public struct Namespaces {
public static let availableReactions: Int8 = 19
public static let resolvedByPhonePeers: Int8 = 20
public static let attachMenuBots: Int8 = 21
public static let notificationSoundList: Int8 = 22
}
public struct UnorderedItemList {

View file

@ -1,3 +1,4 @@
import Foundation
import Postbox
public enum PeerMuteState: Equatable {
@ -36,102 +37,147 @@ private enum PeerMessageSoundValue: Int32 {
case bundledModern
case bundledClassic
case `default`
case cloud
}
public enum PeerMessageSound: Equatable {
public enum Id: Hashable {
case none
case `default`
case bundledModern(id: Int32)
case bundledClassic(id: Int32)
case cloud(fileId: Int64)
}
case none
case `default`
case bundledModern(id: Int32)
case bundledClassic(id: Int32)
case cloud(fileId: Int64)
public var id: Id {
switch self {
case .none:
return .none
case .default:
return .default
case let .bundledModern(id):
return .bundledModern(id: id)
case let .bundledClassic(id):
return .bundledClassic(id: id)
case let .cloud(fileId):
return .cloud(fileId: fileId)
}
}
static func decodeInline(_ container: KeyedDecodingContainer<StringCodingKey>) throws -> PeerMessageSound {
switch try container.decode(Int32.self, forKey: "s.v") {
case PeerMessageSoundValue.none.rawValue:
return .none
case PeerMessageSoundValue.bundledModern.rawValue:
return .bundledModern(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0)
case PeerMessageSoundValue.bundledClassic.rawValue:
return .bundledClassic(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0)
case PeerMessageSoundValue.default.rawValue:
case PeerMessageSoundValue.none.rawValue:
return .none
case PeerMessageSoundValue.bundledModern.rawValue:
return .bundledModern(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0)
case PeerMessageSoundValue.bundledClassic.rawValue:
return .bundledClassic(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0)
case PeerMessageSoundValue.default.rawValue:
return .default
case PeerMessageSoundValue.cloud.rawValue:
do {
return .cloud(fileId: try container.decode(Int64.self, forKey: "s.cloud.fileId"))
} catch {
return .default
default:
assertionFailure()
return .bundledModern(id: 0)
}
default:
assertionFailure()
return .bundledModern(id: 0)
}
}
static func decodeInline(_ container: PostboxDecoder) -> PeerMessageSound {
switch container.decodeInt32ForKey("s.v", orElse: 0) {
case PeerMessageSoundValue.none.rawValue:
return .none
case PeerMessageSoundValue.bundledModern.rawValue:
return .bundledModern(id: container.decodeInt32ForKey("s.i", orElse: 0))
case PeerMessageSoundValue.bundledClassic.rawValue:
return .bundledClassic(id: container.decodeInt32ForKey("s.i", orElse: 0))
case PeerMessageSoundValue.default.rawValue:
return .default
default:
assertionFailure()
return .bundledModern(id: 0)
case PeerMessageSoundValue.none.rawValue:
return .none
case PeerMessageSoundValue.bundledModern.rawValue:
return .bundledModern(id: container.decodeInt32ForKey("s.i", orElse: 0))
case PeerMessageSoundValue.bundledClassic.rawValue:
return .bundledClassic(id: container.decodeInt32ForKey("s.i", orElse: 0))
case PeerMessageSoundValue.default.rawValue:
return .default
case PeerMessageSoundValue.cloud.rawValue:
return .cloud(fileId: container.decodeInt64ForKey("s.cloud.fileId", orElse: 0))
default:
assertionFailure()
return .bundledModern(id: 0)
}
}
func encodeInline(_ container: inout KeyedEncodingContainer<StringCodingKey>) throws {
switch self {
case .none:
try container.encode(PeerMessageSoundValue.none.rawValue, forKey: "s.v")
case let .bundledModern(id):
try container.encode(PeerMessageSoundValue.bundledModern.rawValue, forKey: "s.v")
try container.encode(id, forKey: "s.i")
case let .bundledClassic(id):
try container.encode(PeerMessageSoundValue.bundledClassic.rawValue, forKey: "s.v")
try container.encode(id, forKey: "s.i")
case .default:
try container.encode(PeerMessageSoundValue.default.rawValue, forKey: "s.v")
case .none:
try container.encode(PeerMessageSoundValue.none.rawValue, forKey: "s.v")
case let .bundledModern(id):
try container.encode(PeerMessageSoundValue.bundledModern.rawValue, forKey: "s.v")
try container.encode(id, forKey: "s.i")
case let .bundledClassic(id):
try container.encode(PeerMessageSoundValue.bundledClassic.rawValue, forKey: "s.v")
try container.encode(id, forKey: "s.i")
case let .cloud(fileId):
try container.encode(PeerMessageSoundValue.cloud.rawValue, forKey: "s.v")
try container.encode(fileId, forKey: "s.cloud.fileId")
case .default:
try container.encode(PeerMessageSoundValue.default.rawValue, forKey: "s.v")
}
}
func encodeInline(_ encoder: PostboxEncoder) {
switch self {
case .none:
encoder.encodeInt32(PeerMessageSoundValue.none.rawValue, forKey: "s.v")
case let .bundledModern(id):
encoder.encodeInt32(PeerMessageSoundValue.bundledModern.rawValue, forKey: "s.v")
encoder.encodeInt32(id, forKey: "s.i")
case let .bundledClassic(id):
encoder.encodeInt32(PeerMessageSoundValue.bundledClassic.rawValue, forKey: "s.v")
encoder.encodeInt32(id, forKey: "s.i")
case .default:
encoder.encodeInt32(PeerMessageSoundValue.default.rawValue, forKey: "s.v")
case .none:
encoder.encodeInt32(PeerMessageSoundValue.none.rawValue, forKey: "s.v")
case let .bundledModern(id):
encoder.encodeInt32(PeerMessageSoundValue.bundledModern.rawValue, forKey: "s.v")
encoder.encodeInt32(id, forKey: "s.i")
case let .bundledClassic(id):
encoder.encodeInt32(PeerMessageSoundValue.bundledClassic.rawValue, forKey: "s.v")
encoder.encodeInt32(id, forKey: "s.i")
case let .cloud(fileId):
encoder.encodeInt32(PeerMessageSoundValue.cloud.rawValue, forKey: "s.v")
encoder.encodeInt64(fileId, forKey: "s.cloud.fileId")
case .default:
encoder.encodeInt32(PeerMessageSoundValue.default.rawValue, forKey: "s.v")
}
}
public static func ==(lhs: PeerMessageSound, rhs: PeerMessageSound) -> Bool {
switch lhs {
case .none:
if case .none = rhs {
return true
} else {
return false
}
case let .bundledModern(id):
if case .bundledModern(id) = rhs {
return true
} else {
return false
}
case let .bundledClassic(id):
if case .bundledClassic(id) = rhs {
return true
} else {
return false
}
case .default:
if case .default = rhs {
return true
} else {
return false
}
case .none:
if case .none = rhs {
return true
} else {
return false
}
case let .bundledModern(id):
if case .bundledModern(id) = rhs {
return true
} else {
return false
}
case let .bundledClassic(id):
if case .bundledClassic(id) = rhs {
return true
} else {
return false
}
case .default:
if case .default = rhs {
return true
} else {
return false
}
case let .cloud(fileId):
if case .cloud(fileId) = rhs {
return true
} else {
return false
}
}
}
}

View file

@ -0,0 +1,241 @@
import Foundation
import SwiftSignalKit
import Postbox
import TelegramApi
public final class NotificationSoundList: Equatable, Codable {
public final class NotificationSound: Equatable, Codable {
private enum CodingKeys: String, CodingKey {
case file
}
public let file: TelegramMediaFile
public init(
file: TelegramMediaFile
) {
self.file = file
}
public static func ==(lhs: NotificationSound, rhs: NotificationSound) -> Bool {
if lhs.file != rhs.file {
return false
}
return true
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let fileData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .file)
self.file = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: fileData.data)))
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(PostboxEncoder().encodeObjectToRawData(self.file), forKey: .file)
}
}
private enum CodingKeys: String, CodingKey {
case hash
case sounds
}
public let hash: Int64
public let sounds: [NotificationSound]
public init(
hash: Int64,
sounds: [NotificationSound]
) {
self.hash = hash
self.sounds = sounds
}
public static func ==(lhs: NotificationSoundList, rhs: NotificationSoundList) -> Bool {
if lhs.hash != rhs.hash {
return false
}
if lhs.sounds != rhs.sounds {
return false
}
return true
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.hash = try container.decode(Int64.self, forKey: .hash)
self.sounds = try container.decode([NotificationSound].self, forKey: .sounds)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.hash, forKey: .hash)
try container.encode(self.sounds, forKey: .sounds)
}
}
private extension NotificationSoundList.NotificationSound {
convenience init?(apiDocument: Api.Document) {
guard let file = telegramMediaFileFromApiDocument(apiDocument) else {
return nil
}
self.init(file: file)
}
}
func _internal_cachedNotificationSoundList(postbox: Postbox) -> Signal<NotificationSoundList?, NoError> {
return postbox.transaction { transaction -> NotificationSoundList? in
return _internal_cachedNotificationSoundList(transaction: transaction)
}
}
func _internal_cachedNotificationSoundListCacheKey() -> ItemCacheEntryId {
let key = ValueBoxKey(length: 8)
key.setInt64(0, value: 0)
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.notificationSoundList, key: key)
}
func _internal_cachedNotificationSoundList(transaction: Transaction) -> NotificationSoundList? {
let cached = transaction.retrieveItemCacheEntry(id: _internal_cachedNotificationSoundListCacheKey())?.get(NotificationSoundList.self)
if let cached = cached {
return cached
} else {
return nil
}
}
func _internal_setCachedNotificationSoundList(transaction: Transaction, notificationSoundList: NotificationSoundList) {
if let entry = CodableEntry(notificationSoundList) {
transaction.putItemCacheEntry(id: _internal_cachedNotificationSoundListCacheKey(), entry: entry, collectionSpec: ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 10))
}
}
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)
|> mapToSignal { current in
return (network.request(Api.functions.account.getSavedRingtones(hash: current?.hash ?? 0))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.account.SavedRingtones?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<Never, NoError> in
return postbox.transaction { transaction -> Signal<Never, NoError> in
guard let result = result else {
return .complete()
}
switch result {
case let .savedRingtones(hash, ringtones):
let notificationSoundList = NotificationSoundList(
hash: hash,
sounds: ringtones.compactMap(NotificationSoundList.NotificationSound.init(apiDocument:))
)
_internal_setCachedNotificationSoundList(transaction: transaction, notificationSoundList: notificationSoundList)
case .savedRingtonesNotModified:
break
}
var signals: [Signal<Never, NoError>] = []
if let notificationSoundList = _internal_cachedNotificationSoundList(transaction: transaction) {
var resources: [MediaResource] = []
for sound in notificationSoundList.sounds {
resources.append(sound.file.resource)
}
for resource in resources {
signals.append(
fetchedMediaResource(mediaBox: postbox.mediaBox, reference: .standalone(resource: resource))
|> ignoreValues
|> `catch` { _ -> Signal<Never, NoError> in
return .complete()
}
)
}
}
return combineLatest(signals)
|> ignoreValues
}
|> switchToLatest
})
}
return signal.start(completed: {
subscriber.putCompletion()
})
}
}
func managedSynchronizeNotificationSoundList(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
let poll = pollNotificationSoundList(postbox: postbox, network: network)
return (
poll
|> then(
.complete()
|> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue())
)
)
|> restart
}
func _internal_saveNotificationSound(account: Account, file: TelegramMediaFile) -> Signal<Never, UploadNotificationSoundError> {
guard let resource = file.resource as? CloudDocumentMediaResource else {
return .fail(.generic)
}
return account.network.request(Api.functions.account.saveRingtone(id: .inputDocument(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference)), unsave: .boolFalse))
|> mapError { _ -> UploadNotificationSoundError in
return .generic
}
|> mapToSignal { _ -> Signal<Never, UploadNotificationSoundError> in
return pollNotificationSoundList(postbox: account.postbox, network: account.network)
|> castError(UploadNotificationSoundError.self)
}
}
public enum UploadNotificationSoundError {
case generic
}
func _internal_uploadNotificationSound(account: Account, title: String, data: Data) -> Signal<NotificationSoundList.NotificationSound, UploadNotificationSoundError> {
return multipartUpload(network: account.network, postbox: account.postbox, source: .data(data), encrypt: false, tag: nil, hintFileSize: data.count, hintFileIsLarge: false, forceNoBigParts: true, useLargerParts: false, increaseParallelParts: false, useMultiplexedRequests: false, useCompression: false)
|> mapError { _ -> UploadNotificationSoundError in
return .generic
}
|> mapToSignal { value -> Signal<NotificationSoundList.NotificationSound, UploadNotificationSoundError> in
switch value {
case let .inputFile(file):
return account.network.request(Api.functions.account.uploadRingtone(file: file, fileName: title, mimeType: "audio/mpeg"))
|> mapError { _ -> UploadNotificationSoundError in
return .generic
}
|> mapToSignal { result -> Signal<NotificationSoundList.NotificationSound, UploadNotificationSoundError> in
guard let file = telegramMediaFileFromApiDocument(result) else {
return .fail(.generic)
}
return account.postbox.transaction { transaction -> NotificationSoundList.NotificationSound in
let item = NotificationSoundList.NotificationSound(file: file)
account.postbox.mediaBox.storeResourceData(file.resource.id, data: data, synchronous: true)
let notificationSoundList = _internal_cachedNotificationSoundList(transaction: transaction) ?? NotificationSoundList(hash: 0, sounds: [])
let updatedNotificationSoundList = NotificationSoundList(hash: notificationSoundList.hash, sounds: [item] + notificationSoundList.sounds)
_internal_setCachedNotificationSoundList(transaction: transaction, notificationSoundList: updatedNotificationSoundList)
return item
}
|> castError(UploadNotificationSoundError.self)
}
default:
return .never()
}
}
}

View file

@ -1,3 +1,4 @@
import Foundation
import Postbox
public enum EnginePeer: Equatable {
@ -75,6 +76,7 @@ public enum EnginePeer: Equatable {
case `default`
case bundledModern(id: Int32)
case bundledClassic(id: Int32)
case cloud(fileId: Int64)
}
public enum DisplayPreviews {
@ -200,6 +202,8 @@ public extension EnginePeer.NotificationSettings.MessageSound {
self = .bundledClassic(id: id)
case let .bundledModern(id):
self = .bundledModern(id: id)
case let .cloud(fileId):
self = .cloud(fileId: fileId)
}
}
@ -213,6 +217,8 @@ public extension EnginePeer.NotificationSettings.MessageSound {
return .bundledClassic(id: id)
case let .bundledModern(id):
return .bundledModern(id: id)
case let .cloud(fileId):
return .cloud(fileId: fileId)
}
}
}

View file

@ -684,6 +684,25 @@ public extension TelegramEngine {
public func updatePeerAllowedReactions(peerId: PeerId, allowedReactions: [String]) -> Signal<Never, UpdatePeerAllowedReactionsError> {
return _internal_updatePeerAllowedReactions(account: account, peerId: peerId, allowedReactions: allowedReactions)
}
public func notificationSoundList() -> Signal<NotificationSoundList?, NoError> {
let key = PostboxViewKey.cachedItem(_internal_cachedNotificationSoundListCacheKey())
return self.account.postbox.combinedView(keys: [key])
|> map { views -> NotificationSoundList? in
guard let view = views.views[key] as? CachedItemView else {
return nil
}
return view.value?.get(NotificationSoundList.self)
}
}
public func saveNotificationSound(file: TelegramMediaFile) -> Signal<Never, UploadNotificationSoundError> {
return _internal_saveNotificationSound(account: self.account, file: file)
}
public func uploadNotificationSound(title: String, data: Data) -> Signal<NotificationSoundList.NotificationSound, UploadNotificationSoundError> {
return _internal_uploadNotificationSound(account: self.account, title: title, data: data)
}
}
}

View file

@ -38,6 +38,18 @@ public func presentationStringsFormattedNumber(_ count: Int32, _ groupingSeparat
}
}
public func dayIntervalString(strings: PresentationStrings, days: Int32) -> String {
return strings.MessageTimer_Days(max(0, days))
}
public func hoursIntervalString(strings: PresentationStrings, hours: Int32) -> String {
return strings.MessageTimer_Hours(max(0, hours))
}
public func minutesIntervalString(strings: PresentationStrings, minutes: Int32) -> String {
return strings.MessageTimer_Minutes(max(0, minutes))
}
public func timeIntervalString(strings: PresentationStrings, value: Int32, preferLowerValue: Bool = false) -> String {
if preferLowerValue {
if value <= 60 {

View file

@ -273,6 +273,8 @@ public enum PresentationResourceKey: Int32 {
case chatKeyboardActionButtonProfileIcon
case chatKeyboardActionButtonAddToChatIcon
case chatKeyboardActionButtonWebAppIcon
case uploadToneIcon
}
public enum PresentationResourceParameterKey: Hashable {

View file

@ -269,4 +269,10 @@ public struct PresentationResourcesItemList {
})?.stretchableImage(withLeftCapWidth: 25, topCapHeight: 25)
})
}
public static func uploadToneIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.uploadToneIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Settings/UploadTone"), color: theme.list.itemAccentColor)
})
}
}

View file

@ -28,41 +28,52 @@ private let classicSoundNamePaths: [KeyPath<PresentationStrings, String>] = [
\.NotificationsSound_Telegraph
]
private func soundName(strings: PresentationStrings, sound: PeerMessageSound) -> String {
private func soundName(strings: PresentationStrings, sound: PeerMessageSound, notificationSoundList: NotificationSoundList?) -> String {
switch sound {
case .none:
return strings.NotificationsSound_None
case .default:
return ""
case let .bundledModern(id):
if id >= 0 && Int(id) < modernSoundsNamePaths.count {
return strings[keyPath: modernSoundsNamePaths[Int(id)]]
case .none:
return strings.NotificationsSound_None
case .default:
return ""
case let .bundledModern(id):
if id >= 0 && Int(id) < modernSoundsNamePaths.count {
return strings[keyPath: modernSoundsNamePaths[Int(id)]]
}
return "Sound \(id)"
case let .bundledClassic(id):
if id >= 0 && Int(id) < classicSoundNamePaths.count {
return strings[keyPath: classicSoundNamePaths[Int(id)]]
}
return "Sound \(id)"
case let .cloud(fileId):
guard let notificationSoundList = notificationSoundList else {
//TODO:localize
return "Loading..."
}
for sound in notificationSoundList.sounds {
if sound.file.fileId.id == fileId {
return sound.file.fileName ?? "Cloud Tone"
}
return "Sound \(id)"
case let .bundledClassic(id):
if id >= 0 && Int(id) < classicSoundNamePaths.count {
return strings[keyPath: classicSoundNamePaths[Int(id)]]
}
return "Sound \(id)"
}
return ""
}
}
public func localizedPeerNotificationSoundString(strings: PresentationStrings, sound: PeerMessageSound, default: PeerMessageSound? = nil) -> String {
public func localizedPeerNotificationSoundString(strings: PresentationStrings, notificationSoundList: NotificationSoundList?, sound: PeerMessageSound, default: PeerMessageSound? = nil) -> String {
switch sound {
case .default:
if let defaultSound = `default` {
let name = soundName(strings: strings, sound: defaultSound)
let actualName: String
if name.isEmpty {
actualName = soundName(strings: strings, sound: .bundledModern(id: 0))
} else {
actualName = name
}
return strings.UserInfo_NotificationsDefaultSound(actualName).string
case .default:
if let defaultSound = `default` {
let name = soundName(strings: strings, sound: defaultSound, notificationSoundList: notificationSoundList)
let actualName: String
if name.isEmpty {
actualName = soundName(strings: strings, sound: .bundledModern(id: 0), notificationSoundList: notificationSoundList)
} else {
return strings.UserInfo_NotificationsDefault
actualName = name
}
default:
return soundName(strings: strings, sound: sound)
return strings.UserInfo_NotificationsDefaultSound(actualName).string
} else {
return strings.UserInfo_NotificationsDefault
}
default:
return soundName(strings: strings, sound: sound, notificationSoundList: notificationSoundList)
}
}

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "clearmessages_24.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,285 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 3.000000 3.630371 cm
0.000000 0.000000 0.000000 scn
6.036711 3.044792 m
5.888044 2.396624 l
6.036711 3.044792 l
h
4.213051 1.739638 m
3.887771 2.319654 l
3.887771 2.319654 l
4.213051 1.739638 l
h
1.977577 1.386564 m
1.720352 0.773327 l
1.977577 1.386564 l
h
2.890895 4.595274 m
2.498061 4.058705 l
2.890895 4.595274 l
h
8.000000 16.704628 m
12.112072 16.704628 15.335000 13.688025 15.335000 10.096902 c
16.665001 10.096902 l
16.665001 14.539012 12.724484 18.034630 8.000000 18.034630 c
8.000000 16.704628 l
h
15.335000 10.096902 m
15.335000 6.505779 12.112072 3.489175 8.000000 3.489175 c
8.000000 2.159175 l
12.724484 2.159175 16.665001 5.654792 16.665001 10.096902 c
15.335000 10.096902 l
h
8.000000 3.489175 m
7.372782 3.489175 6.764923 3.560034 6.185379 3.692961 c
5.888044 2.396624 l
6.564841 2.241389 7.272436 2.159175 8.000000 2.159175 c
8.000000 3.489175 l
h
6.185379 3.692961 m
5.804111 3.780411 5.513260 3.569372 5.413143 3.494156 c
5.290826 3.402263 5.147437 3.265127 5.034352 3.161364 c
4.781663 2.929504 4.434368 2.626192 3.887771 2.319654 c
4.538331 1.159622 l
5.211778 1.537300 5.645048 1.916672 5.933547 2.181390 c
6.091055 2.325915 6.158414 2.390541 6.212014 2.430810 c
6.287813 2.487756 6.138047 2.339281 5.888044 2.396624 c
6.185379 3.692961 l
h
3.887771 2.319654 m
3.572365 2.142771 3.165311 2.048659 2.790003 2.014445 c
2.607043 1.997766 2.446026 1.996657 2.327112 2.003073 c
2.267397 2.006294 2.224190 2.011101 2.197881 2.015177 c
2.158949 2.021208 2.183327 2.021393 2.234801 1.999803 c
1.720352 0.773327 l
1.821844 0.730755 1.926930 0.711287 1.994275 0.700853 c
2.074244 0.688465 2.162884 0.679998 2.255463 0.675005 c
2.441139 0.664988 2.666504 0.667671 2.910749 0.689938 c
3.389851 0.733614 4.000499 0.858000 4.538331 1.159622 c
3.887771 2.319654 l
h
2.234801 1.999803 m
2.265677 1.986851 2.404851 1.923249 2.493219 1.747771 c
2.589725 1.556132 2.551083 1.383581 2.526376 1.313473 c
2.504906 1.252550 2.480861 1.226551 2.497980 1.249567 c
2.510608 1.266544 2.534224 1.295128 2.576988 1.342783 c
2.735965 1.519941 3.080277 1.865030 3.376156 2.318596 c
2.262219 3.045261 l
2.039068 2.703184 1.800315 2.468651 1.587115 2.231068 c
1.536834 2.175037 1.480586 2.110241 1.430826 2.043344 c
1.385558 1.982486 1.316601 1.882117 1.271991 1.755535 c
1.224144 1.619764 1.184133 1.390259 1.305339 1.149572 c
1.418406 0.925049 1.608346 0.820307 1.720352 0.773327 c
2.234801 1.999803 l
h
3.376156 2.318596 m
3.725287 2.853793 3.824730 3.434122 3.801171 3.906185 c
3.789388 4.142282 3.746260 4.366606 3.677134 4.560054 c
3.618218 4.724927 3.504569 4.970161 3.283730 5.131843 c
2.498061 4.058705 l
2.393648 4.135148 2.394127 4.198050 2.424695 4.112509 c
2.445051 4.055541 2.466761 3.961368 2.472824 3.839892 c
2.484955 3.596812 2.432118 3.305708 2.262219 3.045261 c
3.376156 2.318596 l
h
3.283730 5.131843 m
1.614924 6.353613 0.665000 8.040656 0.665000 10.096902 c
-0.665000 10.096902 l
-0.665000 7.571545 0.525193 5.503087 2.498061 4.058705 c
3.283730 5.131843 l
h
0.665000 10.096902 m
0.665000 13.688025 3.887928 16.704628 8.000000 16.704628 c
8.000000 18.034630 l
3.275515 18.034630 -0.665000 14.539012 -0.665000 10.096902 c
0.665000 10.096902 l
h
f
n
Q
q
-1.000000 -0.000000 -0.000000 1.000000 21.700012 1.535767 cm
0.000000 0.000000 0.000000 scn
6.036711 3.139397 m
5.888044 2.491228 l
6.036711 3.139397 l
h
4.213051 1.834243 m
3.887771 2.414258 l
3.887771 2.414258 l
4.213051 1.834243 l
h
1.977577 1.481169 m
1.720352 0.867930 l
1.977577 1.481169 l
h
2.890895 4.689878 m
2.498061 4.153310 l
2.890895 4.689878 l
h
1.435227 13.141423 m
1.613510 13.462519 1.497738 13.867344 1.176643 14.045628 c
0.855548 14.223910 0.450722 14.108138 0.272439 13.787044 c
1.435227 13.141423 l
h
9.828376 2.430831 m
10.188738 2.501724 10.423399 2.851326 10.352506 3.211688 c
10.281612 3.572050 9.932011 3.806711 9.571649 3.735818 c
9.828376 2.430831 l
h
8.000000 3.583779 m
7.372782 3.583779 6.764923 3.654638 6.185379 3.787565 c
5.888044 2.491228 l
6.564841 2.335994 7.272436 2.253779 8.000000 2.253779 c
8.000000 3.583779 l
h
6.185379 3.787565 m
5.804111 3.875015 5.513260 3.663977 5.413143 3.588760 c
5.290826 3.496867 5.147437 3.359732 5.034352 3.255968 c
4.781663 3.024109 4.434368 2.720797 3.887771 2.414258 c
4.538331 1.254228 l
5.211778 1.631905 5.645048 2.011276 5.933547 2.275994 c
6.091055 2.420520 6.158414 2.485146 6.212014 2.525414 c
6.287813 2.582360 6.138047 2.433886 5.888044 2.491228 c
6.185379 3.787565 l
h
3.887771 2.414258 m
3.572365 2.237375 3.165311 2.143264 2.790003 2.109050 c
2.607043 2.092371 2.446026 2.091262 2.327112 2.097677 c
2.267397 2.100899 2.224190 2.105705 2.197881 2.109781 c
2.158949 2.115812 2.183327 2.115997 2.234801 2.094407 c
1.720352 0.867930 l
1.821844 0.825360 1.926930 0.805891 1.994275 0.795458 c
2.074244 0.783070 2.162884 0.774603 2.255463 0.769608 c
2.441139 0.759591 2.666504 0.762276 2.910749 0.784542 c
3.389851 0.828218 4.000499 0.952604 4.538331 1.254228 c
3.887771 2.414258 l
h
2.234801 2.094407 m
2.265677 2.081455 2.404851 2.017854 2.493219 1.842376 c
2.589725 1.650737 2.551083 1.478186 2.526376 1.408076 c
2.504906 1.347156 2.480861 1.321156 2.497980 1.344172 c
2.510608 1.361148 2.534224 1.389732 2.576988 1.437387 c
2.735965 1.614546 3.080277 1.959635 3.376156 2.413200 c
2.262219 3.139866 l
2.039068 2.797789 1.800315 2.563255 1.587115 2.325672 c
1.536834 2.269642 1.480586 2.204845 1.430826 2.137948 c
1.385558 2.077090 1.316601 1.976722 1.271991 1.850140 c
1.224144 1.714369 1.184133 1.484863 1.305339 1.244177 c
1.418406 1.019652 1.608346 0.914912 1.720352 0.867930 c
2.234801 2.094407 l
h
3.376156 2.413200 m
3.725287 2.948398 3.824730 3.528727 3.801171 4.000790 c
3.789388 4.236886 3.746260 4.461210 3.677134 4.654658 c
3.618218 4.819531 3.504569 5.064766 3.283730 5.226447 c
2.498061 4.153310 l
2.393648 4.229753 2.394127 4.292655 2.424695 4.207113 c
2.445051 4.150146 2.466761 4.055972 2.472824 3.934497 c
2.484955 3.691417 2.432118 3.400312 2.262219 3.139866 c
3.376156 2.413200 l
h
3.283730 5.226447 m
1.614924 6.448217 0.665000 8.135260 0.665000 10.191506 c
-0.665000 10.191506 l
-0.665000 7.666149 0.525193 5.597691 2.498061 4.153310 c
3.283730 5.226447 l
h
0.665000 10.191506 m
0.665000 11.250713 0.941389 12.252002 1.435227 13.141423 c
0.272439 13.787044 l
-0.326097 12.709055 -0.665000 11.486644 -0.665000 10.191506 c
0.665000 10.191506 l
h
9.571649 3.735818 m
9.065956 3.636334 8.540168 3.583779 8.000000 3.583779 c
8.000000 2.253779 l
8.626554 2.253779 9.238318 2.314750 9.828376 2.430831 c
9.571649 3.735818 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 7.335022 9.700195 cm
0.000000 0.000000 0.000000 scn
1.135226 7.265065 m
0.875527 7.524764 0.454473 7.524764 0.194774 7.265065 c
-0.064925 7.005366 -0.064925 6.584311 0.194774 6.324613 c
2.724548 3.794839 l
0.194774 1.265065 l
-0.064925 1.005366 -0.064925 0.584311 0.194774 0.324613 c
0.454473 0.064914 0.875527 0.064914 1.135226 0.324613 c
3.665000 2.854387 l
6.194774 0.324613 l
6.454473 0.064914 6.875527 0.064914 7.135226 0.324613 c
7.394925 0.584311 7.394925 1.005366 7.135226 1.265065 c
4.605452 3.794839 l
7.135226 6.324613 l
7.394925 6.584311 7.394925 7.005366 7.135226 7.265065 c
6.875527 7.524764 6.454473 7.524764 6.194774 7.265065 c
3.665000 4.735291 l
1.135226 7.265065 l
h
f*
n
Q
endstream
endobj
3 0 obj
7291
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000007381 00000 n
0000007404 00000 n
0000007577 00000 n
0000007651 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
7710
%%EOF

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "custom_24.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,163 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 10.500000 15.669922 cm
0.000000 0.000000 0.000000 scn
0.000000 1.995078 m
-0.367269 1.995078 -0.665000 1.697348 -0.665000 1.330078 c
-0.665000 0.962809 -0.367269 0.665078 0.000000 0.665078 c
0.000000 1.995078 l
h
9.000000 0.665078 m
9.367270 0.665078 9.665000 0.962809 9.665000 1.330078 c
9.665000 1.697348 9.367270 1.995078 9.000000 1.995078 c
9.000000 0.665078 l
h
0.000000 0.665078 m
9.000000 0.665078 l
9.000000 1.995078 l
0.000000 1.995078 l
0.000000 0.665078 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 4.500000 5.669922 cm
0.000000 0.000000 0.000000 scn
0.000000 1.995078 m
-0.367269 1.995078 -0.665000 1.697348 -0.665000 1.330078 c
-0.665000 0.962809 -0.367269 0.665078 0.000000 0.665078 c
0.000000 1.995078 l
h
9.000000 0.665078 m
9.367270 0.665078 9.665000 0.962809 9.665000 1.330078 c
9.665000 1.697348 9.367270 1.995078 9.000000 1.995078 c
9.000000 0.665078 l
h
0.000000 0.665078 m
9.000000 0.665078 l
9.000000 1.995078 l
0.000000 1.995078 l
0.000000 0.665078 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 4.000000 12.669922 cm
0.000000 0.000000 0.000000 scn
5.335000 4.330078 m
5.335000 3.040493 4.289585 1.995078 3.000000 1.995078 c
3.000000 0.665078 l
5.024124 0.665078 6.665000 2.305954 6.665000 4.330078 c
5.335000 4.330078 l
h
3.000000 1.995078 m
1.710415 1.995078 0.665000 3.040493 0.665000 4.330078 c
-0.665000 4.330078 l
-0.665000 2.305954 0.975876 0.665078 3.000000 0.665078 c
3.000000 1.995078 l
h
0.665000 4.330078 m
0.665000 5.619663 1.710415 6.665078 3.000000 6.665078 c
3.000000 7.995078 l
0.975876 7.995078 -0.665000 6.354202 -0.665000 4.330078 c
0.665000 4.330078 l
h
3.000000 6.665078 m
4.289585 6.665078 5.335000 5.619663 5.335000 4.330078 c
6.665000 4.330078 l
6.665000 6.354202 5.024124 7.995078 3.000000 7.995078 c
3.000000 6.665078 l
h
f
n
Q
q
1.000000 0.000000 -0.000000 1.000000 14.000000 2.669922 cm
0.000000 0.000000 0.000000 scn
5.335000 4.330078 m
5.335000 3.040493 4.289585 1.995078 3.000000 1.995078 c
3.000000 0.665078 l
5.024124 0.665078 6.665000 2.305954 6.665000 4.330078 c
5.335000 4.330078 l
h
3.000000 1.995078 m
1.710415 1.995078 0.665000 3.040493 0.665000 4.330078 c
-0.665000 4.330078 l
-0.665000 2.305954 0.975876 0.665078 3.000000 0.665078 c
3.000000 1.995078 l
h
0.665000 4.330078 m
0.665000 5.619663 1.710415 6.665078 3.000000 6.665078 c
3.000000 7.995078 l
0.975876 7.995078 -0.665000 6.354202 -0.665000 4.330078 c
0.665000 4.330078 l
h
3.000000 6.665078 m
4.289585 6.665078 5.335000 5.619663 5.335000 4.330078 c
6.665000 4.330078 l
6.665000 6.354202 5.024124 7.995078 3.000000 7.995078 c
3.000000 6.665078 l
h
f
n
Q
endstream
endobj
3 0 obj
2650
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000002740 00000 n
0000002763 00000 n
0000002936 00000 n
0000003010 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
3069
%%EOF

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "downloadtone_24.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,116 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 2.334961 1.926270 cm
0.000000 0.000000 0.000000 scn
18.499836 17.264488 m
18.499828 17.485374 18.289789 17.645796 18.076683 17.587671 c
14.576791 16.633081 l
14.431045 16.593330 14.329936 16.460947 14.329941 16.309877 c
14.330013 13.944344 l
18.253044 15.014344 l
18.398790 15.054096 18.499899 15.186479 18.499895 15.337549 c
18.499836 17.264488 l
h
13.000040 13.073683 m
12.999941 16.309837 l
12.999918 17.060677 13.502439 17.718637 14.226819 17.916210 c
17.726713 18.870800 l
18.785870 19.159685 19.829802 18.362379 19.829836 17.264528 c
19.829895 15.337589 l
19.829918 14.586750 19.327396 13.928788 18.603016 13.731215 c
14.330040 12.565768 l
14.330040 5.073744 l
14.330001 5.073744 l
14.330006 4.174320 l
14.330013 2.634279 13.299263 1.284771 11.813485 0.879566 c
11.386369 0.763084 l
9.429031 0.229277 7.499888 1.702747 7.499878 3.731570 c
7.499871 5.119122 8.428559 6.335007 9.767220 6.700088 c
13.000040 7.581746 l
13.000040 13.073662 l
13.000040 13.073683 l
h
12.999995 6.203160 m
10.117160 5.416950 l
9.357137 5.209676 8.829874 4.519358 8.829878 3.731577 c
8.829884 2.579716 9.925153 1.743153 11.036430 2.046223 c
11.463547 2.162704 l
12.370687 2.410101 13.000010 3.234043 13.000006 4.174314 c
12.999995 6.203160 l
h
3.665000 17.738770 m
4.032269 17.738770 4.330000 17.441038 4.330000 17.073769 c
4.330000 10.679222 l
6.194774 12.543995 l
6.454473 12.803694 6.875527 12.803694 7.135226 12.543995 c
7.394925 12.284297 7.394925 11.863242 7.135226 11.603544 c
4.135226 8.603543 l
3.875527 8.343845 3.454473 8.343845 3.194774 8.603543 c
0.194774 11.603544 l
-0.064925 11.863242 -0.064925 12.284297 0.194774 12.543995 c
0.454473 12.803694 0.875527 12.803694 1.135226 12.543995 c
3.000000 10.679222 l
3.000000 17.073769 l
3.000000 17.441038 3.297731 17.738770 3.665000 17.738770 c
h
f*
n
Q
endstream
endobj
3 0 obj
1860
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000001950 00000 n
0000001973 00000 n
0000002146 00000 n
0000002220 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2279
%%EOF

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "addtone_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,118 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 2.335022 2.524536 cm
0.000000 0.000000 0.000000 scn
24.000023 22.149782 m
24.000023 22.372349 23.786995 22.533037 23.572990 22.471893 c
18.572990 21.043322 l
18.429174 21.002232 18.330023 20.870783 18.330023 20.721212 c
18.330023 17.357124 l
23.757053 18.907703 l
23.900869 18.948795 24.000023 19.080244 24.000023 19.229815 c
24.000023 22.149782 l
h
18.330023 15.973903 m
24.122433 17.628878 l
24.837221 17.833101 25.330023 18.486425 25.330023 19.229815 c
25.330023 22.149782 l
25.330023 23.255974 24.271240 24.054613 23.207611 23.750721 c
18.207611 22.322149 l
17.492825 22.117924 17.000023 21.464602 17.000023 20.721212 c
17.000023 16.475513 l
17.000023 8.977081 l
12.574430 7.712626 l
11.050592 7.277245 10.000000 5.884441 10.000000 4.299627 c
10.000000 1.941366 12.257193 0.238766 14.524715 0.886629 c
15.671853 1.214382 l
17.245243 1.663923 18.330000 3.102016 18.330000 4.738369 c
18.330000 5.475513 l
18.330023 5.475513 l
18.330023 15.973903 l
h
17.000000 7.593853 m
12.939809 6.433800 l
11.986943 6.161552 11.330000 5.290623 11.330000 4.299627 c
11.330000 2.824991 12.741438 1.760342 14.159337 2.165457 c
15.306474 2.493210 l
16.308893 2.779615 17.000000 3.695837 17.000000 4.738369 c
17.000000 7.593853 l
h
5.665000 21.140503 m
6.032269 21.140503 6.330000 20.842772 6.330000 20.475502 c
6.330000 16.140503 l
10.665000 16.140503 l
11.032269 16.140503 11.330000 15.842772 11.330000 15.475503 c
11.330000 15.108233 11.032269 14.810503 10.665000 14.810503 c
6.330000 14.810503 l
6.330000 10.475503 l
6.330000 10.108233 6.032269 9.810503 5.665000 9.810503 c
5.297730 9.810503 5.000000 10.108233 5.000000 10.475503 c
5.000000 14.810503 l
0.665000 14.810503 l
0.297731 14.810503 0.000000 15.108233 0.000000 15.475503 c
0.000000 15.842772 0.297731 16.140503 0.665000 16.140503 c
5.000000 16.140503 l
5.000000 20.475502 l
5.000000 20.842772 5.297730 21.140503 5.665000 21.140503 c
h
f*
n
Q
endstream
endobj
3 0 obj
1956
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 30.000000 30.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000002046 00000 n
0000002069 00000 n
0000002242 00000 n
0000002316 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
2375
%%EOF

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -260,7 +260,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private let temporaryHiddenGalleryMediaDisposable = MetaDisposable()
private let chatBackgroundNode: WallpaperBackgroundNode
private var controllerInteraction: ChatControllerInteraction?
private(set) var controllerInteraction: ChatControllerInteraction?
private var interfaceInteraction: ChatPanelInterfaceInteraction?
private let messageContextDisposable = MetaDisposable()
@ -5679,7 +5679,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self, case let .message(index) = toIndex {
if case let .message(messageSubject, _, _) = strongSelf.subject, initial, case let .id(messageId) = messageSubject, messageId != index.id {
if messageId.peerId == index.id.peerId {
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(text: strongSelf.presentationData.strings.Conversation_MessageDoesntExist), elevatedLayout: false, action: { _ in return true }), in: .current)
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.Conversation_MessageDoesntExist), elevatedLayout: false, action: { _ in return true }), in: .current)
}
} else if let controllerInteraction = strongSelf.controllerInteraction {
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) {
@ -8168,7 +8168,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
presentAddMembers(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, parentController: strongSelf, groupPeer: peer, selectAddMemberDisposable: strongSelf.selectAddMemberDisposable, addMemberDisposable: strongSelf.addMemberDisposable)
}, presentGigagroupHelp: { [weak self] in
if let strongSelf = self {
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(text: strongSelf.presentationData.strings.Conversation_GigagroupDescription), elevatedLayout: false, action: { _ in return true }), in: .current)
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.Conversation_GigagroupDescription), elevatedLayout: false, action: { _ in return true }), in: .current)
}
}, editMessageMedia: { [weak self] messageId, draw in
if let strongSelf = self {
@ -8295,6 +8295,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}))
})
}
}, chatController: { [weak self] in
return self
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get(), inlineSearch: self.performingInlineSearch.get()))
do {
@ -9074,7 +9076,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in return nil }), textAlignment: .center)
let controller = richTextAlertController(context: strongSelf.context, title: attributedTitle, text: attributedText, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(text: strongSelf.presentationData.strings.BroadcastGroups_LimitAlert_SettingsTip), elevatedLayout: false, action: { _ in return false }), in: .current)
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(title: nil, text: strongSelf.presentationData.strings.BroadcastGroups_LimitAlert_SettingsTip), elevatedLayout: false, action: { _ in return false }), in: .current)
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.BroadcastGroups_LimitAlert_LearnMore, action: {
let context = strongSelf.context
@ -15387,18 +15389,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let controller = peerAutoremoveSetupScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, peerId: peer.id, completion: { [weak self] updatedValue in
if case let .updated(value) = updatedValue {
let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, peerId: peer.id, style: .default, mode: .autoremove, currentTime: self.presentationInterfaceState.autoremoveTimeout, dismissByTapOutside: true, completion: { [weak self] value in
guard let strongSelf = self else {
return
}
let _ = (strongSelf.context.engine.peers.setChatMessageAutoremoveTimeoutInteractively(peerId: peer.id, timeout: value == 0 ? nil : value)
|> deliverOnMainQueue).start(completed: {
guard let strongSelf = self else {
return
}
strongSelf.updateChatPresentationInterfaceState(animated: false, interactive: false, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
var isOn: Bool = true
var text: String?
if let myValue = value.value {
text = strongSelf.presentationData.strings.Conversation_AutoremoveChanged("\(timeIntervalString(strings: strongSelf.presentationData.strings, value: myValue))").string
if value != 0 {
text = strongSelf.presentationData.strings.Conversation_AutoremoveChanged("\(timeIntervalString(strings: strongSelf.presentationData.strings, value: value))").string
} else {
isOn = false
text = strongSelf.presentationData.strings.Conversation_AutoremoveOff
@ -15406,10 +15411,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let text = text {
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, action: { _ in return false }), in: .current)
}
}
})
})
self.chatDisplayNode.dismissInput()
self.push(controller)
self.present(controller, in: .window(.root))
}
private func presentChatRequestAdminInfo() {

View file

@ -29,6 +29,7 @@ import TranslateUI
import DebugSettingsUI
import ChatPresentationInterfaceState
import Pasteboard
import SettingsUI
private struct MessageContextMenuData {
let starStatus: Bool?
@ -819,51 +820,6 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}
f(.default)
})))
if resourceAvailable {
for media in message.media {
if let file = media as? TelegramMediaFile, (["audio/mp3", "audio/mpeg3"] as [String]).contains(file.mimeType.lowercased()) {
actions.append(.action(ContextMenuActionItem(text: "Set as Message Tone", icon: { _ in
return nil
}, action: { _, f in
for media in message.media {
if let file = media as? TelegramMediaFile {
let _ = (context.account.postbox.mediaBox.resourceData(file.resource, option: .incremental(waitUntilFetchStatus: false))
|> take(1)
|> deliverOnMainQueue).start(next: { data in
if data.complete {
let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
let soundsDirectoryPath = documentsDirectoryPath + "/Sounds"
let _ = try? FileManager.default.createDirectory(atPath: soundsDirectoryPath, withIntermediateDirectories: true, attributes: nil)
let containerSoundsPath = context.sharedContext.applicationBindings.containerPath + "/Library/Sounds"
let _ = try? FileManager.default.createDirectory(atPath: containerSoundsPath, withIntermediateDirectories: true, attributes: nil)
let soundFileName = "\(UInt32.random(in: 0 ..< UInt32.max)).mp3"
let soundPath = soundsDirectoryPath + "/\(soundFileName)"
let _ = try? FileManager.default.copyItem(atPath: data.path, toPath: soundPath)
let _ = try? FileManager.default.copyItem(atPath: data.path, toPath: "\(containerSoundsPath)/\(soundFileName)")
let _ = updateInAppNotificationSettingsInteractively(accountManager: context.sharedContext.accountManager, { settings in
var settings = settings
settings.customSound = soundFileName
return settings
}).start()
}
})
}
}
f(.default)
})))
}
}
}
}
let (canTranslate, _) = canTranslateText(context: context, text: messageText, showTranslate: translationSettings.showTranslate, ignoredLanguages: translationSettings.ignoredLanguages)
@ -914,6 +870,54 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
}
}
for media in message.media {
if let file = media as? TelegramMediaFile, let size = file.size, size < 200 * 1024, (["audio/mpeg", "audio/mp3", "audio/mpeg3"] as [String]).contains(file.mimeType.lowercased()) {
actions.append(.action(ContextMenuActionItem(text: "Save for Notifications", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/DownloadTone"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
let _ = context.engine.peers.saveNotificationSound(file: file).start(completed: {
//TODO:localize
controllerInteraction.displayUndo(.notificationSoundAdded(title: "Sound added", text: "You can now use this sound as a notification tone in your [custom notification settings]().", action: {
controllerInteraction.navigationController()?.pushViewController(notificationsAndSoundsController(context: context, exceptionsList: nil))
}))
})
f(.default)
})))
/*
let _ = (context.account.postbox.mediaBox.resourceData(file.resource, option: .incremental(waitUntilFetchStatus: false))
|> take(1)
|> deliverOnMainQueue).start(next: { data in
if data.complete {
let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
let soundsDirectoryPath = documentsDirectoryPath + "/Sounds"
let _ = try? FileManager.default.createDirectory(atPath: soundsDirectoryPath, withIntermediateDirectories: true, attributes: nil)
let containerSoundsPath = context.sharedContext.applicationBindings.containerPath + "/Library/Sounds"
let _ = try? FileManager.default.createDirectory(atPath: containerSoundsPath, withIntermediateDirectories: true, attributes: nil)
let soundFileName = "\(UInt32.random(in: 0 ..< UInt32.max)).mp3"
let soundPath = soundsDirectoryPath + "/\(soundFileName)"
let _ = try? FileManager.default.copyItem(atPath: data.path, toPath: soundPath)
let _ = try? FileManager.default.copyItem(atPath: data.path, toPath: "\(containerSoundsPath)/\(soundFileName)")
let _ = updateInAppNotificationSettingsInteractively(accountManager: context.sharedContext.accountManager, { settings in
var settings = settings
settings.customSound = soundFileName
return settings
}).start()
}
})*/
}
}
var downloadableMediaResourceInfos: [String] = []
for media in message.media {
if let file = media as? TelegramMediaFile {

View file

@ -55,6 +55,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
private let textNode: TextNode
private var spoilerTextNode: TextNode?
private var dustNode: InvisibleInkDustNode?
private let actionButton: HighlightableButtonNode
private let actionButtonTitleNode: ImmediateTextNode
private let actionButtonBackgroundNode: ASImageNode
private let imageNode: TransformImageNode
private let imageNodeContainer: ASDisplayNode
@ -93,6 +96,14 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
self.closeButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -8.0, bottom: -8.0, right: -8.0)
self.closeButton.displaysAsynchronously = false
self.actionButton = HighlightableButtonNode()
self.actionButton.isHidden = true
self.actionButtonTitleNode = ImmediateTextNode()
self.actionButtonTitleNode.isHidden = true
self.actionButtonBackgroundNode = ASImageNode()
self.actionButtonBackgroundNode.isHidden = true
self.actionButtonBackgroundNode.displaysAsynchronously = false
self.listButton = HighlightableButtonNode()
self.listButton.hitTestSlop = UIEdgeInsets(top: -8.0, left: -8.0, bottom: -8.0, right: -8.0)
self.listButton.displaysAsynchronously = false
@ -153,8 +164,21 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
}
}
self.actionButton.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
if highlighted {
strongSelf.actionButton.layer.removeAnimation(forKey: "opacity")
strongSelf.actionButton.alpha = 0.4
} else {
strongSelf.actionButton.alpha = 1.0
strongSelf.actionButton.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
}
}
}
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: [.touchUpInside])
self.listButton.addTarget(self, action: #selector(self.listPressed), forControlEvents: [.touchUpInside])
self.actionButton.addTarget(self, action: #selector(self.actionButtonPressed), forControlEvents: [.touchUpInside])
self.addSubnode(self.contextContainer)
@ -168,6 +192,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
self.imageNodeContainer.addSubnode(self.imageNode)
self.contentContainer.addSubnode(self.imageNodeContainer)
self.actionButton.addSubnode(self.actionButtonBackgroundNode)
self.actionButton.addSubnode(self.actionButtonTitleNode)
self.buttonsContainer.addSubnode(self.actionButton)
self.buttonsContainer.addSubnode(self.closeButton)
self.buttonsContainer.addSubnode(self.listButton)
self.contextContainer.addSubnode(self.buttonsContainer)
@ -207,6 +234,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(interfaceState.theme), for: [])
self.listButton.setImage(PresentationResourcesChat.chatInputPanelPinnedListIconImage(interfaceState.theme), for: [])
self.separatorNode.backgroundColor = interfaceState.theme.rootController.navigationBar.separatorColor
self.actionButtonBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 14.0 * 2.0, color: interfaceState.theme.list.itemCheckColors.fillColor, strokeColor: nil, strokeWidth: nil, backgroundColor: nil)
}
if self.statusDisposable == nil, let interfaceInteraction = self.interfaceInteraction, let statuses = interfaceInteraction.statuses {
@ -259,6 +288,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
self.contextContainer.isGestureEnabled = !isReplyThread
var actionTitle: String?
var messageUpdated = false
var messageUpdatedAnimation: PinnedMessageAnimation?
if let currentMessage = self.currentMessage, let pinnedMessage = interfaceState.pinnedMessage {
@ -286,6 +316,16 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
}
}
if let currentMessage = self.currentMessage {
for attribute in currentMessage.message.attributes {
if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), attribute.rows.count == 1, attribute.rows[0].buttons.count == 1 {
actionTitle = attribute.rows[0].buttons[0].title
}
}
} else {
actionTitle = nil
}
if isReplyThread {
self.closeButton.isHidden = true
self.listButton.isHidden = true
@ -302,12 +342,34 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
self.closeButton.isHidden = true
}
let rightInset: CGFloat = 18.0 + rightInset
var rightInset: CGFloat = 18.0 + rightInset
let buttonsContainerSize = CGSize(width: 16.0, height: panelHeight)
self.buttonsContainer.frame = CGRect(origin: CGPoint(x: width - buttonsContainerSize.width - rightInset, y: 0.0), size: buttonsContainerSize)
let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0))
if let actionTitle = actionTitle {
self.actionButton.isHidden = false
self.actionButtonBackgroundNode.isHidden = false
self.actionButtonTitleNode.isHidden = false
self.actionButtonTitleNode.attributedText = NSAttributedString(string: actionTitle, font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: interfaceState.theme.list.itemCheckColors.foregroundColor)
let actionButtonTitleSize = self.actionButtonTitleNode.updateLayout(CGSize(width: 150.0, height: .greatestFiniteMagnitude))
let actionButtonSize = CGSize(width: actionButtonTitleSize.width + 20.0, height: 28.0)
let actionButtonFrame = CGRect(origin: CGPoint(x: (buttonsContainerSize.width - closeButtonSize.width + 1.0) - 8.0 - actionButtonSize.width, y: floor((panelHeight - actionButtonSize.height) / 2.0)), size: actionButtonSize)
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
transition.updateFrame(node: self.actionButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: actionButtonFrame.size))
transition.updateFrame(node: self.actionButtonTitleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((actionButtonFrame.width - actionButtonTitleSize.width) / 2.0), y: floorToScreenPixels((actionButtonFrame.height - actionButtonTitleSize.height) / 2.0)), size: actionButtonTitleSize))
rightInset += actionButtonSize.width + 8.0
} else {
self.actionButton.isHidden = true
self.actionButtonBackgroundNode.isHidden = true
self.actionButtonTitleNode.isHidden = true
}
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: buttonsContainerSize.width - closeButtonSize.width + 1.0, y: 19.0), size: closeButtonSize))
let listButtonSize = self.listButton.measure(CGSize(width: 100.0, height: 100.0))
@ -323,7 +385,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
self.clippingContainer.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))
self.contentContainer.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))
if self.currentLayout?.0 != width || self.currentLayout?.1 != leftInset || self.currentLayout?.2 != rightInset {
if self.currentLayout?.0 != width || self.currentLayout?.1 != leftInset || self.currentLayout?.2 != rightInset || messageUpdated {
self.currentLayout = (width, leftInset, rightInset)
if let currentMessage = self.currentMessage {
@ -377,12 +439,17 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
targetQueue = self.queue
}
let contentLeftInset: CGFloat = leftInset + 10.0
var textLineInset: CGFloat = 10.0
var rightInset: CGFloat = 18.0 + rightInset
let textRightInset: CGFloat = 0.0
if !self.actionButton.isHidden {
rightInset += self.actionButton.bounds.width + 8.0
}
targetQueue.async { [weak self] in
let contentLeftInset: CGFloat = leftInset + 10.0
var textLineInset: CGFloat = 10.0
let rightInset: CGFloat = 18.0 + rightInset
let textRightInset: CGFloat = 0.0
var updatedMediaReference: AnyMediaReference?
var imageDimensions: CGSize?
@ -610,4 +677,63 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
interfaceInteraction.openPinnedList(message.message.id)
}
}
@objc private func actionButtonPressed() {
if let interfaceInteraction = self.interfaceInteraction, let controller = interfaceInteraction.chatController() as? ChatControllerImpl, let controllerInteraction = controller.controllerInteraction, let message = self.currentMessage?.message {
for attribute in message.attributes {
if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), attribute.rows.count == 1, attribute.rows[0].buttons.count == 1 {
let button = attribute.rows[0].buttons[0]
switch button.action {
case .text:
controllerInteraction.sendMessage(button.title)
case let .url(url):
controllerInteraction.openUrl(url, true, nil, nil)
case .requestMap:
controllerInteraction.shareCurrentLocation()
case .requestPhone:
controllerInteraction.shareAccountContact()
case .openWebApp:
controllerInteraction.requestMessageActionCallback(message.id, nil, true, false)
case let .callback(requiresPassword, data):
controllerInteraction.requestMessageActionCallback(message.id, data, false, requiresPassword)
case let .switchInline(samePeer, query):
var botPeer: Peer?
var found = false
for attribute in message.attributes {
if let attribute = attribute as? InlineBotMessageAttribute {
if let peerId = attribute.peerId {
botPeer = message.peers[peerId]
found = true
}
}
}
if !found {
botPeer = message.author
}
var peerId: PeerId?
if samePeer {
peerId = message.id.peerId
}
if let botPeer = botPeer, let addressName = botPeer.addressName {
controllerInteraction.activateSwitchInline(peerId, "@\(addressName) \(query)")
}
case .payment:
controllerInteraction.openCheckoutOrReceipt(message.id)
case let .urlAuth(url, buttonId):
controllerInteraction.requestMessageActionUrlAuth(url, .message(id: message.id, buttonId: buttonId))
case .setupPoll:
break
case let .openUserProfile(peerId):
controllerInteraction.openPeer(peerId, .info, nil, nil)
case let .openWebView(url, simple):
controllerInteraction.openWebView(button.title, url, simple)
}
break
}
}
}
}
}

View file

@ -151,6 +151,8 @@ final class ChatRecentActionsController: TelegramBaseController {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, chatController: {
return nil
}, statuses: nil)
self.navigationItem.titleView = self.titleView

View file

@ -946,27 +946,31 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}
private func presentAutoremoveSetup() {
let peer = self.peer
let controller = peerAutoremoveSetupScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: peer.id, completion: { [weak self] updatedValue in
if case let .updated(value) = updatedValue {
/*let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peer.id, style: .default, mode: .autoremove, currentTime: currentValue, dismissByTapOutside: true, completion: { [weak self] value in
guard let strongSelf = self else {
return
}
let _ = (strongSelf.context.engine.peers.setChatMessageAutoremoveTimeoutInteractively(peerId: strongSelf.peer.id, timeout: value == 0 ? nil : value)
|> deliverOnMainQueue).start(completed: {
guard let strongSelf = self else {
return
}
var isOn: Bool = true
var text: String?
if let myValue = value.value {
text = strongSelf.presentationData.strings.Conversation_AutoremoveChanged("\(timeIntervalString(strings: strongSelf.presentationData.strings, value: myValue))").string
if value != 0 {
text = strongSelf.presentationData.strings.Conversation_AutoremoveChanged("\(timeIntervalString(strings: strongSelf.presentationData.strings, value: value))").string
} else {
isOn = false
text = strongSelf.presentationData.strings.Conversation_AutoremoveOff
}
if let text = text {
strongSelf.presentController(UndoOverlayController(presentationData: strongSelf.presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, action: { _ in return false }), .current, nil)
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, action: { _ in return false }), in: .current)
}
}
})
})
self.pushController(controller)
self.view.endEditing(true)
self.present(controller, in: .window(.root))*/
}
}

View file

@ -273,6 +273,10 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
private let cancelButton: HighlightableButtonNode
private let doneButton: SolidRoundedButtonNode
private let disableButton: HighlightableButtonNode
private let disableButtonTitle: ImmediateTextNode
private var initialTime: Int32?
private var pickerView: TimerPickerView?
private var containerLayout: (ContainerViewLayout, CGFloat)?
@ -287,6 +291,7 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
self.presentationData = presentationData
self.dismissByTapOutside = dismissByTapOutside
self.mode = mode
self.initialTime = currentTime
self.wrappingScrollNode = ASScrollNode()
self.wrappingScrollNode.view.alwaysBounceVertical = true
@ -349,6 +354,22 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
self.doneButton = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 52.0, cornerRadius: 11.0, gloss: false)
self.doneButton.title = self.presentationData.strings.Conversation_Timer_Send
self.disableButton = HighlightableButtonNode()
self.disableButtonTitle = ImmediateTextNode()
self.disableButton.addSubnode(self.disableButtonTitle)
//TODO:localize
self.disableButtonTitle.attributedText = NSAttributedString(string: "Disable Auto-Delete", font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemAccentColor)
self.disableButton.isHidden = true
switch self.mode {
case .autoremove:
if self.initialTime != nil {
self.disableButton.isHidden = false
}
default:
break
}
super.init()
self.backgroundColor = nil
@ -369,17 +390,24 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
self.contentContainerNode.addSubnode(self.textNode)
self.contentContainerNode.addSubnode(self.cancelButton)
self.contentContainerNode.addSubnode(self.doneButton)
self.contentContainerNode.addSubnode(self.disableButton)
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
self.doneButton.pressed = { [weak self] in
if let strongSelf = self, let pickerView = strongSelf.pickerView {
strongSelf.doneButton.isUserInteractionEnabled = false
if let pickerView = pickerView as? TimerCustomPickerView {
strongSelf.completion?(timerValues[pickerView.selectedRow(inComponent: 0)])
switch strongSelf.mode {
case .sendTimer:
strongSelf.completion?(timerValues[pickerView.selectedRow(inComponent: 0)])
case .autoremove:
let timeInterval = pickerView.selectedRow(inComponent: 0) * 24 * 60 * 60 + pickerView.selectedRow(inComponent: 1) * 60 * 60 + pickerView.selectedRow(inComponent: 2) * 60
strongSelf.completion?(Int32(timeInterval))
case .mute:
break
}
} else if let pickerView = pickerView as? TimerDatePickerView {
switch strongSelf.mode {
case .autoremove:
strongSelf.completion?(Int32(pickerView.countDownDuration))
case .mute:
let timeInterval = max(0, Int32(pickerView.date.timeIntervalSince1970) - Int32(Date().timeIntervalSince1970))
strongSelf.completion?(timeInterval)
@ -390,9 +418,15 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
}
}
self.disableButton.addTarget(self, action: #selector(self.disableButtonPressed), forControlEvents: .touchUpInside)
self.setupPickerView(currentTime: currentTime)
}
@objc private func disableButtonPressed() {
self.completion?(0)
}
func setupPickerView(currentTime: Int32? = nil) {
if let pickerView = self.pickerView {
pickerView.removeFromSuperview()
@ -408,17 +442,24 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
self.contentContainerNode.view.addSubview(pickerView)
self.pickerView = pickerView
case .autoremove:
let pickerView = TimerDatePickerView()
pickerView.locale = localeWithStrings(self.presentationData.strings)
pickerView.datePickerMode = .countDownTimer
if #available(iOS 13.4, *) {
pickerView.preferredDatePickerStyle = .wheels
}
pickerView.selectorColor = UIColor(rgb: 0xffffff, alpha: 0.18)
pickerView.addTarget(self, action: #selector(self.dataPickerChanged), for: .valueChanged)
let pickerView = TimerCustomPickerView()
pickerView.dataSource = self
pickerView.delegate = self
pickerView.selectorColor = self.presentationData.theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.18)
self.contentContainerNode.view.addSubview(pickerView)
self.pickerView = pickerView
if let value = self.initialTime {
let days = value / (24 * 60 * 60)
let hours = (value % (24 * 60 * 60)) / (60 * 60)
let minutes = (value % (60 * 60)) / 60
pickerView.selectRow(Int(days), inComponent: 0, animated: false)
pickerView.selectRow(Int(hours), inComponent: 1, animated: false)
pickerView.selectRow(Int(minutes), inComponent: 2, animated: false)
}
case .mute:
let pickerView = TimerDatePickerView()
pickerView.locale = localeWithStrings(self.presentationData.strings)
@ -436,35 +477,87 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
}
@objc private func dataPickerChanged() {
guard let _ = self.pickerView as? TimerDatePickerView else {
return
}
if let (layout, navigationBarHeight) = self.containerLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
switch self.mode {
case .sendTimer:
return 1
case .autoremove:
return 3
case .mute:
return 0
}
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return timerValues.count
switch self.mode {
case .sendTimer:
return timerValues.count
case .autoremove:
switch component {
case 0:
return 365
case 1:
return 24
case 2:
return 60
default:
return 0
}
case .mute:
return 0
}
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let value = timerValues[row]
let string = timeIntervalString(strings: self.presentationData.strings, value: value)
if let view = view as? TimerPickerItemView {
switch self.mode {
case .sendTimer:
let value = timerValues[row]
let string = timeIntervalString(strings: self.presentationData.strings, value: value)
if let view = view as? TimerPickerItemView {
view.value = (value, string)
return view
}
let view = TimerPickerItemView()
view.value = (value, string)
view.textColor = .white
return view
case .autoremove:
let itemView: TimerPickerItemView
if let current = view as? TimerPickerItemView {
itemView = current
} else {
itemView = TimerPickerItemView()
itemView.textColor = self.presentationData.theme.list.itemPrimaryTextColor
}
let string: String
switch component {
case 0:
string = dayIntervalString(strings: self.presentationData.strings, days: Int32(row))
case 1:
string = hoursIntervalString(strings: self.presentationData.strings, hours: Int32(row))
case 2:
string = minutesIntervalString(strings: self.presentationData.strings, minutes: Int32(row))
default:
preconditionFailure()
}
itemView.value = (Int32(row), string)
return itemView
case .mute:
preconditionFailure()
}
let view = TimerPickerItemView()
view.value = (value, string)
view.textColor = .white
return view
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.dataPickerChanged()
}
func updatePresentationData(_ presentationData: PresentationData) {
@ -575,11 +668,16 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
let cleanInsets = layout.insets(options: [.statusBar])
insets.top = max(10.0, insets.top)
let buttonOffset: CGFloat = 0.0
var buttonOffset: CGFloat = 0.0
let bottomInset: CGFloat = 10.0 + cleanInsets.bottom
let titleHeight: CGFloat = 54.0
var contentHeight = titleHeight + bottomInset + 52.0 + 17.0
let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight)
if !self.disableButton.isHidden {
buttonOffset += 52.0
}
contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight + buttonOffset
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 0.0)
@ -612,11 +710,8 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
case .sendTimer:
break
case .autoremove:
if let pickerView = self.pickerView as? TimerDatePickerView, pickerView.countDownDuration > 0.0 {
self.doneButton.title = "Auto-Delete after \(timeIntervalString(strings: self.presentationData.strings, value: Int32(pickerView.countDownDuration)))"
} else {
self.doneButton.title = self.presentationData.strings.Common_Close
}
//TODO:localize
self.doneButton.title = "Set Auto-Delete"
case .mute:
if let pickerView = self.pickerView as? TimerDatePickerView {
let timeInterval = max(0, Int32(pickerView.date.timeIntervalSince1970) - Int32(Date().timeIntervalSince1970))
@ -635,7 +730,13 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi
}
let doneButtonHeight = self.doneButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 16.0 - buttonOffset, width: contentFrame.width, height: doneButtonHeight))
let doneButtonFrame = CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 16.0 - buttonOffset, width: contentFrame.width, height: doneButtonHeight)
transition.updateFrame(node: self.doneButton, frame: doneButtonFrame)
let disableButtonTitleSize = self.disableButtonTitle.updateLayout(CGSize(width: contentFrame.width, height: doneButtonHeight))
let disableButtonFrame = CGRect(origin: CGPoint(x: doneButtonFrame.minX, y: doneButtonFrame.maxY), size: CGSize(width: contentFrame.width - buttonInset * 2.0, height: doneButtonHeight))
transition.updateFrame(node: self.disableButton, frame: disableButtonFrame)
transition.updateFrame(node: self.disableButtonTitle, frame: CGRect(origin: CGPoint(x: floor((disableButtonFrame.width - disableButtonTitleSize.width) / 2.0), y: floor((disableButtonFrame.height - disableButtonTitleSize.height) / 2.0)), size: disableButtonTitleSize))
self.pickerView?.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))

View file

@ -346,6 +346,8 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { node, save in
displayCopyProtectionTip(node, save)
}, chatController: {
return nil
}, statuses: nil)
self.selectionPanel.interfaceInteraction = interfaceInteraction
@ -3540,6 +3542,42 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
var items: [ContextMenuItem] = []
var isSoundEnabled = true
if let notificationSettings = self.data?.notificationSettings {
switch notificationSettings.messageSound {
case .none:
isSoundEnabled = false
default:
break
}
}
if !isSoundEnabled {
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Enable Sound", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Unmute"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
guard let strongSelf = self else {
return
}
let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .default).start()
})))
} else {
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Disable Sound", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
guard let strongSelf = self else {
return
}
let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .none).start()
})))
}
items.append(.action(ContextMenuActionItem(text: "Mute for...", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Mute2d"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] c, _ in
@ -3586,59 +3624,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
c.pushItems(items: .single(ContextController.Items(content: .list(subItems))))
})))
items.append(.separator)
var isSoundEnabled = true
if let notificationSettings = self.data?.notificationSettings {
switch notificationSettings.messageSound {
case .none:
isSoundEnabled = false
default:
break
}
}
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Sound On", icon: { theme in
if !isSoundEnabled {
return nil
}
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
guard let strongSelf = self else {
return
}
if isSoundEnabled {
return
}
let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .default).start()
})))
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Sound Off", icon: { theme in
if isSoundEnabled {
return nil
}
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.default)
guard let strongSelf = self else {
return
}
if !isSoundEnabled {
return
}
let _ = strongSelf.context.engine.peers.updatePeerNotificationSoundInteractive(peerId: strongSelf.peerId, sound: .none).start()
})))
items.append(.separator)
items.append(.action(ContextMenuActionItem(text: "Customize", icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Settings"), color: theme.contextMenu.primaryColor)
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Customize"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
@ -3738,16 +3727,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
canChangeColors = true
}
if canChangeColors {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ChangeColors, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor)
}, action: { _, f in
f(.dismissWithoutContent)
self?.openChatForThemeChange()
})))
}
var currentAutoremoveTimeout: Int32?
if let cachedData = data.cachedData as? CachedUserData {
switch cachedData.autoremoveTimeout {
@ -3979,26 +3958,38 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
})))
}
if canChangeColors {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ChangeColors, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor)
}, action: { _, f in
f(.dismissWithoutContent)
self?.openChatForThemeChange()
})))
}
if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser && user.botInfo == nil && !user.flags.contains(.isSupport) {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_StartSecretChat, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
}, action: { _, f in
f(.dismissWithoutContent)
self?.openStartSecretChat()
})))
}
/*if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser {
items.append(.action(ContextMenuActionItem(text: "", icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.primaryColor)
}, action: { [weak self] _, f in
f(.dismissWithoutContent)
self?.openStartSecretChat()
})))
}*/
let clearPeerHistory = ClearPeerHistory(context: strongSelf.context, peer: user, chatPeer: user, cachedData: strongSelf.data?.cachedData)
if clearPeerHistory.canClearForMyself != nil || clearPeerHistory.canClearForEveryone != nil {
if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser {
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Clear Messages", icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ClearMessages"), color: theme.contextMenu.primaryColor)
}, action: { c, _ in
self?.openClearHistory(contextController: c, clearPeerHistory: clearPeerHistory, peer: user, chatPeer: user)
})))
}
}
if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser && user.botInfo == nil && !user.flags.contains(.isSupport) {
if data.isContact {
@ -4006,7 +3997,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} else {
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_BlockUser, textColor: .destructive, icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.contextMenu.destructiveColor)
}, action: { [weak self] _, f in
}, action: { _, f in
f(.dismissWithoutContent)
self?.updateBlocked(block: true)
@ -4058,6 +4049,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
})))
}
let clearPeerHistory = ClearPeerHistory(context: strongSelf.context, peer: channel, chatPeer: channel, cachedData: strongSelf.data?.cachedData)
if clearPeerHistory.canClearForMyself != nil || clearPeerHistory.canClearForEveryone != nil {
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Clear Messages", icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ClearMessages"), color: theme.contextMenu.primaryColor)
}, action: { c, _ in
self?.openClearHistory(contextController: c, clearPeerHistory: clearPeerHistory, peer: channel, chatPeer: channel)
})))
}
switch channel.info {
case .broadcast:
if case .member = channel.participationStatus, !headerButtons.contains(.leave) {
@ -4087,6 +4088,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
}
} else if let group = peer as? TelegramGroup {
let clearPeerHistory = ClearPeerHistory(context: strongSelf.context, peer: group, chatPeer: group, cachedData: strongSelf.data?.cachedData)
if clearPeerHistory.canClearForMyself != nil || clearPeerHistory.canClearForEveryone != nil {
//TODO:localize
items.append(.action(ContextMenuActionItem(text: "Clear Messages", icon: { theme in
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ClearMessages"), color: theme.contextMenu.primaryColor)
}, action: { c, _ in
self?.openClearHistory(contextController: c, clearPeerHistory: clearPeerHistory, peer: group, chatPeer: group)
})))
}
if case .Member = group.membership, !headerButtons.contains(.leave) {
if !items.isEmpty {
items.append(.separator)
@ -4162,28 +4173,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
private func openAutoremove(currentValue: Int32?) {
/*let controller = peerAutoremoveSetupScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId, completion: { [weak self] updatedValue in
if case let .updated(value) = updatedValue {
guard let strongSelf = self else {
return
}
var isOn: Bool = true
var text: String?
if let myValue = value.value {
text = strongSelf.presentationData.strings.Conversation_AutoremoveChanged("\(timeIntervalString(strings: strongSelf.presentationData.strings, value: myValue))").string
} else {
isOn = false
text = strongSelf.presentationData.strings.Conversation_AutoremoveOff
}
if let text = text {
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .autoDelete(isOn: isOn, title: nil, text: text), elevatedLayout: false, action: { _ in return false }), in: .current)
}
}
})
self.controller?.view.endEditing(true)
self.controller?.push(controller)*/
let controller = ChatTimerScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId, style: .default, mode: .autoremove, currentTime: currentValue, dismissByTapOutside: true, completion: { [weak self] value in
guard let strongSelf = self else {
return
@ -4340,6 +4329,94 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
})
}
private func openClearHistory(contextController: ContextControllerProtocol, clearPeerHistory: ClearPeerHistory, peer: Peer, chatPeer: Peer) {
var subItems: [ContextMenuItem] = []
subItems.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Common_Back, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
}, action: { c, _ in
c.popItems()
})))
subItems.append(.separator)
//TODO:localize
guard let anyType = clearPeerHistory.canClearForEveryone ?? clearPeerHistory.canClearForMyself else {
return
}
let title: String
switch anyType {
case .user, .secretChat, .savedMessages:
title = "Are you sure you want to delete all messages with \(EnginePeer(chatPeer).compactDisplayTitle)?"
case .group, .channel:
title = "Are you sure you want to delete all messages in \(EnginePeer(chatPeer).compactDisplayTitle)?"
}
subItems.append(.action(ContextMenuActionItem(text: title, textLayout: .multiline, textFont: .small, icon: { _ in
return nil
}, action: nil as ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void) -> Void)?)))
let beginClear: (InteractiveHistoryClearingType) -> Void = { [weak self] type in
guard let strongSelf = self else {
return
}
let statusText: String
if case .forEveryone = type {
statusText = strongSelf.presentationData.strings.Undo_ChatClearedForBothSides
} else {
statusText = strongSelf.presentationData.strings.Undo_ChatCleared
}
strongSelf.controller?.present(UndoOverlayController(presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, content: .removedChat(text: statusText), elevatedLayout: false, action: { value in
if value == .commit {
guard let strongSelf = self else {
return false
}
let _ = strongSelf.context.engine.messages.clearHistoryInteractively(peerId: peer.id, type: type).start(completed: {
})
return true
} else if value == .undo {
return true
}
return false
}), in: .current)
}
if let canClearForEveryone = clearPeerHistory.canClearForEveryone {
let text: String
switch canClearForEveryone {
case .user, .secretChat, .savedMessages:
text = self.presentationData.strings.Conversation_DeleteMessagesFor(EnginePeer(chatPeer).compactDisplayTitle).string
case .channel, .group:
text = self.presentationData.strings.Conversation_DeleteMessagesForEveryone
}
subItems.append(.action(ContextMenuActionItem(text: text, textColor: .destructive, icon: { _ in
return nil
}, action: { _, f in
f(.default)
beginClear(.forEveryone)
})))
}
if let _ = clearPeerHistory.canClearForMyself {
let text: String = self.presentationData.strings.Conversation_DeleteMessagesForMe
subItems.append(.action(ContextMenuActionItem(text: text, textColor: .destructive, icon: { _ in
return nil
}, action: { _, f in
f(.default)
beginClear(.forLocalPeer)
})))
}
contextController.pushItems(items: .single(ContextController.Items(content: .list(subItems))))
}
private func openUsername(value: String) {
let shareController = ShareController(context: self.context, subject: .url("https://t.me/\(value)"), updatedPresentationData: self.controller?.updatedPresentationData)
shareController.completed = { [weak self] peerIds in
@ -4541,16 +4618,19 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
private func editingOpenNotificationSettings() {
let peerId = self.peerId
let _ = (self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in
let _ = (combineLatest(self.context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in
let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings
let globalSettings: GlobalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) ?? GlobalNotificationSettings.defaultSettings
return (peerSettings, globalSettings)
}
|> deliverOnMainQueue).start(next: { [weak self] peerSettings, globalSettings in
}, self.context.engine.peers.notificationSoundList())
|> deliverOnMainQueue).start(next: { [weak self] settings, notificationSoundList in
guard let strongSelf = self else {
return
}
let muteSettingsController = notificationMuteSettingsController(presentationData: strongSelf.presentationData, notificationSettings: globalSettings.effective.groupChats, soundSettings: nil, openSoundSettings: {
let (peerSettings, globalSettings) = settings
let muteSettingsController = notificationMuteSettingsController(presentationData: strongSelf.presentationData, notificationSoundList: notificationSoundList, notificationSettings: globalSettings.effective.groupChats, soundSettings: nil, openSoundSettings: {
guard let strongSelf = self else {
return
}
@ -4660,7 +4740,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|> deliverOnMainQueue).start(completed: { [weak self] in
if let strongSelf = self, let peer = strongSelf.data?.peer {
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let controller = UndoOverlayController(presentationData: presentationData, content: .info(text: presentationData.strings.Conversation_DeletedFromContacts(EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false })
let controller = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Conversation_DeletedFromContacts(EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false })
controller.keepOnParentDismissal = true
strongSelf.controller?.present(controller, in: .window(.root))
@ -8480,3 +8560,73 @@ func presentAddMembers(context: AccountContext, updatedPresentationData: (initia
}
})
}
struct ClearPeerHistory {
enum ClearType {
case savedMessages
case secretChat
case group
case channel
case user
}
var canClearCache: Bool = false
var canClearForMyself: ClearType? = nil
var canClearForEveryone: ClearType? = nil
init(context: AccountContext, peer: Peer, chatPeer: Peer, cachedData: CachedPeerData?) {
if peer.id == context.account.peerId {
canClearCache = false
canClearForMyself = .savedMessages
canClearForEveryone = nil
} else if chatPeer is TelegramSecretChat {
canClearCache = false
canClearForMyself = .secretChat
canClearForEveryone = nil
} else if let group = chatPeer as? TelegramGroup {
canClearCache = false
switch group.role {
case .creator:
canClearForMyself = .group
canClearForEveryone = .group
case .admin, .member:
canClearForMyself = .group
canClearForEveryone = nil
}
} else if let channel = chatPeer as? TelegramChannel {
var canDeleteHistory = false
if let cachedData = cachedData as? CachedChannelData {
canDeleteHistory = cachedData.flags.contains(.canDeleteHistory)
}
var canDeleteLocally = true
if case .broadcast = channel.info {
canDeleteLocally = false
} else if channel.username != nil {
canDeleteLocally = false
}
if !canDeleteHistory {
canClearCache = true
canClearForMyself = canDeleteLocally ? .channel : nil
canClearForEveryone = nil
} else {
canClearCache = true
canClearForMyself = canDeleteLocally ? .channel : nil
canClearForEveryone = .channel
}
} else {
canClearCache = false
canClearForMyself = .user
if let user = chatPeer as? TelegramUser, user.botInfo != nil {
canClearForEveryone = nil
} else {
canClearForEveryone = .user
}
}
}
}

View file

@ -347,6 +347,8 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, chatController: {
return nil
}, statuses: nil)
self.readyValue.set(self.chatListNode.ready)

View file

@ -23,6 +23,9 @@
#import "platform/darwin/VideoSampleBufferView.h"
#import "platform/darwin/VideoCaptureView.h"
#import "platform/darwin/CustomExternalCapturer.h"
#include "platform/darwin/iOS/tgcalls_audio_device_module_ios.h"
#endif
#import "group/GroupInstanceImpl.h"
@ -1039,9 +1042,11 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
[strongSelf signalingDataEmitted:mappedData];
}
}];
},
.createAudioDeviceModule = [](webrtc::TaskQueueFactory *taskQueueFactory) -> rtc::scoped_refptr<webrtc::AudioDeviceModule> {
return rtc::make_ref_counted<webrtc::tgcalls_ios_adm::AudioDeviceModuleIOS>(false, false, 1);
}
});
_state = OngoingCallStateInitializing;
_signalBars = 4;
}

View file

@ -12,7 +12,7 @@ public enum UndoOverlayContent {
case hidArchive(title: String, text: String, undo: Bool)
case revealedArchive(title: String, text: String, undo: Bool)
case succeed(text: String)
case info(text: String)
case info(title: String?, text: String)
case emoji(name: String, text: String)
case swipeToReply(title: String, text: String)
case actionSucceeded(title: String, text: String, cancel: String)
@ -40,6 +40,7 @@ public enum UndoOverlayContent {
case paymentSent(currencyValue: String, itemTitle: String)
case inviteRequestSent(title: String, text: String)
case image(image: UIImage, text: String)
case notificationSoundAdded(title: String, text: String, action: (() -> Void)?)
}
public enum UndoOverlayAction {

View file

@ -167,13 +167,17 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
self.textNode.maximumNumberOfLines = 5
displayUndo = false
self.originalRemainingSeconds = 3
case let .info(text):
case let .info(title, text):
self.avatarNode = nil
self.iconNode = nil
self.iconCheckNode = nil
self.animationNode = AnimationNode(animation: "anim_infotip", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0)
self.animatedStickerNode = nil
if let title = title {
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
}
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in return nil }), textAlignment: .natural)
@ -750,6 +754,32 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
self.textNode.maximumNumberOfLines = 2
displayUndo = false
self.originalRemainingSeconds = 5
case let .notificationSoundAdded(title, text, action):
self.avatarNode = nil
self.iconNode = nil
self.iconCheckNode = nil
self.animationNode = AnimationNode(animation: "anim_notificationsound", colors: [:], scale: 0.066)
self.animatedStickerNode = nil
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white)
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { _ in return nil }), textAlignment: .natural)
self.textNode.attributedText = attributedText
self.textNode.maximumNumberOfLines = 5
displayUndo = false
self.originalRemainingSeconds = 5
if let action = action {
self.textNode.tapAttributeAction = { attributes, _ in
if let _ = attributes[NSAttributedString.Key(rawValue: "URL")] {
action()
}
}
}
case let .image(image, text):
self.avatarNode = nil
self.iconNode = ASImageNode()
@ -792,7 +822,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
switch content {
case .removedChat:
self.panelWrapperNode.addSubnode(self.timerTextNode)
case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .sticker, .copy, .mediaSaved, .paymentSent, .image, .inviteRequestSent:
case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .sticker, .copy, .mediaSaved, .paymentSent, .image, .inviteRequestSent, .notificationSoundAdded:
break
case .dice:
self.panelWrapperNode.clipsToBounds = true