mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 05:03:45 +00:00
Download animations and navigation bar fixes
This commit is contained in:
parent
c9631285bf
commit
06fc9e6aab
@ -17,6 +17,8 @@
|
||||
091346982183498A00846E49 /* InstantPageArticleNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091346972183498A00846E49 /* InstantPageArticleNode.swift */; };
|
||||
0913469A218528D200846E49 /* InstantPageTableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09134699218528D200846E49 /* InstantPageTableItem.swift */; };
|
||||
0913469C21883C3700846E49 /* InstantPageDetailsItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0913469B21883C3700846E49 /* InstantPageDetailsItem.swift */; };
|
||||
091417F221EF4E5D00C8325A /* WallpaperGalleryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091417F121EF4E5D00C8325A /* WallpaperGalleryController.swift */; };
|
||||
091417F421EF4F5F00C8325A /* WallpaperGalleryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 091417F321EF4F5F00C8325A /* WallpaperGalleryItem.swift */; };
|
||||
091BEAB3214552D9003AEA30 /* Vision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D02DADBE2138D76F00116225 /* Vision.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
092F368D2154AAEA001A9F49 /* SFCompactRounded-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 092F368C2154AAE9001A9F49 /* SFCompactRounded-Semibold.otf */; };
|
||||
092F36902157AB46001A9F49 /* ItemListCallListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 092F368F2157AB46001A9F49 /* ItemListCallListItem.swift */; };
|
||||
@ -1141,6 +1143,8 @@
|
||||
091346972183498A00846E49 /* InstantPageArticleNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPageArticleNode.swift; sourceTree = "<group>"; };
|
||||
09134699218528D200846E49 /* InstantPageTableItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPageTableItem.swift; sourceTree = "<group>"; };
|
||||
0913469B21883C3700846E49 /* InstantPageDetailsItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPageDetailsItem.swift; sourceTree = "<group>"; };
|
||||
091417F121EF4E5D00C8325A /* WallpaperGalleryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperGalleryController.swift; sourceTree = "<group>"; };
|
||||
091417F321EF4F5F00C8325A /* WallpaperGalleryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperGalleryItem.swift; sourceTree = "<group>"; };
|
||||
092F368C2154AAE9001A9F49 /* SFCompactRounded-Semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SFCompactRounded-Semibold.otf"; sourceTree = "<group>"; };
|
||||
092F368F2157AB46001A9F49 /* ItemListCallListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemListCallListItem.swift; sourceTree = "<group>"; };
|
||||
09310D14213BC5DE0020033A /* anim_read.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = anim_read.json; sourceTree = "<group>"; };
|
||||
@ -3148,6 +3152,8 @@
|
||||
09F664CF21EBCFB900AB7E26 /* WallpaperCropNode.swift */,
|
||||
09DD5D5121ED175300D7007A /* WallpaperColorPickerNode.swift */,
|
||||
0900678C21ED5EA800530762 /* WallpaperColorPanelNode.swift */,
|
||||
091417F121EF4E5D00C8325A /* WallpaperGalleryController.swift */,
|
||||
091417F321EF4F5F00C8325A /* WallpaperGalleryItem.swift */,
|
||||
);
|
||||
name = Themes;
|
||||
sourceTree = "<group>";
|
||||
@ -5871,6 +5877,7 @@
|
||||
D093D7E22062F40100BC3599 /* SecureIdDocumentFormControllerNode.swift in Sources */,
|
||||
D0B2F7702052B5A800D3BFB9 /* InviteContactsControllerNode.swift in Sources */,
|
||||
D0EC6E211EB9F58900EBF1C3 /* InstantPageController.swift in Sources */,
|
||||
091417F221EF4E5D00C8325A /* WallpaperGalleryController.swift in Sources */,
|
||||
D0671F232143BDA6000A8AE7 /* TwoStepVerificationEmptyItem.swift in Sources */,
|
||||
D0EC6E221EB9F58900EBF1C3 /* InstantPageControllerNode.swift in Sources */,
|
||||
D0EC6E231EB9F58900EBF1C3 /* StickerPackPreviewController.swift in Sources */,
|
||||
@ -5935,6 +5942,7 @@
|
||||
D01C06BE1FBCAF06001561AB /* ChatMessageBubbleMosaicLayout.swift in Sources */,
|
||||
0900678D21ED5EA800530762 /* WallpaperColorPanelNode.swift in Sources */,
|
||||
D0EC6E451EB9F58900EBF1C3 /* ItemListMultilineTextItem.swift in Sources */,
|
||||
091417F421EF4F5F00C8325A /* WallpaperGalleryItem.swift in Sources */,
|
||||
D02F4AE91FCF370B004DFBAE /* ChatMessageInteractiveMediaBadge.swift in Sources */,
|
||||
D0EC6E461EB9F58900EBF1C3 /* ItemListLoadingIndicatorEmptyStateItem.swift in Sources */,
|
||||
D067B4A5211C911C00796039 /* LegacyChannelIntroController.swift in Sources */,
|
||||
|
||||
@ -3619,7 +3619,11 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
|
||||
|
||||
if let button = leftNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.leftNavigationButton, target: self, selector: #selector(self.leftNavigationButtonAction)) {
|
||||
if self.leftNavigationButton != button {
|
||||
self.navigationItem.setLeftBarButton(button.buttonItem, animated: transition.isAnimated)
|
||||
var animated = transition.isAnimated
|
||||
if let currentButton = self.leftNavigationButton?.action, currentButton == button.action {
|
||||
animated = false
|
||||
}
|
||||
self.navigationItem.setLeftBarButton(button.buttonItem, animated: animated)
|
||||
self.leftNavigationButton = button
|
||||
}
|
||||
} else if let _ = self.leftNavigationButton {
|
||||
@ -3629,7 +3633,11 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
|
||||
|
||||
if let button = rightNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.rightNavigationButton, target: self, selector: #selector(self.rightNavigationButtonAction), chatInfoNavigationButton: self.chatInfoNavigationButton) {
|
||||
if self.rightNavigationButton != button {
|
||||
self.navigationItem.setRightBarButton(button.buttonItem, animated: transition.isAnimated)
|
||||
var animated = transition.isAnimated
|
||||
if let currentButton = self.rightNavigationButton?.action, currentButton == button.action {
|
||||
animated = false
|
||||
}
|
||||
self.navigationItem.setRightBarButton(button.buttonItem, animated: animated)
|
||||
self.rightNavigationButton = button
|
||||
}
|
||||
} else if let _ = self.rightNavigationButton {
|
||||
|
||||
@ -11,7 +11,7 @@ final class ChatBackgroundNode: ASDisplayNode {
|
||||
didSet {
|
||||
if oldValue != self.parallaxEnabled {
|
||||
if self.parallaxEnabled {
|
||||
let amount = 16.0
|
||||
let amount = 24.0
|
||||
|
||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||
horizontal.minimumRelativeValue = -amount
|
||||
@ -57,10 +57,10 @@ final class ChatBackgroundNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private var backgroundImageForWallpaper: (TelegramWallpaper, PresentationWallpaperMode, UIImage)?
|
||||
private var backgroundImageForWallpaper: (TelegramWallpaper, WallpaperPresentationOptions, UIImage)?
|
||||
private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)?
|
||||
|
||||
func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: PresentationWallpaperMode = .still, postbox: Postbox) -> UIImage? {
|
||||
func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: WallpaperPresentationOptions = [], postbox: Postbox) -> UIImage? {
|
||||
var backgroundImage: UIImage?
|
||||
if wallpaper == backgroundImageForWallpaper?.0, mode == backgroundImageForWallpaper?.1 {
|
||||
backgroundImage = backgroundImageForWallpaper?.2
|
||||
@ -77,7 +77,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: Presentat
|
||||
})
|
||||
case let .image(representations):
|
||||
if let largest = largestImageRepresentation(representations) {
|
||||
if case .blurred = mode {
|
||||
if mode.contains(.blur) {
|
||||
var image: UIImage?
|
||||
let _ = postbox.mediaBox.cachedResourceRepresentation(largest.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in
|
||||
if data.complete {
|
||||
@ -91,7 +91,7 @@ func chatControllerBackgroundImage(wallpaper: TelegramWallpaper, mode: Presentat
|
||||
}
|
||||
}
|
||||
case let .file(file):
|
||||
if case .blurred = mode {
|
||||
if mode.contains(.blur) {
|
||||
var image: UIImage?
|
||||
let _ = postbox.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in
|
||||
if data.complete {
|
||||
@ -255,7 +255,7 @@ func backgroundContrastColor(for image: Signal<UIImage?, NoError>) -> Signal<UIC
|
||||
})
|
||||
|
||||
var matching: Int = 0
|
||||
var total: Int = Int(context.size.width) * Int(context.size.height)
|
||||
let total: Int = Int(context.size.width) * Int(context.size.height)
|
||||
for y in 0 ..< Int(context.size.height) {
|
||||
for x in 0 ..< Int(context.size.width) {
|
||||
var saturation: CGFloat = 0.0
|
||||
|
||||
@ -241,7 +241,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
self.backgroundNode.image = chatControllerBackgroundImage(wallpaper: chatPresentationInterfaceState.chatWallpaper, mode: chatPresentationInterfaceState.chatWallpaperMode, postbox: account.postbox)
|
||||
if case .perspective = chatPresentationInterfaceState.chatWallpaperMode {
|
||||
if chatPresentationInterfaceState.chatWallpaperMode.contains(.motion) {
|
||||
self.backgroundNode.parallaxEnabled = true
|
||||
}
|
||||
self.historyNode.verticalScrollIndicatorColor = UIColor(white: 0.5, alpha: 0.8)
|
||||
@ -540,28 +540,28 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
self.containerLayoutAndNavigationBarHeight = (layout, navigationBarHeight)
|
||||
|
||||
let transitionIsAnimated: Bool
|
||||
if case .immediate = transition {
|
||||
transitionIsAnimated = false
|
||||
} else {
|
||||
transitionIsAnimated = true
|
||||
}
|
||||
|
||||
if let _ = self.chatPresentationInterfaceState.search, let interfaceInteraction = self.interfaceInteraction {
|
||||
var activate = false
|
||||
if self.searchNavigationNode == nil {
|
||||
activate = true
|
||||
self.searchNavigationNode = ChatSearchNavigationContentNode(theme: self.chatPresentationInterfaceState.theme, strings: self.chatPresentationInterfaceState.strings, chatLocation: self.chatPresentationInterfaceState.chatLocation, interaction: interfaceInteraction)
|
||||
}
|
||||
self.navigationBar?.setContentNode(self.searchNavigationNode, animated: transitionIsAnimated)
|
||||
self.searchNavigationNode?.update(presentationInterfaceState: self.chatPresentationInterfaceState)
|
||||
if activate {
|
||||
self.searchNavigationNode?.activate()
|
||||
}
|
||||
} else if let _ = self.searchNavigationNode {
|
||||
self.searchNavigationNode = nil
|
||||
self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated)
|
||||
}
|
||||
// let transitionIsAnimated: Bool
|
||||
// if case .immediate = transition {
|
||||
// transitionIsAnimated = false
|
||||
// } else {
|
||||
// transitionIsAnimated = true
|
||||
// }
|
||||
//
|
||||
// if let _ = self.chatPresentationInterfaceState.search, let interfaceInteraction = self.interfaceInteraction {
|
||||
// var activate = false
|
||||
// if self.searchNavigationNode == nil {
|
||||
// activate = true
|
||||
// self.searchNavigationNode = ChatSearchNavigationContentNode(theme: self.chatPresentationInterfaceState.theme, strings: self.chatPresentationInterfaceState.strings, chatLocation: self.chatPresentationInterfaceState.chatLocation, interaction: interfaceInteraction)
|
||||
// }
|
||||
// self.navigationBar?.setContentNode(self.searchNavigationNode, animated: transitionIsAnimated)
|
||||
// self.searchNavigationNode?.update(presentationInterfaceState: self.chatPresentationInterfaceState)
|
||||
// if activate {
|
||||
// self.searchNavigationNode?.activate()
|
||||
// }
|
||||
// } else if let _ = self.searchNavigationNode {
|
||||
// self.searchNavigationNode = nil
|
||||
// self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated)
|
||||
// }
|
||||
|
||||
var dismissedTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode?
|
||||
var immediatelyLayoutTitleAccessoryPanelNodeAndAnimateAppearance = false
|
||||
@ -1316,12 +1316,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if self.chatPresentationInterfaceState != chatPresentationInterfaceState {
|
||||
let themeUpdated = self.chatPresentationInterfaceState.theme !== chatPresentationInterfaceState.theme
|
||||
|
||||
if self.chatPresentationInterfaceState.chatWallpaper != chatPresentationInterfaceState.chatWallpaper {
|
||||
if self.chatPresentationInterfaceState.chatWallpaper != chatPresentationInterfaceState.chatWallpaper || self.chatPresentationInterfaceState.chatWallpaperMode != chatPresentationInterfaceState.chatWallpaperMode {
|
||||
self.backgroundNode.image = chatControllerBackgroundImage(wallpaper: chatPresentationInterfaceState.chatWallpaper, mode: chatPresentationInterfaceState.chatWallpaperMode, postbox: account.postbox)
|
||||
}
|
||||
|
||||
if self.chatPresentationInterfaceState.chatWallpaperMode != chatPresentationInterfaceState.chatWallpaperMode {
|
||||
if case .perspective = chatPresentationInterfaceState.chatWallpaperMode {
|
||||
|
||||
if chatPresentationInterfaceState.chatWallpaperMode.contains(.motion) {
|
||||
self.backgroundNode.parallaxEnabled = true
|
||||
} else {
|
||||
self.backgroundNode.parallaxEnabled = false
|
||||
@ -1393,6 +1391,29 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
let layoutTransition: ContainedViewLayoutTransition = transition
|
||||
|
||||
let transitionIsAnimated: Bool
|
||||
if case .immediate = transition {
|
||||
transitionIsAnimated = false
|
||||
} else {
|
||||
transitionIsAnimated = true
|
||||
}
|
||||
|
||||
if let _ = self.chatPresentationInterfaceState.search, let interfaceInteraction = self.interfaceInteraction {
|
||||
var activate = false
|
||||
if self.searchNavigationNode == nil {
|
||||
activate = true
|
||||
self.searchNavigationNode = ChatSearchNavigationContentNode(theme: self.chatPresentationInterfaceState.theme, strings: self.chatPresentationInterfaceState.strings, chatLocation: self.chatPresentationInterfaceState.chatLocation, interaction: interfaceInteraction)
|
||||
}
|
||||
self.navigationBar?.setContentNode(self.searchNavigationNode, animated: transitionIsAnimated)
|
||||
self.searchNavigationNode?.update(presentationInterfaceState: self.chatPresentationInterfaceState)
|
||||
if activate {
|
||||
self.searchNavigationNode?.activate()
|
||||
}
|
||||
} else if let _ = self.searchNavigationNode {
|
||||
self.searchNavigationNode = nil
|
||||
self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated)
|
||||
}
|
||||
|
||||
if updatedInputFocus {
|
||||
if !self.ignoreUpdateHeight {
|
||||
self.scheduleLayoutTransitionRequest(layoutTransition)
|
||||
|
||||
@ -335,7 +335,7 @@ final class ChatPresentationInterfaceState: Equatable {
|
||||
let search: ChatSearchData?
|
||||
let searchQuerySuggestionResult: ChatPresentationInputQueryResult?
|
||||
let chatWallpaper: TelegramWallpaper
|
||||
let chatWallpaperMode: PresentationWallpaperMode
|
||||
let chatWallpaperMode: WallpaperPresentationOptions
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
@ -344,7 +344,7 @@ final class ChatPresentationInterfaceState: Equatable {
|
||||
let accountPeerId: PeerId
|
||||
let mode: ChatControllerPresentationMode
|
||||
|
||||
init(chatWallpaper: TelegramWallpaper, chatWallpaperMode: PresentationWallpaperMode, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, fontSize: PresentationFontSize, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation) {
|
||||
init(chatWallpaper: TelegramWallpaper, chatWallpaperMode: WallpaperPresentationOptions, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, fontSize: PresentationFontSize, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation) {
|
||||
self.interfaceState = ChatInterfaceState()
|
||||
self.inputTextPanelState = ChatTextInputPanelState()
|
||||
self.editMessageState = nil
|
||||
@ -383,7 +383,7 @@ final class ChatPresentationInterfaceState: Equatable {
|
||||
self.mode = mode
|
||||
}
|
||||
|
||||
init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, isContact: Bool, hasBots: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: Message?, peerIsBlocked: Bool, peerIsMuted: Bool, canReportPeer: Bool, callsAvailable: Bool, callsPrivate: Bool, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, chatWallpaper: TelegramWallpaper, chatWallpaperMode: PresentationWallpaperMode, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, fontSize: PresentationFontSize, accountPeerId: PeerId, mode: ChatControllerPresentationMode) {
|
||||
init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, isContact: Bool, hasBots: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: Message?, peerIsBlocked: Bool, peerIsMuted: Bool, canReportPeer: Bool, callsAvailable: Bool, callsPrivate: Bool, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, chatWallpaper: TelegramWallpaper, chatWallpaperMode: WallpaperPresentationOptions, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, fontSize: PresentationFontSize, accountPeerId: PeerId, mode: ChatControllerPresentationMode) {
|
||||
self.interfaceState = interfaceState
|
||||
self.chatLocation = chatLocation
|
||||
self.renderedPeer = renderedPeer
|
||||
@ -712,7 +712,7 @@ final class ChatPresentationInterfaceState: Equatable {
|
||||
return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, isContact: self.isContact, hasBots: self.hasBots, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, canReportPeer: self.canReportPeer, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: self.chatWallpaper, chatWallpaperMode: self.chatWallpaperMode, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode)
|
||||
}
|
||||
|
||||
func updatedChatWallpaper(_ chatWallpaper: TelegramWallpaper, mode: PresentationWallpaperMode) -> ChatPresentationInterfaceState {
|
||||
func updatedChatWallpaper(_ chatWallpaper: TelegramWallpaper, mode: WallpaperPresentationOptions) -> ChatPresentationInterfaceState {
|
||||
return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, isContact: self.isContact, hasBots: self.hasBots, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, canReportPeer: self.canReportPeer, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, chatWallpaper: chatWallpaper, chatWallpaperMode: mode, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, fontSize: self.fontSize, accountPeerId: self.accountPeerId, mode: self.mode)
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@ func openChatWallpaper(account: Account, message: Message, present: @escaping (V
|
||||
let _ = (resolveUrl(account: account, url: content.url)
|
||||
|> deliverOnMainQueue).start(next: { resolvedUrl in
|
||||
if case let .wallpaper(parameter) = resolvedUrl {
|
||||
let source: WallpaperListPreviewSource
|
||||
let source: WallpaperListSource
|
||||
switch parameter {
|
||||
case let .slug(slug):
|
||||
source = .slug(slug, content.file)
|
||||
|
||||
@ -304,7 +304,7 @@ class PermissionInfoItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: strongSelf.titleNode.frame.maxY + 9.0), size: textLayout.size)
|
||||
|
||||
strongSelf.closeButton.frame = CGRect(x: params.width - rightInset - 21.0, y: 10.0, width: 32.0, height: 32.0)
|
||||
strongSelf.closeButton.frame = CGRect(x: params.width - rightInset - 26.0, y: 10.0, width: 32.0, height: 32.0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ public final class PresentationData: Equatable {
|
||||
public let strings: PresentationStrings
|
||||
public let theme: PresentationTheme
|
||||
public let chatWallpaper: TelegramWallpaper
|
||||
public let chatWallpaperMode: PresentationWallpaperMode
|
||||
public let chatWallpaperMode: WallpaperPresentationOptions
|
||||
public let volumeControlStatusBarIcons: PresentationVolumeControlStatusBarIcons
|
||||
public let fontSize: PresentationFontSize
|
||||
public let dateTimeFormat: PresentationDateTimeFormat
|
||||
@ -54,7 +54,7 @@ public final class PresentationData: Equatable {
|
||||
public let nameSortOrder: PresentationPersonNameOrder
|
||||
public let disableAnimations: Bool
|
||||
|
||||
public init(strings: PresentationStrings, theme: PresentationTheme, chatWallpaper: TelegramWallpaper, chatWallpaperMode: PresentationWallpaperMode, volumeControlStatusBarIcons: PresentationVolumeControlStatusBarIcons, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, nameSortOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
public init(strings: PresentationStrings, theme: PresentationTheme, chatWallpaper: TelegramWallpaper, chatWallpaperMode: WallpaperPresentationOptions, volumeControlStatusBarIcons: PresentationVolumeControlStatusBarIcons, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, nameSortOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
self.strings = strings
|
||||
self.theme = theme
|
||||
self.chatWallpaper = chatWallpaper
|
||||
@ -236,7 +236,7 @@ public func currentPresentationDataAndSettings(postbox: Postbox) -> Signal<Initi
|
||||
|
||||
let effectiveTheme: PresentationThemeReference
|
||||
var effectiveChatWallpaper: TelegramWallpaper = themeSettings.chatWallpaper
|
||||
var effectiveChatWallpaperMode: PresentationWallpaperMode = themeSettings.chatWallpaperMode
|
||||
var effectiveChatWallpaperOptions: WallpaperPresentationOptions = themeSettings.chatWallpaperOptions
|
||||
|
||||
if automaticThemeShouldSwitchNow(themeSettings.automaticThemeSwitchSetting, currentTheme: themeSettings.theme) {
|
||||
effectiveTheme = .builtin(themeSettings.automaticThemeSwitchSetting.theme)
|
||||
@ -245,10 +245,10 @@ public func currentPresentationDataAndSettings(postbox: Postbox) -> Signal<Initi
|
||||
switch themeSettings.automaticThemeSwitchSetting.theme {
|
||||
case .nightAccent:
|
||||
effectiveChatWallpaper = .color(0x18222d)
|
||||
effectiveChatWallpaperMode = .still
|
||||
effectiveChatWallpaperOptions = []
|
||||
case .nightGrayscale:
|
||||
effectiveChatWallpaper = .color(0x000000)
|
||||
effectiveChatWallpaperMode = .still
|
||||
effectiveChatWallpaperOptions = []
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -281,7 +281,7 @@ public func currentPresentationDataAndSettings(postbox: Postbox) -> Signal<Initi
|
||||
let dateTimeFormat = currentDateTimeFormat()
|
||||
let nameDisplayOrder = contactSettings.nameDisplayOrder
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, chatWallpaperMode: effectiveChatWallpaperMode, volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations), automaticMediaDownloadSettings: automaticMediaDownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings)
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, chatWallpaperMode: effectiveChatWallpaperOptions, volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations), automaticMediaDownloadSettings: automaticMediaDownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, experimentalUISettings: experimentalUISettings)
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +375,7 @@ public func updatedPresentationData(postbox: Postbox, applicationBindings: Teleg
|
||||
let themeValue: PresentationTheme
|
||||
let effectiveTheme: PresentationThemeReference
|
||||
var effectiveChatWallpaper: TelegramWallpaper = themeSettings.chatWallpaper
|
||||
var effectiveChatWallpaperMode: PresentationWallpaperMode = themeSettings.chatWallpaperMode
|
||||
var effectiveChatWallpaperOptions: WallpaperPresentationOptions = themeSettings.chatWallpaperOptions
|
||||
|
||||
if shouldSwitch {
|
||||
effectiveTheme = .builtin(themeSettings.automaticThemeSwitchSetting.theme)
|
||||
@ -384,10 +384,10 @@ public func updatedPresentationData(postbox: Postbox, applicationBindings: Teleg
|
||||
switch themeSettings.automaticThemeSwitchSetting.theme {
|
||||
case .nightAccent:
|
||||
effectiveChatWallpaper = .color(0x18222d)
|
||||
effectiveChatWallpaperMode = .still
|
||||
effectiveChatWallpaperOptions = []
|
||||
case .nightGrayscale:
|
||||
effectiveChatWallpaper = .color(0x000000)
|
||||
effectiveChatWallpaperMode = .still
|
||||
effectiveChatWallpaperOptions = []
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -429,7 +429,7 @@ public func updatedPresentationData(postbox: Postbox, applicationBindings: Teleg
|
||||
let nameDisplayOrder = contactSettings.nameDisplayOrder
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
|
||||
return PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, chatWallpaperMode: effectiveChatWallpaperMode, volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations)
|
||||
return PresentationData(strings: stringsValue, theme: themeValue, chatWallpaper: effectiveChatWallpaper, chatWallpaperMode: effectiveChatWallpaperOptions, volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations)
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
@ -445,5 +445,5 @@ public func defaultPresentationData() -> PresentationData {
|
||||
let nameSortOrder = currentPersonNameSortOrder()
|
||||
|
||||
let themeSettings = PresentationThemeSettings.defaultSettings
|
||||
return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, chatWallpaper: .builtin, chatWallpaperMode: .still, volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations)
|
||||
return PresentationData(strings: defaultPresentationStrings, theme: defaultPresentationTheme, chatWallpaper: .builtin, chatWallpaperMode: [], volumeControlStatusBarIcons: volumeControlStatusBarIcons(), fontSize: themeSettings.fontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, disableAnimations: themeSettings.disableAnimations)
|
||||
}
|
||||
|
||||
@ -10,10 +10,19 @@ public enum PresentationBuiltinThemeReference: Int32 {
|
||||
case nightAccent = 3
|
||||
}
|
||||
|
||||
public enum PresentationWallpaperMode: Int32 {
|
||||
case still
|
||||
case perspective
|
||||
case blurred
|
||||
public struct WallpaperPresentationOptions: OptionSet {
|
||||
public var rawValue: Int32
|
||||
|
||||
public init(rawValue: Int32) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
public init() {
|
||||
self.rawValue = 0
|
||||
}
|
||||
|
||||
public static let motion = WallpaperPresentationOptions(rawValue: 1 << 0)
|
||||
public static let blur = WallpaperPresentationOptions(rawValue: 1 << 1)
|
||||
}
|
||||
|
||||
public enum PresentationThemeReference: PostboxCoding, Equatable {
|
||||
@ -147,7 +156,7 @@ public struct AutomaticThemeSwitchSetting: PostboxCoding, Equatable {
|
||||
|
||||
public struct PresentationThemeSettings: PreferencesEntry {
|
||||
public var chatWallpaper: TelegramWallpaper
|
||||
public var chatWallpaperMode: PresentationWallpaperMode
|
||||
public var chatWallpaperOptions: WallpaperPresentationOptions
|
||||
public var theme: PresentationThemeReference
|
||||
public var themeAccentColor: Int32?
|
||||
public var fontSize: PresentationFontSize
|
||||
@ -164,12 +173,12 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
}
|
||||
|
||||
public static var defaultSettings: PresentationThemeSettings {
|
||||
return PresentationThemeSettings(chatWallpaper: .builtin, chatWallpaperMode: .still, theme: .builtin(.dayClassic), themeAccentColor: nil, fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .none, theme: .nightAccent), disableAnimations: true)
|
||||
return PresentationThemeSettings(chatWallpaper: .builtin, chatWallpaperOptions: [], theme: .builtin(.dayClassic), themeAccentColor: nil, fontSize: .regular, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(trigger: .none, theme: .nightAccent), disableAnimations: true)
|
||||
}
|
||||
|
||||
public init(chatWallpaper: TelegramWallpaper, chatWallpaperMode: PresentationWallpaperMode, theme: PresentationThemeReference, themeAccentColor: Int32?, fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, disableAnimations: Bool) {
|
||||
public init(chatWallpaper: TelegramWallpaper, chatWallpaperOptions: WallpaperPresentationOptions, theme: PresentationThemeReference, themeAccentColor: Int32?, fontSize: PresentationFontSize, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, disableAnimations: Bool) {
|
||||
self.chatWallpaper = chatWallpaper
|
||||
self.chatWallpaperMode = chatWallpaperMode
|
||||
self.chatWallpaperOptions = chatWallpaperOptions
|
||||
self.theme = theme
|
||||
self.themeAccentColor = themeAccentColor
|
||||
self.fontSize = fontSize
|
||||
@ -179,7 +188,7 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.chatWallpaper = (decoder.decodeObjectForKey("w", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper) ?? .builtin
|
||||
self.chatWallpaperMode = PresentationWallpaperMode(rawValue: decoder.decodeInt32ForKey("m", orElse: 0)) ?? .still
|
||||
self.chatWallpaperOptions = WallpaperPresentationOptions(rawValue: decoder.decodeInt32ForKey("o", orElse: 0))
|
||||
self.theme = decoder.decodeObjectForKey("t", decoder: { PresentationThemeReference(decoder: $0) }) as! PresentationThemeReference
|
||||
self.themeAccentColor = decoder.decodeOptionalInt32ForKey("themeAccentColor")
|
||||
self.fontSize = PresentationFontSize(rawValue: decoder.decodeInt32ForKey("f", orElse: PresentationFontSize.regular.rawValue)) ?? .regular
|
||||
@ -189,7 +198,7 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeObject(self.chatWallpaper, forKey: "w")
|
||||
encoder.encodeInt32(self.chatWallpaperMode.rawValue, forKey: "m")
|
||||
encoder.encodeInt32(self.chatWallpaperOptions.rawValue, forKey: "o")
|
||||
encoder.encodeObject(self.theme, forKey: "t")
|
||||
if let themeAccentColor = self.themeAccentColor {
|
||||
encoder.encodeInt32(themeAccentColor, forKey: "themeAccentColor")
|
||||
@ -210,7 +219,7 @@ public struct PresentationThemeSettings: PreferencesEntry {
|
||||
}
|
||||
|
||||
public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool {
|
||||
return lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatWallpaperMode == rhs.chatWallpaperMode && lhs.theme == rhs.theme && lhs.themeAccentColor == rhs.themeAccentColor && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.disableAnimations == rhs.disableAnimations
|
||||
return lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatWallpaperOptions == rhs.chatWallpaperOptions && lhs.theme == rhs.theme && lhs.themeAccentColor == rhs.themeAccentColor && lhs.fontSize == rhs.fontSize && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.disableAnimations == rhs.disableAnimations
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ final class RadialCheckContentNode: RadialStatusContentNode {
|
||||
self.isLayerBacked = true
|
||||
}
|
||||
|
||||
func animateProgress() {
|
||||
func animateProgress(delay: Double) {
|
||||
self.animationCompletionTimer?.invalidate()
|
||||
self.animationCompletionTimer = nil
|
||||
let animation = POPBasicAnimation()
|
||||
@ -64,6 +64,7 @@ final class RadialCheckContentNode: RadialStatusContentNode {
|
||||
animation.toValue = 1.0 as NSNumber
|
||||
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
|
||||
animation.duration = 0.25
|
||||
animation.beginTime = delay
|
||||
animation.completionBlock = { [weak self] _, _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.animationCompletionTimer?.invalidate()
|
||||
@ -163,10 +164,10 @@ final class RadialCheckContentNode: RadialStatusContentNode {
|
||||
self.layer.animateScale(from: 1.0, to: 0.6, duration: duration, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func animateIn(from: RadialStatusNodeState) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||
self.layer.animateScale(from: 0.7, to: 1.0, duration: duration)
|
||||
self.animateProgress()
|
||||
override func animateIn(from: RadialStatusNodeState, delay: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, delay: delay)
|
||||
self.layer.animateScale(from: 0.7, to: 1.0, duration: duration, delay: delay)
|
||||
self.animateProgress(delay: delay)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -294,8 +294,8 @@ final class RadialCloudProgressContentNode: RadialStatusContentNode {
|
||||
self.cancelNode.layer.animateScale(from: 1.0, to: 0.3, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func animateIn(from: RadialStatusNodeState) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
self.cancelNode.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15)
|
||||
override func animateIn(from: RadialStatusNodeState, delay: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: delay)
|
||||
self.cancelNode.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15, delay: delay)
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,11 +116,8 @@ final class RadialDownloadContentNode: RadialStatusContentNode {
|
||||
let diameter = min(bounds.size.width, bounds.size.height)
|
||||
let factor = diameter / 50.0
|
||||
|
||||
var lineWidth: CGFloat = 2.0
|
||||
if diameter < 24.0 {
|
||||
lineWidth = 1.3
|
||||
}
|
||||
|
||||
let lineWidth: CGFloat = max(1.6, 2.25 * factor)
|
||||
|
||||
self.leftLine.lineWidth = lineWidth
|
||||
self.rightLine.lineWidth = lineWidth
|
||||
self.arrowBody.lineWidth = lineWidth
|
||||
@ -142,34 +139,35 @@ final class RadialDownloadContentNode: RadialStatusContentNode {
|
||||
|
||||
private let duration: Double = 0.2
|
||||
|
||||
override func prepareAnimateOut(completion: @escaping () -> Void) {
|
||||
override func prepareAnimateOut(completion: @escaping (Double) -> Void) {
|
||||
let bounds = self.bounds
|
||||
let diameter = min(bounds.size.width, bounds.size.height)
|
||||
let factor = diameter / 50.0
|
||||
|
||||
var bodyPath = UIBezierPath()
|
||||
if let path = try? svgPath("M1.20125335,62.2095675 C1.78718228,62.9863141 2.3877868,63.7395876 3.00158591,64.4690754 C22.1087455,87.1775489 54.0019347,86.8368674 54.0066002,54.0178571 L54.0066002,0.625 ", scale: CGPoint(x: 0.333333 * factor, y: 0.333333 * factor), offset: CGPoint(x: 7.0 * factor, y: (17.0 - UIScreenPixel) * factor)) {
|
||||
|
||||
if let path = try? svgPath("M1.10890748,47.3077093 C2.74202161,51.7201715 4.79761832,55.7299828 7.15775768,59.3122505 C25.4413606,87.0634763 62.001605,89.1563513 62.0066002,54.0178571 L62.0066002,0.625 ", scale: CGPoint(x: 0.333333 * factor, y: 0.333333 * factor), offset: CGPoint(x: (4.0 + UIScreenPixel) * factor, y: (17.0 - UIScreenPixel) * factor)) {
|
||||
bodyPath = path
|
||||
}
|
||||
|
||||
self.arrowBody.path = bodyPath.cgPath
|
||||
self.arrowBody.strokeStart = 0.62
|
||||
self.arrowBody.strokeStart = 0.65
|
||||
|
||||
self.leftLine.animateStrokeEnd(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
self.rightLine.animateStrokeEnd(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
|
||||
self.leftLine.animateAlpha(from: 1.0, to: 0.0, duration: 0.23, delay: 0.07, removeOnCompletion: false) { finished in
|
||||
completion()
|
||||
self.leftLine.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, delay: 0.07, removeOnCompletion: false) { finished in
|
||||
completion(0.0)
|
||||
}
|
||||
self.rightLine.animateAlpha(from: 1.0, to: 0.0, duration: 0.23, delay: 0.07, removeOnCompletion: false)
|
||||
self.rightLine.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, delay: 0.07, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func animateOut(to: RadialStatusNodeState, completion: @escaping () -> Void) {
|
||||
self.arrowBody.animateStrokeStart(from: 0.62, to: 0.0, duration: 0.5, removeOnCompletion: false, completion: { _ in
|
||||
self.arrowBody.animateStrokeStart(from: 0.65, to: 0.0, duration: 0.5, removeOnCompletion: false, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
self.arrowBody.animateStrokeEnd(from: 1.0, to: 0.0, duration: 0.5, removeOnCompletion: false, completion: nil)
|
||||
self.arrowBody.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, delay: 0.4, removeOnCompletion: false)
|
||||
self.arrowBody.animateAlpha(from: 1.0, to: 0.0, duration: 0.01, delay: 0.4, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func prepareAnimateIn(from: RadialStatusNodeState?) {
|
||||
@ -178,28 +176,28 @@ final class RadialDownloadContentNode: RadialStatusContentNode {
|
||||
let factor = diameter / 50.0
|
||||
|
||||
var bodyPath = UIBezierPath()
|
||||
if let path = try? svgPath("M1.20125335,62.2095675 C1.78718228,62.9863141 2.3877868,63.7395876 3.00158591,64.4690754 C22.1087455,87.1775489 54.0019347,86.8368674 54.0066002,54.0178571 L54.0066002,0.625 ", scale: CGPoint(x: -0.333333 * factor, y: 0.333333 * factor), offset: CGPoint(x: 43.0 * factor, y: (17.0 - UIScreenPixel) * factor)) {
|
||||
if let path = try? svgPath("M1.10890748,47.3077093 C2.74202161,51.7201715 4.79761832,55.7299828 7.15775768,59.3122505 C25.4413606,87.0634763 62.001605,89.1563513 62.0066002,54.0178571 L62.0066002,0.625 ", scale: CGPoint(x: -0.333333 * factor, y: 0.333333 * factor), offset: CGPoint(x: (46.0 - UIScreenPixel) * factor, y: (17.0 - UIScreenPixel) * factor)) {
|
||||
bodyPath = path
|
||||
}
|
||||
|
||||
self.arrowBody.path = bodyPath.cgPath
|
||||
self.arrowBody.strokeStart = 0.62
|
||||
self.arrowBody.strokeStart = 0.65
|
||||
}
|
||||
|
||||
override func animateIn(from: RadialStatusNodeState) {
|
||||
override func animateIn(from: RadialStatusNodeState, delay: Double) {
|
||||
if case .progress = from {
|
||||
self.arrowBody.animateStrokeStart(from: 0.62, to: 0.62, duration: 0.25, removeOnCompletion: false, completion: nil)
|
||||
self.arrowBody.animateStrokeEnd(from: 0.62, to: 1.0, duration: 0.25, removeOnCompletion: false, completion: nil)
|
||||
self.arrowBody.animateStrokeStart(from: 0.65, to: 0.65, duration: 0.25, delay: delay, removeOnCompletion: false, completion: nil)
|
||||
self.arrowBody.animateStrokeEnd(from: 0.65, to: 1.0, duration: 0.25, delay: delay, removeOnCompletion: false, completion: nil)
|
||||
|
||||
self.leftLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false)
|
||||
self.rightLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false)
|
||||
self.leftLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.25, delay: delay, removeOnCompletion: false)
|
||||
self.rightLine.animateStrokeEnd(from: 0.0, to: 1.0, duration: 0.25, delay: delay, removeOnCompletion: false)
|
||||
|
||||
self.arrowBody.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false)
|
||||
self.leftLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false)
|
||||
self.rightLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: 0.0, removeOnCompletion: false)
|
||||
self.arrowBody.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: delay, removeOnCompletion: false)
|
||||
self.leftLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: delay, removeOnCompletion: false)
|
||||
self.rightLine.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, delay: delay, removeOnCompletion: false)
|
||||
} else {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||
self.layer.animateScale(from: 0.7, to: 1.0, duration: duration)
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, delay: delay)
|
||||
self.layer.animateScale(from: 0.7, to: 1.0, duration: duration, delay: delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,14 +152,16 @@ private final class RadialProgressContentSpinnerNode: ASDisplayNode {
|
||||
super.willEnterHierarchy()
|
||||
|
||||
let basicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
||||
basicAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
|
||||
basicAnimation.duration = 1.5
|
||||
let fromValue = Float.pi + 0.33
|
||||
var fromValue = Float.pi + 0.58
|
||||
if let presentation = self.layer.presentation(), let value = (presentation.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue {
|
||||
fromValue = value
|
||||
}
|
||||
basicAnimation.fromValue = NSNumber(value: fromValue)
|
||||
basicAnimation.toValue = NSNumber(value: fromValue + Float.pi * 2.0)
|
||||
basicAnimation.repeatCount = Float.infinity
|
||||
basicAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
|
||||
basicAnimation.beginTime = 0.0 //1.0
|
||||
basicAnimation.beginTime = 0.0
|
||||
|
||||
self.layer.add(basicAnimation, forKey: "progressRotation")
|
||||
}
|
||||
@ -274,14 +276,6 @@ final class RadialProgressContentNode: RadialStatusContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func enqueueReadyForTransition(_ f: @escaping () -> Void) {
|
||||
if self.spinnerNode.isAnimatingProgress && self.progress == 1.0 {
|
||||
self.enqueuedReadyForTransition = f
|
||||
} else {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
@ -291,10 +285,9 @@ final class RadialProgressContentNode: RadialStatusContentNode {
|
||||
self.cancelNode.frame = bounds
|
||||
}
|
||||
|
||||
override func prepareAnimateOut(completion: @escaping () -> Void) {
|
||||
self.cancelNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.15, removeOnCompletion: false, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
override func prepareAnimateOut(completion: @escaping (Double) -> Void) {
|
||||
self.cancelNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.15, removeOnCompletion: false, completion: { _ in })
|
||||
completion(0.0)
|
||||
}
|
||||
|
||||
override func animateOut(to: RadialStatusNodeState, completion: @escaping () -> Void) {
|
||||
@ -308,11 +301,11 @@ final class RadialProgressContentNode: RadialStatusContentNode {
|
||||
self.spinnerNode.progress = self.progress
|
||||
}
|
||||
|
||||
override func animateIn(from: RadialStatusNodeState) {
|
||||
override func animateIn(from: RadialStatusNodeState, delay: Double) {
|
||||
if case .download = from {
|
||||
} else {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, delay: delay)
|
||||
}
|
||||
self.cancelNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2)
|
||||
self.cancelNode.layer.animateScale(from: 0.2, to: 1.0, duration: 0.2, delay: delay)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,8 @@ class RadialStatusContentNode: ASDisplayNode {
|
||||
|
||||
private let duration: Double = 0.2
|
||||
|
||||
func prepareAnimateOut(completion: @escaping () -> Void) {
|
||||
completion()
|
||||
func prepareAnimateOut(completion: @escaping (Double) -> Void) {
|
||||
completion(0.0)
|
||||
}
|
||||
|
||||
func animateOut(to: RadialStatusNodeState, completion: @escaping () -> Void) {
|
||||
@ -23,8 +23,8 @@ class RadialStatusContentNode: ASDisplayNode {
|
||||
func prepareAnimateIn(from: RadialStatusNodeState?) {
|
||||
}
|
||||
|
||||
func animateIn(from: RadialStatusNodeState) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration)
|
||||
self.layer.animateScale(from: 0.2, to: 1.0, duration: duration)
|
||||
func animateIn(from: RadialStatusNodeState, delay: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration, delay: delay)
|
||||
self.layer.animateScale(from: 0.2, to: 1.0, duration: duration, delay: delay)
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,23 +173,18 @@ public final class RadialStatusNode: ASControlNode {
|
||||
}
|
||||
}
|
||||
})
|
||||
previousContentNode.prepareAnimateOut(completion: {
|
||||
previousContentNode.prepareAnimateOut(completion: { delay in
|
||||
if let contentNode = strongSelf.contentNode {
|
||||
strongSelf.addSubnode(contentNode)
|
||||
contentNode.frame = strongSelf.bounds
|
||||
contentNode.prepareAnimateIn(from: fromState)
|
||||
if strongSelf.isNodeLoaded {
|
||||
contentNode.layout()
|
||||
contentNode.animateIn(from: fromState)
|
||||
contentNode.animateIn(from: fromState, delay: delay)
|
||||
}
|
||||
}
|
||||
if backgroundColor != nil {
|
||||
strongSelf.transitionToBackgroundColor(backgroundColor, previousContentNode: previousContentNode, animated: animated, completion: completion)
|
||||
}
|
||||
})
|
||||
if backgroundColor == nil {
|
||||
strongSelf.transitionToBackgroundColor(backgroundColor, previousContentNode: previousContentNode, animated: animated, completion: completion)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
previousContentNode.removeFromSupernode()
|
||||
strongSelf.contentNode = strongSelf.nextContentNode
|
||||
|
||||
@ -96,8 +96,8 @@ final class RadialStatusSecretTimeoutContentNode: RadialStatusContentNode {
|
||||
})
|
||||
}
|
||||
|
||||
override func animateIn(from: RadialStatusNodeState) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
override func animateIn(from: RadialStatusNodeState, delay: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: delay)
|
||||
}
|
||||
|
||||
override func willEnterHierarchy() {
|
||||
|
||||
@ -388,7 +388,7 @@ class SearchBarNode: ASDisplayNode, UITextFieldDelegate {
|
||||
}
|
||||
if self.theme != theme {
|
||||
self.backgroundNode.backgroundColor = theme.background
|
||||
if fieldStyle != .modern {
|
||||
if self.fieldStyle != .modern {
|
||||
self.separatorNode.backgroundColor = theme.separator
|
||||
}
|
||||
self.textBackgroundNode.image = generateBackground(foregroundColor: theme.inputFill, diameter: self.fieldStyle.cornerDiameter)
|
||||
|
||||
@ -100,7 +100,6 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
convertedRepresentations.append(ImageRepresentationWithReference(representation: representation, reference: .standalone(resource: representation.resource)))
|
||||
}
|
||||
let dimensions = file.file.dimensions ?? CGSize(width: 100.0, height: 100.0)
|
||||
convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .standalone(resource: file.file.resource)))
|
||||
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: account, fileReference: .standalone(media: file.file), representations: convertedRepresentations, autoFetchFullSize: true))
|
||||
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: dimensions.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
||||
apply()
|
||||
@ -116,13 +115,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: largestImageRepresentation(representations)!.dimensions.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
||||
apply()
|
||||
case let .file(file):
|
||||
var convertedRepresentations: [ImageRepresentationWithReference] = []
|
||||
for representation in file.file.previewRepresentations {
|
||||
convertedRepresentations.append(ImageRepresentationWithReference(representation: representation, reference: .standalone(resource: representation.resource)))
|
||||
}
|
||||
let dimensions = file.file.dimensions ?? CGSize(width: 100.0, height: 100.0)
|
||||
convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .standalone(resource: file.file.resource)))
|
||||
self.imageNode.setSignal(chatAvatarGalleryPhoto(account: account, fileReference: .standalone(media: file.file), representations: convertedRepresentations, autoFetchFullSize: true))
|
||||
let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: dimensions.aspectFilled(size), boundingSize: size, intrinsicInsets: UIEdgeInsets()))
|
||||
apply()
|
||||
}
|
||||
|
||||
@ -112,9 +112,9 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
}
|
||||
|
||||
self.player.addObserver(self, forKeyPath: "rate", options: [], context: nil)
|
||||
playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
|
||||
playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
|
||||
playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
|
||||
self.playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
|
||||
self.playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
|
||||
self.playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
|
||||
|
||||
self._bufferingStatus.set(.single(nil))
|
||||
}
|
||||
|
||||
@ -76,20 +76,18 @@ public final class TelegramRootController: NavigationController {
|
||||
self.rootTabController = tabBarController
|
||||
self.pushViewController(tabBarController, animated: false)
|
||||
|
||||
///TESTBED
|
||||
|
||||
guard let controller = self.viewControllers.last as? ViewController else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) {
|
||||
//(controller.navigationController as? NavigationController)?.pushViewController(ThemeGridController(account: self.account))
|
||||
|
||||
// guard let controller = self.viewControllers.last as? ViewController else {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) {
|
||||
// //(controller.navigationController as? NavigationController)?.pushViewController(ThemeGridController(account: self.account))
|
||||
//
|
||||
// let wrapperNode = ASDisplayNode()
|
||||
// let bounds = controller.displayNode.bounds
|
||||
// wrapperNode.frame = bounds
|
||||
// wrapperNode.backgroundColor = .gray
|
||||
// //controller.displayNode.addSubnode(wrapperNode)
|
||||
// controller.displayNode.addSubnode(wrapperNode)
|
||||
//
|
||||
// let radialStatusSize: CGFloat = 50.0
|
||||
// let statusNode = RadialStatusNode(backgroundNodeColor: UIColor(rgb: 0x000000, alpha: 0.6))
|
||||
@ -107,16 +105,21 @@ public final class TelegramRootController: NavigationController {
|
||||
// smth = false
|
||||
// //statusNode.transitionToState(.play(color), animated: true, completion: {})
|
||||
// statusNode.transitionToState(.download(.white), animated: true, completion: {})
|
||||
// //statusNode.transitionToState(.none, animated: true, completion: {})
|
||||
//// statusNode.transitionToState(.progress(color: color, lineWidth: nil, value: 1.0, cancelEnabled: true), animated: true, completion: {})
|
||||
//// statusNode.transitionToState(.none, animated: true, completion: {
|
||||
//// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.85) {
|
||||
//// statusNode.transitionToState(.download(.white), animated: true, completion: {})
|
||||
//// }
|
||||
//// })
|
||||
// } else {
|
||||
// smth = true
|
||||
// statusNode.transitionToState(.progress(color: color, lineWidth: nil, value: 0.3, cancelEnabled: true), animated: true, completion: {})
|
||||
// statusNode.transitionToState(.progress(color: color, lineWidth: nil, value: 0.1, cancelEnabled: true), animated: true, completion: {})
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// button.addTarget(self, action: #selector(self.mock), forControlEvents: .touchUpInside)
|
||||
// statusNode.transitionToState(.download(.white), animated: false, completion: {})
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
@objc func mock() {
|
||||
|
||||
@ -220,7 +220,7 @@ class ThemeGalleryController: ViewController {
|
||||
wallpaper = value
|
||||
}
|
||||
let _ = (updatePresentationThemeSettingsInteractively(postbox: strongSelf.account.postbox, { current in
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperMode: .still, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperOptions: [], theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
}) |> deliverOnMainQueue).start(completed: {
|
||||
self?.dismiss(forceAway: true)
|
||||
})
|
||||
|
||||
@ -103,6 +103,8 @@ final class ThemeGridController: ViewController {
|
||||
override func loadDisplayNode() {
|
||||
self.displayNode = ThemeGridControllerNode(account: self.account, presentationData: self.presentationData, presentPreviewController: { [weak self] source in
|
||||
if let strongSelf = self {
|
||||
//let controller = WallpaperGalleryController(account: strongSelf.account, source: source)
|
||||
//self?.present(controller, in: .window(.root), with: nil, blockInteraction: true)
|
||||
let controller = WallpaperListPreviewController(account: strongSelf.account, source: source)
|
||||
controller.apply = { [weak self, weak controller] wallpaper, mode, cropRect in
|
||||
if let strongSelf = self {
|
||||
@ -236,7 +238,7 @@ final class ThemeGridController: ViewController {
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
private func uploadCustomWallpaper(_ wallpaper: WallpaperEntry, mode: PresentationWallpaperMode, cropRect: CGRect?) {
|
||||
private func uploadCustomWallpaper(_ wallpaper: WallpaperEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?) {
|
||||
let imageSignal: Signal<UIImage, NoError>
|
||||
switch wallpaper {
|
||||
case .wallpaper:
|
||||
@ -305,7 +307,7 @@ final class ThemeGridController: ViewController {
|
||||
let account = self.account
|
||||
let updateWallpaper: (TelegramWallpaper) -> Void = { wallpaper in
|
||||
let _ = (updatePresentationThemeSettingsInteractively(postbox: account.postbox, { current in
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperMode: mode, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperOptions: mode, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
})).start()
|
||||
}
|
||||
|
||||
@ -315,7 +317,7 @@ final class ThemeGridController: ViewController {
|
||||
|
||||
let _ = uploadWallpaper(account: account, resource: resource).start(next: { status in
|
||||
if case let .complete(wallpaper) = status {
|
||||
if case .blurred = mode, case let .file(_, _, _, _, file, _) = wallpaper {
|
||||
if mode.contains(.blur), case let .file(_, _, _, _, file, _) = wallpaper {
|
||||
let _ = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true).start(completed: {
|
||||
updateWallpaper(wallpaper)
|
||||
})
|
||||
@ -326,7 +328,7 @@ final class ThemeGridController: ViewController {
|
||||
})
|
||||
}
|
||||
|
||||
if case .blurred = mode {
|
||||
if mode.contains(.blur) {
|
||||
let _ = account.postbox.mediaBox.cachedResourceRepresentation(resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true).start(completed: {
|
||||
completion()
|
||||
})
|
||||
|
||||
@ -121,7 +121,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
private var presentationData: PresentationData
|
||||
private var controllerInteraction: ThemeGridControllerInteraction?
|
||||
|
||||
private let presentPreviewController: (WallpaperListPreviewSource) -> Void
|
||||
private let presentPreviewController: (WallpaperListSource) -> Void
|
||||
private let presentGallery: () -> Void
|
||||
private let presentColors: () -> Void
|
||||
private let emptyStateUpdated: (Bool) -> Void
|
||||
@ -161,7 +161,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
|
||||
private var disposable: Disposable?
|
||||
|
||||
init(account: Account, presentationData: PresentationData, presentPreviewController: @escaping (WallpaperListPreviewSource) -> Void, presentGallery: @escaping () -> Void, presentColors: @escaping () -> Void, emptyStateUpdated: @escaping (Bool) -> Void, deleteWallpapers: @escaping ([TelegramWallpaper], @escaping () -> Void) -> Void, shareWallpapers: @escaping ([TelegramWallpaper]) -> Void, popViewController: @escaping () -> Void) {
|
||||
init(account: Account, presentationData: PresentationData, presentPreviewController: @escaping (WallpaperListSource) -> Void, presentGallery: @escaping () -> Void, presentColors: @escaping () -> Void, emptyStateUpdated: @escaping (Bool) -> Void, deleteWallpapers: @escaping ([TelegramWallpaper], @escaping () -> Void) -> Void, shareWallpapers: @escaping ([TelegramWallpaper]) -> Void, popViewController: @escaping () -> Void) {
|
||||
self.account = account
|
||||
self.presentationData = presentationData
|
||||
self.presentPreviewController = presentPreviewController
|
||||
@ -217,7 +217,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
if let entries = entries, !entries.isEmpty {
|
||||
let wallpapers = entries.map { $0.wallpaper }
|
||||
|
||||
var mode: PresentationWallpaperMode?
|
||||
var mode: WallpaperPresentationOptions?
|
||||
if wallpaper == strongSelf.presentationData.chatWallpaper {
|
||||
mode = strongSelf.presentationData.chatWallpaperMode
|
||||
}
|
||||
|
||||
@ -13,11 +13,11 @@ class ThemeSettingsChatPreviewItem: ListViewItem, ItemListItem {
|
||||
let sectionId: ItemListSectionId
|
||||
let fontSize: PresentationFontSize
|
||||
let wallpaper: TelegramWallpaper
|
||||
let wallpaperMode: PresentationWallpaperMode
|
||||
let wallpaperMode: WallpaperPresentationOptions
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let nameDisplayOrder: PresentationPersonNameOrder
|
||||
|
||||
init(account: Account, theme: PresentationTheme, componentTheme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, wallpaper: TelegramWallpaper, wallpaperMode: PresentationWallpaperMode, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder) {
|
||||
init(account: Account, theme: PresentationTheme, componentTheme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, fontSize: PresentationFontSize, wallpaper: TelegramWallpaper, wallpaperMode: WallpaperPresentationOptions, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder) {
|
||||
self.account = account
|
||||
self.theme = theme
|
||||
self.componentTheme = componentTheme
|
||||
@ -139,7 +139,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
|
||||
})
|
||||
case let .image(representations):
|
||||
if let largest = largestImageRepresentation(representations) {
|
||||
if case .blurred = item.wallpaperMode {
|
||||
if item.wallpaperMode.contains(.blur) {
|
||||
var image: UIImage?
|
||||
let _ = item.account.postbox.mediaBox.cachedResourceRepresentation(largest.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in
|
||||
if data.complete {
|
||||
@ -153,7 +153,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
case let .file(file):
|
||||
if case .blurred = item.wallpaperMode {
|
||||
if item.wallpaperMode.contains(.blur) {
|
||||
var image: UIImage?
|
||||
let _ = item.account.postbox.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true, attemptSynchronously: true).start(next: { data in
|
||||
if data.complete {
|
||||
|
||||
@ -35,7 +35,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
case fontSizeHeader(PresentationTheme, String)
|
||||
case fontSize(PresentationTheme, PresentationFontSize)
|
||||
case chatPreviewHeader(PresentationTheme, String)
|
||||
case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationWallpaperMode, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder)
|
||||
case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, WallpaperPresentationOptions, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder)
|
||||
case wallpaper(PresentationTheme, String)
|
||||
case accentColor(PresentationTheme, String, Int32)
|
||||
case autoNightTheme(PresentationTheme, String, String)
|
||||
@ -210,7 +210,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
private func themeSettingsControllerEntries(presentationData: PresentationData, theme: PresentationTheme, themeAccentColor: Int32?, autoNightSettings: AutomaticThemeSwitchSetting, strings: PresentationStrings, wallpaper: TelegramWallpaper, wallpaperMode: PresentationWallpaperMode, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, disableAnimations: Bool) -> [ThemeSettingsControllerEntry] {
|
||||
private func themeSettingsControllerEntries(presentationData: PresentationData, theme: PresentationTheme, themeAccentColor: Int32?, autoNightSettings: AutomaticThemeSwitchSetting, strings: PresentationStrings, wallpaper: TelegramWallpaper, wallpaperMode: WallpaperPresentationOptions, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, disableAnimations: Bool) -> [ThemeSettingsControllerEntry] {
|
||||
var entries: [ThemeSettingsControllerEntry] = []
|
||||
|
||||
entries.append(.fontSizeHeader(presentationData.theme, strings.Appearance_TextSize))
|
||||
@ -270,25 +270,25 @@ public func themeSettingsController(account: Account) -> ViewController {
|
||||
wallpaper = .color(0x18222D)
|
||||
theme = .builtin(.nightAccent)
|
||||
}
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperMode: .still, theme: theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperOptions: [], theme: theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
}).start()
|
||||
}, selectFontSize: { size in
|
||||
let _ = updatePresentationThemeSettingsInteractively(postbox: account.postbox, { current in
|
||||
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, chatWallpaperMode: current.chatWallpaperMode, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: size, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, chatWallpaperOptions: current.chatWallpaperOptions, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: size, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
}).start()
|
||||
}, openWallpaperSettings: {
|
||||
pushControllerImpl?(ThemeGridController(account: account))
|
||||
}, openAccentColor: { color in
|
||||
presentControllerImpl?(ThemeAccentColorActionSheet(account: account, currentValue: color, applyValue: { color in
|
||||
let _ = updatePresentationThemeSettingsInteractively(postbox: account.postbox, { current in
|
||||
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, chatWallpaperMode: current.chatWallpaperMode, theme: current.theme, themeAccentColor: color, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, chatWallpaperOptions: current.chatWallpaperOptions, theme: current.theme, themeAccentColor: color, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
}).start()
|
||||
}))
|
||||
}, openAutoNightTheme: {
|
||||
pushControllerImpl?(themeAutoNightSettingsController(account: account))
|
||||
}, disableAnimations: { disabled in
|
||||
let _ = updatePresentationThemeSettingsInteractively(postbox: account.postbox, { current in
|
||||
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, chatWallpaperMode: current.chatWallpaperMode, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: disabled)
|
||||
return PresentationThemeSettings(chatWallpaper: current.chatWallpaper, chatWallpaperOptions: current.chatWallpaperOptions, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: disabled)
|
||||
}).start()
|
||||
})
|
||||
|
||||
@ -304,7 +304,7 @@ public func themeSettingsController(account: Account) -> ViewController {
|
||||
let theme: PresentationTheme
|
||||
let fontSize: PresentationFontSize
|
||||
let wallpaper: TelegramWallpaper
|
||||
let wallpaperMode: PresentationWallpaperMode
|
||||
let wallpaperMode: WallpaperPresentationOptions
|
||||
let strings: PresentationStrings
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let disableAnimations: Bool
|
||||
@ -324,7 +324,7 @@ public func themeSettingsController(account: Account) -> ViewController {
|
||||
}
|
||||
}
|
||||
wallpaper = settings.chatWallpaper
|
||||
wallpaperMode = settings.chatWallpaperMode
|
||||
wallpaperMode = settings.chatWallpaperOptions
|
||||
fontSize = settings.fontSize
|
||||
|
||||
if let localizationSettings = preferences.values[localizationSettingsKey] as? LocalizationSettings {
|
||||
|
||||
@ -291,11 +291,19 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
|
||||
let location = recognizer.location(in: recognizer.view)
|
||||
let transition = recognizer.translation(in: recognizer.view)
|
||||
let newHue = max(0.0, min(1.0, self.colorHSV.0 + transition.x / size.width))
|
||||
let newSaturation = max(0.0, min(1.0, self.colorHSV.1 - transition.y / (size.height - 66.0)))
|
||||
self.colorHSV.0 = newHue
|
||||
self.colorHSV.1 = newSaturation
|
||||
if recognizer.state == .began {
|
||||
let newHue = max(0.0, min(1.0, location.x / size.width))
|
||||
let newSaturation = max(0.0, min(1.0, (1.0 - location.y / (size.height - 66.0))))
|
||||
self.colorHSV.0 = newHue
|
||||
self.colorHSV.1 = newSaturation
|
||||
} else {
|
||||
let newHue = max(0.0, min(1.0, self.colorHSV.0 + transition.x / size.width))
|
||||
let newSaturation = max(0.0, min(1.0, self.colorHSV.1 - transition.y / (size.height - 66.0)))
|
||||
self.colorHSV.0 = newHue
|
||||
self.colorHSV.1 = newSaturation
|
||||
}
|
||||
|
||||
switch recognizer.state {
|
||||
case .began:
|
||||
|
||||
302
TelegramUI/WallpaperGalleryController.swift
Normal file
302
TelegramUI/WallpaperGalleryController.swift
Normal file
@ -0,0 +1,302 @@
|
||||
import Foundation
|
||||
import Display
|
||||
import QuickLook
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import TelegramCore
|
||||
import Photos
|
||||
|
||||
enum WallpaperListType {
|
||||
case wallpapers(WallpaperPresentationOptions?)
|
||||
case colors
|
||||
}
|
||||
|
||||
enum WallpaperListSource {
|
||||
case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, type: WallpaperListType)
|
||||
case wallpaper(TelegramWallpaper)
|
||||
case slug(String, TelegramMediaFile?)
|
||||
case asset(PHAsset, UIImage?)
|
||||
case contextResult(ChatContextResult)
|
||||
case customColor(Int32?)
|
||||
}
|
||||
|
||||
enum WallpaperGalleryEntry: Equatable {
|
||||
case wallpaper(TelegramWallpaper)
|
||||
case asset(PHAsset, UIImage?)
|
||||
case contextResult(ChatContextResult)
|
||||
|
||||
public static func ==(lhs: WallpaperGalleryEntry, rhs: WallpaperGalleryEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .wallpaper(wallpaper):
|
||||
if case .wallpaper(wallpaper) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .asset(lhsAsset, _):
|
||||
if case let .asset(rhsAsset, _) = rhs, lhsAsset.localIdentifier == rhsAsset.localIdentifier {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .contextResult(lhsResult):
|
||||
if case let .contextResult(rhsResult) = rhs, lhsResult.id == rhsResult.id {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WallpaperGalleryController: ViewController {
|
||||
private var galleryNode: GalleryControllerNode {
|
||||
return self.displayNode as! GalleryControllerNode
|
||||
}
|
||||
|
||||
private let account: Account
|
||||
private let source: WallpaperListSource
|
||||
var apply: ((WallpaperEntry, WallpaperPresentationOptions, CGRect?) -> Void)?
|
||||
|
||||
private let _ready = Promise<Bool>()
|
||||
override var ready: Promise<Bool> {
|
||||
return self._ready
|
||||
}
|
||||
private var didSetReady = false
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private var entries: [WallpaperGalleryEntry] = []
|
||||
private var centralEntryIndex: Int?
|
||||
|
||||
private let centralItemControlsColor = Promise<UIColor>()
|
||||
private let centralItemStatus = Promise<MediaResourceStatus>()
|
||||
private let centralItemAttributesDisposable = DisposableSet();
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
private var toolbarNode: ThemeGalleryToolbarNode?
|
||||
|
||||
init(account: Account, source: WallpaperListSource) {
|
||||
self.account = account
|
||||
self.source = source
|
||||
self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData))
|
||||
|
||||
self.title = self.presentationData.strings.Wallpaper_Title
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style
|
||||
|
||||
switch source {
|
||||
case let .list(wallpapers, central, type):
|
||||
self.entries = wallpapers.map { .wallpaper($0) }
|
||||
self.centralEntryIndex = wallpapers.index(of: central)!
|
||||
|
||||
//if case let .wallpapers(wallpaperMode) = type, let mode = wallpaperMode {
|
||||
// self.segmentedControl.selectedSegmentIndex = Int(clamping: mode.rawValue)
|
||||
//}
|
||||
case let .slug(slug, file):
|
||||
if let file = file {
|
||||
self.entries = [.wallpaper(.file(id: 0, accessHash: 0, isCreator: false, slug: slug, file: file, color: nil))]
|
||||
self.centralEntryIndex = 0
|
||||
}
|
||||
case let .wallpaper(wallpaper):
|
||||
self.entries = [.wallpaper(wallpaper)]
|
||||
self.centralEntryIndex = 0
|
||||
case let .asset(asset, thumbnailImage):
|
||||
self.entries = [.asset(asset, thumbnailImage)]
|
||||
self.centralEntryIndex = 0
|
||||
case let .contextResult(result):
|
||||
self.entries = [.contextResult(result)]
|
||||
self.centralEntryIndex = 0
|
||||
case let .customColor(color):
|
||||
let initialColor = color ?? 0x000000
|
||||
self.entries = [.wallpaper(.color(initialColor))]
|
||||
self.centralEntryIndex = 0
|
||||
}
|
||||
|
||||
// let initialEntries: [ThemeGalleryEntry] = wallpapers.map { ThemeGalleryEntry.wallpaper($0) }
|
||||
// let entriesSignal: Signal<[ThemeGalleryEntry], NoError> = .single(initialEntries)
|
||||
//
|
||||
// self.disposable.set((entriesSignal |> deliverOnMainQueue).start(next: { [weak self] entries in
|
||||
// if let strongSelf = self {
|
||||
// strongSelf.entries = entries
|
||||
// strongSelf.centralEntryIndex = wallpapers.index(of: centralWallpaper)!
|
||||
// if strongSelf.isViewLoaded {
|
||||
// strongSelf.galleryNode.pager.replaceItems(strongSelf.entries.map({ ThemeGalleryItem(account: account, entry: $0) }), centralItemIndex: strongSelf.centralEntryIndex, keepFirst: true)
|
||||
//
|
||||
// let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in
|
||||
// strongSelf?.didSetReady = true
|
||||
// }
|
||||
// strongSelf._ready.set(ready |> map { true })
|
||||
// }
|
||||
// }
|
||||
// }))
|
||||
|
||||
self.presentationDataDisposable = (account.telegramApplicationContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
let previousStrings = strongSelf.presentationData.strings
|
||||
|
||||
strongSelf.presentationData = presentationData
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||
strongSelf.updateThemeAndStrings()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
//self.centralItemAttributesDisposable.add(self.centralItemTitleView.get().start(next: { [weak self] titleView in
|
||||
// self?.navigationItem.titleView = titleView
|
||||
//}))
|
||||
|
||||
// self.centralItemAttributesDisposable.add(self.centralItemFooterContentNode.get().start(next: { [weak self] footerContentNode in
|
||||
// self?.galleryNode.updatePresentationState({
|
||||
// $0.withUpdatedFooterContentNode(footerContentNode)
|
||||
// }, transition: .immediate)
|
||||
// }))
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
self.presentationDataDisposable?.dispose()
|
||||
self.centralItemAttributesDisposable.dispose()
|
||||
}
|
||||
|
||||
private func updateThemeAndStrings() {
|
||||
self.title = self.presentationData.strings.Wallpaper_Title
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style
|
||||
self.toolbarNode?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings)
|
||||
}
|
||||
|
||||
@objc func donePressed() {
|
||||
self.dismiss(forceAway: false)
|
||||
}
|
||||
|
||||
private func dismiss(forceAway: Bool) {
|
||||
let completion = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
|
||||
//self.galleryNode.modalAnimateOut(completion: completion)
|
||||
}
|
||||
|
||||
override func loadDisplayNode() {
|
||||
let controllerInteraction = GalleryControllerInteraction(presentController: { [weak self] controller, arguments in
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { controller, ready in
|
||||
})
|
||||
self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction, pageGap: 0.0)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.statusBar = self.statusBar
|
||||
self.galleryNode.navigationBar = self.navigationBar
|
||||
|
||||
self.galleryNode.transitionDataForCentralItem = { [weak self] in
|
||||
// if let strongSelf = self {
|
||||
// if let centralItemNode = strongSelf.galleryNode.pager.centralItemNode(), let presentationArguments = strongSelf.presentationArguments as? ThemePreviewControllerPresentationArguments {
|
||||
// if let transitionArguments = presentationArguments.transitionArguments(strongSelf.entries[centralItemNode.index]) {
|
||||
// return (transitionArguments.transitionNode, transitionArguments.addToTransitionSurface)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
self.galleryNode.dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
|
||||
self.galleryNode.pager.centralItemIndexUpdated = { [weak self] index in
|
||||
if let strongSelf = self {
|
||||
if let index = index {
|
||||
if let node = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
//strongSelf.centralItemTitle.set(node.title())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.galleryNode.backgroundNode.backgroundColor = nil
|
||||
self.galleryNode.backgroundNode.isOpaque = false
|
||||
self.galleryNode.isBackgroundExtendedOverNavigationBar = true
|
||||
|
||||
let presentationData = self.account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
let toolbarNode = ThemeGalleryToolbarNode(theme: presentationData.theme, strings: presentationData.strings)
|
||||
self.toolbarNode = toolbarNode
|
||||
self.galleryNode.addSubnode(toolbarNode)
|
||||
self.galleryNode.toolbarNode = toolbarNode
|
||||
toolbarNode.cancel = { [weak self] in
|
||||
//self?.dismiss(forceAway: true)
|
||||
}
|
||||
toolbarNode.done = { [weak self] in
|
||||
// if let strongSelf = self {
|
||||
// if let centralItemNode = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
// if !strongSelf.entries.isEmpty {
|
||||
// let wallpaper: TelegramWallpaper
|
||||
// switch strongSelf.entries[centralItemNode.index] {
|
||||
// case let .wallpaper(value):
|
||||
// wallpaper = value
|
||||
// }
|
||||
// let _ = (updatePresentationThemeSettingsInteractively(postbox: strongSelf.account.postbox, { current in
|
||||
// return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperOptions: [], theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
// }) |> deliverOnMainQueue).start(completed: {
|
||||
// self?.dismiss(forceAway: true)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
let ready = self.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak self] _ in
|
||||
self?.didSetReady = true
|
||||
}
|
||||
self._ready.set(ready |> map { true })
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.galleryNode.modalAnimateIn()
|
||||
}
|
||||
|
||||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.galleryNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
self.galleryNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.toolbarNode!, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - 49.0 - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width, height: 49.0 + layout.intrinsicInsets.bottom)))
|
||||
self.toolbarNode!.updateLayout(size: CGSize(width: layout.size.width, height: 49.0), layout: layout, transition: transition)
|
||||
|
||||
let replace = self.validLayout == nil
|
||||
self.validLayout = (layout, 0.0)
|
||||
|
||||
if replace {
|
||||
self.galleryNode.pager.replaceItems(self.entries.map({ WallpaperGalleryItem(account: self.account, entry: $0) }), centralItemIndex: self.centralEntryIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension GalleryControllerNode {
|
||||
func modalAnimateIn(completion: (() -> Void)? = nil) {
|
||||
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
|
||||
func modalAnimateOut(completion: (() -> Void)? = nil) {
|
||||
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: kCAMediaTimingFunctionEaseInEaseOut, removeOnCompletion: false, completion: { _ in
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
}
|
||||
369
TelegramUI/WallpaperGalleryItem.swift
Normal file
369
TelegramUI/WallpaperGalleryItem.swift
Normal file
@ -0,0 +1,369 @@
|
||||
import Foundation
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import LegacyComponents
|
||||
|
||||
class WallpaperGalleryItem: GalleryItem {
|
||||
let account: Account
|
||||
let entry: WallpaperGalleryEntry
|
||||
|
||||
init(account: Account, entry: WallpaperGalleryEntry) {
|
||||
self.account = account
|
||||
self.entry = entry
|
||||
}
|
||||
|
||||
func node() -> GalleryItemNode {
|
||||
let node = WallpaperGalleryItemNode(account: self.account)
|
||||
node.setEntry(self.entry)
|
||||
return node
|
||||
}
|
||||
|
||||
func updateNode(node: GalleryItemNode) {
|
||||
if let node = node as? WallpaperGalleryItemNode {
|
||||
node.setEntry(self.entry)
|
||||
}
|
||||
}
|
||||
|
||||
func thumbnailItem() -> (Int64, GalleryThumbnailItem)? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
let progressDiameter: CGFloat = 50.0
|
||||
|
||||
final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
private let account: Account
|
||||
private var entry: WallpaperGalleryEntry?
|
||||
private var contentSize: CGSize?
|
||||
|
||||
let wrapperNode: ASDisplayNode
|
||||
let imageNode: TransformImageNode
|
||||
private let statusNode: RadialStatusNode
|
||||
private let blurredNode: BlurredImageNode
|
||||
let cropNode: WallpaperCropNode
|
||||
|
||||
fileprivate let _ready = Promise<Void>()
|
||||
private let fetchDisposable = MetaDisposable()
|
||||
private let statusDisposable = MetaDisposable()
|
||||
|
||||
let controlsColor = Promise<UIColor>(.white)
|
||||
let status = Promise<MediaResourceStatus>(.Local)
|
||||
|
||||
init(account: Account) {
|
||||
self.account = account
|
||||
|
||||
self.wrapperNode = ASDisplayNode()
|
||||
self.imageNode = TransformImageNode()
|
||||
self.imageNode.contentAnimations = .subsequentUpdates
|
||||
self.cropNode = WallpaperCropNode()
|
||||
self.statusNode = RadialStatusNode(backgroundNodeColor: UIColor(white: 0.0, alpha: 0.6))
|
||||
self.statusNode.frame = CGRect(x: 0.0, y: 0.0, width: progressDiameter, height: progressDiameter)
|
||||
self.statusNode.isUserInteractionEnabled = false
|
||||
|
||||
self.blurredNode = BlurredImageNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
self.backgroundColor = .black
|
||||
|
||||
self.imageNode.imageUpdated = { [weak self] _ in
|
||||
self?._ready.set(.single(Void()))
|
||||
}
|
||||
|
||||
self.imageNode.view.contentMode = .scaleAspectFill
|
||||
self.imageNode.clipsToBounds = true
|
||||
|
||||
self.addSubnode(self.wrapperNode)
|
||||
self.addSubnode(self.statusNode)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.fetchDisposable.dispose()
|
||||
self.statusDisposable.dispose()
|
||||
}
|
||||
|
||||
var cropRect: CGRect? {
|
||||
guard let entry = self.entry else {
|
||||
return nil
|
||||
}
|
||||
switch entry {
|
||||
case .asset, .contextResult:
|
||||
return self.cropNode.cropRect
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func ready() -> Signal<Void, NoError> {
|
||||
return self._ready.get()
|
||||
}
|
||||
|
||||
fileprivate func setEntry(_ entry: WallpaperGalleryEntry) {
|
||||
if self.entry != entry {
|
||||
self.entry = entry
|
||||
|
||||
let signal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
||||
let fetchSignal: Signal<FetchResourceSourceType, FetchResourceError>
|
||||
let statusSignal: Signal<MediaResourceStatus, NoError>
|
||||
let displaySize: CGSize
|
||||
let contentSize: CGSize
|
||||
|
||||
switch entry {
|
||||
case let .wallpaper(wallpaper):
|
||||
switch wallpaper {
|
||||
case .builtin:
|
||||
displaySize = CGSize(width: 640.0, height: 1136.0)
|
||||
contentSize = displaySize
|
||||
signal = settingsBuiltinWallpaperImage(account: account)
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
case let .color(color):
|
||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||
contentSize = displaySize
|
||||
signal = .never()
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
self.backgroundColor = UIColor(rgb: UInt32(bitPattern: color))
|
||||
case let .file(file):
|
||||
let dimensions = file.file.dimensions ?? CGSize(width: 100.0, height: 100.0)
|
||||
contentSize = dimensions
|
||||
displaySize = dimensions.dividedByScreenScale().integralFloor
|
||||
|
||||
var convertedRepresentations: [ImageRepresentationWithReference] = []
|
||||
for representation in file.file.previewRepresentations {
|
||||
convertedRepresentations.append(ImageRepresentationWithReference(representation: representation, reference: .standalone(resource: representation.resource)))
|
||||
}
|
||||
convertedRepresentations.append(ImageRepresentationWithReference(representation: .init(dimensions: dimensions, resource: file.file.resource), reference: .standalone(resource: file.file.resource)))
|
||||
signal = chatMessageImageFile(account: account, fileReference: .standalone(media: file.file), thumbnail: false)
|
||||
fetchSignal = fetchedMediaResource(postbox: account.postbox, reference: convertedRepresentations[convertedRepresentations.count - 1].reference)
|
||||
statusSignal = account.postbox.mediaBox.resourceStatus(file.file.resource)
|
||||
case let .image(representations):
|
||||
if let largestSize = largestImageRepresentation(representations) {
|
||||
contentSize = largestSize.dimensions
|
||||
displaySize = largestSize.dimensions.dividedByScreenScale().integralFloor
|
||||
|
||||
let convertedRepresentations: [ImageRepresentationWithReference] = representations.map({ ImageRepresentationWithReference(representation: $0, reference: .wallpaper(resource: $0.resource)) })
|
||||
signal = chatAvatarGalleryPhoto(account: account, representations: convertedRepresentations)
|
||||
|
||||
if let largestIndex = convertedRepresentations.index(where: { $0.representation == largestSize }) {
|
||||
fetchSignal = fetchedMediaResource(postbox: account.postbox, reference: convertedRepresentations[largestIndex].reference)
|
||||
} else {
|
||||
fetchSignal = .complete()
|
||||
}
|
||||
statusSignal = account.postbox.mediaBox.resourceStatus(largestSize.resource)
|
||||
} else {
|
||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||
contentSize = displaySize
|
||||
signal = .never()
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
}
|
||||
}
|
||||
self.cropNode.removeFromSupernode()
|
||||
case let .asset(asset, _):
|
||||
let dimensions = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
|
||||
contentSize = dimensions
|
||||
displaySize = dimensions.dividedByScreenScale().integralFloor
|
||||
signal = photoWallpaper(postbox: account.postbox, photoLibraryResource: PhotoLibraryMediaResource(localIdentifier: asset.localIdentifier, uniqueId: arc4random64()))
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
self.wrapperNode.addSubnode(self.cropNode)
|
||||
case let .contextResult(result):
|
||||
var imageDimensions: CGSize?
|
||||
var imageResource: TelegramMediaResource?
|
||||
var thumbnailDimensions: CGSize?
|
||||
var thumbnailResource: TelegramMediaResource?
|
||||
switch result {
|
||||
case let .externalReference(_, _, _, _, _, _, content, thumbnail, _):
|
||||
if let content = content {
|
||||
imageResource = content.resource
|
||||
}
|
||||
if let thumbnail = thumbnail {
|
||||
thumbnailResource = thumbnail.resource
|
||||
thumbnailDimensions = thumbnail.dimensions
|
||||
}
|
||||
if let dimensions = content?.dimensions {
|
||||
imageDimensions = dimensions
|
||||
}
|
||||
case let .internalReference(_, _, _, _, _, image, _, _):
|
||||
if let image = image {
|
||||
if let imageRepresentation = imageRepresentationLargerThan(image.representations, size: CGSize(width: 1000.0, height: 800.0)) {
|
||||
imageDimensions = imageRepresentation.dimensions
|
||||
imageResource = imageRepresentation.resource
|
||||
}
|
||||
if let thumbnailRepresentation = imageRepresentationLargerThan(image.representations, size: CGSize(width: 200.0, height: 100.0)) {
|
||||
thumbnailDimensions = thumbnailRepresentation.dimensions
|
||||
thumbnailResource = thumbnailRepresentation.resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let imageResource = imageResource, let imageDimensions = imageDimensions {
|
||||
contentSize = imageDimensions
|
||||
displaySize = imageDimensions.dividedByScreenScale().integralFloor
|
||||
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
if let thumbnailResource = thumbnailResource, let thumbnailDimensions = thumbnailDimensions {
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: thumbnailDimensions, resource: thumbnailResource))
|
||||
}
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: imageResource))
|
||||
let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil)
|
||||
|
||||
signal = chatMessagePhoto(postbox: account.postbox, photoReference: .standalone(media: tmpImage))
|
||||
fetchSignal = fetchedMediaResource(postbox: account.postbox, reference: .media(media: .standalone(media: tmpImage), resource: imageResource))
|
||||
statusSignal = account.postbox.mediaBox.resourceStatus(imageResource)
|
||||
} else {
|
||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||
contentSize = displaySize
|
||||
signal = .never()
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
}
|
||||
self.wrapperNode.addSubnode(self.cropNode)
|
||||
}
|
||||
self.contentSize = contentSize
|
||||
|
||||
if self.cropNode.supernode == nil {
|
||||
self.imageNode.contentMode = .scaleAspectFill
|
||||
self.wrapperNode.addSubnode(self.imageNode)
|
||||
} else {
|
||||
self.imageNode.contentMode = .scaleToFill
|
||||
}
|
||||
|
||||
let imagePromise = Promise<UIImage?>()
|
||||
self.imageNode.setSignal(signal, dispatchOnDisplayLink: false)
|
||||
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: displaySize, boundingSize: displaySize, intrinsicInsets: UIEdgeInsets()))()
|
||||
self.imageNode.imageUpdated = { [weak self] image in
|
||||
if let strongSelf = self {
|
||||
var image = image
|
||||
if let scaledImage = image {
|
||||
if scaledImage.size.width > 2048.0 || scaledImage.size.height > 2048.0 {
|
||||
image = TGScaleImageToPixelSize(image, scaledImage.size.fitted(CGSize(width: 2048.0, height: 2048.0)))
|
||||
}
|
||||
}
|
||||
strongSelf.blurredNode.image = image
|
||||
imagePromise.set(.single(image))
|
||||
}
|
||||
}
|
||||
self.fetchDisposable.set(fetchSignal.start())
|
||||
|
||||
let statusForegroundColor = UIColor.white
|
||||
self.statusDisposable.set((statusSignal
|
||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||
if let strongSelf = self {
|
||||
let state: RadialStatusNodeState
|
||||
switch status {
|
||||
case let .Fetching(_, progress):
|
||||
let adjustedProgress = max(progress, 0.027)
|
||||
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: false)
|
||||
case .Local:
|
||||
state = .none
|
||||
case .Remote:
|
||||
state = .progress(color: statusForegroundColor, lineWidth: nil, value: 0.027, cancelEnabled: false)
|
||||
}
|
||||
strongSelf.statusNode.transitionToState(state, completion: {})
|
||||
}
|
||||
}))
|
||||
|
||||
let controlsColorSignal: Signal<UIColor, NoError>
|
||||
if case let .wallpaper(wallpaper) = entry {
|
||||
controlsColorSignal = chatBackgroundContrastColor(wallpaper: wallpaper, postbox: account.postbox)
|
||||
} else {
|
||||
controlsColorSignal = backgroundContrastColor(for: imagePromise.get())
|
||||
}
|
||||
self.controlsColor.set(.single(.white) |> then(controlsColorSignal))
|
||||
self.status.set(statusSignal)
|
||||
}
|
||||
}
|
||||
|
||||
func setParallaxEnabled(_ enabled: Bool) {
|
||||
if enabled {
|
||||
let amount = 24.0
|
||||
|
||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||
horizontal.minimumRelativeValue = -amount
|
||||
horizontal.maximumRelativeValue = amount
|
||||
|
||||
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
||||
vertical.minimumRelativeValue = -amount
|
||||
vertical.maximumRelativeValue = amount
|
||||
|
||||
let group = UIMotionEffectGroup()
|
||||
group.motionEffects = [horizontal, vertical]
|
||||
self.wrapperNode.view.addMotionEffect(group)
|
||||
} else {
|
||||
for effect in self.imageNode.view.motionEffects {
|
||||
self.wrapperNode.view.removeMotionEffect(effect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setBlurEnabled(_ enabled: Bool, animated: Bool) {
|
||||
let blurRadius: CGFloat = 45.0
|
||||
|
||||
if enabled {
|
||||
if self.blurredNode.supernode == nil {
|
||||
if self.cropNode.supernode != nil {
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
self.imageNode.addSubnode(self.blurredNode)
|
||||
} else {
|
||||
self.blurredNode.frame = self.imageNode.frame
|
||||
self.addSubnode(self.blurredNode)
|
||||
}
|
||||
}
|
||||
|
||||
if animated {
|
||||
self.blurredNode.blurView.blurRadius = 0.0
|
||||
UIView.animate(withDuration: 0.3, delay: 0.0, options: UIViewAnimationOptions(rawValue: 7 << 16), animations: {
|
||||
self.blurredNode.blurView.blurRadius = blurRadius
|
||||
}, completion: nil)
|
||||
} else {
|
||||
self.blurredNode.blurView.blurRadius = blurRadius
|
||||
}
|
||||
} else {
|
||||
if self.blurredNode.supernode != nil {
|
||||
if animated {
|
||||
UIView.animate(withDuration: 0.3, delay: 0.0, options: UIViewAnimationOptions(rawValue: 7 << 16), animations: {
|
||||
self.blurredNode.blurView.blurRadius = 0.0
|
||||
}, completion: { finished in
|
||||
if finished {
|
||||
self.blurredNode.removeFromSupernode()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
self.blurredNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func visibilityUpdated(isVisible: Bool) {
|
||||
super.visibilityUpdated(isVisible: isVisible)
|
||||
}
|
||||
|
||||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
super.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition)
|
||||
|
||||
self.wrapperNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||
if self.cropNode.supernode == nil {
|
||||
self.imageNode.frame = self.wrapperNode.bounds
|
||||
self.blurredNode.frame = self.imageNode.frame
|
||||
} else {
|
||||
self.cropNode.frame = self.wrapperNode.bounds
|
||||
self.cropNode.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
if self.cropNode.supernode != nil, let contentSize = self.contentSize, self.cropNode.zoomableContent == nil {
|
||||
let fittedSize = TGScaleToFit(self.cropNode.bounds.size, contentSize)
|
||||
self.cropNode.zoomableContent = (contentSize, self.imageNode)
|
||||
self.cropNode.zoom(to: CGRect(x: (contentSize.width - fittedSize.width) / 2.0, y: (contentSize.height - fittedSize.height) / 2.0, width: fittedSize.width, height: fittedSize.height))
|
||||
}
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
}
|
||||
|
||||
self.statusNode.frame = CGRect(x: layout.safeInsets.left + floorToScreenPixels((layout.size.width - layout.safeInsets.left - layout.safeInsets.right - progressDiameter) / 2.0), y: floorToScreenPixels((layout.size.height - progressDiameter) / 2.0), width: progressDiameter, height: progressDiameter)
|
||||
}
|
||||
}
|
||||
@ -6,20 +6,6 @@ import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import Photos
|
||||
|
||||
enum WallpaperListType {
|
||||
case wallpapers(PresentationWallpaperMode?)
|
||||
case colors
|
||||
}
|
||||
|
||||
enum WallpaperListPreviewSource {
|
||||
case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, type: WallpaperListType)
|
||||
case wallpaper(TelegramWallpaper)
|
||||
case slug(String, TelegramMediaFile?)
|
||||
case asset(PHAsset, UIImage?)
|
||||
case contextResult(ChatContextResult)
|
||||
case customColor(Int32?)
|
||||
}
|
||||
|
||||
final class WallpaperListPreviewController: ViewController {
|
||||
private var controllerNode: WallpaperListPreviewControllerNode {
|
||||
return self.displayNode as! WallpaperListPreviewControllerNode
|
||||
@ -31,7 +17,7 @@ final class WallpaperListPreviewController: ViewController {
|
||||
}
|
||||
|
||||
private let account: Account
|
||||
private let source: WallpaperListPreviewSource
|
||||
private let source: WallpaperListSource
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
@ -41,9 +27,9 @@ final class WallpaperListPreviewController: ViewController {
|
||||
|
||||
private var didPlayPresentationAnimation = false
|
||||
|
||||
var apply: ((WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void)?
|
||||
var apply: ((WallpaperEntry, WallpaperPresentationOptions, CGRect?) -> Void)?
|
||||
|
||||
init(account: Account, source: WallpaperListPreviewSource) {
|
||||
init(account: Account, source: WallpaperListSource) {
|
||||
self.account = account
|
||||
self.source = source
|
||||
|
||||
@ -121,7 +107,7 @@ final class WallpaperListPreviewController: ViewController {
|
||||
case let .wallpaper(wallpaper):
|
||||
let completion: () -> Void = {
|
||||
let _ = (updatePresentationThemeSettingsInteractively(postbox: strongSelf.account.postbox, { current in
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperMode: mode, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
return PresentationThemeSettings(chatWallpaper: wallpaper, chatWallpaperOptions: mode, theme: current.theme, themeAccentColor: current.themeAccentColor, fontSize: current.fontSize, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, disableAnimations: current.disableAnimations)
|
||||
})
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
self?.dismiss()
|
||||
@ -133,7 +119,7 @@ final class WallpaperListPreviewController: ViewController {
|
||||
let _ = installWallpaper(account: strongSelf.account, wallpaper: wallpaper).start()
|
||||
}
|
||||
|
||||
if case .blurred = mode {
|
||||
if mode.contains(.blur) {
|
||||
var resource: MediaResource?
|
||||
switch wallpaper {
|
||||
case let .file(file):
|
||||
|
||||
@ -195,7 +195,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
self.imageNode.contentMode = .scaleAspectFill
|
||||
self.wrapperNode.addSubnode(self.imageNode)
|
||||
}
|
||||
self.wrapperNode.addSubnode(self.statusNode)
|
||||
self.addSubnode(self.statusNode)
|
||||
|
||||
let imagePromise = Promise<UIImage?>()
|
||||
self.imageNode.setSignal(signal, dispatchOnDisplayLink: false)
|
||||
@ -258,7 +258,7 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
|
||||
func setParallaxEnabled(_ enabled: Bool) {
|
||||
if enabled {
|
||||
let amount = 16.0
|
||||
let amount = 24.0
|
||||
|
||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||
horizontal.minimumRelativeValue = -amount
|
||||
@ -342,9 +342,9 @@ private final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
|
||||
private let account: Account
|
||||
private var presentationData: PresentationData
|
||||
private let source: WallpaperListPreviewSource
|
||||
private let source: WallpaperListSource
|
||||
private let dismiss: () -> Void
|
||||
private let apply: (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void
|
||||
private let apply: (WallpaperEntry, WallpaperPresentationOptions, CGRect?) -> Void
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
@ -380,7 +380,7 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
private var visibleBackgroundNodesOffset: CGFloat = 0.0
|
||||
|
||||
init(account: Account, presentationData: PresentationData, source: WallpaperListPreviewSource, dismiss: @escaping () -> Void, apply: @escaping (WallpaperEntry, PresentationWallpaperMode, CGRect?) -> Void) {
|
||||
init(account: Account, presentationData: PresentationData, source: WallpaperListSource, dismiss: @escaping () -> Void, apply: @escaping (WallpaperEntry, WallpaperPresentationOptions, CGRect?) -> Void) {
|
||||
self.account = account
|
||||
self.presentationData = presentationData
|
||||
self.source = source
|
||||
@ -843,15 +843,13 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
@objc private func indexChanged() {
|
||||
guard let mode = PresentationWallpaperMode(rawValue: Int32(self.segmentedControl.selectedSegmentIndex)) else {
|
||||
return
|
||||
}
|
||||
|
||||
let index = self.segmentedControl.selectedSegmentIndex
|
||||
|
||||
if let node = self.centralNode() {
|
||||
if mode == .perspective {
|
||||
if index == 1 {
|
||||
node.setParallaxEnabled(true)
|
||||
node.setBlurEnabled(false, animated: true)
|
||||
} else if mode == .blurred {
|
||||
} else if index == 2 {
|
||||
node.setParallaxEnabled(false)
|
||||
node.setBlurEnabled(true, animated: true)
|
||||
} else {
|
||||
@ -867,16 +865,16 @@ final class WallpaperListPreviewControllerNode: ViewControllerTracingNode {
|
||||
|
||||
@objc private func applyPressed() {
|
||||
if let wallpaper = self.centralWallpaper {
|
||||
let mode: PresentationWallpaperMode
|
||||
var options: WallpaperPresentationOptions = []
|
||||
switch self.segmentedControl.selectedSegmentIndex {
|
||||
case 1:
|
||||
mode = .perspective
|
||||
options.insert(.motion)
|
||||
case 2:
|
||||
mode = .blurred
|
||||
options.insert(.blur)
|
||||
default:
|
||||
mode = .still
|
||||
break
|
||||
}
|
||||
self.apply(wallpaper, mode, self.centralNode()?.cropRect)
|
||||
self.apply(wallpaper, options, self.centralNode()?.cropRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user