Swiftgram/TelegramUI/AutomaticMediaDownloadSettings.swift
2018-06-16 20:03:02 +03:00

232 lines
11 KiB
Swift

import Foundation
import Postbox
import SwiftSignalKit
import TelegramCore
public struct AutomaticMediaDownloadCategory: PostboxCoding, Equatable {
public var cellular: Bool
public var wifi: Bool
public var sizeLimit: Int32
public init(cellular: Bool, wifi: Bool, sizeLimit: Int32) {
self.cellular = cellular
self.wifi = wifi
self.sizeLimit = sizeLimit
}
public init(decoder: PostboxDecoder) {
self.cellular = decoder.decodeInt32ForKey("cellular", orElse: 0) != 0
self.wifi = decoder.decodeInt32ForKey("wifi", orElse: 0) != 0
self.sizeLimit = decoder.decodeInt32ForKey("sizeLimit", orElse: 0)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt32(self.cellular ? 1 : 0, forKey: "cellular")
encoder.encodeInt32(self.wifi ? 1 : 0, forKey: "wifi")
encoder.encodeInt32(self.sizeLimit, forKey: "sizeLimit")
}
}
public struct AutomaticMediaDownloadCategories: Equatable, PostboxCoding {
public var photo: AutomaticMediaDownloadCategory
public var video: AutomaticMediaDownloadCategory
public var file: AutomaticMediaDownloadCategory
public var voiceMessage: AutomaticMediaDownloadCategory
public var videoMessage: AutomaticMediaDownloadCategory
public init(photo: AutomaticMediaDownloadCategory, video: AutomaticMediaDownloadCategory, file: AutomaticMediaDownloadCategory, voiceMessage: AutomaticMediaDownloadCategory, videoMessage: AutomaticMediaDownloadCategory) {
self.photo = photo
self.video = video
self.file = file
self.voiceMessage = voiceMessage
self.videoMessage = videoMessage
}
public init(decoder: PostboxDecoder) {
self.photo = decoder.decodeObjectForKey("photo", decoder: AutomaticMediaDownloadCategory.init(decoder:)) as! AutomaticMediaDownloadCategory
self.video = decoder.decodeObjectForKey("video", decoder: AutomaticMediaDownloadCategory.init(decoder:)) as! AutomaticMediaDownloadCategory
self.file = decoder.decodeObjectForKey("file", decoder: AutomaticMediaDownloadCategory.init(decoder:)) as! AutomaticMediaDownloadCategory
self.voiceMessage = decoder.decodeObjectForKey("voiceMessage", decoder: AutomaticMediaDownloadCategory.init(decoder:)) as! AutomaticMediaDownloadCategory
self.videoMessage = decoder.decodeObjectForKey("videoMessage", decoder: AutomaticMediaDownloadCategory.init(decoder:)) as! AutomaticMediaDownloadCategory
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(self.photo, forKey: "photo")
encoder.encodeObject(self.video, forKey: "video")
encoder.encodeObject(self.file, forKey: "file")
encoder.encodeObject(self.voiceMessage, forKey: "voiceMessage")
encoder.encodeObject(self.videoMessage, forKey: "videoMessage")
}
}
public struct AutomaticMediaDownloadPeers: Equatable, PostboxCoding {
public var contacts: AutomaticMediaDownloadCategories
public var otherPrivate: AutomaticMediaDownloadCategories
public var groups: AutomaticMediaDownloadCategories
public var channels: AutomaticMediaDownloadCategories
public init(contacts: AutomaticMediaDownloadCategories, otherPrivate: AutomaticMediaDownloadCategories, groups: AutomaticMediaDownloadCategories, channels: AutomaticMediaDownloadCategories) {
self.contacts = contacts
self.otherPrivate = otherPrivate
self.groups = groups
self.channels = channels
}
public init(decoder: PostboxDecoder) {
self.contacts = decoder.decodeObjectForKey("contacts", decoder: AutomaticMediaDownloadCategories.init(decoder:)) as! AutomaticMediaDownloadCategories
self.otherPrivate = decoder.decodeObjectForKey("otherPrivate", decoder: AutomaticMediaDownloadCategories.init(decoder:)) as! AutomaticMediaDownloadCategories
self.groups = decoder.decodeObjectForKey("groups", decoder: AutomaticMediaDownloadCategories.init(decoder:)) as! AutomaticMediaDownloadCategories
self.channels = decoder.decodeObjectForKey("channels", decoder: AutomaticMediaDownloadCategories.init(decoder:)) as! AutomaticMediaDownloadCategories
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(self.contacts, forKey: "contacts")
encoder.encodeObject(self.otherPrivate, forKey: "otherPrivate")
encoder.encodeObject(self.groups, forKey: "groups")
encoder.encodeObject(self.channels, forKey: "channels")
}
}
public struct AutomaticMediaDownloadSettings: PreferencesEntry, Equatable {
public var masterEnabled: Bool
public var peers: AutomaticMediaDownloadPeers
public var autoplayGifs: Bool
public var saveIncomingPhotos: Bool
public static var defaultSettings: AutomaticMediaDownloadSettings {
let defaultCategory = AutomaticMediaDownloadCategories(
photo: AutomaticMediaDownloadCategory(cellular: true, wifi: true, sizeLimit: Int32.max),
video: AutomaticMediaDownloadCategory(cellular: false, wifi: false, sizeLimit: 1 * 1024 * 1024),
file: AutomaticMediaDownloadCategory(cellular: false, wifi: false, sizeLimit: 1 * 1024 * 1024),
voiceMessage: AutomaticMediaDownloadCategory(cellular: true, wifi: true, sizeLimit: Int32.max),
videoMessage: AutomaticMediaDownloadCategory(cellular: false, wifi: false, sizeLimit: Int32.max)
)
return AutomaticMediaDownloadSettings(masterEnabled: true, peers: AutomaticMediaDownloadPeers(
contacts: defaultCategory,
otherPrivate: defaultCategory,
groups: defaultCategory,
channels: defaultCategory
), autoplayGifs: true, saveIncomingPhotos: false)
}
init(masterEnabled: Bool, peers: AutomaticMediaDownloadPeers, autoplayGifs: Bool, saveIncomingPhotos: Bool) {
self.masterEnabled = masterEnabled
self.peers = peers
self.autoplayGifs = autoplayGifs
self.saveIncomingPhotos = saveIncomingPhotos
}
public init(decoder: PostboxDecoder) {
self.masterEnabled = decoder.decodeInt32ForKey("masterEnabled", orElse: 1) != 0
self.peers = (decoder.decodeObjectForKey("peers", decoder: AutomaticMediaDownloadPeers.init(decoder:)) as? AutomaticMediaDownloadPeers) ?? AutomaticMediaDownloadSettings.defaultSettings.peers
self.autoplayGifs = decoder.decodeInt32ForKey("autoplayGifs", orElse: 1) != 0
self.saveIncomingPhotos = decoder.decodeInt32ForKey("siph", orElse: 0) != 0
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt32(self.masterEnabled ? 1 : 0, forKey: "masterEnabled")
encoder.encodeObject(self.peers, forKey: "peers")
encoder.encodeInt32(self.autoplayGifs ? 1 : 0, forKey: "autoplayGifs")
encoder.encodeInt32(self.saveIncomingPhotos ? 1 : 0, forKey: "siph")
}
public func isEqual(to: PreferencesEntry) -> Bool {
if let to = to as? AutomaticMediaDownloadSettings {
return self == to
} else {
return false
}
}
}
public func updatedAutomaticMediaDownloadSettings(postbox: Postbox) -> Signal<AutomaticMediaDownloadSettings, NoError> {
return postbox.preferencesView(keys: [ApplicationSpecificPreferencesKeys.automaticMediaDownloadSettings])
|> map { view -> AutomaticMediaDownloadSettings in
let automaticMediaDownloadSettings: AutomaticMediaDownloadSettings
if let value = view.values[ApplicationSpecificPreferencesKeys.automaticMediaDownloadSettings] as? AutomaticMediaDownloadSettings {
automaticMediaDownloadSettings = value
} else {
automaticMediaDownloadSettings = AutomaticMediaDownloadSettings.defaultSettings
}
return automaticMediaDownloadSettings
}
}
func updateMediaDownloadSettingsInteractively(postbox: Postbox, _ f: @escaping (AutomaticMediaDownloadSettings) -> AutomaticMediaDownloadSettings) -> Signal<Void, NoError> {
return postbox.transaction { transaction -> Void in
transaction.updatePreferencesEntry(key: ApplicationSpecificPreferencesKeys.automaticMediaDownloadSettings, { entry in
let currentSettings: AutomaticMediaDownloadSettings
if let entry = entry as? AutomaticMediaDownloadSettings {
currentSettings = entry
} else {
currentSettings = AutomaticMediaDownloadSettings.defaultSettings
}
let updated = f(currentSettings)
return updated
})
}
}
private func categoriesForPeer(_ peer: Peer, settings: AutomaticMediaDownloadSettings) -> AutomaticMediaDownloadCategories {
if let _ = peer as? TelegramUser {
return settings.peers.contacts
} else if let _ = peer as? TelegramSecretChat {
return settings.peers.contacts
} else if let channel = peer as? TelegramChannel {
if case .broadcast = channel.info {
return settings.peers.channels
} else {
return settings.peers.groups
}
} else {
return settings.peers.channels
}
}
private func categoryForPeerAndMedia(settings: AutomaticMediaDownloadSettings, peer: Peer, media: Media) -> (AutomaticMediaDownloadCategory, Int32?)? {
let categories = categoriesForPeer(peer, settings: settings)
if let _ = media as? TelegramMediaImage {
return (categories.photo, nil)
} else if let file = media as? TelegramMediaFile {
for attribute in file.attributes {
switch attribute {
case let .Video(_, _, flags):
if flags.contains(.instantRoundVideo) {
return (categories.videoMessage, file.size.flatMap(Int32.init))
} else {
return (categories.video, file.size.flatMap(Int32.init))
}
case let .Audio(isVoice, _, _, _, _):
if isVoice {
return (categories.voiceMessage, file.size.flatMap(Int32.init))
}
default:
break
}
}
return (categories.file, file.size.flatMap(Int32.init))
} else {
return nil
}
}
public func shouldDownloadMediaAutomatically(settings: AutomaticMediaDownloadSettings, peer: Peer?, media: Media) -> Bool {
if !settings.masterEnabled {
return false
}
guard let peer = peer else {
return false
}
if let (category, size) = categoryForPeerAndMedia(settings: settings, peer: peer, media: media) {
if let size = size {
return category.cellular && size <= category.sizeLimit
} else if category.sizeLimit == Int32.max {
return category.cellular
} else {
return false
}
} else {
return false
}
}