Merge commit '7621e2f8dec938cf48181c8b10afc9b01f444e68' into beta

This commit is contained in:
Ilya Laktyushin
2025-12-06 02:17:48 +04:00
commit 8344b97e03
28070 changed files with 7995182 additions and 0 deletions
@@ -0,0 +1,52 @@
import Foundation
import Postbox
import TelegramApi
import SwiftSignalKit
public func updateAutodownloadSettingsInteractively(accountManager: AccountManager<TelegramAccountManagerTypes>, _ f: @escaping (AutodownloadSettings) -> AutodownloadSettings) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
transaction.updateSharedData(SharedDataKeys.autodownloadSettings, { entry in
let currentSettings: AutodownloadSettings
if let entry = entry?.get(AutodownloadSettings.self) {
currentSettings = entry
} else {
currentSettings = AutodownloadSettings.defaultSettings
}
return PreferencesEntry(f(currentSettings))
})
}
}
extension AutodownloadPresetSettings {
init(apiAutodownloadSettings: Api.AutoDownloadSettings) {
switch apiAutodownloadSettings {
case let .autoDownloadSettings(flags, photoSizeMax, videoSizeMax, fileSizeMax, videoUploadMaxbitrate, _, _):
self.init(disabled: (flags & (1 << 0)) != 0, photoSizeMax: Int64(photoSizeMax), videoSizeMax: videoSizeMax, fileSizeMax: fileSizeMax, preloadLargeVideo: (flags & (1 << 1)) != 0, lessDataForPhoneCalls: (flags & (1 << 3)) != 0, videoUploadMaxbitrate: videoUploadMaxbitrate)
}
}
}
extension AutodownloadSettings {
init(apiAutodownloadSettings: Api.account.AutoDownloadSettings) {
switch apiAutodownloadSettings {
case let .autoDownloadSettings(low, medium, high):
self.init(lowPreset: AutodownloadPresetSettings(apiAutodownloadSettings: low), mediumPreset: AutodownloadPresetSettings(apiAutodownloadSettings: medium), highPreset: AutodownloadPresetSettings(apiAutodownloadSettings: high))
}
}
}
func apiAutodownloadPresetSettings(_ autodownloadPresetSettings: AutodownloadPresetSettings) -> Api.AutoDownloadSettings {
var flags: Int32 = 0
if autodownloadPresetSettings.disabled {
flags |= (1 << 0)
}
if autodownloadPresetSettings.preloadLargeVideo {
flags |= (1 << 1)
}
if autodownloadPresetSettings.lessDataForPhoneCalls {
flags |= (1 << 3)
}
return .autoDownloadSettings(flags: flags, photoSizeMax: Int32(autodownloadPresetSettings.photoSizeMax), videoSizeMax: autodownloadPresetSettings.videoSizeMax, fileSizeMax: autodownloadPresetSettings.fileSizeMax, videoUploadMaxbitrate: autodownloadPresetSettings.videoUploadMaxbitrate, smallQueueActiveOperationsMax: 0, largeQueueActiveOperationsMax: 0)
}
@@ -0,0 +1,31 @@
import Foundation
import Postbox
import SwiftSignalKit
public func updateCacheStorageSettingsInteractively(accountManager: AccountManager<TelegramAccountManagerTypes>, _ f: @escaping (CacheStorageSettings) -> CacheStorageSettings) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
transaction.updateSharedData(SharedDataKeys.cacheStorageSettings, { entry in
let currentSettings: CacheStorageSettings
if let entry = entry?.get(CacheStorageSettings.self) {
currentSettings = entry
} else {
currentSettings = CacheStorageSettings.defaultSettings
}
return PreferencesEntry(f(currentSettings))
})
}
}
public func updateAccountSpecificCacheStorageSettingsInteractively(postbox: Postbox, _ f: @escaping (AccountSpecificCacheStorageSettings) -> AccountSpecificCacheStorageSettings) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Void in
transaction.updatePreferencesEntry(key: PreferencesKeys.accountSpecificCacheStorageSettings, { entry in
let currentSettings: AccountSpecificCacheStorageSettings
if let entry = entry?.get(AccountSpecificCacheStorageSettings.self) {
currentSettings = entry
} else {
currentSettings = AccountSpecificCacheStorageSettings.defaultSettings
}
return PreferencesEntry(f(currentSettings))
})
}
}
@@ -0,0 +1,20 @@
import Foundation
import Postbox
import SwiftSignalKit
import MtProtoKit
public func updateContentPrivacySettings(postbox: Postbox, _ f: @escaping (ContentPrivacySettings) -> ContentPrivacySettings) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Void in
var updated: ContentPrivacySettings?
transaction.updatePreferencesEntry(key: PreferencesKeys.contentPrivacySettings, { current in
if let current = current?.get(ContentPrivacySettings.self) {
updated = f(current)
return PreferencesEntry(updated)
} else {
updated = f(ContentPrivacySettings.defaultSettings)
return PreferencesEntry(updated)
}
})
}
}
@@ -0,0 +1,86 @@
import Foundation
import Postbox
import TelegramApi
import SwiftSignalKit
public struct ContentSettings: Equatable {
public static var `default` = ContentSettings(ignoreContentRestrictionReasons: [], addContentRestrictionReasons: [])
public var ignoreContentRestrictionReasons: Set<String>
public var addContentRestrictionReasons: [String]
public init(ignoreContentRestrictionReasons: Set<String>, addContentRestrictionReasons: [String]) {
self.ignoreContentRestrictionReasons = ignoreContentRestrictionReasons
self.addContentRestrictionReasons = addContentRestrictionReasons
}
}
extension ContentSettings {
init(appConfiguration: AppConfiguration) {
var reasons: [String] = []
var addContentRestrictionReasons: [String] = []
if let data = appConfiguration.data {
if let reasonsData = data["ignore_restriction_reasons"] as? [String] {
reasons = reasonsData
}
if let addContentRestrictionReasonsData = data["restriction_add_platforms"] as? [String] {
addContentRestrictionReasons = addContentRestrictionReasonsData
}
}
self.init(ignoreContentRestrictionReasons: Set(reasons), addContentRestrictionReasons: addContentRestrictionReasons)
}
}
public func getContentSettings(transaction: Transaction) -> ContentSettings {
let appConfiguration: AppConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
return ContentSettings(appConfiguration: appConfiguration)
}
public func getContentSettings(postbox: Postbox) -> Signal<ContentSettings, NoError> {
return postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|> map { view -> ContentSettings in
let appConfiguration: AppConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) ?? AppConfiguration.defaultValue
return ContentSettings(appConfiguration: appConfiguration)
}
|> distinctUntilChanged
}
public struct ContentSettingsConfiguration: Equatable {
public static var `default` = ContentSettingsConfiguration(sensitiveContentEnabled: false, canAdjustSensitiveContent: false)
public var sensitiveContentEnabled: Bool
public var canAdjustSensitiveContent: Bool
public init(sensitiveContentEnabled: Bool, canAdjustSensitiveContent: Bool) {
self.sensitiveContentEnabled = sensitiveContentEnabled
self.canAdjustSensitiveContent = canAdjustSensitiveContent
}
}
public func contentSettingsConfiguration(network: Network) -> Signal<ContentSettingsConfiguration, NoError> {
return network.request(Api.functions.account.getContentSettings())
|> map { result -> ContentSettingsConfiguration in
switch result {
case let .contentSettings(flags):
return ContentSettingsConfiguration(sensitiveContentEnabled: (flags & (1 << 0)) != 0, canAdjustSensitiveContent: (flags & (1 << 1)) != 0)
}
}
|> `catch` { _ -> Signal<ContentSettingsConfiguration, NoError> in
return .single(.default)
}
}
public func updateRemoteContentSettingsConfiguration(postbox: Postbox, network: Network, sensitiveContentEnabled: Bool) -> Signal<Never, NoError> {
var flags: Int32 = 0
if sensitiveContentEnabled {
flags |= 1 << 0
}
return network.request(Api.functions.account.setContentSettings(flags: flags))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> mapToSignal { _ -> Signal<Never, NoError> in
return updateAppConfigurationOnce(postbox: postbox, network: network)
|> ignoreValues
}
}
@@ -0,0 +1,53 @@
import Foundation
import Postbox
import TelegramApi
extension MessageNotificationSettings {
init(apiSettings: Api.PeerNotifySettings) {
switch apiSettings {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
let sound: Api.NotificationSound?
let storiesSound: Api.NotificationSound?
#if os(iOS)
sound = iosSound
storiesSound = storiesIosSound
#elseif os(macOS)
sound = desktopSound
storiesSound = storiesDesktopSound
#endif
let displayPreviews: Bool
if let showPreviews = showPreviews, case .boolFalse = showPreviews {
displayPreviews = false
} else {
displayPreviews = true
}
let storiesMutedValue: PeerStoryNotificationSettings.Mute
if let storiesMuted = storiesMuted {
storiesMutedValue = storiesMuted == .boolTrue ? .muted : .unmuted
} else {
storiesMutedValue = .default
}
var storiesHideSenderValue: PeerStoryNotificationSettings.HideSender
if let storiesHideSender = storiesHideSender {
storiesHideSenderValue = storiesHideSender == .boolTrue ? .hide : .show
} else {
storiesHideSenderValue = .default
}
self = MessageNotificationSettings(
enabled: muteUntil == 0,
displayPreviews: displayPreviews,
sound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault),
storySettings: PeerStoryNotificationSettings(
mute: storiesMutedValue,
hideSender: storiesHideSenderValue,
sound: PeerMessageSound(apiSound: sound ?? .notificationSoundDefault)
)
)
}
}
}
@@ -0,0 +1,17 @@
import Foundation
import Postbox
public func currentLimitsConfiguration(transaction: Transaction) -> LimitsConfiguration {
if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration)?.get(LimitsConfiguration.self) {
return entry
} else {
return LimitsConfiguration.defaultValue
}
}
func updateLimitsConfiguration(transaction: Transaction, configuration: LimitsConfiguration) {
if currentLimitsConfiguration(transaction: transaction) != configuration {
transaction.setPreferencesEntry(key: PreferencesKeys.limitsConfiguration, value: PreferencesEntry(configuration))
}
}
@@ -0,0 +1,25 @@
import Foundation
import Postbox
import SwiftSignalKit
import MtProtoKit
public func updateLoggingSettings(accountManager: AccountManager<TelegramAccountManagerTypes>, _ f: @escaping (LoggingSettings) -> LoggingSettings) -> Signal<Void, NoError> {
return accountManager.transaction { transaction -> Void in
var updated: LoggingSettings?
transaction.updateSharedData(SharedDataKeys.loggingSettings, { current in
if let current = current?.get(LoggingSettings.self) {
updated = f(current)
return PreferencesEntry(updated)
} else {
updated = f(LoggingSettings.defaultSettings)
return PreferencesEntry(updated)
}
})
if let updated = updated {
Logger.shared.logToFile = updated.logToFile
Logger.shared.logToConsole = updated.logToConsole
Logger.shared.redactSensitiveData = updated.redactSensitiveData
}
}
}
@@ -0,0 +1,40 @@
import Foundation
import Postbox
import SwiftSignalKit
import MtProtoKit
public func updateNetworkSettingsInteractively(postbox: Postbox, network: Network, _ f: @escaping (NetworkSettings) -> NetworkSettings) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Void in
updateNetworkSettingsInteractively(transaction: transaction, network: network, f)
}
}
extension NetworkSettings {
var mtNetworkSettings: MTNetworkSettings {
return MTNetworkSettings(reducedBackupDiscoveryTimeout: self.reducedBackupDiscoveryTimeout)
}
}
public func updateNetworkSettingsInteractively(transaction: Transaction, network: Network?, _ f: @escaping (NetworkSettings) -> NetworkSettings) {
var updateNetwork = false
var updatedSettings: NetworkSettings?
transaction.updatePreferencesEntry(key: PreferencesKeys.networkSettings, { current in
let previous = current?.get(NetworkSettings.self) ?? NetworkSettings.defaultSettings
let updated = f(previous)
updatedSettings = updated
if updated.reducedBackupDiscoveryTimeout != previous.reducedBackupDiscoveryTimeout {
updateNetwork = true
}
if updated.backupHostOverride != previous.backupHostOverride {
updateNetwork = true
}
return PreferencesEntry(updated)
})
if let network = network, updateNetwork, let updatedSettings = updatedSettings {
network.context.updateApiEnvironment { current in
return current?.withUpdatedNetworkSettings(updatedSettings.mtNetworkSettings)
}
}
}
@@ -0,0 +1,90 @@
import Foundation
import Postbox
import TelegramApi
import SwiftSignalKit
extension PeerStatusSettings {
init(apiSettings: Api.PeerSettings) {
switch apiSettings {
case let .peerSettings(flags, geoDistance, requestChatTitle, requestChatDate, businessBotId, businessBotManageUrl, chargePaidMessageStars, registrationMonth, phoneCountry, nameChangeDate, photoChangeDate):
var result = PeerStatusSettings.Flags()
if (flags & (1 << 1)) != 0 {
result.insert(.canAddContact)
}
if (flags & (1 << 0)) != 0 {
result.insert(.canReport)
}
if (flags & (1 << 2)) != 0 {
result.insert(.canBlock)
}
if (flags & (1 << 3)) != 0 {
result.insert(.canShareContact)
}
if (flags & (1 << 4)) != 0 {
result.insert(.addExceptionWhenAddingContact)
}
if (flags & (1 << 7)) != 0 {
result.insert(.autoArchived)
}
if (flags & (1 << 8)) != 0 {
result.insert(.suggestAddMembers)
}
var managingBot: ManagingBot?
if let businessBotId {
let businessBotPaused = (flags & (1 << 11)) != 0
let businessBotCanReply = (flags & (1 << 12)) != 0
managingBot = ManagingBot(
id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(businessBotId)),
manageUrl: businessBotManageUrl,
isPaused: businessBotPaused,
canReply: businessBotCanReply
)
}
self = PeerStatusSettings(
flags: result,
geoDistance: geoDistance,
requestChatTitle: requestChatTitle,
requestChatDate: requestChatDate,
requestChatIsChannel: (flags & (1 << 10)) != 0,
managingBot: managingBot,
paidMessageStars: chargePaidMessageStars.flatMap { StarsAmount(value: $0, nanos: 0) },
registrationDate: registrationMonth,
phoneCountry: phoneCountry,
nameChangeDate: nameChangeDate,
photoChangeDate: photoChangeDate
)
}
}
}
public func unarchiveAutomaticallyArchivedPeer(account: Account, peerId: PeerId) {
let _ = (account.postbox.transaction { transaction -> Void in
_internal_updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: .root)
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let currentData = current as? CachedUserData, let currentStatusSettings = currentData.peerStatusSettings {
var statusSettings = currentStatusSettings
statusSettings.flags.remove(.canBlock)
statusSettings.flags.remove(.canReport)
statusSettings.flags.remove(.autoArchived)
return currentData.withUpdatedPeerStatusSettings(statusSettings)
} else if let currentData = current as? CachedGroupData, let currentStatusSettings = currentData.peerStatusSettings {
var statusSettings = currentStatusSettings
statusSettings.flags.remove(.canReport)
statusSettings.flags.remove(.autoArchived)
return currentData.withUpdatedPeerStatusSettings(statusSettings)
} else if let currentData = current as? CachedChannelData, let currentStatusSettings = currentData.peerStatusSettings {
var statusSettings = currentStatusSettings
statusSettings.flags.remove(.canReport)
statusSettings.flags.remove(.autoArchived)
return currentData.withUpdatedPeerStatusSettings(statusSettings)
}else {
return current
}
})
}
|> deliverOnMainQueue).start()
let _ = _internal_updatePeerMuteSetting(account: account, peerId: peerId, threadId: nil, muteInterval: nil).start()
}
@@ -0,0 +1,446 @@
import Foundation
import Postbox
import TelegramApi
public final class SelectivePrivacyPeer: Equatable {
public let peer: Peer
public let participantCount: Int32?
public init(peer: Peer, participantCount: Int32?) {
self.peer = peer
self.participantCount = participantCount
}
public static func ==(lhs: SelectivePrivacyPeer, rhs: SelectivePrivacyPeer) -> Bool {
if !lhs.peer.isEqual(rhs.peer) {
return false
}
if lhs.participantCount != rhs.participantCount {
return false
}
return true
}
public var userCount: Int {
if let participantCount = self.participantCount {
return Int(participantCount)
} else if let group = self.peer as? TelegramGroup {
return group.participantCount
} else {
return 1
}
}
}
public enum SelectivePrivacySettings: Equatable {
case enableEveryone(disableFor: [PeerId: SelectivePrivacyPeer])
case enableContacts(enableFor: [PeerId: SelectivePrivacyPeer], disableFor: [PeerId: SelectivePrivacyPeer], enableForPremium: Bool, enableForBots: Bool)
case disableEveryone(enableFor: [PeerId: SelectivePrivacyPeer], enableForCloseFriends: Bool, enableForPremium: Bool, enableForBots: Bool)
public static func ==(lhs: SelectivePrivacySettings, rhs: SelectivePrivacySettings) -> Bool {
switch lhs {
case let .enableEveryone(disableFor):
if case .enableEveryone(disableFor) = rhs {
return true
} else {
return false
}
case let .enableContacts(enableFor, disableFor, enableForPremium, enableForBots):
if case .enableContacts(enableFor, disableFor, enableForPremium, enableForBots) = rhs {
return true
} else {
return false
}
case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, enableForBots):
if case .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, enableForBots) = rhs {
return true
} else {
return false
}
}
}
func withEnabledPeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, enableForBots):
return .disableEveryone(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots)
case let .enableContacts(enableFor, disableFor, enableForPremium, enableForBots):
return .enableContacts(enableFor: enableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), disableFor: disableFor, enableForPremium: enableForPremium, enableForBots: enableForBots)
case .enableEveryone:
return self
}
}
func withDisabledPeers(_ peers: [PeerId: SelectivePrivacyPeer]) -> SelectivePrivacySettings {
switch self {
case .disableEveryone:
return self
case let .enableContacts(enableFor, disableFor, enableForPremium, enableForBots):
return .enableContacts(enableFor: enableFor, disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }), enableForPremium: enableForPremium, enableForBots: enableForBots)
case let .enableEveryone(disableFor):
return .enableEveryone(disableFor: disableFor.merging(peers, uniquingKeysWith: { lhs, rhs in lhs }))
}
}
func withEnableForPremium(_ enableForPremium: Bool) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, enableForCloseFriends, _, enableForBots):
return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots)
case let .enableContacts(enableFor, disableFor, _, enableForBots):
return .enableContacts(enableFor: enableFor, disableFor: disableFor, enableForPremium: enableForPremium, enableForBots: enableForBots)
case .enableEveryone:
return self
}
}
func withEnableForCloseFriends(_ enableForCloseFriends: Bool) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, _, enableForPremium, enableForBots):
return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots)
case .enableContacts:
return self
case .enableEveryone:
return self
}
}
func withEnableForBots(_ enableForBots: Bool?) -> SelectivePrivacySettings {
switch self {
case let .disableEveryone(enableFor, enableForCloseFriends, enableForPremium, _):
return .disableEveryone(enableFor: enableFor, enableForCloseFriends: enableForCloseFriends, enableForPremium: enableForPremium, enableForBots: enableForBots == true)
case let .enableContacts(enableFor, disableFor, enableForPremium, _):
return .enableContacts(enableFor: enableFor, disableFor: disableFor, enableForPremium: enableForPremium, enableForBots: enableForBots == true)
case let .enableEveryone(disableFor):
return .enableEveryone(disableFor: disableFor)
}
}
}
public struct AccountPrivacySettings: Equatable {
public var presence: SelectivePrivacySettings
public var groupInvitations: SelectivePrivacySettings
public var voiceCalls: SelectivePrivacySettings
public var voiceCallsP2P: SelectivePrivacySettings
public var profilePhoto: SelectivePrivacySettings
public var forwards: SelectivePrivacySettings
public var phoneNumber: SelectivePrivacySettings
public var phoneDiscoveryEnabled: Bool
public var voiceMessages: SelectivePrivacySettings
public var bio: SelectivePrivacySettings
public var birthday: SelectivePrivacySettings
public var giftsAutoSave: SelectivePrivacySettings
public var noPaidMessages: SelectivePrivacySettings
public var savedMusic: SelectivePrivacySettings
public var globalSettings: GlobalPrivacySettings
public var accountRemovalTimeout: Int32
public var messageAutoremoveTimeout: Int32?
public init(presence: SelectivePrivacySettings, groupInvitations: SelectivePrivacySettings, voiceCalls: SelectivePrivacySettings, voiceCallsP2P: SelectivePrivacySettings, profilePhoto: SelectivePrivacySettings, forwards: SelectivePrivacySettings, phoneNumber: SelectivePrivacySettings, phoneDiscoveryEnabled: Bool, voiceMessages: SelectivePrivacySettings, bio: SelectivePrivacySettings, birthday: SelectivePrivacySettings, giftsAutoSave: SelectivePrivacySettings, noPaidMessages: SelectivePrivacySettings, savedMusic: SelectivePrivacySettings, globalSettings: GlobalPrivacySettings, accountRemovalTimeout: Int32, messageAutoremoveTimeout: Int32?) {
self.presence = presence
self.groupInvitations = groupInvitations
self.voiceCalls = voiceCalls
self.voiceCallsP2P = voiceCallsP2P
self.profilePhoto = profilePhoto
self.forwards = forwards
self.phoneNumber = phoneNumber
self.phoneDiscoveryEnabled = phoneDiscoveryEnabled
self.voiceMessages = voiceMessages
self.bio = bio
self.birthday = birthday
self.giftsAutoSave = giftsAutoSave
self.noPaidMessages = noPaidMessages
self.savedMusic = savedMusic
self.globalSettings = globalSettings
self.accountRemovalTimeout = accountRemovalTimeout
self.messageAutoremoveTimeout = messageAutoremoveTimeout
}
public static func ==(lhs: AccountPrivacySettings, rhs: AccountPrivacySettings) -> Bool {
if lhs.presence != rhs.presence {
return false
}
if lhs.groupInvitations != rhs.groupInvitations {
return false
}
if lhs.voiceCalls != rhs.voiceCalls {
return false
}
if lhs.voiceCallsP2P != rhs.voiceCallsP2P {
return false
}
if lhs.profilePhoto != rhs.profilePhoto {
return false
}
if lhs.forwards != rhs.forwards {
return false
}
if lhs.phoneNumber != rhs.phoneNumber {
return false
}
if lhs.phoneDiscoveryEnabled != rhs.phoneDiscoveryEnabled {
return false
}
if lhs.voiceMessages != rhs.voiceMessages {
return false
}
if lhs.bio != rhs.bio {
return false
}
if lhs.birthday != rhs.birthday {
return false
}
if lhs.giftsAutoSave != rhs.giftsAutoSave {
return false
}
if lhs.noPaidMessages != rhs.noPaidMessages {
return false
}
if lhs.savedMusic != rhs.savedMusic {
return false
}
if lhs.globalSettings != rhs.globalSettings {
return false
}
if lhs.accountRemovalTimeout != rhs.accountRemovalTimeout {
return false
}
if lhs.messageAutoremoveTimeout != rhs.messageAutoremoveTimeout {
return false
}
return true
}
}
extension SelectivePrivacySettings {
init(apiRules: [Api.PrivacyRule], peers: [PeerId: SelectivePrivacyPeer]) {
var current: SelectivePrivacySettings = .disableEveryone(enableFor: [:], enableForCloseFriends: false, enableForPremium: false, enableForBots: false)
var disableFor: [PeerId: SelectivePrivacyPeer] = [:]
var enableFor: [PeerId: SelectivePrivacyPeer] = [:]
var enableForCloseFriends: Bool = false
var enableForPremium: Bool = false
var enableForBots: Bool?
for rule in apiRules {
switch rule {
case .privacyValueAllowAll:
current = .enableEveryone(disableFor: [:])
case .privacyValueAllowContacts:
current = .enableContacts(enableFor: [:], disableFor: [:], enableForPremium: false, enableForBots: false)
case let .privacyValueAllowUsers(users):
for id in users {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] {
enableFor[peer.peer.id] = peer
}
}
case .privacyValueDisallowAll:
break
case .privacyValueDisallowContacts:
break
case let .privacyValueDisallowUsers(users):
for id in users {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id))] {
disableFor[peer.peer.id] = peer
}
}
case let .privacyValueAllowChatParticipants(chats):
for id in chats {
for possibleId in [PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))] {
if let peer = peers[possibleId] {
enableFor[peer.peer.id] = peer
}
}
}
case let .privacyValueDisallowChatParticipants(chats):
for id in chats {
for possibleId in [PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))] {
if let peer = peers[possibleId] {
disableFor[peer.peer.id] = peer
}
}
}
case .privacyValueAllowCloseFriends:
enableForCloseFriends = true
case .privacyValueAllowPremium:
enableForPremium = true
case .privacyValueAllowBots:
enableForBots = true
case .privacyValueDisallowBots:
break
}
}
self = current.withEnabledPeers(enableFor).withDisabledPeers(disableFor).withEnableForCloseFriends(enableForCloseFriends).withEnableForPremium(enableForPremium).withEnableForBots(enableForBots)
}
}
public struct GlobalMessageAutoremoveTimeoutSettings: Equatable, Codable {
public static var `default` = GlobalMessageAutoremoveTimeoutSettings(
messageAutoremoveTimeout: nil
)
public var messageAutoremoveTimeout: Int32?
public init(messageAutoremoveTimeout: Int32?) {
self.messageAutoremoveTimeout = messageAutoremoveTimeout
}
}
func updateGlobalMessageAutoremoveTimeoutSettings(transaction: Transaction, _ f: (GlobalMessageAutoremoveTimeoutSettings) -> GlobalMessageAutoremoveTimeoutSettings) {
transaction.updatePreferencesEntry(key: PreferencesKeys.globalMessageAutoremoveTimeoutSettings, { current in
let previous = current?.get(GlobalMessageAutoremoveTimeoutSettings.self) ?? GlobalMessageAutoremoveTimeoutSettings.default
let updated = f(previous)
return PreferencesEntry(updated)
})
}
public struct TelegramDisallowedGifts: OptionSet, Codable {
public var rawValue: Int32
public init() {
self.rawValue = 0
}
public init(rawValue: Int32) {
self.rawValue = rawValue
}
public static let unlimited = TelegramDisallowedGifts(rawValue: 1 << 0)
public static let limited = TelegramDisallowedGifts(rawValue: 1 << 1)
public static let unique = TelegramDisallowedGifts(rawValue: 1 << 2)
public static let premium = TelegramDisallowedGifts(rawValue: 1 << 3)
public static let channel = TelegramDisallowedGifts(rawValue: 1 << 4)
public static let All: TelegramDisallowedGifts = [
.unlimited,
.limited,
.unique,
.premium
]
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
let value = try? container.decode(Int32.self, forKey: "v")
self = TelegramDisallowedGifts(rawValue: value ?? 0)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.rawValue, forKey: "v")
}
}
extension TelegramDisallowedGifts {
init(apiDisallowedGifts: Api.DisallowedGiftsSettings?) {
var disallowedGifts: TelegramDisallowedGifts = []
switch apiDisallowedGifts {
case let .disallowedGiftsSettings(giftFlags):
if (giftFlags & (1 << 0)) != 0 {
disallowedGifts.insert(.unlimited)
}
if (giftFlags & (1 << 1)) != 0 {
disallowedGifts.insert(.limited)
}
if (giftFlags & (1 << 2)) != 0 {
disallowedGifts.insert(.unique)
}
if (giftFlags & (1 << 3)) != 0 {
disallowedGifts.insert(.premium)
}
if (giftFlags & (1 << 4)) != 0 {
disallowedGifts.insert(.channel)
}
default:
break
}
self = disallowedGifts
}
}
public struct GlobalPrivacySettings: Equatable, Codable {
public enum NonContactChatsPrivacy: Equatable, Codable {
case everybody
case requirePremium
case paidMessages(StarsAmount)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
switch (try? container.decode(Int32.self, forKey: "t")) ?? 0 {
case 0:
self = .everybody
case 1:
self = .requirePremium
case 2:
self = .paidMessages(StarsAmount(value: try container.decodeIfPresent(Int64.self, forKey: "stars") ?? 0, nanos: 0))
default:
assertionFailure()
self = .everybody
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
switch self {
case .everybody:
try container.encode(0 as Int32, forKey: "t")
case .requirePremium:
try container.encode(1 as Int32, forKey: "t")
case let .paidMessages(amount):
try container.encode(2 as Int32, forKey: "t")
try container.encode(amount.value, forKey: "stars")
}
}
}
public static var `default` = GlobalPrivacySettings(
automaticallyArchiveAndMuteNonContacts: false,
keepArchivedUnmuted: true,
keepArchivedFolders: true,
hideReadTime: false,
nonContactChatsPrivacy: .everybody,
disallowedGifts: [],
displayGiftButton: false
)
public var automaticallyArchiveAndMuteNonContacts: Bool
public var keepArchivedUnmuted: Bool
public var keepArchivedFolders: Bool
public var hideReadTime: Bool
public var nonContactChatsPrivacy: NonContactChatsPrivacy
public var disallowedGifts: TelegramDisallowedGifts
public var displayGiftButton: Bool
public init(
automaticallyArchiveAndMuteNonContacts: Bool,
keepArchivedUnmuted: Bool,
keepArchivedFolders: Bool,
hideReadTime: Bool,
nonContactChatsPrivacy: NonContactChatsPrivacy,
disallowedGifts: TelegramDisallowedGifts,
displayGiftButton: Bool
) {
self.automaticallyArchiveAndMuteNonContacts = automaticallyArchiveAndMuteNonContacts
self.keepArchivedUnmuted = keepArchivedUnmuted
self.keepArchivedFolders = keepArchivedFolders
self.hideReadTime = hideReadTime
self.nonContactChatsPrivacy = nonContactChatsPrivacy
self.disallowedGifts = disallowedGifts
self.displayGiftButton = displayGiftButton
}
}
func fetchGlobalPrivacySettings(transaction: Transaction) -> GlobalPrivacySettings {
return transaction.getPreferencesEntry(key: PreferencesKeys.globalPrivacySettings)?.get(GlobalPrivacySettings.self) ?? GlobalPrivacySettings.default
}
func updateGlobalPrivacySettings(transaction: Transaction, _ f: (GlobalPrivacySettings) -> GlobalPrivacySettings) {
transaction.updatePreferencesEntry(key: PreferencesKeys.globalPrivacySettings, { current in
let previous = current?.get(GlobalPrivacySettings.self) ?? GlobalPrivacySettings.default
let updated = f(previous)
return PreferencesEntry(updated)
})
}
@@ -0,0 +1,32 @@
import Foundation
import Postbox
import SwiftSignalKit
import MtProtoKit
public func updateProxySettingsInteractively(accountManager: AccountManager<TelegramAccountManagerTypes>, _ f: @escaping (ProxySettings) -> ProxySettings) -> Signal<Bool, NoError> {
return accountManager.transaction { transaction -> Bool in
return updateProxySettingsInteractively(transaction: transaction, f)
}
}
extension ProxyServerSettings {
var mtProxySettings: MTSocksProxySettings {
switch self.connection {
case let .socks5(username, password):
return MTSocksProxySettings(ip: self.host, port: UInt16(clamping: self.port), username: username, password: password, secret: nil)
case let .mtp(secret):
return MTSocksProxySettings(ip: self.host, port: UInt16(clamping: self.port), username: nil, password: nil, secret: secret)
}
}
}
public func updateProxySettingsInteractively(transaction: AccountManagerModifier<TelegramAccountManagerTypes>, _ f: @escaping (ProxySettings) -> ProxySettings) -> Bool {
var hasChanges = false
transaction.updateSharedData(SharedDataKeys.proxySettings, { current in
let previous = current?.get(ProxySettings.self) ?? ProxySettings.defaultSettings
let updated = f(previous)
hasChanges = previous != updated
return PreferencesEntry(updated)
})
return hasChanges
}
@@ -0,0 +1,44 @@
import Postbox
import SwiftSignalKit
public struct ReactionSettings: Equatable, Codable {
public static var `default` = ReactionSettings(quickReaction: .builtin("👍"))
public var quickReaction: MessageReaction.Reaction
public init(quickReaction: MessageReaction.Reaction) {
self.quickReaction = quickReaction
}
}
public extension ReactionSettings {
func effectiveQuickReaction(hasPremium: Bool) -> MessageReaction.Reaction {
switch self.quickReaction {
case .builtin:
return self.quickReaction
case .custom:
if hasPremium {
return self.quickReaction
} else {
return ReactionSettings.default.quickReaction
}
case .stars:
return self.quickReaction
}
}
}
func updateReactionSettings(transaction: Transaction, _ f: (ReactionSettings) -> ReactionSettings) {
transaction.updatePreferencesEntry(key: PreferencesKeys.reactionSettings, { current in
let previous = current?.get(ReactionSettings.self) ?? ReactionSettings.default
let updated = f(previous)
return PreferencesEntry(updated)
})
}
public func updateReactionSettingsInteractively(postbox: Postbox, _ f: @escaping (ReactionSettings) -> ReactionSettings) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Void in
updateReactionSettings(transaction: transaction, f)
}
|> ignoreValues
}
@@ -0,0 +1,17 @@
import Postbox
public func currentVoipConfiguration(transaction: Transaction) -> VoipConfiguration {
if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.voipConfiguration)?.get(VoipConfiguration.self) {
return entry
} else {
return VoipConfiguration.defaultValue
}
}
func updateVoipConfiguration(transaction: Transaction, _ f: (VoipConfiguration) -> VoipConfiguration) {
let current = currentVoipConfiguration(transaction: transaction)
let updated = f(current)
if updated != current {
transaction.setPreferencesEntry(key: PreferencesKeys.voipConfiguration, value: PreferencesEntry(updated))
}
}