mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
Theme file reference invalidation
This commit is contained in:
parent
2f1e573cbf
commit
f13301f7d0
@ -90,7 +90,7 @@ public final class ThemePreviewController: ViewController {
|
|||||||
self.theme.get()
|
self.theme.get()
|
||||||
|> mapToSignal { theme in
|
|> mapToSignal { theme in
|
||||||
if let file = theme?.file {
|
if let file = theme?.file {
|
||||||
return telegramThemeData(account: context.account, accountManager: context.sharedContext.accountManager, resource: file.resource)
|
return telegramThemeData(account: context.account, accountManager: context.sharedContext.accountManager, reference: .standalone(resource: file.resource))
|
||||||
|> mapToSignal { data -> Signal<PresentationTheme, NoError> in
|
|> mapToSignal { data -> Signal<PresentationTheme, NoError> in
|
||||||
guard let data = data, let presentationTheme = makePresentationTheme(data: data) else {
|
guard let data = data, let presentationTheme = makePresentationTheme(data: data) else {
|
||||||
return .complete()
|
return .complete()
|
||||||
|
|||||||
@ -142,6 +142,39 @@ public enum WebpageReferenceContent: PostboxCoding, Hashable, Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ThemeReference: PostboxCoding, Hashable, Equatable {
|
||||||
|
case slug(String)
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
switch decoder.decodeInt32ForKey("r", orElse: 0) {
|
||||||
|
case 0:
|
||||||
|
self = .slug(decoder.decodeStringForKey("s", orElse: ""))
|
||||||
|
default:
|
||||||
|
self = .slug("")
|
||||||
|
assertionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
switch self {
|
||||||
|
case let .slug(slug):
|
||||||
|
encoder.encodeInt32(0, forKey: "r")
|
||||||
|
encoder.encodeString(slug, forKey: "s")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: ThemeReference, rhs: ThemeReference) -> Bool {
|
||||||
|
switch lhs {
|
||||||
|
case let .slug(slug):
|
||||||
|
if case .slug(slug) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum AnyMediaReference: Equatable {
|
public enum AnyMediaReference: Equatable {
|
||||||
case standalone(media: Media)
|
case standalone(media: Media)
|
||||||
case message(message: MessageReference, media: Media)
|
case message(message: MessageReference, media: Media)
|
||||||
@ -430,6 +463,7 @@ public enum MediaResourceReference: Equatable {
|
|||||||
case messageAuthorAvatar(message: MessageReference, resource: MediaResource)
|
case messageAuthorAvatar(message: MessageReference, resource: MediaResource)
|
||||||
case wallpaper(resource: MediaResource)
|
case wallpaper(resource: MediaResource)
|
||||||
case stickerPackThumbnail(stickerPack: StickerPackReference, resource: MediaResource)
|
case stickerPackThumbnail(stickerPack: StickerPackReference, resource: MediaResource)
|
||||||
|
case theme(theme: ThemeReference, resource: MediaResource)
|
||||||
|
|
||||||
public var resource: MediaResource {
|
public var resource: MediaResource {
|
||||||
switch self {
|
switch self {
|
||||||
@ -445,6 +479,8 @@ public enum MediaResourceReference: Equatable {
|
|||||||
return resource
|
return resource
|
||||||
case let .stickerPackThumbnail(_, resource):
|
case let .stickerPackThumbnail(_, resource):
|
||||||
return resource
|
return resource
|
||||||
|
case let .theme(_, resource):
|
||||||
|
return resource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,6 +522,12 @@ public enum MediaResourceReference: Equatable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case let .theme(lhsTheme, lhsResource):
|
||||||
|
if case let .theme(rhsTheme, rhsResource) = rhs, lhsTheme == rhsTheme, lhsResource.isEqual(to: rhsResource) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,6 +141,7 @@ private enum MediaReferenceRevalidationKey: Hashable {
|
|||||||
case savedGifs
|
case savedGifs
|
||||||
case peer(peer: PeerReference)
|
case peer(peer: PeerReference)
|
||||||
case wallpapers
|
case wallpapers
|
||||||
|
case themes
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class MediaReferenceRevalidationItemContext {
|
private final class MediaReferenceRevalidationItemContext {
|
||||||
@ -402,6 +403,26 @@ final class MediaReferenceRevalidationContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func themes(postbox: Postbox, network: Network, background: Bool) -> Signal<[TelegramTheme], RevalidateMediaReferenceError> {
|
||||||
|
return self.genericItem(key: .themes, background: background, request: { next, error in
|
||||||
|
return (telegramThemes(postbox: postbox, network: network, accountManager: nil, forceUpdate: true)
|
||||||
|
|> take(1)
|
||||||
|
|> mapError { _ -> RevalidateMediaReferenceError in
|
||||||
|
return .generic
|
||||||
|
}).start(next: { value in
|
||||||
|
next(value)
|
||||||
|
}, error: { _ in
|
||||||
|
error(.generic)
|
||||||
|
})
|
||||||
|
}) |> mapToSignal { next -> Signal<[TelegramTheme], RevalidateMediaReferenceError> in
|
||||||
|
if let next = next as? [TelegramTheme] {
|
||||||
|
return .single(next)
|
||||||
|
} else {
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RevalidatedMediaResource {
|
struct RevalidatedMediaResource {
|
||||||
@ -586,6 +607,16 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
|||||||
}
|
}
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
|
case let .theme(themeReference, resource):
|
||||||
|
return revalidationContext.themes(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation)
|
||||||
|
|> mapToSignal { themes -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||||
|
for theme in themes {
|
||||||
|
if let file = theme.file, file.resource.id.isEqual(to: resource.id) {
|
||||||
|
return .single(RevalidatedMediaResource(updatedResource: file.resource, updatedReference: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .fail(.generic)
|
||||||
|
}
|
||||||
case .standalone:
|
case .standalone:
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ let telegramThemeFormat = "ios"
|
|||||||
let telegramThemeFileExtension = "tgios-theme"
|
let telegramThemeFileExtension = "tgios-theme"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public func telegramThemes(postbox: Postbox, network: Network, accountManager: AccountManager, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> {
|
public func telegramThemes(postbox: Postbox, network: Network, accountManager: AccountManager?, forceUpdate: Bool = false) -> Signal<[TelegramTheme], NoError> {
|
||||||
let fetch: ([TelegramTheme]?, Int32?) -> Signal<[TelegramTheme], NoError> = { current, hash in
|
let fetch: ([TelegramTheme]?, Int32?) -> Signal<[TelegramTheme], NoError> = { current, hash in
|
||||||
network.request(Api.functions.account.getThemes(format: telegramThemeFormat, hash: hash ?? 0))
|
network.request(Api.functions.account.getThemes(format: telegramThemeFormat, hash: hash ?? 0))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
@ -31,18 +31,20 @@ public func telegramThemes(postbox: Postbox, network: Network, accountManager: A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|> mapToSignal { items, hash -> Signal<[TelegramTheme], NoError> in
|
|> mapToSignal { items, hash -> Signal<[TelegramTheme], NoError> in
|
||||||
let _ = accountManager.transaction { transaction in
|
if let accountManager = accountManager {
|
||||||
transaction.updateSharedData(SharedDataKeys.themeSettings, { current in
|
let _ = accountManager.transaction { transaction in
|
||||||
var updated = current as? ThemeSettings ?? ThemeSettings(currentTheme: nil)
|
transaction.updateSharedData(SharedDataKeys.themeSettings, { current in
|
||||||
for theme in items {
|
var updated = current as? ThemeSettings ?? ThemeSettings(currentTheme: nil)
|
||||||
if theme.id == updated.currentTheme?.id {
|
for theme in items {
|
||||||
updated = ThemeSettings(currentTheme: theme)
|
if theme.id == updated.currentTheme?.id {
|
||||||
break
|
updated = ThemeSettings(currentTheme: theme)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return updated
|
||||||
return updated
|
})
|
||||||
})
|
}.start()
|
||||||
}.start()
|
}
|
||||||
|
|
||||||
return postbox.transaction { transaction -> [TelegramTheme] in
|
return postbox.transaction { transaction -> [TelegramTheme] in
|
||||||
var entries: [OrderedItemListEntry] = []
|
var entries: [OrderedItemListEntry] = []
|
||||||
|
|||||||
@ -84,7 +84,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager {
|
|||||||
guard let file = theme.file else {
|
guard let file = theme.file else {
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
return telegramThemeData(account: account, accountManager: accountManager, resource: file.resource)
|
return telegramThemeData(account: account, accountManager: accountManager, reference: .standalone(resource: file.resource))
|
||||||
|> mapToSignal { data -> Signal<(PresentationThemeReference, PresentationTheme?), NoError> in
|
|> mapToSignal { data -> Signal<(PresentationThemeReference, PresentationTheme?), NoError> in
|
||||||
guard let data = data, let presentationTheme = makePresentationTheme(data: data) else {
|
guard let data = data, let presentationTheme = makePresentationTheme(data: data) else {
|
||||||
return .complete()
|
return .complete()
|
||||||
|
|||||||
@ -699,8 +699,8 @@ public func photoWallpaper(postbox: Postbox, photoLibraryResource: PhotoLibraryM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func telegramThemeData(account: Account, accountManager: AccountManager, resource: MediaResource, synchronousLoad: Bool = false) -> Signal<Data?, NoError> {
|
public func telegramThemeData(account: Account, accountManager: AccountManager, reference: MediaResourceReference, synchronousLoad: Bool = false) -> Signal<Data?, NoError> {
|
||||||
let maybeFetched = accountManager.mediaBox.resourceData(resource, option: .complete(waitUntilFetchStatus: false), attemptSynchronously: synchronousLoad)
|
let maybeFetched = accountManager.mediaBox.resourceData(reference.resource, option: .complete(waitUntilFetchStatus: false), attemptSynchronously: synchronousLoad)
|
||||||
return maybeFetched
|
return maybeFetched
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> mapToSignal { maybeData in
|
|> mapToSignal { maybeData in
|
||||||
@ -708,15 +708,15 @@ public func telegramThemeData(account: Account, accountManager: AccountManager,
|
|||||||
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
||||||
return .single(loadedData)
|
return .single(loadedData)
|
||||||
} else {
|
} else {
|
||||||
let data = account.postbox.mediaBox.resourceData(resource, option: .complete(waitUntilFetchStatus: false), attemptSynchronously: false)
|
let data = account.postbox.mediaBox.resourceData(reference.resource, option: .complete(waitUntilFetchStatus: false), attemptSynchronously: false)
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let fetch = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: .standalone(resource: resource)).start()
|
let fetch = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: reference).start()
|
||||||
let disposable = (data
|
let disposable = (data
|
||||||
|> map { data -> Data? in
|
|> map { data -> Data? in
|
||||||
return data.complete ? try? Data(contentsOf: URL(fileURLWithPath: data.path)) : nil
|
return data.complete ? try? Data(contentsOf: URL(fileURLWithPath: data.path)) : nil
|
||||||
}).start(next: { next in
|
}).start(next: { next in
|
||||||
if let data = next {
|
if let data = next {
|
||||||
accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
accountManager.mediaBox.storeResourceData(reference.resource.id, data: data)
|
||||||
}
|
}
|
||||||
subscriber.putNext(next)
|
subscriber.putNext(next)
|
||||||
}, error: { error in
|
}, error: { error in
|
||||||
@ -1153,13 +1153,14 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the
|
|||||||
colorsSignal = .single(((topBackgroundColor, bottomBackgroundColor), (incomingColor, incomingColor), outgoingColor, nil, rotation))
|
colorsSignal = .single(((topBackgroundColor, bottomBackgroundColor), (incomingColor, incomingColor), outgoingColor, nil, rotation))
|
||||||
} else {
|
} else {
|
||||||
var resource: MediaResource?
|
var resource: MediaResource?
|
||||||
|
var reference: MediaResourceReference?
|
||||||
if case let .local(theme) = theme {
|
if case let .local(theme) = theme {
|
||||||
resource = theme.resource
|
reference = .standalone(resource: theme.resource)
|
||||||
} else if case let .cloud(theme) = theme {
|
} else if case let .cloud(theme) = theme, let resource = theme.theme.file?.resource {
|
||||||
resource = theme.theme.file?.resource
|
reference = .theme(theme: .slug(theme.theme.slug), resource: resource)
|
||||||
}
|
}
|
||||||
if let resource = resource {
|
if let reference = reference {
|
||||||
colorsSignal = telegramThemeData(account: account, accountManager: accountManager, resource: resource, synchronousLoad: false)
|
colorsSignal = telegramThemeData(account: account, accountManager: accountManager, reference: reference, synchronousLoad: false)
|
||||||
|> mapToSignal { data -> Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in
|
|> mapToSignal { data -> Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in
|
||||||
if let data = data, let theme = makePresentationTheme(data: data) {
|
if let data = data, let theme = makePresentationTheme(data: data) {
|
||||||
var wallpaperSignal: Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> = .complete()
|
var wallpaperSignal: Signal<((UIColor, UIColor?), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> = .complete()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user