mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
43947a3dd3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -217,33 +217,37 @@ private func notificationsAndSoundsEntries(presentationData: PresentationData, d
|
||||
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: selectedSound == .none))
|
||||
if let notificationSoundList = notificationSoundList {
|
||||
for listSound in notificationSoundList.sounds {
|
||||
let cloudSounds = notificationSoundList.sounds.filter({ CloudSoundBuiltinCategory(id: $0.file.fileId.id) == nil })
|
||||
let modernSounds = notificationSoundList.sounds.filter({ CloudSoundBuiltinCategory(id: $0.file.fileId.id) == .modern })
|
||||
let classicSounds = notificationSoundList.sounds.filter({ CloudSoundBuiltinCategory(id: $0.file.fileId.id) == .classic })
|
||||
|
||||
for listSound in cloudSounds {
|
||||
let sound: PeerMessageSound = .cloud(fileId: listSound.file.fileId.id)
|
||||
if state.removedSounds.contains(where: { $0.id == sound.id }) {
|
||||
continue
|
||||
}
|
||||
entries.append(.sound(section: .cloud, index: Int32(entries.count), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: selectedSound.id == sound.id, canBeDeleted: true))
|
||||
}
|
||||
}
|
||||
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, notificationSoundList: notificationSoundList, sound: .default, default: defaultSound), selected: selectedSound.id == .default))
|
||||
}
|
||||
entries.append(.none(section: .modern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: 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, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
}
|
||||
|
||||
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, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
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, notificationSoundList: notificationSoundList, sound: .default, default: defaultSound), selected: selectedSound.id == .default))
|
||||
}
|
||||
entries.append(.none(section: .modern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: selectedSound.id == .none))
|
||||
for i in 0 ..< modernSounds.count {
|
||||
let sound: PeerMessageSound = .cloud(fileId: modernSounds[i].file.fileId.id)
|
||||
entries.append(.sound(section: .modern, index: Int32(100 + i), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
}
|
||||
|
||||
entries.append(.classicHeader(presentationData.theme, presentationData.strings.Notifications_ClassicTones))
|
||||
for i in 0 ..< classicSounds.count {
|
||||
let sound: PeerMessageSound = .cloud(fileId: classicSounds[i].file.fileId.id)
|
||||
entries.append(.sound(section: .classic, index: Int32(200 + i), theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
}
|
||||
}
|
||||
|
||||
return entries
|
||||
@ -457,7 +461,7 @@ public func notificationSoundSelectionController(context: AccountContext, update
|
||||
|
||||
state.removedSounds.append(sound)
|
||||
if state.selectedSound.id == sound.id {
|
||||
state.selectedSound = .bundledModern(id: 0)
|
||||
state.selectedSound = defaultCloudPeerNotificationSound
|
||||
}
|
||||
|
||||
return state
|
||||
|
@ -274,9 +274,12 @@ private func notificationPeerExceptionEntries(presentationData: PresentationData
|
||||
|
||||
index = 1000
|
||||
|
||||
//entries.append(.none(section: .cloud, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: selectedSound == .none))
|
||||
if let notificationSoundList = notificationSoundList {
|
||||
for listSound in notificationSoundList.sounds {
|
||||
let cloudSounds = notificationSoundList.sounds.filter({ CloudSoundBuiltinCategory(id: $0.file.fileId.id) == nil })
|
||||
let modernSounds = notificationSoundList.sounds.filter({ CloudSoundBuiltinCategory(id: $0.file.fileId.id) == .modern })
|
||||
let classicSounds = notificationSoundList.sounds.filter({ CloudSoundBuiltinCategory(id: $0.file.fileId.id) == .classic })
|
||||
|
||||
for listSound in cloudSounds {
|
||||
let sound: PeerMessageSound = .cloud(fileId: listSound.file.fileId.id)
|
||||
if state.removedSounds.contains(where: { $0.id == sound.id }) {
|
||||
continue
|
||||
@ -284,38 +287,38 @@ private func notificationPeerExceptionEntries(presentationData: PresentationData
|
||||
entries.append(.sound(index: index, section: .soundCloud, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: selectedSound.id == sound.id, canBeDeleted: true))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
||||
index = 2000
|
||||
|
||||
entries.append(.uploadSound(index: index, text: presentationData.strings.Notifications_UploadSound))
|
||||
index += 1
|
||||
entries.append(.cloudInfo(index: index, text: presentationData.strings.Notifications_MessageSoundInfo))
|
||||
index += 1
|
||||
|
||||
entries.append(.soundModernHeader(index: index, theme: presentationData.theme, title: presentationData.strings.Notifications_AlertTones))
|
||||
|
||||
index = 3000
|
||||
|
||||
entries.append(.default(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .default, default: state.defaultSound), selected: selectedSound == .default))
|
||||
index += 1
|
||||
|
||||
entries.append(.none(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: 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, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
|
||||
index = 2000
|
||||
|
||||
entries.append(.uploadSound(index: index, text: presentationData.strings.Notifications_UploadSound))
|
||||
index += 1
|
||||
}
|
||||
|
||||
entries.append(.soundClassicHeader(index: index, theme: presentationData.theme, title: presentationData.strings.Notifications_ClassicTones))
|
||||
index += 1
|
||||
|
||||
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, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
entries.append(.cloudInfo(index: index, text: presentationData.strings.Notifications_MessageSoundInfo))
|
||||
index += 1
|
||||
|
||||
entries.append(.soundModernHeader(index: index, theme: presentationData.theme, title: presentationData.strings.Notifications_AlertTones))
|
||||
|
||||
index = 3000
|
||||
|
||||
entries.append(.default(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .default, default: state.defaultSound), selected: selectedSound == .default))
|
||||
index += 1
|
||||
|
||||
entries.append(.none(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: .none), selected: selectedSound == .none))
|
||||
index += 1
|
||||
|
||||
for i in 0 ..< modernSounds.count {
|
||||
let sound: PeerMessageSound = .cloud(fileId: modernSounds[i].file.fileId.id)
|
||||
entries.append(.sound(index: index, section: .soundModern, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
index += 1
|
||||
}
|
||||
|
||||
entries.append(.soundClassicHeader(index: index, theme: presentationData.theme, title: presentationData.strings.Notifications_ClassicTones))
|
||||
index += 1
|
||||
|
||||
for i in 0 ..< classicSounds.count {
|
||||
let sound: PeerMessageSound = .cloud(fileId: classicSounds[i].file.fileId.id)
|
||||
entries.append(.sound(index: index, section: .soundClassic, theme: presentationData.theme, text: localizedPeerNotificationSoundString(strings: presentationData.strings, notificationSoundList: notificationSoundList, sound: sound), sound: sound, selected: sound.id == selectedSound.id, canBeDeleted: false))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,7 +519,7 @@ public func notificationPeerExceptionController(context: AccountContext, updated
|
||||
|
||||
state.removedSounds.append(sound)
|
||||
if state.selectedSound.id == sound.id {
|
||||
state.selectedSound = .bundledModern(id: 0)
|
||||
state.selectedSound = defaultCloudPeerNotificationSound
|
||||
}
|
||||
|
||||
return state
|
||||
|
@ -492,7 +492,7 @@ private enum NotificationsAndSoundsEntry: ItemListNodeEntry {
|
||||
|
||||
private func filteredGlobalSound(_ sound: PeerMessageSound) -> PeerMessageSound {
|
||||
if case .default = sound {
|
||||
return .bundledModern(id: 0)
|
||||
return defaultCloudPeerNotificationSound
|
||||
} else {
|
||||
return sound
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ private enum NotificationsPeerCategoryEntry: ItemListNodeEntry {
|
||||
|
||||
private func filteredGlobalSound(_ sound: PeerMessageSound) -> PeerMessageSound {
|
||||
if case .default = sound {
|
||||
return .bundledModern(id: 0)
|
||||
return defaultCloudPeerNotificationSound
|
||||
} else {
|
||||
return sound
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ private func notificationSearchableItems(context: AccountContext, settings: Glob
|
||||
|
||||
func filteredGlobalSound(_ sound: PeerMessageSound) -> PeerMessageSound {
|
||||
if case .default = sound {
|
||||
return .bundledModern(id: 0)
|
||||
return defaultCloudPeerNotificationSound
|
||||
} else {
|
||||
return sound
|
||||
}
|
||||
|
@ -855,6 +855,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[-1222230163] = { return Api.account.SavedRingtone.parse_savedRingtone($0) }
|
||||
dict[523271863] = { return Api.account.SavedRingtone.parse_savedRingtoneConverted($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) }
|
||||
@ -1570,6 +1572,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.SavedRingtone:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.account.SavedRingtones:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.account.SentEmailCode:
|
||||
|
@ -658,6 +658,56 @@ public extension Api.account {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.account {
|
||||
enum SavedRingtone: TypeConstructorDescription {
|
||||
case savedRingtone
|
||||
case savedRingtoneConverted(document: Api.Document)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .savedRingtone:
|
||||
if boxed {
|
||||
buffer.appendInt32(-1222230163)
|
||||
}
|
||||
|
||||
break
|
||||
case .savedRingtoneConverted(let document):
|
||||
if boxed {
|
||||
buffer.appendInt32(523271863)
|
||||
}
|
||||
document.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .savedRingtone:
|
||||
return ("savedRingtone", [])
|
||||
case .savedRingtoneConverted(let document):
|
||||
return ("savedRingtoneConverted", [("document", String(describing: document))])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_savedRingtone(_ reader: BufferReader) -> SavedRingtone? {
|
||||
return Api.account.SavedRingtone.savedRingtone
|
||||
}
|
||||
public static func parse_savedRingtoneConverted(_ reader: BufferReader) -> SavedRingtone? {
|
||||
var _1: Api.Document?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.Document
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.account.SavedRingtone.savedRingtoneConverted(document: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.account {
|
||||
enum SavedRingtones: TypeConstructorDescription {
|
||||
case savedRingtones(hash: Int64, ringtones: [Api.Document])
|
||||
@ -1140,83 +1190,3 @@ public extension Api.auth {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.auth {
|
||||
enum ExportedAuthorization: TypeConstructorDescription {
|
||||
case exportedAuthorization(id: Int64, bytes: Buffer)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .exportedAuthorization(let id, let bytes):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1271602504)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeBytes(bytes, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .exportedAuthorization(let id, let bytes):
|
||||
return ("exportedAuthorization", [("id", String(describing: id)), ("bytes", String(describing: bytes))])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_exportedAuthorization(_ reader: BufferReader) -> ExportedAuthorization? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Buffer?
|
||||
_2 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.auth.ExportedAuthorization.exportedAuthorization(id: _1!, bytes: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,83 @@
|
||||
public extension Api.auth {
|
||||
enum ExportedAuthorization: TypeConstructorDescription {
|
||||
case exportedAuthorization(id: Int64, bytes: Buffer)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .exportedAuthorization(let id, let bytes):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1271602504)
|
||||
}
|
||||
serializeInt64(id, buffer: buffer, boxed: false)
|
||||
serializeBytes(bytes, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .exportedAuthorization(let id, let bytes):
|
||||
return ("exportedAuthorization", [("id", String(describing: id)), ("bytes", String(describing: bytes))])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_exportedAuthorization(_ reader: BufferReader) -> ExportedAuthorization? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Buffer?
|
||||
_2 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.auth.ExportedAuthorization.exportedAuthorization(id: _1!, bytes: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
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)
|
||||
@ -1264,61 +1344,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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,61 @@
|
||||
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]?)
|
||||
@ -1292,39 +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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,39 @@
|
||||
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)
|
||||
|
@ -795,16 +795,16 @@ public extension Api.functions.account {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.account {
|
||||
static func saveRingtone(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
static func saveRingtone(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.SavedRingtone>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-369618141)
|
||||
buffer.appendInt32(1038768899)
|
||||
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
|
||||
return (FunctionDescription(name: "account.saveRingtone", parameters: [("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SavedRingtone? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
var result: Api.account.SavedRingtone?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
result = Api.parse(reader, signature: signature) as? Api.account.SavedRingtone
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
@ -68,7 +68,7 @@ extension PeerMessageSound {
|
||||
} else if soundId >= 2 && soundId <= 9 {
|
||||
parsedSound = .bundledClassic(id: soundId - 2)
|
||||
} else {
|
||||
parsedSound = .bundledModern(id: 0)
|
||||
parsedSound = defaultCloudPeerNotificationSound
|
||||
}
|
||||
}
|
||||
self = parsedSound
|
||||
|
@ -1311,11 +1311,11 @@ public final class AccountStateManager {
|
||||
public func messagesForNotification(transaction: Transaction, id: MessageId, alwaysReturnMessage: Bool) -> (messages: [Message], notify: Bool, sound: PeerMessageSound, displayContents: Bool) {
|
||||
guard let message = transaction.getMessage(id) else {
|
||||
Logger.shared.log("AccountStateManager", "notification message doesn't exist")
|
||||
return ([], false, .bundledModern(id: 0), false)
|
||||
return ([], false, defaultCloudPeerNotificationSound, false)
|
||||
}
|
||||
|
||||
var notify = true
|
||||
var sound: PeerMessageSound = .bundledModern(id: 0)
|
||||
var sound: PeerMessageSound = defaultCloudPeerNotificationSound
|
||||
var muted = false
|
||||
var displayContents = true
|
||||
|
||||
@ -1349,7 +1349,7 @@ public func messagesForNotification(transaction: Transaction, id: MessageId, alw
|
||||
}
|
||||
|
||||
if let notificationSettings = transaction.getPeerNotificationSettings(notificationPeerId) as? TelegramPeerNotificationSettings {
|
||||
var defaultSound: PeerMessageSound = .bundledModern(id: 0)
|
||||
var defaultSound: PeerMessageSound = defaultCloudPeerNotificationSound
|
||||
var defaultNotify: Bool = true
|
||||
if let globalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) {
|
||||
if id.peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
|
@ -6,7 +6,7 @@ public struct MessageNotificationSettings: Codable, Equatable {
|
||||
public var sound: PeerMessageSound
|
||||
|
||||
public static var defaultSettings: MessageNotificationSettings {
|
||||
return MessageNotificationSettings(enabled: true, displayPreviews: true, sound: .bundledModern(id: 0))
|
||||
return MessageNotificationSettings(enabled: true, displayPreviews: true, sound: defaultCloudPeerNotificationSound)
|
||||
}
|
||||
|
||||
public init(enabled: Bool, displayPreviews: Bool, sound: PeerMessageSound) {
|
||||
|
@ -1,6 +1,78 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
|
||||
private let cloudSoundMapping: [Int32: Int64] = [
|
||||
2: 5078299559046677200,
|
||||
3: 5078299559046677201,
|
||||
4: 5078299559046677202,
|
||||
5: 5078299559046677203,
|
||||
6: 5078299559046677204,
|
||||
7: 5078299559046677205,
|
||||
8: 5078299559046677206,
|
||||
9: 5078299559046677207,
|
||||
100: 5078299559046677208,
|
||||
101: 5078299559046677209,
|
||||
102: 5078299559046677210,
|
||||
103: 5078299559046677211,
|
||||
104: 5078299559046677212,
|
||||
105: 5078299559046677213,
|
||||
106: 5078299559046677214,
|
||||
107: 5078299559046677215,
|
||||
108: 5078299559046677216,
|
||||
109: 5078299559046677217,
|
||||
110: 5078299559046677218,
|
||||
111: 5078299559046677219
|
||||
]
|
||||
|
||||
public let defaultCloudPeerNotificationSound: PeerMessageSound = .cloud(fileId: cloudSoundMapping[100]!)
|
||||
|
||||
public enum CloudSoundBuiltinCategory {
|
||||
case modern
|
||||
case classic
|
||||
|
||||
public init?(id: Int64) {
|
||||
for (key, value) in cloudSoundMapping {
|
||||
if value == id {
|
||||
if key < 50 {
|
||||
self = .classic
|
||||
return
|
||||
} else {
|
||||
self = .modern
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func getCloudSoundOrDefault(id: Int32, isModern: Bool) -> Int64 {
|
||||
if isModern {
|
||||
if let value = cloudSoundMapping[id + 100] {
|
||||
return value
|
||||
}
|
||||
} else {
|
||||
if let value = cloudSoundMapping[id + 2] {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
return cloudSoundMapping[100]!
|
||||
}
|
||||
|
||||
public func getCloudLegacySound(id: Int64) -> (id: Int32, category: CloudSoundBuiltinCategory)? {
|
||||
for (key, value) in cloudSoundMapping {
|
||||
if value == id {
|
||||
if key < 50 {
|
||||
return (key - 2, .classic)
|
||||
} else {
|
||||
return (key - 100, .modern)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
public enum PeerMuteState: Equatable {
|
||||
case `default`
|
||||
case unmuted
|
||||
@ -75,9 +147,9 @@ public enum PeerMessageSound: Equatable {
|
||||
case PeerMessageSoundValue.none.rawValue:
|
||||
return .none
|
||||
case PeerMessageSoundValue.bundledModern.rawValue:
|
||||
return .bundledModern(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0)
|
||||
return .cloud(fileId: getCloudSoundOrDefault(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0, isModern: true))
|
||||
case PeerMessageSoundValue.bundledClassic.rawValue:
|
||||
return .bundledClassic(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0)
|
||||
return .cloud(fileId: getCloudSoundOrDefault(id: (try? container.decode(Int32.self, forKey: "s.i")) ?? 0, isModern: false))
|
||||
case PeerMessageSoundValue.default.rawValue:
|
||||
return .default
|
||||
case PeerMessageSoundValue.cloud.rawValue:
|
||||
@ -88,7 +160,7 @@ public enum PeerMessageSound: Equatable {
|
||||
}
|
||||
default:
|
||||
assertionFailure()
|
||||
return .bundledModern(id: 0)
|
||||
return defaultCloudPeerNotificationSound
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,16 +169,16 @@ public enum PeerMessageSound: Equatable {
|
||||
case PeerMessageSoundValue.none.rawValue:
|
||||
return .none
|
||||
case PeerMessageSoundValue.bundledModern.rawValue:
|
||||
return .bundledModern(id: container.decodeInt32ForKey("s.i", orElse: 0))
|
||||
return .cloud(fileId: getCloudSoundOrDefault(id: container.decodeInt32ForKey("s.i", orElse: 0), isModern: true))
|
||||
case PeerMessageSoundValue.bundledClassic.rawValue:
|
||||
return .bundledClassic(id: container.decodeInt32ForKey("s.i", orElse: 0))
|
||||
return .cloud(fileId: getCloudSoundOrDefault(id: container.decodeInt32ForKey("s.i", orElse: 0), isModern: false))
|
||||
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)
|
||||
return defaultCloudPeerNotificationSound
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,13 +216,13 @@ func _internal_saveNotificationSound(account: Account, file: FileMediaReference,
|
||||
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: unsave ? .boolTrue : .boolFalse))
|
||||
|> `catch` { error -> Signal<Api.Bool, MTRpcError> in
|
||||
|> `catch` { error -> Signal<Api.account.SavedRingtone, MTRpcError> in
|
||||
if error.errorDescription == "FILE_REFERENCE_EXPIRED" {
|
||||
return revalidateMediaResourceReference(postbox: account.postbox, network: account.network, revalidationContext: account.mediaReferenceRevalidationContext, info: TelegramCloudMediaResourceFetchInfo(reference: file.abstract.resourceReference(file.media.resource), preferBackgroundReferenceRevalidation: false, continueInBackground: false), resource: file.media.resource)
|
||||
|> mapError { _ -> MTRpcError in
|
||||
return MTRpcError(errorCode: 500, errorDescription: "Internal")
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Api.Bool, MTRpcError> in
|
||||
|> mapToSignal { result -> Signal<Api.account.SavedRingtone, MTRpcError> in
|
||||
guard let resource = result.updatedResource as? CloudDocumentMediaResource else {
|
||||
return .fail(MTRpcError(errorCode: 500, errorDescription: "Internal"))
|
||||
}
|
||||
@ -328,7 +328,7 @@ public func resolvedNotificationSound(sound: PeerMessageSound, notificationSound
|
||||
return sound
|
||||
}
|
||||
}
|
||||
return .bundledModern(id: 0)
|
||||
return defaultCloudPeerNotificationSound
|
||||
} else {
|
||||
return .default
|
||||
}
|
||||
|
@ -45,6 +45,19 @@ private func soundName(strings: PresentationStrings, sound: PeerMessageSound, no
|
||||
}
|
||||
return "Sound \(id)"
|
||||
case let .cloud(fileId):
|
||||
if let (id, legacyCategory) = getCloudLegacySound(id: fileId) {
|
||||
switch legacyCategory {
|
||||
case .modern:
|
||||
if id >= 0 && Int(id) < modernSoundsNamePaths.count {
|
||||
return strings[keyPath: modernSoundsNamePaths[Int(id)]]
|
||||
}
|
||||
case .classic:
|
||||
if id >= 0 && Int(id) < classicSoundNamePaths.count {
|
||||
return strings[keyPath: classicSoundNamePaths[Int(id)]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard let notificationSoundList = notificationSoundList else {
|
||||
return strings.Channel_NotificationLoading
|
||||
}
|
||||
@ -87,15 +100,14 @@ public func localizedPeerNotificationSoundString(strings: PresentationStrings, n
|
||||
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)
|
||||
actualName = soundName(strings: strings, sound: defaultCloudPeerNotificationSound, notificationSoundList: notificationSoundList)
|
||||
} else {
|
||||
actualName = name
|
||||
}
|
||||
return strings.UserInfo_NotificationsDefaultSound(actualName).string
|
||||
} else {
|
||||
let name = soundName(strings: strings, sound: .bundledModern(id: 0), notificationSoundList: notificationSoundList)
|
||||
let name = soundName(strings: strings, sound: defaultCloudPeerNotificationSound, notificationSoundList: notificationSoundList)
|
||||
return name
|
||||
//return strings.UserInfo_NotificationsDefault
|
||||
}
|
||||
default:
|
||||
let name = soundName(strings: strings, sound: sound, notificationSoundList: notificationSoundList)
|
||||
|
@ -683,7 +683,9 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
}
|
||||
|
||||
for media in message.media {
|
||||
if let file = media as? TelegramMediaFile, let size = file.size, size < 1 * 1024 * 1024, let duration = file.duration, duration < 60, (["audio/mpeg", "audio/mp3", "audio/mpeg3"] as [String]).contains(file.mimeType.lowercased()), let fileName = file.fileName, (fileName as NSString).pathExtension.lowercased() == "mp3" {
|
||||
if let file = media as? TelegramMediaFile, let size = file.size, size < 1 * 1024 * 1024, let duration = file.duration, duration < 60, (["audio/mpeg", "audio/mp3", "audio/mpeg3", "audio/ogg"] as [String]).contains(file.mimeType.lowercased()) {
|
||||
let fileName = file.fileName ?? "Tone"
|
||||
|
||||
var isAlreadyAdded = false
|
||||
if let notificationSoundList = notificationSoundList, notificationSoundList.sounds.contains(where: { $0.file.fileId == file.fileId }) {
|
||||
isAlreadyAdded = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user