From d60588b3f1c8b94b5eced941db56308904cdb846 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 22 Oct 2021 18:59:41 +0400 Subject: [PATCH 1/2] Various Improvements --- ...onSequenceCountrySelectionController.swift | 1 - ...quenceCountrySelectionControllerNode.swift | 8 +- submodules/Display/Source/GenerateImage.swift | 27 +- .../Sources/InviteLinkEditController.swift | 24 +- .../Sources/InviteLinkListController.swift | 6 +- .../Sources/InviteLinkViewController.swift | 13 +- .../Sources/InviteRequestsController.swift | 83 ++++-- .../Sources/InviteRequestsSearchItem.swift | 86 +++++- .../Sources/ItemListInviteRequestItem.swift | 3 +- .../Sources/ListMessageSnippetItemNode.swift | 10 +- .../Sources/LocationViewControllerNode.swift | 11 +- .../Sources/ThemeCarouselItem.swift | 2 +- .../Sources/ThemePickerController.swift | 270 +++++++++++------- .../Sources/Themes/EditThemeController.swift | 8 +- .../Themes/ThemeAccentColorController.swift | 6 +- .../ThemeAutoNightSettingsController.swift | 2 +- .../Themes/ThemeSettingsController.swift | 3 +- .../Themes/ThemeSettingsThemeItem.swift | 11 +- .../Sources/SolidRoundedButtonNode.swift | 5 +- .../SyncCore/SyncCore_TelegramTheme.swift | 2 +- .../Themes/TelegramEngineThemes.swift | 4 + .../Sources/PresentationData.swift | 9 +- .../Resources/PresentationResourceKey.swift | 1 + .../PresentationResourcesItemList.swift | 6 + .../Settings/EditTheme.imageset/Contents.json | 12 + .../Settings/EditTheme.imageset/colors_30.pdf | 212 ++++++++++++++ .../Sources/ThemeUpdateManager.swift | 2 +- .../Sources/WallpaperUploadManager.swift | 2 +- .../Sources/PresentationThemeSettings.swift | 45 ++- .../Sources/WallpaperResources.swift | 22 +- 30 files changed, 690 insertions(+), 206 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/colors_30.pdf diff --git a/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift b/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift index 383977cb28..0754461c56 100644 --- a/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift +++ b/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionController.swift @@ -143,7 +143,6 @@ private final class AuthorizationSequenceCountrySelectionNavigationContentNode: self.addSubnode(self.searchBar) self.searchBar.cancel = { [weak self] in - //self?.searchBar.deactivate(clear: false) self?.cancel() } diff --git a/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionControllerNode.swift b/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionControllerNode.swift index b8df9acdae..7e22571f46 100644 --- a/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionControllerNode.swift +++ b/submodules/CountrySelectionUI/Sources/AuthorizationSequenceCountrySelectionControllerNode.swift @@ -162,7 +162,13 @@ private func searchCountries(items: [((String, String), String, [Int])], query: var result: [((String, String), String, Int)] = [] for item in items { - let string = "\(item.0) \(item.1)" + let componentsOne = item.0.0.components(separatedBy: " ") + let abbrOne = componentsOne.compactMap { $0.first.flatMap { String($0) } }.reduce(into: String(), { $0.append(contentsOf: $1) }).replacingOccurrences(of: "&", with: "") + + let componentsTwo = item.0.0.components(separatedBy: " ") + let abbrTwo = componentsTwo.compactMap { $0.first.flatMap { String($0) } }.reduce(into: String(), { $0.append(contentsOf: $1) }).replacingOccurrences(of: "&", with: "") + + let string = "\(item.0.0) \((item.0.1)) \(item.1) \(abbrOne) \(abbrTwo)" let tokens = stringTokens(string) if matchStringTokens(tokens, with: queryTokens) { for code in item.2 { diff --git a/submodules/Display/Source/GenerateImage.swift b/submodules/Display/Source/GenerateImage.swift index 83a49888c7..a3a1775129 100644 --- a/submodules/Display/Source/GenerateImage.swift +++ b/submodules/Display/Source/GenerateImage.swift @@ -687,6 +687,7 @@ public func readCGFloat(_ index: inout UnsafePointer, end: UnsafePointer< public func drawSvgPath(_ context: CGContext, path: StaticString, strokeOnMove: Bool = false) throws { var index: UnsafePointer = path.utf8Start let end = path.utf8Start.advanced(by: path.utf8CodeUnitCount) + var currentPoint = CGPoint() while index < end { let c = index.pointee index = index.successor() @@ -696,18 +697,32 @@ public func drawSvgPath(_ context: CGContext, path: StaticString, strokeOnMove: let y = try readCGFloat(&index, end: end, separator: 32) //print("Move to \(x), \(y)") - context.move(to: CGPoint(x: x, y: y)) + currentPoint = CGPoint(x: x, y: y) + context.move(to: currentPoint) } else if c == 76 { // L let x = try readCGFloat(&index, end: end, separator: 44) let y = try readCGFloat(&index, end: end, separator: 32) //print("Line to \(x), \(y)") - context.addLine(to: CGPoint(x: x, y: y)) + currentPoint = CGPoint(x: x, y: y) + context.addLine(to: currentPoint) if strokeOnMove { context.strokePath() - context.move(to: CGPoint(x: x, y: y)) + context.move(to: currentPoint) } + } else if c == 72 { // H + let x = try readCGFloat(&index, end: end, separator: 32) + + //print("Move to \(x), \(y)") + currentPoint = CGPoint(x: x, y: currentPoint.y) + context.addLine(to: currentPoint) + } else if c == 86 { // V + let y = try readCGFloat(&index, end: end, separator: 32) + + //print("Move to \(x), \(y)") + currentPoint = CGPoint(x: currentPoint.x, y: y) + context.addLine(to: currentPoint) } else if c == 67 { // C let x1 = try readCGFloat(&index, end: end, separator: 44) let y1 = try readCGFloat(&index, end: end, separator: 32) @@ -715,12 +730,14 @@ public func drawSvgPath(_ context: CGContext, path: StaticString, strokeOnMove: let y2 = try readCGFloat(&index, end: end, separator: 32) let x = try readCGFloat(&index, end: end, separator: 44) let y = try readCGFloat(&index, end: end, separator: 32) - context.addCurve(to: CGPoint(x: x, y: y), control1: CGPoint(x: x1, y: y1), control2: CGPoint(x: x2, y: y2)) + + currentPoint = CGPoint(x: x, y: y) + context.addCurve(to: currentPoint, control1: CGPoint(x: x1, y: y1), control2: CGPoint(x: x2, y: y2)) //print("Line to \(x), \(y)") if strokeOnMove { context.strokePath() - context.move(to: CGPoint(x: x, y: y)) + context.move(to: currentPoint) } } else if c == 90 { // Z if index != end && index.pointee != 32 { diff --git a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift index bd5bc8f6fc..c84fdf038b 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift @@ -306,15 +306,15 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { } } -private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: InviteLinkEditControllerState, presentationData: PresentationData) -> [InviteLinksEditEntry] { +private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: InviteLinkEditControllerState, isGroup: Bool, isPublic: Bool, presentationData: PresentationData) -> [InviteLinksEditEntry] { var entries: [InviteLinksEditEntry] = [] entries.append(.requestApproval(presentationData.theme, presentationData.strings.InviteLink_Create_RequestApproval, state.requestApproval)) var requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel if state.requestApproval { - requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOnInfoChannel + requestApprovalInfoText = isGroup ? presentationData.strings.InviteLink_Create_RequestApprovalOnInfoGroup : presentationData.strings.InviteLink_Create_RequestApprovalOnInfoChannel } else { - requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel + requestApprovalInfoText = isGroup ? presentationData.strings.InviteLink_Create_RequestApprovalOnInfoGroup : presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel } entries.append(.requestApprovalInfo(presentationData.theme, requestApprovalInfoText)) @@ -460,9 +460,14 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let previousState = Atomic(value: nil) - let signal = combineLatest(presentationData, statePromise.get()) + let signal = combineLatest( + presentationData, + statePromise.get(), + context.engine.data.subscribe( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + )) |> deliverOnMainQueue - |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, state, peer -> (ItemListControllerState, (ItemListNodeState, Any)) in let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { dismissImpl?() }) @@ -524,8 +529,15 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio animateChanges = true } + let isGroup: Bool + if case let .channel(channel) = peer, case .broadcast = channel.info { + isGroup = false + } else { + isGroup = true + } + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(invite == nil ? presentationData.strings.InviteLink_Create_Title : presentationData.strings.InviteLink_Create_EditTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkEditControllerEntries(invite: invite, state: state, presentationData: presentationData), style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkEditControllerEntries(invite: invite, state: state, isGroup: isGroup, isPublic: !(peer?.addressName?.isEmpty ?? true), presentationData: presentationData), style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges) return (controllerState, (listState, arguments)) } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift index b408548374..9e55622cfc 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift @@ -784,7 +784,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio }))) } - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node, blurBackground: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node, keepInPlace: false, blurBackground: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) presentInGlobalOverlayImpl?(contextController) }, openAdmin: { admin in let controller = inviteLinkListController(context: context, peerId: peerId, admin: admin) @@ -957,10 +957,10 @@ final class InviteLinkContextExtractedContentSource: ContextExtractedContentSour private let controller: ViewController private let sourceNode: ContextExtractedContentContainingNode - init(controller: ViewController, sourceNode: ContextExtractedContentContainingNode, blurBackground: Bool) { + init(controller: ViewController, sourceNode: ContextExtractedContentContainingNode, keepInPlace: Bool, blurBackground: Bool) { self.controller = controller self.sourceNode = sourceNode - self.keepInPlace = true + self.keepInPlace = keepInPlace self.blurBackground = blurBackground } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index 6b17f12d5b..10a494e048 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -808,17 +808,19 @@ public final class InviteLinkViewController: ViewController { } let navigationController = parentController.navigationController as? NavigationController - self.controller?.dismiss() - + + let invitationsContext = parentController.invitationsContext let revokedInvitationsContext = parentController.revokedInvitationsContext if let navigationController = navigationController { let updatedPresentationData = (self.presentationData, parentController.presentationDataPromise.get()) - let controller = inviteLinkEditController(context: self.context, updatedPresentationData: updatedPresentationData, peerId: self.peerId, invite: self.invite, completion: { invite in + let controller = inviteLinkEditController(context: self.context, updatedPresentationData: updatedPresentationData, peerId: self.peerId, invite: self.invite, completion: { [weak self] invite in if let invite = invite { if invite.isRevoked { invitationsContext?.remove(invite) revokedInvitationsContext?.add(invite.withUpdated(isRevoked: true)) + + self?.controller?.dismiss() } else { invitationsContext?.update(invite) } @@ -934,7 +936,6 @@ public final class InviteLinkViewController: ViewController { var titleText = self.presentationData.strings.InviteLink_InviteLink - var subtitleText = "" var subtitleColor = self.presentationData.theme.list.itemSecondaryTextColor if self.invite.isRevoked { @@ -981,11 +982,11 @@ public final class InviteLinkViewController: ViewController { transition.updateFrame(node: self.titleNode, frame: titleFrame) let editSize = self.editButton.measure(CGSize(width: layout.size.width, height: headerHeight)) - let editFrame = CGRect(origin: CGPoint(x: 16.0, y: 18.0), size: editSize) + let editFrame = CGRect(origin: CGPoint(x: 16.0 + layout.safeInsets.left, y: 18.0), size: editSize) transition.updateFrame(node: self.editButton, frame: editFrame) let doneSize = self.doneButton.measure(CGSize(width: layout.size.width, height: headerHeight)) - let doneFrame = CGRect(origin: CGPoint(x: layout.size.width - doneSize.width - 16.0, y: 18.0), size: doneSize) + let doneFrame = CGRect(origin: CGPoint(x: layout.size.width - doneSize.width - 16.0 - layout.safeInsets.right, y: 18.0), size: doneSize) transition.updateFrame(node: self.doneButton, frame: doneFrame) } diff --git a/submodules/InviteLinksUI/Sources/InviteRequestsController.swift b/submodules/InviteLinksUI/Sources/InviteRequestsController.swift index 5aef68b6f7..5e86a712f9 100644 --- a/submodules/InviteLinksUI/Sources/InviteRequestsController.swift +++ b/submodules/InviteLinksUI/Sources/InviteRequestsController.swift @@ -160,6 +160,7 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? var presentInGlobalOverlayImpl: ((ViewController) -> Void)? var navigateToProfileImpl: ((EnginePeer) -> Void)? + var navigateToChatImpl: ((EnginePeer) -> Void)? var dismissInputImpl: (() -> Void)? var dismissTooltipsImpl: (() -> Void)? @@ -214,33 +215,56 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio guard let node = node as? ContextExtractedContentContainingNode else { return } - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - var items: [ContextMenuItem] = [] + + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ) + |> deliverOnMainQueue).start(next: { peer in + guard let peer = peer else { + return + } + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let addString: String + if case let .channel(channel) = peer, case .broadcast = channel.info { + addString = presentationData.strings.MemberRequests_AddToChannel + } else { + addString = presentationData.strings.MemberRequests_AddToGroup + } + var items: [ContextMenuItem] = [] - items.append(.action(ContextMenuActionItem(text: presentationData.strings.MemberRequests_AddToGroup, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) - }, action: { _, f in - f(.dismissWithoutContent) + items.append(.action(ContextMenuActionItem(text: addString, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + + approveRequestImpl(peer) + }))) - approveRequestImpl(peer) - }))) - - items.append(.action(ContextMenuActionItem(text: presentationData.strings.MemberRequests_Dismiss, textColor: .destructive, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) - }, action: { _, f in - f(.dismissWithoutContent) + items.append(.action(ContextMenuActionItem(text: presentationData.strings.ContactList_Context_SendMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + + navigateToChatImpl?(peer) + }))) - denyRequestImpl(peer) - }))) - - let dismissPromise = ValuePromise(false) - let source = InviteRequestsContextExtractedContentSource(sourceNode: node, keepInPlace: false, blurBackground: true, centerVertically: true, shouldBeDismissed: dismissPromise.get()) -// sourceNode.requestDismiss = { -// dismissPromise.set(true) -// } - - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(source), items: .single(ContextController.Items(items: items)), gesture: gesture) - presentInGlobalOverlayImpl?(contextController) + items.append(.action(ContextMenuActionItem(text: presentationData.strings.MemberRequests_Dismiss, textColor: .destructive, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) + }, action: { _, f in + f(.dismissWithoutContent) + + denyRequestImpl(peer) + }))) + + let dismissPromise = ValuePromise(false) + let source = InviteRequestsContextExtractedContentSource(sourceNode: node, keepInPlace: false, blurBackground: true, centerVertically: true, shouldBeDismissed: dismissPromise.get()) + // sourceNode.requestDismiss = { + // dismissPromise.set(true) + // } + + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(source), items: .single(ContextController.Items(items: items)), gesture: gesture) + presentInGlobalOverlayImpl?(contextController) + }) }) let previousEntries = Atomic<[InviteRequestsEntry]>(value: []) @@ -298,10 +322,14 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio arguments.approveRequest(peer) }, denyRequest: { peer in arguments.denyRequest(peer) + }, navigateToChat: { peer in + navigateToChatImpl?(peer) }, pushController: { c in pushControllerImpl?(c) }, dismissInput: { dismissInputImpl?() + }, presentInGlobalOverlay: { c in + presentInGlobalOverlayImpl?(c) }) } @@ -347,6 +375,11 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio navigationController.pushViewController(controller) } } + navigateToChatImpl = { [weak controller] peer in + if let navigationController = controller?.navigationController as? NavigationController { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer.id))) + } + } dismissInputImpl = { [weak controller] in controller?.view.endEditing(true) } @@ -367,7 +400,7 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio } -private final class InviteRequestsContextExtractedContentSource: ContextExtractedContentSource { +final class InviteRequestsContextExtractedContentSource: ContextExtractedContentSource { var keepInPlace: Bool let ignoreContentTouches: Bool = false let blurBackground: Bool diff --git a/submodules/InviteLinksUI/Sources/InviteRequestsSearchItem.swift b/submodules/InviteLinksUI/Sources/InviteRequestsSearchItem.swift index c2d3ce7487..31654a74b2 100644 --- a/submodules/InviteLinksUI/Sources/InviteRequestsSearchItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteRequestsSearchItem.swift @@ -15,6 +15,7 @@ import MergeLists import ChatListSearchItemHeader import ItemListUI import SearchUI +import ContextUI private let searchBarFont = Font.regular(17.0) @@ -101,22 +102,26 @@ final class InviteRequestsSearchItem: ItemListControllerSearch { let openPeer: (EnginePeer) -> Void let approveRequest: (EnginePeer) -> Void let denyRequest: (EnginePeer) -> Void + let navigateToChat: (EnginePeer) -> Void let pushController: (ViewController) -> Void + let presentInGlobalOverlay: (ViewController) -> Void let dismissInput: () -> Void private var updateActivity: ((Bool) -> Void)? private var activity: ValuePromise = ValuePromise(ignoreRepeated: false) private let activityDisposable = MetaDisposable() - init(context: AccountContext, peerId: PeerId, cancel: @escaping () -> Void, openPeer: @escaping (EnginePeer) -> Void, approveRequest: @escaping (EnginePeer) -> Void, denyRequest: @escaping (EnginePeer) -> Void, pushController: @escaping (ViewController) -> Void, dismissInput: @escaping () -> Void) { + init(context: AccountContext, peerId: PeerId, cancel: @escaping () -> Void, openPeer: @escaping (EnginePeer) -> Void, approveRequest: @escaping (EnginePeer) -> Void, denyRequest: @escaping (EnginePeer) -> Void, navigateToChat: @escaping (EnginePeer) -> Void, pushController: @escaping (ViewController) -> Void, dismissInput: @escaping () -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) { self.context = context self.peerId = peerId self.cancel = cancel self.openPeer = openPeer self.approveRequest = approveRequest self.denyRequest = denyRequest + self.navigateToChat = navigateToChat self.pushController = pushController self.dismissInput = dismissInput + self.presentInGlobalOverlay = presentInGlobalOverlay self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal in if value { return .single(value) |> delay(0.2, queue: Queue.mainQueue()) @@ -159,25 +164,27 @@ final class InviteRequestsSearchItem: ItemListControllerSearch { } func node(current: ItemListControllerSearchNode?, titleContentNode: (NavigationBarContentNode & ItemListControllerSearchNavigationContentNode)?) -> ItemListControllerSearchNode { - return InviteRequestsSearchItemNode(context: self.context, peerId: self.peerId, openPeer: self.openPeer, approveRequest: self.approveRequest, denyRequest: self.denyRequest, cancel: self.cancel, updateActivity: { [weak self] value in + return InviteRequestsSearchItemNode(context: self.context, peerId: self.peerId, openPeer: self.openPeer, approveRequest: self.approveRequest, denyRequest: self.denyRequest, navigateToChat: self.navigateToChat, cancel: self.cancel, updateActivity: { [weak self] value in self?.activity.set(value) }, pushController: { [weak self] c in self?.pushController(c) - }, dismissInput: self.dismissInput) + }, dismissInput: self.dismissInput, presentInGlobalOverlay: self.presentInGlobalOverlay) } } private final class InviteRequestsSearchItemNode: ItemListControllerSearchNode { private let containerNode: InviteRequestsSearchContainerNode - init(context: AccountContext, peerId: PeerId, openPeer: @escaping (EnginePeer) -> Void, approveRequest: @escaping (EnginePeer) -> Void, denyRequest: @escaping (EnginePeer) -> Void, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, dismissInput: @escaping () -> Void) { + init(context: AccountContext, peerId: PeerId, openPeer: @escaping (EnginePeer) -> Void, approveRequest: @escaping (EnginePeer) -> Void, denyRequest: @escaping (EnginePeer) -> Void, navigateToChat: @escaping (EnginePeer) -> Void, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, dismissInput: @escaping () -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) { self.containerNode = InviteRequestsSearchContainerNode(context: context, forceTheme: nil, peerId: peerId, openPeer: { peer in openPeer(peer) }, approveRequest: { peer in approveRequest(peer) }, denyRequest: { peer in denyRequest(peer) - }, updateActivity: updateActivity, pushController: pushController) + }, navigateToChat: { peer in + navigateToChat(peer) + }, updateActivity: updateActivity, pushController: pushController, presentInGlobalOverlay: presentInGlobalOverlay) self.containerNode.cancel = { cancel() } @@ -335,7 +342,7 @@ public final class InviteRequestsSearchContainerNode: SearchDisplayControllerCon } } - public init(context: AccountContext, forceTheme: PresentationTheme?, peerId: PeerId, openPeer: @escaping (EnginePeer) -> Void, approveRequest: @escaping (EnginePeer) -> Void, denyRequest: @escaping (EnginePeer) -> Void, updateActivity: @escaping (Bool) -> Void, pushController: @escaping (ViewController) -> Void) { + public init(context: AccountContext, forceTheme: PresentationTheme?, peerId: PeerId, openPeer: @escaping (EnginePeer) -> Void, approveRequest: @escaping (EnginePeer) -> Void, denyRequest: @escaping (EnginePeer) -> Void, navigateToChat: @escaping (EnginePeer) -> Void, updateActivity: @escaping (Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) { self.context = context self.openPeer = openPeer @@ -391,8 +398,62 @@ public final class InviteRequestsSearchContainerNode: SearchDisplayControllerCon }, denyRequest: { [weak self] peer in denyRequest(peer) self?.processedPeerIds.insert(peer.id) - }, peerContextAction: { _, _, _ in + }, peerContextAction: { [weak self] peer, node, gesture in + guard let node = node as? ContextExtractedContentContainingNode else { + return + } + let _ = (context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let peer = peer else { + return + } + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let addString: String + if case let .channel(channel) = peer, case .broadcast = channel.info { + addString = presentationData.strings.MemberRequests_AddToChannel + } else { + addString = presentationData.strings.MemberRequests_AddToGroup + } + var items: [ContextMenuItem] = [] + + items.append(.action(ContextMenuActionItem(text: addString, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, f in + f(.dismissWithoutContent) + + approveRequest(peer) + self?.processedPeerIds.insert(peer.id) + }))) + + items.append(.action(ContextMenuActionItem(text: presentationData.strings.ContactList_Context_SendMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + + navigateToChat(peer) + }))) + + items.append(.action(ContextMenuActionItem(text: presentationData.strings.MemberRequests_Dismiss, textColor: .destructive, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) + }, action: { [weak self] _, f in + f(.dismissWithoutContent) + + denyRequest(peer) + self?.processedPeerIds.insert(peer.id) + }))) + + let dismissPromise = ValuePromise(false) + let source = InviteRequestsContextExtractedContentSource(sourceNode: node, keepInPlace: false, blurBackground: true, centerVertically: true, shouldBeDismissed: dismissPromise.get()) + // sourceNode.requestDismiss = { + // dismissPromise.set(true) + // } + + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(source), items: .single(ContextController.Items(items: items)), gesture: gesture) + presentInGlobalOverlay(contextController) + }) }) let presentationDataPromise = self.presentationDataPromise @@ -412,13 +473,20 @@ public final class InviteRequestsSearchContainerNode: SearchDisplayControllerCon let foundItems = combineLatest(searchQuery, context.account.postbox.peerView(id: peerId) |> take(1)) |> mapToSignal { query, peerView -> Signal<[InviteRequestsSearchEntry]?, NoError> in - guard let query = query, !query.isEmpty else { + guard let query = query, !query.isEmpty, let peer = peerViewMainPeer(peerView) else { return .single(nil) } updateActivity(true) let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: query)) let _ = previousRequestsContext.swap(requestsContext) + let isGroup: Bool + if let channel = peer as? TelegramChannel, case .broadcast = channel.info { + isGroup = false + } else { + isGroup = true + } + return combineLatest(requestsContext.state, presentationDataPromise.get(), processedPeerIds.get()) |> mapToSignal { state, presentationData, processedPeerIds -> Signal<[InviteRequestsSearchEntry]?, NoError> in if !state.hasLoadedOnce { @@ -431,7 +499,7 @@ public final class InviteRequestsSearchContainerNode: SearchDisplayControllerCon if processedPeerIds.contains(importer.peer.peerId) { continue } - entries.append(InviteRequestsSearchEntry(index: index, request: importer, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, isGroup: false)) + entries.append(InviteRequestsSearchEntry(index: index, request: importer, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, isGroup: isGroup)) index += 1 } return .single(entries) diff --git a/submodules/InviteLinksUI/Sources/ItemListInviteRequestItem.swift b/submodules/InviteLinksUI/Sources/ItemListInviteRequestItem.swift index 580e6fe9d1..20e5623f38 100644 --- a/submodules/InviteLinksUI/Sources/ItemListInviteRequestItem.swift +++ b/submodules/InviteLinksUI/Sources/ItemListInviteRequestItem.swift @@ -198,6 +198,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode { self.subtitleNode.contentsScale = UIScreen.main.scale self.expandedSubtitleNode = TextNode() + self.expandedSubtitleNode.alpha = 0.0 self.expandedSubtitleNode.isUserInteractionEnabled = false self.expandedSubtitleNode.contentMode = .left self.expandedSubtitleNode.contentsScale = UIScreen.main.scale @@ -517,7 +518,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode { let rightInset: CGFloat = 16.0 + params.rightInset let verticalInset: CGFloat = 9.0 - let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 44.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (expandedSubtitleLayout, expandedSubtitleApply) = makeExpandedSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitleAttributedString, backgroundColor: nil, maximumNumberOfLines: 5, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (dateLayout, dateApply) = makeDateLayout(TextNodeLayoutArguments(attributedString: dateAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) diff --git a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift index 09615cee7e..9d70f1decf 100644 --- a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift @@ -307,10 +307,10 @@ public final class ListMessageSnippetItemNode: ListMessageNode { mutableDescriptionText.append(NSAttributedString(string: text + "\n", font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)) } - let plainUrlString = NSAttributedString(string: content.displayUrl, font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemAccentColor) + let plainUrlString = NSAttributedString(string: content.url.replacingOccurrences(of: "https://", with: ""), font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemAccentColor) let urlString = NSMutableAttributedString() urlString.append(plainUrlString) - urlString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.URL), value: content.displayUrl, range: NSMakeRange(0, urlString.length)) + urlString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.URL), value: content.url, range: NSMakeRange(0, urlString.length)) linkText = urlString descriptionText = mutableDescriptionText @@ -395,7 +395,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode { } let urlAttributedString = NSMutableAttributedString() - urlAttributedString.append(NSAttributedString(string: urlString, font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemAccentColor)) + urlAttributedString.append(NSAttributedString(string: urlString.replacingOccurrences(of: "https://", with: ""), font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemAccentColor)) if item.presentationData.theme.theme.list.itemAccentColor.isEqual(item.presentationData.theme.theme.list.itemPrimaryTextColor) { urlAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: NSMakeRange(0, urlAttributedString.length)) } @@ -439,7 +439,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode { } let urlAttributedString = NSMutableAttributedString() - urlAttributedString.append(NSAttributedString(string: urlString, font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemAccentColor)) + urlAttributedString.append(NSAttributedString(string: urlString.replacingOccurrences(of: "https://", with: ""), font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemAccentColor)) if item.presentationData.theme.theme.list.itemAccentColor.isEqual(item.presentationData.theme.theme.list.itemPrimaryTextColor) { urlAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: NSMakeRange(0, urlAttributedString.length)) } @@ -505,7 +505,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode { let (descriptionNodeLayout, descriptionNodeApply) = descriptionNodeMakeLayout(TextNodeLayoutArguments(attributedString: descriptionText, backgroundColor: nil, maximumNumberOfLines: descriptionMaxNumberOfLines, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - params.rightInset - 16.0 - 8.0, height: CGFloat.infinity), alignment: .natural, lineSpacing: 0.3, cutout: nil, insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))) - let (linkNodeLayout, linkNodeApply) = linkNodeMakeLayout(TextNodeLayoutArguments(attributedString: linkText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - params.rightInset - 16.0 - 8.0, height: CGFloat.infinity), alignment: .natural, lineSpacing: 0.3, cutout: isInstantView ? TextNodeCutout(topLeft: CGSize(width: 14.0, height: 8.0)) : nil, insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))) + let (linkNodeLayout, linkNodeApply) = linkNodeMakeLayout(TextNodeLayoutArguments(attributedString: linkText, backgroundColor: nil, maximumNumberOfLines: 4, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - params.rightInset - 16.0 - 8.0, height: CGFloat.infinity), alignment: .natural, lineSpacing: 0.3, cutout: isInstantView ? TextNodeCutout(topLeft: CGSize(width: 14.0, height: 8.0)) : nil, insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))) var instantViewImage: UIImage? if isInstantView { instantViewImage = PresentationResourcesChat.sharedMediaInstantViewIcon(item.presentationData.theme.theme) diff --git a/submodules/LocationUI/Sources/LocationViewControllerNode.swift b/submodules/LocationUI/Sources/LocationViewControllerNode.swift index 0f4c6bf1f3..bd2ec4a05a 100644 --- a/submodules/LocationUI/Sources/LocationViewControllerNode.swift +++ b/submodules/LocationUI/Sources/LocationViewControllerNode.swift @@ -38,6 +38,7 @@ private struct LocationViewTransaction { let insertions: [ListViewInsertItem] let updates: [ListViewUpdateItem] let gotTravelTimes: Bool + let count: Int } private enum LocationViewEntryId: Hashable { @@ -184,7 +185,7 @@ private func preparedTransition(from fromEntries: [LocationViewEntry], to toEntr let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, interaction: interaction), directionHint: nil) } let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, interaction: interaction), directionHint: nil) } - return LocationViewTransaction(deletions: deletions, insertions: insertions, updates: updates, gotTravelTimes: gotTravelTimes) + return LocationViewTransaction(deletions: deletions, insertions: insertions, updates: updates, gotTravelTimes: gotTravelTimes, count: toEntries.count) } enum LocationViewLocation: Equatable { @@ -453,7 +454,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan var drivingTime: Double? var transitTime: Double? var walkingTime: Double? - if !isLocationView { + if !isLocationView && message.author?.id != context.account.peerId { if let (previousTimestamp, maybeDrivingTime, maybeTransitTime, maybeWalkingTime) = travelTimes[message.id] { drivingTime = maybeDrivingTime transitTime = maybeTransitTime @@ -704,7 +705,11 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan var index: Int = 0 var offset: CGFloat = 0.0 if transition.gotTravelTimes { - index = 1 + if transition.count > 1 { + index = 1 + } else { + index = 0 + } offset = 0.0 } else if transition.insertions.count > 2 { index = 2 diff --git a/submodules/SettingsUI/Sources/ThemeCarouselItem.swift b/submodules/SettingsUI/Sources/ThemeCarouselItem.swift index a78aa1bf2e..419bd2e4d6 100644 --- a/submodules/SettingsUI/Sources/ThemeCarouselItem.swift +++ b/submodules/SettingsUI/Sources/ThemeCarouselItem.swift @@ -363,7 +363,7 @@ private final class ThemeCarouselThemeItemIconNode : ListViewItemNode { var string: String? if let _ = item.themeReference.emoticon { } else { - string = "⚙️" + string = "🎨" } let emojiTitle = NSAttributedString(string: string ?? "", font: Font.regular(20.0), textColor: .black) diff --git a/submodules/SettingsUI/Sources/ThemePickerController.swift b/submodules/SettingsUI/Sources/ThemePickerController.swift index 7c4c06933f..17ec6c0794 100644 --- a/submodules/SettingsUI/Sources/ThemePickerController.swift +++ b/submodules/SettingsUI/Sources/ThemePickerController.swift @@ -22,9 +22,9 @@ import AnimationUI private final class ThemePickerControllerArguments { let context: AccountContext - let selectTheme: (PresentationThemeReference) -> Void + let selectTheme: (TelegramBaseTheme?, PresentationThemeReference) -> Void let previewTheme: (PresentationThemeReference) -> Void - let selectAccentColor: (PresentationThemeAccentColor?) -> Void + let selectAccentColor: (TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void let openAccentColorPicker: (PresentationThemeReference, Bool) -> Void let editTheme: (PresentationCloudTheme) -> Void let editCurrentTheme: () -> Void @@ -32,7 +32,7 @@ private final class ThemePickerControllerArguments { let themeContextAction: (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void let colorContextAction: (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void - init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, previewTheme: @escaping (PresentationThemeReference) -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor?) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, Bool) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, editCurrentTheme: @escaping () -> Void, createNewTheme: @escaping () -> Void, themeContextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void, colorContextAction: @escaping (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void) { + init(context: AccountContext, selectTheme: @escaping (TelegramBaseTheme?, PresentationThemeReference) -> Void, previewTheme: @escaping (PresentationThemeReference) -> Void, selectAccentColor: @escaping (TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, Bool) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, editCurrentTheme: @escaping () -> Void, createNewTheme: @escaping () -> Void, themeContextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void, colorContextAction: @escaping (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void) { self.context = context self.selectTheme = selectTheme self.previewTheme = previewTheme @@ -57,7 +57,7 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry { case themes(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, Bool, [String: [StickerPackItem]]) case customHeader(PresentationTheme, String) case chatPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) - case theme(PresentationTheme, PresentationStrings, [PresentationThemeReference], [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper], PresentationThemeAccentColor?) + case theme(PresentationTheme, PresentationStrings, [PresentationThemeReference], [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], [Int64: TelegramWallpaper], PresentationThemeAccentColor?, [Int64: TelegramBaseTheme]) case accentColor(PresentationTheme, PresentationThemeReference, PresentationThemeReference, [PresentationThemeReference], ThemeSettingsColorOption?) case editTheme(PresentationTheme, String) case createTheme(PresentationTheme, String) @@ -120,8 +120,8 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry { } else { return false } - case let .theme(lhsTheme, lhsStrings, lhsThemes, lhsAllThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeSpecificChatWallpapers, lhsCurrentColor): - if case let .theme(rhsTheme, rhsStrings, rhsThemes, rhsAllThemes, rhsCurrentTheme, rhsThemeAccentColors, rhsThemeSpecificChatWallpapers, rhsCurrentColor) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsThemes == rhsThemes, lhsAllThemes == rhsAllThemes, lhsCurrentTheme == rhsCurrentTheme, lhsThemeAccentColors == rhsThemeAccentColors, lhsThemeSpecificChatWallpapers == rhsThemeSpecificChatWallpapers, lhsCurrentColor == rhsCurrentColor { + case let .theme(lhsTheme, lhsStrings, lhsThemes, lhsAllThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeSpecificChatWallpapers, lhsCurrentColor, lhsThemePreferredBaseTheme): + if case let .theme(rhsTheme, rhsStrings, rhsThemes, rhsAllThemes, rhsCurrentTheme, rhsThemeAccentColors, rhsThemeSpecificChatWallpapers, rhsCurrentColor, rhsThemePreferredBaseTheme) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings, lhsThemes == rhsThemes, lhsAllThemes == rhsAllThemes, lhsCurrentTheme == rhsCurrentTheme, lhsThemeAccentColors == rhsThemeAccentColors, lhsThemeSpecificChatWallpapers == rhsThemeSpecificChatWallpapers, lhsCurrentColor == rhsCurrentColor, lhsThemePreferredBaseTheme == rhsThemePreferredBaseTheme { return true } else { return false @@ -166,14 +166,14 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry { return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .chatPreview(theme, wallpaper, fontSize, chatBubbleCorners, strings, dateTimeFormat, nameDisplayOrder, items): return ThemeSettingsChatPreviewItem(context: arguments.context, theme: theme, componentTheme: theme, strings: strings, sectionId: self.section, fontSize: fontSize, chatBubbleCorners: chatBubbleCorners, wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, messageItems: items) - case let .theme(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers, _): - return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, allThemes: allThemes, displayUnsupported: true, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, currentTheme: currentTheme, updatedTheme: { theme in + case let .theme(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers, _, themePreferredBaseTheme): + return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, allThemes: allThemes, displayUnsupported: true, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, themePreferredBaseTheme: themePreferredBaseTheme, currentTheme: currentTheme, updatedTheme: { theme in if case let .cloud(theme) = theme, theme.theme.file == nil && theme.theme.settings == nil { if theme.theme.isCreator { arguments.editTheme(theme) } } else { - arguments.selectTheme(theme) + arguments.selectTheme(nil, theme) } }, contextAction: { theme, node, gesture in arguments.themeContextAction(theme.index == currentTheme.index, theme, node, gesture) @@ -246,16 +246,24 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry { } } + + let baseTheme: TelegramBaseTheme? + if case let .builtin(theme) = generalThemeReference { + baseTheme = theme.baseTheme + } else { + baseTheme = nil + } + return ThemeSettingsAccentColorItem(theme: theme, sectionId: self.section, generalThemeReference: generalThemeReference, themeReference: currentTheme, colors: colorItems, currentColor: currentColor, updated: { color in if let color = color { switch color { case let .accentColor(color): - arguments.selectAccentColor(color) + arguments.selectAccentColor(baseTheme, color) case let .theme(theme): - arguments.selectTheme(theme) + arguments.selectTheme(baseTheme, theme) } } else { - arguments.selectAccentColor(nil) + arguments.selectAccentColor(nil, nil) } }, contextAction: { isCurrent, theme, color, node, gesture in arguments.colorContextAction(isCurrent, theme, color, node, gesture) @@ -263,7 +271,7 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry { arguments.openAccentColorPicker(currentTheme, create) }, tag: ThemeSettingsEntryTag.accentColor) case let .editTheme(theme, text): - return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.makeVisibleIcon(theme), title: text, sectionId: self.section, height: .generic, editing: false, action: { + return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.makeEditThemeIcon(theme), title: text, sectionId: self.section, height: .generic, editing: false, action: { arguments.editCurrentTheme() }) case let .createTheme(theme, text): @@ -292,17 +300,23 @@ private func themePickerControllerEntries(presentationData: PresentationData, pr } let generalThemeReference: PresentationThemeReference - if case let .cloud(theme) = themeReference, let settings = theme.theme.settings?.first { - generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) + if case let .cloud(theme) = themeReference, let settings = theme.theme.settings { + if let baseTheme = presentationThemeSettings.themePreferredBaseTheme[themeReference.index] { + generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: baseTheme)) + } else if let first = settings.first { + generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: first.baseTheme)) + } else { + generalThemeReference = themeReference + } } else { generalThemeReference = themeReference } - entries.append(.theme(presentationData.theme, presentationData.strings, generalThemes, availableThemes, themeReference, presentationThemeSettings.themeSpecificAccentColors, presentationThemeSettings.themeSpecificChatWallpapers, presentationThemeSettings.themeSpecificAccentColors[themeReference.index])) + entries.append(.theme(presentationData.theme, presentationData.strings, generalThemes, availableThemes, themeReference, presentationThemeSettings.themeSpecificAccentColors, presentationThemeSettings.themeSpecificChatWallpapers, presentationThemeSettings.themeSpecificAccentColors[themeReference.index], presentationThemeSettings.themePreferredBaseTheme)) if case let .builtin(builtinTheme) = generalThemeReference { let colorThemes = availableThemes.filter { reference in - if case let .cloud(theme) = reference, let settings = theme.theme.settings?.first, settings.baseTheme == builtinTheme.baseTheme { + if case let .cloud(theme) = reference, let settings = theme.theme.settings, settings.contains(where: { $0.baseTheme == builtinTheme.baseTheme }) { return true } else { return false @@ -344,8 +358,8 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme var getNavigationControllerImpl: (() -> NavigationController?)? var presentCrossfadeControllerImpl: ((Bool) -> Void)? - var selectThemeImpl: ((PresentationThemeReference) -> Void)? - var selectAccentColorImpl: ((PresentationThemeAccentColor?) -> Void)? + var selectThemeImpl: ((TelegramBaseTheme?, PresentationThemeReference) -> Void)? + var selectAccentColorImpl: ((TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void)? var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)? let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start() @@ -379,15 +393,15 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let nightModePreviewPromise = ValuePromise(false) - let arguments = ThemePickerControllerArguments(context: context, selectTheme: { theme in - selectThemeImpl?(theme) + let arguments = ThemePickerControllerArguments(context: context, selectTheme: { baseTheme, theme in + selectThemeImpl?(baseTheme, theme) }, previewTheme: { themeReference in if let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference) { let controller = ThemePreviewController(context: context, previewTheme: theme, source: .settings(themeReference, nil, false)) pushControllerImpl?(controller) } - }, selectAccentColor: { accentColor in - selectAccentColorImpl?(accentColor) + }, selectAccentColor: { currentBaseTheme, accentColor in + selectAccentColorImpl?(currentBaseTheme, accentColor) }, openAccentColorPicker: { themeReference, create in openAccentColorPickerImpl?(themeReference, create) }, editTheme: { theme in @@ -398,7 +412,30 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme }) pushControllerImpl?(controller) }, editCurrentTheme: { - + let _ = (context.sharedContext.accountManager.transaction { transaction -> PresentationThemeReference in + let settings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings)?.get(PresentationThemeSettings.self) ?? PresentationThemeSettings.defaultSettings + + let themeReference: PresentationThemeReference + let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered + if autoNightModeTriggered { + themeReference = settings.automaticThemeSwitchSetting.theme + } else { + themeReference = settings.theme + } + + return themeReference + } + |> deliverOnMainQueue).start(next: { themeReference in + guard case let .cloud(cloudTheme) = themeReference else { + return + } + let controller = editThemeController(context: context, mode: .edit(cloudTheme), navigateToChat: { peerId in + if let navigationController = getNavigationControllerImpl?() { + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId))) + } + }) + pushControllerImpl?(controller) + }) }, createNewTheme: { let _ = (context.sharedContext.accountManager.transaction { transaction -> PresentationThemeReference in let settings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings)?.get(PresentationThemeSettings.self) ?? PresentationThemeSettings.defaultSettings @@ -558,9 +595,9 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme if isCurrent, let currentThemeIndex = themes.firstIndex(where: { $0.id == theme.theme.id }) { if let settings = theme.theme.settings?.first { if settings.baseTheme == .night { - selectAccentColorImpl?(PresentationThemeAccentColor(baseColor: .blue)) + selectAccentColorImpl?(nil, PresentationThemeAccentColor(baseColor: .blue)) } else { - selectAccentColorImpl?(nil) + selectAccentColorImpl?(nil, nil) } } else { let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) @@ -571,7 +608,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme } else { newTheme = .builtin(.nightAccent) } - selectThemeImpl?(newTheme) + selectThemeImpl?(nil, newTheme) } } @@ -808,12 +845,12 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) if let previousThemeIndex = previousThemeIndex { let theme = themes[themes.index(before: previousThemeIndex.base)] - selectThemeImpl?(.cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: theme.isCreator ? context.account.id : nil))) + selectThemeImpl?(nil, .cloud(PresentationCloudTheme(theme: theme, resolvedWallpaper: nil, creatorAccountId: theme.isCreator ? context.account.id : nil))) } else { if settings.baseTheme == .night { - selectAccentColorImpl?(PresentationThemeAccentColor(baseColor: .blue)) + selectAccentColorImpl?(nil, PresentationThemeAccentColor(baseColor: .blue)) } else { - selectAccentColorImpl?(nil) + selectAccentColorImpl?(nil, nil) } } } @@ -863,10 +900,10 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme themeReference = settings.theme // } - let rightNavigationButton = ItemListNavigationButton(content: .node(switchNode), style: .regular, enabled: true, action: { -// nightModePreviewPromise.set(!nightModePreview) -// switchNode?.play(isDark: presentationData.theme.overallDarkAppearance, theme: presentationData.theme) -// presentCrossfadeControllerImpl?(false) + let rightNavigationButton = ItemListNavigationButton(content: .node(switchNode), style: .regular, enabled: true, action: { [weak switchNode] in + nightModePreviewPromise.set(!nightModePreview) + switchNode?.play(isDark: presentationData.theme.overallDarkAppearance, theme: presentationData.theme) + presentCrossfadeControllerImpl?(false) }) var defaultThemes: [PresentationThemeReference] = [] @@ -985,7 +1022,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme context.sharedContext.presentGlobalController(crossfadeController, nil) } } - selectThemeImpl = { theme in + selectThemeImpl = { baseTheme, theme in guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme) else { return } @@ -1029,9 +1066,14 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme var baseThemeIndex: Int64? var updatedThemeBaseIndex: Int64? + var updatedBaseTheme: TelegramBaseTheme? if case let .cloud(info) = theme { updatedTheme = .cloud(PresentationCloudTheme(theme: info.theme, resolvedWallpaper: resolvedWallpaper, creatorAccountId: info.theme.isCreator ? context.account.id : nil)) - if let settings = info.theme.settings?.first { + if let baseTheme = baseTheme, let settings = info.theme.settings?.first(where: { $0.baseTheme == baseTheme }) { + updatedBaseTheme = baseTheme + baseThemeIndex = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)).index + updatedThemeBaseIndex = baseThemeIndex + } else if let settings = info.theme.settings?.first { baseThemeIndex = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)).index updatedThemeBaseIndex = baseThemeIndex } @@ -1040,6 +1082,10 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme } let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in + var updatedThemePreferredBaseTheme = current.themePreferredBaseTheme + if let updatedBaseTheme = updatedBaseTheme { + updatedThemePreferredBaseTheme[updatedTheme.index] = updatedBaseTheme + } var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting if case let .cloud(info) = updatedTheme, info.theme.settings?.contains(where: { $0.baseTheme == .night || $0.baseTheme == .tinted }) ?? false { updatedAutomaticThemeSwitchSetting.theme = updatedTheme @@ -1050,7 +1096,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme updatedAutomaticThemeSwitchSetting.theme = updatedTheme } } - return current.withUpdatedTheme(updatedTheme).withUpdatedAutomaticThemeSwitchSetting(updatedAutomaticThemeSwitchSetting) + return current.withUpdatedTheme(updatedTheme).withUpdatedThemePreferredBaseTheme(updatedThemePreferredBaseTheme).withUpdatedAutomaticThemeSwitchSetting(updatedAutomaticThemeSwitchSetting) // var updatedThemeSpecificAccentColors = current.themeSpecificAccentColors // if let baseThemeIndex = baseThemeIndex { // updatedThemeSpecificAccentColors[baseThemeIndex] = PresentationThemeAccentColor(themeIndex: updatedTheme.index) @@ -1078,73 +1124,93 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme let controller = ThemeAccentColorController(context: context, mode: .colors(themeReference: themeReference, create: create)) pushControllerImpl?(controller) } - selectAccentColorImpl = { accentColor in - var wallpaperSignal: Signal = .single(nil) - if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { - wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) - |> mapToSignal { cachedWallpaper in - if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { - let _ = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource)).start() - - return .single(wallpaper) - - } else { - return .single(nil) - } - } - } + selectAccentColorImpl = { currentBaseTheme, accentColor in + let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in + return current +// var currentTheme = current.theme +// let currentPreferredBaseTheme = currentBaseTheme +// if case let .cloud(theme) = currentTheme, let _ = theme.theme.settings, currentBaseTheme != nil { +// +// } +// +// return PresentationThemeSettings(theme: updatedTheme, themePreferredBaseTheme: themePreferredBaseTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + }).start() - let _ = (wallpaperSignal - |> deliverOnMainQueue).start(next: { presetWallpaper in - let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered - var currentTheme = current.theme - if autoNightModeTriggered { - currentTheme = current.automaticThemeSwitchSetting.theme - } - - let generalThemeReference: PresentationThemeReference - if case let .cloud(theme) = currentTheme, let settings = theme.theme.settings?.first { - generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) - } else { - generalThemeReference = currentTheme - } - - currentTheme = generalThemeReference - var updatedTheme = current.theme - var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting - - if autoNightModeTriggered { - updatedAutomaticThemeSwitchSetting.theme = generalThemeReference - } else { - updatedTheme = generalThemeReference - } - - guard let _ = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.color, wallpaper: presetWallpaper, baseColor: accentColor?.baseColor) else { - return current - } - - var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers - var themeSpecificAccentColors = current.themeSpecificAccentColors - themeSpecificAccentColors[generalThemeReference.index] = accentColor?.withUpdatedWallpaper(presetWallpaper) - - if case .builtin = generalThemeReference { - let index = coloredThemeIndex(reference: currentTheme, accentColor: accentColor) - if let wallpaper = current.themeSpecificChatWallpapers[index] { - if wallpaper.isColorOrGradient || wallpaper.isPattern || wallpaper.isBuiltin { - themeSpecificChatWallpapers[index] = presetWallpaper - } - } else { - themeSpecificChatWallpapers[index] = presetWallpaper - } - } - - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) - }).start() - - presentCrossfadeControllerImpl?(true) - }) + presentCrossfadeControllerImpl?(true) } + + +// var wallpaperSignal: Signal = .single(nil) +// if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { +// wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) +// |> mapToSignal { cachedWallpaper in +// if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { +// let _ = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource)).start() +// +// return .single(wallpaper) +// +// } else { +// return .single(nil) +// } +// } +// } +// +// let _ = (wallpaperSignal +// |> deliverOnMainQueue).start(next: { presetWallpaper in +// let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in +// let autoNightModeTriggered = context.sharedContext.currentPresentationData.with { $0 }.autoNightModeTriggered +// var currentTheme = current.theme +// let currentPreferredBaseTheme = currentBaseTheme +// +// if autoNightModeTriggered { +// currentTheme = current.automaticThemeSwitchSetting.theme +// } +// +// let generalThemeReference: PresentationThemeReference +// if case let .cloud(theme) = currentTheme, let settings = theme.theme.settings, currentBaseTheme != nil && { +// generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) +// } else { +// generalThemeReference = currentTheme +// } +// +// currentTheme = generalThemeReference +// var updatedTheme = current.theme +// var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting +// +// if autoNightModeTriggered { +// updatedAutomaticThemeSwitchSetting.theme = generalThemeReference +// } else { +// updatedTheme = generalThemeReference +// } +// +// guard let _ = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.color, wallpaper: presetWallpaper, baseColor: accentColor?.baseColor) else { +// return current +// } +// +// var themePreferredBaseTheme = current.themePreferredBaseTheme +// if up +// +// var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers +// var themeSpecificAccentColors = current.themeSpecificAccentColors +// themeSpecificAccentColors[generalThemeReference.index] = accentColor?.withUpdatedWallpaper(presetWallpaper) +// +// if case .builtin = generalThemeReference { +// let index = coloredThemeIndex(reference: currentTheme, accentColor: accentColor) +// if let wallpaper = current.themeSpecificChatWallpapers[index] { +// if wallpaper.isColorOrGradient || wallpaper.isPattern || wallpaper.isBuiltin { +// themeSpecificChatWallpapers[index] = presetWallpaper +// } +// } else { +// themeSpecificChatWallpapers[index] = presetWallpaper +// } +// } +// +// return PresentationThemeSettings(theme: updatedTheme, themePreferredBaseTheme: themePreferredBaseTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) +// }).start() +// +// presentCrossfadeControllerImpl?(true) +// }) +// } return controller } diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index e8c14dcbd4..3d319da1cf 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -288,11 +288,11 @@ private func editThemeControllerEntries(presentationData: PresentationData, stat entries.append(.changeColors(presentationData.theme, presentationData.strings.EditTheme_ChangeColors)) if hasSettings { if previewTheme.overallDarkAppearance { - entries.append(.toggleDark(presentationData.theme, "Toggle Base Theme")) +// entries.append(.toggleDark(presentationData.theme, "Toggle Base Theme")) } } else { if !isCreate { - entries.append(.convertToPresetTheme(presentationData.theme, "Convert to Preset Theme")) +// entries.append(.convertToPresetTheme(presentationData.theme, "Convert to Preset Theme")) } entries.append(.uploadTheme(presentationData.theme, uploadText)) entries.append(.uploadInfo(presentationData.theme, uploadInfo)) @@ -643,7 +643,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + return PresentationThemeSettings(theme: themeReference, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) }) |> deliverOnMainQueue).start(completed: { if !hasCustomFile { saveThemeTemplateFile(state.title, themeResource, { @@ -677,7 +677,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil - return PresentationThemeSettings(theme: themeReference, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + return PresentationThemeSettings(theme: themeReference, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) }) |> deliverOnMainQueue).start(completed: { if let themeResource = themeResource, !hasCustomFile { saveThemeTemplateFile(state.title, themeResource, { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index f1985fe4f1..e4763e3c45 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -249,13 +249,14 @@ final class ThemeAccentColorController: ViewController { updatedTheme = themeReference } + let themePreferredBaseTheme = current.themePreferredBaseTheme var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil var themeSpecificAccentColors = current.themeSpecificAccentColors themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + return PresentationThemeSettings(theme: updatedTheme, themePreferredBaseTheme: themePreferredBaseTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) }) |> castError(CreateThemeError.self) } else { @@ -278,13 +279,14 @@ final class ThemeAccentColorController: ViewController { updatedTheme = themeReference } + let themePreferredBaseTheme = current.themePreferredBaseTheme var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = nil var themeSpecificAccentColors = current.themeSpecificAccentColors themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + return PresentationThemeSettings(theme: updatedTheme, themePreferredBaseTheme: themePreferredBaseTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) }) |> castError(CreateThemeError.self) } else { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift index 7d62ed2119..bfa5f81ea8 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAutoNightSettingsController.swift @@ -245,7 +245,7 @@ private enum ThemeAutoNightSettingsControllerEntry: ItemListNodeEntry { case let .themeHeader(_, title): return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) case let .themeItem(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers): - return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, allThemes: allThemes, displayUnsupported: false, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, currentTheme: currentTheme, updatedTheme: { theme in + return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, allThemes: allThemes, displayUnsupported: false, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, themePreferredBaseTheme: [:], currentTheme: currentTheme, updatedTheme: { theme in arguments.updateTheme(theme) }, contextAction: nil) } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index d35df8c30f..e7c56beab9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -1230,6 +1230,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The return current } + let themePreferredBaseTheme = current.themePreferredBaseTheme var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificAccentColors = current.themeSpecificAccentColors themeSpecificAccentColors[generalThemeReference.index] = accentColor?.withUpdatedWallpaper(presetWallpaper) @@ -1245,7 +1246,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } } - return PresentationThemeSettings(theme: updatedTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + return PresentationThemeSettings(theme: updatedTheme, themePreferredBaseTheme: themePreferredBaseTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: updatedAutomaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) }).start() presentCrossfadeControllerImpl?(true) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift index ed581fdae6..0d4e951c76 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift @@ -358,12 +358,13 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem { let displayUnsupported: Bool let themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] let themeSpecificChatWallpapers: [Int64: TelegramWallpaper] + let themePreferredBaseTheme: [Int64: TelegramBaseTheme] let currentTheme: PresentationThemeReference let updatedTheme: (PresentationThemeReference) -> Void let contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)? let tag: ItemListItemTag? - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], allThemes: [PresentationThemeReference], displayUnsupported: Bool, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], currentTheme: PresentationThemeReference, updatedTheme: @escaping (PresentationThemeReference) -> Void, contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?, tag: ItemListItemTag? = nil) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], allThemes: [PresentationThemeReference], displayUnsupported: Bool, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], themePreferredBaseTheme: [Int64: TelegramBaseTheme], currentTheme: PresentationThemeReference, updatedTheme: @escaping (PresentationThemeReference) -> Void, contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?, tag: ItemListItemTag? = nil) { self.context = context self.theme = theme self.strings = strings @@ -372,6 +373,7 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem { self.displayUnsupported = displayUnsupported self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificChatWallpapers = themeSpecificChatWallpapers + self.themePreferredBaseTheme = themePreferredBaseTheme self.currentTheme = currentTheme self.updatedTheme = updatedTheme self.contextAction = contextAction @@ -636,7 +638,12 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { let wallpaper = accentColor?.wallpaper ?? customWallpaper ?? themeWallpaper - let selected = item.currentTheme.index == theme.index || item.currentTheme.generalThemeReference == theme + var baseThemeReference = item.currentTheme.generalThemeReference + if let baseTheme = item.themePreferredBaseTheme[item.currentTheme.index] { + baseThemeReference = PresentationThemeReference.builtin(.init(baseTheme: baseTheme)) + } + + let selected = item.currentTheme.index == theme.index || baseThemeReference == theme entries.append(ThemeSettingsThemeEntry(index: index, themeReference: theme, title: title, accentColor: accentColor, selected: selected, theme: item.theme, wallpaper: wallpaper)) index += 1 } diff --git a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift index 73debceab3..ce348efa81 100644 --- a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift +++ b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift @@ -155,7 +155,10 @@ public final class SolidRoundedButtonNode: ASDisplayNode { self.isUserInteractionEnabled = false - let progressFrame = CGRect(origin: CGPoint(x: (self.frame.width - self.buttonHeight) / 2.0, y: 0.0), size: CGSize(width: self.buttonHeight, height: self.buttonHeight)) + let buttonOffset = self.buttonBackgroundNode.frame.minX + let buttonWidth = self.buttonBackgroundNode.frame.width + + let progressFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(buttonOffset + (buttonWidth - self.buttonHeight) / 2.0), y: 0.0), size: CGSize(width: self.buttonHeight, height: self.buttonHeight)) let progressNode = ASImageNode() progressNode.displaysAsynchronously = false progressNode.frame = progressFrame diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift index f0ff5a16cd..a28dbccfa3 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift @@ -1,7 +1,7 @@ import Foundation import Postbox -public enum TelegramBaseTheme: Int32 { +public enum TelegramBaseTheme: Int32, Codable { case classic case day case night diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift b/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift index e2e2936ff8..ca6283d39a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Themes/TelegramEngineThemes.swift @@ -9,6 +9,10 @@ public extension TelegramEngine { self.account = account } +// public func getThemes(accountManager: AccountManager) -> Signal<[TelegramTheme], NoError> { +// return _internal_getThemes(accountManager: accountManager, postbox: self.account.postbox, network: self.account.network) +// } + public func getChatThemes(accountManager: AccountManager, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> { return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached) } diff --git a/submodules/TelegramPresentationData/Sources/PresentationData.swift b/submodules/TelegramPresentationData/Sources/PresentationData.swift index 5fe876d808..618e60d1b4 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationData.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationData.swift @@ -623,9 +623,16 @@ public func updatedPresentationData(accountManager: AccountManager UIImage? { + return theme.image(PresentationResourceKey.itemListEditThemeIcon.rawValue, { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Settings/EditTheme"), color: theme.list.itemAccentColor) + }) + } + public static func cornersImage(_ theme: PresentationTheme, top: Bool, bottom: Bool) -> UIImage? { if !top && !bottom { return nil diff --git a/submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/Contents.json new file mode 100644 index 0000000000..af411349de --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "colors_30.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/colors_30.pdf b/submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/colors_30.pdf new file mode 100644 index 0000000000..9abe491c68 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/colors_30.pdf @@ -0,0 +1,212 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 5.107361 3.162231 cm +0.000000 0.000000 0.000000 scn +0.136919 4.618919 m +-0.347895 4.163717 l +-0.344284 4.159932 l +0.136919 4.618919 l +h +0.099977 5.143885 m +-0.349349 5.634120 l +-0.360017 5.624343 l +-0.370249 5.614110 l +0.099977 5.143885 l +h +1.511918 5.861061 m +1.044556 6.334151 l +1.041692 6.331286 l +1.511918 5.861061 l +h +3.736765 10.227889 m +4.133279 9.693956 l +4.140501 9.699474 l +3.736765 10.227889 l +h +8.166384 8.960043 m +8.685057 9.376224 l +8.683912 9.377643 l +8.166384 8.960043 l +h +7.604795 3.599786 m +7.210793 4.135567 l +7.203959 4.130404 l +7.604795 3.599786 l +h +0.621717 5.074106 m +0.611081 5.085433 0.666412 5.028751 0.664974 4.909222 c +0.663605 4.795333 0.611284 4.714740 0.570203 4.673659 c +-0.370249 5.614110 l +-0.527953 5.456407 -0.661392 5.219398 -0.664930 4.925216 c +-0.668535 4.625394 -0.536423 4.364540 -0.347880 4.163732 c +0.621717 5.074106 l +h +0.549303 4.653649 m +0.473747 4.584398 0.413424 4.579663 0.524168 4.615534 c +0.558581 4.626680 0.765894 4.687963 0.879854 4.726777 c +1.190154 4.832462 1.603420 5.012111 1.982144 5.390835 c +1.041692 6.331286 l +0.863218 6.152813 0.661790 6.057532 0.451056 5.985758 c +0.304500 5.935842 0.274712 5.932763 0.114334 5.880815 c +0.030287 5.853591 -0.182517 5.787030 -0.349349 5.634120 c +0.549303 4.653649 l +h +1.979271 5.387979 m +2.762335 6.161561 2.983588 7.179695 3.183573 7.926414 c +3.398847 8.730222 3.596982 9.295764 4.133242 9.694006 c +3.340288 10.761772 l +2.396795 10.061108 2.111542 9.064655 1.898849 8.270485 c +1.670867 7.419226 1.519574 6.803399 1.044565 6.334142 c +1.979271 5.387979 l +h +4.140501 9.699474 m +4.938049 10.308843 6.388459 10.104443 7.648856 8.542443 c +8.683912 9.377643 l +7.236722 11.171134 4.988924 12.021493 3.333029 10.756304 c +4.140501 9.699474 l +h +7.647713 8.543863 m +8.319628 7.706477 8.550738 6.867272 8.466406 6.134995 c +8.382251 5.404262 7.974833 4.697357 7.210826 4.135523 c +7.998764 3.064050 l +9.019373 3.814583 9.655708 4.836955 9.787673 5.982832 c +9.919460 7.127166 9.539057 8.311907 8.685055 9.376223 c +7.647713 8.543863 l +h +7.203959 4.130404 m +5.516191 2.855444 2.559140 3.042942 0.618121 5.077906 c +-0.344284 4.159932 l +1.998385 1.703878 5.707231 1.332929 8.005630 3.069168 c +7.203959 4.130404 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 10.981171 8.944946 cm +0.000000 0.000000 0.000000 scn +13.737684 13.620637 m +13.159714 13.949536 l +13.159714 13.949536 l +13.737684 13.620637 l +h +6.273577 2.774412 m +5.766509 3.204652 l +5.766508 3.204652 l +6.273577 2.774412 l +h +12.043029 15.315296 m +11.714130 15.893268 l +11.714130 15.893268 l +12.043029 15.315296 l +h +1.196800 7.851189 m +1.627041 7.344121 l +1.627041 7.344121 l +1.196800 7.851189 l +h +13.159714 13.949536 m +11.531315 11.087968 8.957198 6.965113 5.766509 3.204652 c +6.780646 2.344172 l +10.045283 6.191786 12.665783 10.392434 14.315655 13.291738 c +13.159714 13.949536 l +h +11.714130 15.893268 m +8.814823 14.243399 4.614170 11.622902 0.766559 8.358257 c +1.627041 7.344121 l +5.387496 10.534817 9.510356 13.108930 12.371927 14.737325 c +11.714130 15.893268 l +h +14.315655 13.291738 m +14.798453 14.140153 14.637612 15.061581 14.060793 15.638401 c +13.483974 16.215221 12.562547 16.376064 11.714130 15.893268 c +12.371927 14.737325 l +12.713542 14.931723 12.978041 14.840251 13.120340 14.697950 c +13.262640 14.555650 13.354112 14.291151 13.159714 13.949536 c +14.315655 13.291738 l +h +5.766508 3.204652 m +5.189209 2.524261 4.373246 2.208553 3.548578 2.245499 c +3.489053 0.916832 l +4.697387 0.862698 5.919904 1.329725 6.780646 2.344172 c +5.766508 3.204652 l +h +0.766559 8.358257 m +-0.261784 7.485722 -0.727416 6.241713 -0.658290 5.017560 c +0.669595 5.092544 l +0.622377 5.928712 0.937552 6.759100 1.627041 7.344121 c +0.766559 8.358257 l +h +f +n +Q +q +0.707107 -0.707107 0.707107 0.707107 8.940246 12.901031 cm +0.000000 0.000000 0.000000 scn +6.514392 6.283155 m +4.446240 7.179288 1.798525 7.192235 -0.262776 6.305544 c +0.262776 5.083785 l +1.983177 5.823833 4.249412 5.815088 5.985608 5.062792 c +6.514392 6.283155 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 4016 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Type /Catalog + /Pages 5 0 R + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000004106 00000 n +0000004129 00000 n +0000004302 00000 n +0000004376 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4435 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ThemeUpdateManager.swift b/submodules/TelegramUI/Sources/ThemeUpdateManager.swift index 28752c2da3..24952d8a24 100644 --- a/submodules/TelegramUI/Sources/ThemeUpdateManager.swift +++ b/submodules/TelegramUI/Sources/ThemeUpdateManager.swift @@ -138,7 +138,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager { theme = updatedTheme } - return PreferencesEntry(PresentationThemeSettings(theme: theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion)) + return PreferencesEntry(PresentationThemeSettings(theme: theme, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: current.themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion)) }) }).start() } diff --git a/submodules/TelegramUI/Sources/WallpaperUploadManager.swift b/submodules/TelegramUI/Sources/WallpaperUploadManager.swift index af4adbb5ca..f0f088a636 100644 --- a/submodules/TelegramUI/Sources/WallpaperUploadManager.swift +++ b/submodules/TelegramUI/Sources/WallpaperUploadManager.swift @@ -129,7 +129,7 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager { var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers themeSpecificChatWallpapers[themeReference.index] = updatedWallpaper themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: current.themeSpecificAccentColors[themeReference.index])] = updatedWallpaper - return PresentationThemeSettings(theme: current.theme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) + return PresentationThemeSettings(theme: current.theme, themePreferredBaseTheme: current.themePreferredBaseTheme, themeSpecificAccentColors: current.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: current.useSystemFont, fontSize: current.fontSize, listsFontSize: current.listsFontSize, chatBubbleSettings: current.chatBubbleSettings, automaticThemeSwitchSetting: current.automaticThemeSwitchSetting, largeEmoji: current.largeEmoji, reduceMotion: current.reduceMotion) })).start() } diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index 64ac2c44d4..634a4e9c79 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -591,6 +591,7 @@ public struct PresentationThemeSettings: Codable { } public var theme: PresentationThemeReference + public var themePreferredBaseTheme: [Int64: TelegramBaseTheme] public var themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] public var themeSpecificChatWallpapers: [Int64: TelegramWallpaper] public var useSystemFont: Bool @@ -637,11 +638,12 @@ public struct PresentationThemeSettings: Codable { } public static var defaultSettings: PresentationThemeSettings { - return PresentationThemeSettings(theme: .builtin(.dayClassic), themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, listsFontSize: .regular, chatBubbleSettings: .default, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(force: false, trigger: .system, theme: .builtin(.night)), largeEmoji: true, reduceMotion: false) + return PresentationThemeSettings(theme: .builtin(.dayClassic), themePreferredBaseTheme: [:], themeSpecificAccentColors: [:], themeSpecificChatWallpapers: [:], useSystemFont: true, fontSize: .regular, listsFontSize: .regular, chatBubbleSettings: .default, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting(force: false, trigger: .system, theme: .builtin(.night)), largeEmoji: true, reduceMotion: false) } - public init(theme: PresentationThemeReference, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, listsFontSize: PresentationFontSize, chatBubbleSettings: PresentationChatBubbleSettings, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, reduceMotion: Bool) { + public init(theme: PresentationThemeReference, themePreferredBaseTheme: [Int64: TelegramBaseTheme], themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], themeSpecificChatWallpapers: [Int64: TelegramWallpaper], useSystemFont: Bool, fontSize: PresentationFontSize, listsFontSize: PresentationFontSize, chatBubbleSettings: PresentationChatBubbleSettings, automaticThemeSwitchSetting: AutomaticThemeSwitchSetting, largeEmoji: Bool, reduceMotion: Bool) { self.theme = theme + self.themePreferredBaseTheme = themePreferredBaseTheme self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificChatWallpapers = themeSpecificChatWallpapers self.useSystemFont = useSystemFont @@ -661,6 +663,15 @@ public struct PresentationThemeSettings: Codable { } else { self.theme = .builtin(.dayClassic) } + + var mappedThemePreferredBaseTheme: [Int64: TelegramBaseTheme] = [:] + let themePreferredBaseThemeDict = try container.decode([Int64: Int64].self, forKey: "themePreferredBaseTheme") + for (key, value) in themePreferredBaseThemeDict { + if let baseTheme = TelegramBaseTheme(rawValue: Int32(clamping: value)) { + mappedThemePreferredBaseTheme[key] = baseTheme + } + } + self.themePreferredBaseTheme = mappedThemePreferredBaseTheme let themeSpecificChatWallpapersDict = try container.decode([DictionaryKey: TelegramWallpaperNativeCodable].self, forKey: "themeSpecificChatWallpapers") var mappedThemeSpecificChatWallpapers: [Int64: TelegramWallpaper] = [:] @@ -695,6 +706,12 @@ public struct PresentationThemeSettings: Codable { try container.encode(PostboxEncoder().encodeObjectToRawData(self.theme), forKey: "t") + var mappedThemePreferredBaseTheme: [Int64: Int64] = [:] + for (key, value) in self.themePreferredBaseTheme { + mappedThemePreferredBaseTheme[key] = Int64(value.rawValue) + } + try container.encode(mappedThemePreferredBaseTheme, forKey: "themePreferredBaseTheme") + var mappedThemeSpecificAccentColors: [DictionaryKey: AdaptedPostboxEncoder.RawObjectData] = [:] for (key, value) in self.themeSpecificAccentColors { mappedThemeSpecificAccentColors[DictionaryKey(key)] = PostboxEncoder().encodeObjectToRawData(value) @@ -717,43 +734,47 @@ public struct PresentationThemeSettings: Codable { } public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool { - return lhs.theme == rhs.theme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.chatBubbleSettings == rhs.chatBubbleSettings && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.reduceMotion == rhs.reduceMotion + return lhs.theme == rhs.theme && lhs.themePreferredBaseTheme == rhs.themePreferredBaseTheme && lhs.themeSpecificAccentColors == rhs.themeSpecificAccentColors && lhs.themeSpecificChatWallpapers == rhs.themeSpecificChatWallpapers && lhs.useSystemFont == rhs.useSystemFont && lhs.fontSize == rhs.fontSize && lhs.listsFontSize == rhs.listsFontSize && lhs.chatBubbleSettings == rhs.chatBubbleSettings && lhs.automaticThemeSwitchSetting == rhs.automaticThemeSwitchSetting && lhs.largeEmoji == rhs.largeEmoji && lhs.reduceMotion == rhs.reduceMotion } public func withUpdatedTheme(_ theme: PresentationThemeReference) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + } + + public func withUpdatedThemePreferredBaseTheme(_ themePreferredBaseTheme: [Int64: TelegramBaseTheme]) -> PresentationThemeSettings { + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedThemeSpecificAccentColors(_ themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedThemeSpecificChatWallpapers(_ themeSpecificChatWallpapers: [Int64: TelegramWallpaper]) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedUseSystemFont(_ useSystemFont: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedFontSizes(fontSize: PresentationFontSize, listsFontSize: PresentationFontSize) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, listsFontSize: listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: fontSize, listsFontSize: listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedChatBubbleSettings(_ chatBubbleSettings: PresentationChatBubbleSettings) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedAutomaticThemeSwitchSetting(_ automaticThemeSwitchSetting: AutomaticThemeSwitchSetting) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedLargeEmoji(_ largeEmoji: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, reduceMotion: self.reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: largeEmoji, reduceMotion: self.reduceMotion) } public func withUpdatedReduceMotion(_ reduceMotion: Bool) -> PresentationThemeSettings { - return PresentationThemeSettings(theme: self.theme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: reduceMotion) + return PresentationThemeSettings(theme: self.theme, themePreferredBaseTheme: self.themePreferredBaseTheme, themeSpecificAccentColors: self.themeSpecificAccentColors, themeSpecificChatWallpapers: self.themeSpecificChatWallpapers, useSystemFont: self.useSystemFont, fontSize: self.fontSize, listsFontSize: self.listsFontSize, chatBubbleSettings: self.chatBubbleSettings, automaticThemeSwitchSetting: self.automaticThemeSwitchSetting, largeEmoji: self.largeEmoji, reduceMotion: reduceMotion) } } diff --git a/submodules/WallpaperResources/Sources/WallpaperResources.swift b/submodules/WallpaperResources/Sources/WallpaperResources.swift index 0b77ab9e41..777e7da601 100644 --- a/submodules/WallpaperResources/Sources/WallpaperResources.swift +++ b/submodules/WallpaperResources/Sources/WallpaperResources.swift @@ -1308,7 +1308,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager - if case let .cloud(theme) = theme, let nightMode = nightMode { + if case let .cloud(theme) = theme, theme.theme.settings != nil, let nightMode = nightMode { themeSignal = .single(makePresentationTheme(cloudTheme: theme.theme, dark: nightMode)) } else if case let .builtin(theme) = theme { themeSignal = .single(makeDefaultPresentationTheme(reference: theme, serviceBackgroundColor: nil)) @@ -1485,12 +1485,12 @@ public func themeIconImage(account: Account, accountManager: AccountManager 1 { c.clip() @@ -1504,7 +1504,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager= 2 { - let gradientColors = incomingColors.map { $0.cgColor } as CFArray + let gradientColors = incomingColors.reversed().map { $0.cgColor } as CFArray var locations: [CGFloat] = [] for i in 0 ..< incomingColors.count { @@ -1551,12 +1551,12 @@ public func themeIconImage(account: Account, accountManager: AccountManager 1 { c.clip() @@ -1570,7 +1570,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager= 2 { - let gradientColors = outgoingColors.map { $0.cgColor } as CFArray + let gradientColors = outgoingColors.reversed().map { $0.cgColor } as CFArray var locations: [CGFloat] = [] for i in 0 ..< outgoingColors.count { From 549b669d4abd85a8dbe4d33737d5cade3bc731a8 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 22 Oct 2021 19:21:00 +0400 Subject: [PATCH 2/2] Don't update invitation if nothing is changed --- .../InviteLinksUI/Sources/InviteLinkEditController.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift index c84fdf038b..0df4de556a 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift @@ -506,8 +506,13 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio } presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) }) - } else if let invite = invite { - let _ = (context.engine.peers.editPeerExportedInvitation(peerId: peerId, link: invite.link, expireDate: expireDate, usageLimit: requestNeeded ? 0 : usageLimit, requestNeeded: requestNeeded) + } else if let initialInvite = invite { + if initialInvite.expireDate == expireDate && initialInvite.usageLimit == usageLimit && initialInvite.requestApproval == requestNeeded { + completion?(initialInvite) + dismissImpl?() + return + } + let _ = (context.engine.peers.editPeerExportedInvitation(peerId: peerId, link: initialInvite.link, expireDate: expireDate, usageLimit: requestNeeded ? 0 : usageLimit, requestNeeded: requestNeeded) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic)) |> deliverOnMainQueue).start(next: { invite in completion?(invite)