API update

This commit is contained in:
Ilya Laktyushin
2019-08-29 23:57:12 +03:00
parent 8231bb2e72
commit 569c3d6ac6
7 changed files with 141 additions and 25 deletions

View File

@@ -23,7 +23,6 @@ public final class ThemePreviewController: ViewController {
private let previewTheme: PresentationTheme
private let source: ThemePreviewSource
private let theme = Promise<TelegramTheme?>()
private let wallpaper = Promise<TelegramWallpaper>()
private var controllerNode: ThemePreviewControllerNode {
return self.displayNode as! ThemePreviewControllerNode
@@ -59,15 +58,6 @@ public final class ThemePreviewController: ViewController {
themeName = previewTheme.name.string
}
if case let .file(file) = previewTheme.chat.defaultWallpaper, file.id == 0 {
self.wallpaper.set(cachedWallpaper(account: context.account, slug: file.slug)
|> mapToSignal { wallpaper in
return .single(wallpaper?.wallpaper ?? .color(Int32(bitPattern: previewTheme.chatList.backgroundColor.rgb)))
})
} else {
self.wallpaper.set(.single(previewTheme.chat.defaultWallpaper))
}
if let author = previewTheme.author {
let titleView = CounterContollerTitleView(theme: self.previewTheme)
titleView.title = CounterContollerTitle(title: themeName, counter: author)
@@ -123,11 +113,14 @@ public final class ThemePreviewController: ViewController {
switch strongSelf.source {
case .theme, .slug:
theme = strongSelf.theme.get()
|> take(1)
|> map { theme in
theme = combineLatest(strongSelf.theme.get() |> take(1), strongSelf.controllerNode.wallpaperPromise.get() |> take(1))
|> map { theme, wallpaper in
if let theme = theme {
return .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil))
if case let .file(file) = wallpaper, file.id != 0 {
return .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: wallpaper))
} else {
return .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil))
}
} else {
return nil
}
@@ -175,6 +168,16 @@ public final class ThemePreviewController: ViewController {
}
})
self.displayNodeDidLoad()
let previewTheme = self.previewTheme
if case let .file(file) = previewTheme.chat.defaultWallpaper, file.id == 0 {
self.controllerNode.wallpaperPromise.set(cachedWallpaper(account: self.context.account, slug: file.slug)
|> mapToSignal { wallpaper in
return .single(wallpaper?.wallpaper ?? .color(Int32(bitPattern: previewTheme.chatList.backgroundColor.rgb)))
})
} else {
self.controllerNode.wallpaperPromise.set(.single(previewTheme.chat.defaultWallpaper))
}
}
private func updateStrings() {

View File

@@ -9,6 +9,7 @@ import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
import ChatListUI
import WallpaperResources
private func generateMaskImage(color: UIColor) -> UIImage? {
return generateImage(CGSize(width: 1.0, height: 60.0), opaque: false, rotatedContext: { size, context in
@@ -42,6 +43,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
private var chatNodes: [ListViewItemNode]?
private let maskNode: ASImageNode
private let chatContainerNode: ASDisplayNode
private let instantChatBackgroundNode: WallpaperBackgroundNode
private let remoteChatBackgroundNode: TransformImageNode
private var messageNodes: [ListViewItemNode]?
@@ -52,6 +54,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
private var wallpaperDisposable: Disposable?
private var colorDisposable: Disposable?
private var statusDisposable: Disposable?
init(context: AccountContext, previewTheme: PresentationTheme, dismiss: @escaping () -> Void, apply: @escaping () -> Void) {
self.context = context
@@ -75,15 +78,25 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
self.pageControlNode = PageControlNode(dotColor: previewTheme.chatList.unreadBadgeActiveBackgroundColor, inactiveDotColor: previewTheme.list.pageIndicatorInactiveColor)
self.chatListBackgroundNode = ASDisplayNode()
self.chatContainerNode = ASDisplayNode()
self.instantChatBackgroundNode = WallpaperBackgroundNode()
self.instantChatBackgroundNode.displaysAsynchronously = false
self.instantChatBackgroundNode.image = chatControllerBackgroundImage(theme: previewTheme, wallpaper: previewTheme.chat.defaultWallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, knockoutMode: context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper)
self.instantChatBackgroundNode.motionEnabled = previewTheme.chat.defaultWallpaper.settings?.motion ?? false
self.remoteChatBackgroundNode = TransformImageNode()
self.remoteChatBackgroundNode.backgroundColor = previewTheme.chatList.backgroundColor
self.toolbarNode = WallpaperGalleryToolbarNode(theme: self.previewTheme, strings: self.presentationData.strings)
if case let .file(file) = previewTheme.chat.defaultWallpaper, file.id == 0 {
self.remoteChatBackgroundNode.isHidden = false
self.toolbarNode.setDoneEnabled(false)
} else {
self.remoteChatBackgroundNode.isHidden = true
}
self.maskNode = ASImageNode()
self.maskNode.displaysAsynchronously = false
self.maskNode.displayWithoutProcessing = true
@@ -114,8 +127,10 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
self.addSubnode(self.toolbarNode)
self.scrollNode.addSubnode(self.chatListBackgroundNode)
self.scrollNode.addSubnode(self.instantChatBackgroundNode)
self.scrollNode.addSubnode(self.remoteChatBackgroundNode)
self.scrollNode.addSubnode(self.chatContainerNode)
self.chatContainerNode.addSubnode(self.instantChatBackgroundNode)
self.chatContainerNode.addSubnode(self.remoteChatBackgroundNode)
self.toolbarNode.cancel = {
dismiss()
@@ -137,10 +152,53 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
}
}
})
self.wallpaperDisposable = (self.wallpaperPromise.get()
|> deliverOnMainQueue).start(next: { [weak self] wallpaper in
guard let strongSelf = self else {
return
}
if case let .file(file) = wallpaper {
let dimensions = file.file.dimensions ?? CGSize(width: 100.0, height: 100.0)
let displaySize = dimensions.dividedByScreenScale().integralFloor
var convertedRepresentations: [ImageRepresentationWithReference] = []
for representation in file.file.previewRepresentations {
convertedRepresentations.append(ImageRepresentationWithReference(representation: representation, reference: .wallpaper(resource: representation.resource)))
}
convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .wallpaper(resource: file.file.resource)))
let fileReference = FileMediaReference.standalone(media: file.file)
let signal = wallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, fileReference: fileReference, representations: convertedRepresentations, alwaysShowThumbnailFirst: true, autoFetchFullSize: false)
strongSelf.remoteChatBackgroundNode.setSignal(signal)
let account = strongSelf.context.account
let statusSignal = strongSelf.context.sharedContext.accountManager.mediaBox.resourceStatus(file.file.resource)
|> take(1)
|> mapToSignal { status -> Signal<MediaResourceStatus, NoError> in
if case .Local = status {
return .single(status)
} else {
return account.postbox.mediaBox.resourceStatus(file.file.resource)
}
}
strongSelf.statusDisposable = (statusSignal
|> deliverOnMainQueue).start(next: { [weak self] status in
if let strongSelf = self, case .Local = status {
strongSelf.toolbarNode.setDoneEnabled(true)
}
})
strongSelf.remoteChatBackgroundNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets(), emptyColor: nil))()
}
})
}
deinit {
self.colorDisposable?.dispose()
self.wallpaperDisposable?.dispose()
self.statusDisposable?.dispose()
}
override func didLoad() {
@@ -305,7 +363,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
itemNode!.subnodeTransform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0)
itemNode!.isUserInteractionEnabled = false
messageNodes.append(itemNode!)
self.instantChatBackgroundNode.addSubnode(itemNode!)
self.chatContainerNode.addSubnode(itemNode!)
}
self.messageNodes = messageNodes
}
@@ -326,8 +384,9 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
let toolbarHeight = 49.0 + layout.intrinsicInsets.bottom
self.chatListBackgroundNode.frame = CGRect(x: bounds.width, y: 0.0, width: bounds.width, height: bounds.height)
self.instantChatBackgroundNode.frame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height)
self.remoteChatBackgroundNode.frame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height)
self.chatContainerNode.frame = CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height)
self.instantChatBackgroundNode.frame = self.chatContainerNode.bounds
self.remoteChatBackgroundNode.frame = self.chatContainerNode.bounds
self.scrollNode.view.contentSize = CGSize(width: bounds.width * 2.0, height: bounds.height)

