Download animations and navigation bar fixes

This commit is contained in:
Ilya Laktyushin 2019-01-16 21:32:32 +04:00
parent c9631285bf
commit 06fc9e6aab
30 changed files with 907 additions and 213 deletions

View File

@ -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 */,

View File

@ -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 {

View File

@ -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

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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)

View 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)
}
})
}

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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() {

View File

@ -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)

View File

@ -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()
}

View File

@ -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))
}

View File

@ -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() {

View File

@ -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)
})

View File

@ -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()
})

View File

@ -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
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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:

View 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?()
})
}
}

View 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)
}
}

View File

@ -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):

View 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)
}
}
}