mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
158 lines
9.1 KiB
Swift
158 lines
9.1 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Postbox
|
|
import TelegramCore
|
|
import SwiftSignalKit
|
|
import TelegramPresentationData
|
|
import TelegramUIPreferences
|
|
import MediaResources
|
|
import WallpaperResources
|
|
import AccountContext
|
|
|
|
private final class ThemeUpdateManagerContext {
|
|
let themeReference: PresentationThemeReference
|
|
private let disposable: Disposable
|
|
let isAutoNight: Bool
|
|
|
|
init(themeReference: PresentationThemeReference, disposable: Disposable, isAutoNight: Bool) {
|
|
self.themeReference = themeReference
|
|
self.disposable = disposable
|
|
self.isAutoNight = isAutoNight
|
|
}
|
|
|
|
deinit {
|
|
self.disposable.dispose()
|
|
}
|
|
}
|
|
|
|
final class ThemeUpdateManagerImpl: ThemeUpdateManager {
|
|
private let sharedContext: SharedAccountContext
|
|
private let account: Account
|
|
private var contexts: [Int64: ThemeUpdateManagerContext] = [:]
|
|
private let queue = Queue()
|
|
|
|
private var disposable: Disposable?
|
|
private var currentThemeSettings: PresentationThemeSettings?
|
|
|
|
init(sharedContext: SharedAccountContext, account: Account) {
|
|
self.sharedContext = sharedContext
|
|
self.account = account
|
|
|
|
self.disposable = (sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings])
|
|
|> map { sharedData -> PresentationThemeSettings in
|
|
return sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings]?.get(PresentationThemeSettings.self) ?? PresentationThemeSettings.defaultSettings
|
|
}
|
|
|> deliverOn(queue)).start(next: { [weak self] themeSettings in
|
|
self?.presentationThemeSettingsUpdated(themeSettings)
|
|
})
|
|
}
|
|
|
|
deinit {
|
|
self.disposable?.dispose()
|
|
}
|
|
|
|
private func presentationThemeSettingsUpdated(_ themeSettings: PresentationThemeSettings) {
|
|
let previousThemeSettings = self.currentThemeSettings
|
|
self.currentThemeSettings = themeSettings
|
|
|
|
var previousIds = Set<Int64>()
|
|
if let previousThemeSettings = previousThemeSettings {
|
|
previousIds.insert(previousThemeSettings.theme.index)
|
|
}
|
|
|
|
var validIds = Set<Int64>()
|
|
var themes: [Int64: (PresentationThemeReference, Bool)] = [:]
|
|
if case .cloud = themeSettings.theme {
|
|
validIds.insert(themeSettings.theme.index)
|
|
themes[themeSettings.theme.index] = (themeSettings.theme, false)
|
|
}
|
|
if case .cloud = themeSettings.automaticThemeSwitchSetting.theme, themeSettings.automaticThemeSwitchSetting.trigger != .explicitNone {
|
|
validIds.insert(themeSettings.automaticThemeSwitchSetting.theme.index)
|
|
themes[themeSettings.automaticThemeSwitchSetting.theme.index] = (themeSettings.automaticThemeSwitchSetting.theme, true)
|
|
}
|
|
|
|
if previousIds != validIds {
|
|
for id in validIds {
|
|
if let _ = self.contexts[id] {
|
|
} else if let (theme, isAutoNight) = themes[id], case let .cloud(info) = theme {
|
|
var currentTheme = theme
|
|
let account = self.account
|
|
let accountManager = self.sharedContext.accountManager
|
|
let disposable = (actualizedTheme(account: account, accountManager: accountManager, theme: info.theme)
|
|
|> mapToSignal { theme -> Signal<(PresentationThemeReference, PresentationTheme?), NoError> in
|
|
guard let file = theme.file else {
|
|
return .complete()
|
|
}
|
|
return telegramThemeData(account: account, accountManager: accountManager, reference: .standalone(resource: file.resource))
|
|
|> mapToSignal { data -> Signal<(PresentationThemeReference, PresentationTheme?), NoError> in
|
|
guard let data = data, let presentationTheme = makePresentationTheme(data: data) else {
|
|
return .complete()
|
|
}
|
|
|
|
let resolvedWallpaper: Signal<TelegramWallpaper?, NoError>
|
|
if case let .file(file) = presentationTheme.chat.defaultWallpaper, file.id == 0 {
|
|
resolvedWallpaper = cachedWallpaper(account: account, slug: file.slug, settings: file.settings)
|
|
|> map { wallpaper in
|
|
return wallpaper?.wallpaper
|
|
}
|
|
} else {
|
|
resolvedWallpaper = .single(nil)
|
|
}
|
|
|
|
return resolvedWallpaper
|
|
|> mapToSignal { wallpaper -> Signal<(PresentationThemeReference, PresentationTheme?), NoError> in
|
|
if let wallpaper = wallpaper, case let .file(file) = wallpaper {
|
|
var convertedRepresentations: [ImageRepresentationWithReference] = []
|
|
convertedRepresentations.append(ImageRepresentationWithReference(representation: TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 100, height: 100), resource: file.file.resource, progressiveSizes: [], immediateThumbnailData: nil), reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource)))
|
|
return wallpaperDatas(account: account, accountManager: accountManager, fileReference: .standalone(media: file.file), representations: convertedRepresentations, alwaysShowThumbnailFirst: false, thumbnail: false, onlyFullSize: true, autoFetchFullSize: true, synchronousLoad: false)
|
|
|> mapToSignal { _, fullSizeData, complete -> Signal<(PresentationThemeReference, PresentationTheme?), NoError> in
|
|
guard complete, let fullSizeData = fullSizeData else {
|
|
return .complete()
|
|
}
|
|
accountManager.mediaBox.storeResourceData(file.file.resource.id, data: fullSizeData, synchronous: true)
|
|
return .single((.cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: wallpaper, creatorAccountId: theme.isCreator ? account.id : nil)), presentationTheme))
|
|
}
|
|
} else {
|
|
return .single((.cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: theme.isCreator ? account.id : nil)), presentationTheme))
|
|
}
|
|
}
|
|
}
|
|
}).start(next: { updatedTheme, presentationTheme in
|
|
if updatedTheme != currentTheme {
|
|
currentTheme = updatedTheme
|
|
|
|
let _ = (accountManager.transaction { transaction -> Void in
|
|
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings, { entry in
|
|
let current: PresentationThemeSettings
|
|
if let entry = entry?.get(PresentationThemeSettings.self) {
|
|
current = entry
|
|
} else {
|
|
current = PresentationThemeSettings.defaultSettings
|
|
}
|
|
|
|
var theme = current.theme
|
|
var automaticThemeSwitchSetting = current.automaticThemeSwitchSetting
|
|
if isAutoNight {
|
|
automaticThemeSwitchSetting.theme = updatedTheme
|
|
} else {
|
|
theme = updatedTheme
|
|
}
|
|
|
|
return PreferencesEntry(PresentationThemeSettings(theme: theme, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion))
|
|
})
|
|
}).start()
|
|
}
|
|
})
|
|
self.contexts[id] = ThemeUpdateManagerContext(themeReference: theme, disposable: disposable, isAutoNight: isAutoNight)
|
|
}
|
|
}
|
|
|
|
for id in previousIds {
|
|
if !validIds.contains(id) {
|
|
self.contexts[id] = nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|