View File

@@ -562,7 +562,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
let cloudThemes: [PresentationThemeReference] = cloudThemes.map { .cloud(PresentationCloudTheme(theme: $0, resolvedWallpaper: nil)) }
var availableThemes = defaultThemes
if !defaultThemes.contains(settings.theme) && !cloudThemes.contains(settings.theme) {
if defaultThemes.first(where: { $0.index == settings.theme.index }) == nil && cloudThemes.first(where: { $0.index == settings.theme.index }) == nil {
availableThemes.append(settings.theme)
}
availableThemes.append(contentsOf: cloudThemes)

View File

@@ -412,7 +412,7 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode {
updated = true
}
let selected = theme == item.currentTheme
let selected = theme.index == item.currentTheme.index
if selected {
selectedNode = imageNode
}

View File

@@ -1305,6 +1305,7 @@ public class Account {
self.managedOperationsDisposable.add(managedPendingPeerNotificationSettings(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedSynchronizeAppLogEventsOperations(postbox: self.postbox, network: self.network).start())
self.managedOperationsDisposable.add(managedNotificationSettingsBehaviors(postbox: self.postbox).start())
self.managedOperationsDisposable.add(managedThemesUpdates(accountManager: accountManager, postbox: self.postbox, network: self.network).start())
if !self.supplementary {
self.managedOperationsDisposable.add(managedAnimatedEmojiUpdates(postbox: self.postbox, network: self.network).start())

View File

@@ -2955,6 +2955,14 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
updatedEntries.append(OrderedItemListEntry(id: id, contents: theme))
}
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
accountManager.transaction { transaction in
transaction.updateSharedData(SharedDataKeys.themeSettings, { current in
if let current = current as? ThemeSettings, let theme = current.currentTheme, let updatedTheme = updatedThemes[theme.id] {
return ThemeSettings(currentTheme: updatedTheme)
}
return current
})
}
}
addedIncomingMessageIds.append(contentsOf: addedSecretMessageIds)

View File

@@ -115,18 +115,18 @@ public func getTheme(account: Account, slug: String) -> Signal<TelegramTheme, Ge
}
}
public enum CheckThemeUpdatedResult {
public enum ThemeUpdatedResult {
case updated(TelegramTheme)
case notModified
}
public func checkThemeUpdated(account: Account, theme: TelegramTheme) -> Signal<CheckThemeUpdatedResult, GetThemeError> {
private func checkThemeUpdated(network: Network, theme: TelegramTheme) -> Signal<ThemeUpdatedResult, GetThemeError> {
guard let file = theme.file, let fileId = file.id?.id else {
return .fail(.generic)
}
return account.network.request(Api.functions.account.getTheme(format: themeFormat, theme: .inputTheme(id: theme.id, accessHash: theme.accessHash), documentId: fileId))
return network.request(Api.functions.account.getTheme(format: themeFormat, theme: .inputTheme(id: theme.id, accessHash: theme.accessHash), documentId: fileId))
|> mapError { _ -> GetThemeError in return .generic }
|> map { theme -> CheckThemeUpdatedResult in
|> map { theme -> ThemeUpdatedResult in
if let theme = TelegramTheme(apiTheme: theme) {
return .updated(theme)
} else {
@@ -448,3 +448,48 @@ public func applyTheme(accountManager: AccountManager, account: Account, theme:
}
|> switchToLatest
}
func managedThemesUpdates(accountManager: AccountManager, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
return accountManager.sharedData(keys: [SharedDataKeys.themeSettings])
|> mapToSignal { sharedData -> Signal<Void, NoError> in
let themeSettings = (sharedData.entries[SharedDataKeys.themeSettings] as? ThemeSettings) ?? ThemeSettings(currentTheme: nil)
if let currentTheme = themeSettings.currentTheme {
let poll = Signal<Void, NoError> { subscriber in
return checkThemeUpdated(network: network, theme: currentTheme).start(next: { result in
if case let .updated(updatedTheme) = result {
let _ = accountManager.transaction { transaction in
transaction.updateSharedData(SharedDataKeys.themeSettings, { _ in
return ThemeSettings(currentTheme: updatedTheme)
})
}.start()
let _ = postbox.transaction { transaction in
}
}
subscriber.putCompletion()
})
}
return ((.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue())) |> then(poll)) |> restart
} else {
return .complete()
}
}
}
public func actualizedTheme(accountManager: AccountManager, theme: TelegramTheme) -> Signal<TelegramTheme, NoError> {
var currentTheme = theme
return accountManager.sharedData(keys: [SharedDataKeys.themeSettings])
|> map { sharedData -> TelegramTheme in
let themeSettings = (sharedData.entries[SharedDataKeys.themeSettings] as? ThemeSettings) ?? ThemeSettings(currentTheme: nil)
if let updatedTheme = themeSettings.currentTheme, updatedTheme.id == currentTheme.id {
if updatedTheme != currentTheme {
currentTheme = updatedTheme
return updatedTheme
} else {
return currentTheme
}
} else {
return theme
}
}
}