Various Improvements

This commit is contained in:
Ilya Laktyushin 2021-10-22 18:59:41 +04:00
parent 6c38a5a68f
commit d60588b3f1
30 changed files with 690 additions and 206 deletions

View File

@ -143,7 +143,6 @@ private final class AuthorizationSequenceCountrySelectionNavigationContentNode:
self.addSubnode(self.searchBar) self.addSubnode(self.searchBar)
self.searchBar.cancel = { [weak self] in self.searchBar.cancel = { [weak self] in
//self?.searchBar.deactivate(clear: false)
self?.cancel() self?.cancel()
} }

View File

@ -162,7 +162,13 @@ private func searchCountries(items: [((String, String), String, [Int])], query:
var result: [((String, String), String, Int)] = [] var result: [((String, String), String, Int)] = []
for item in items { 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) let tokens = stringTokens(string)
if matchStringTokens(tokens, with: queryTokens) { if matchStringTokens(tokens, with: queryTokens) {
for code in item.2 { for code in item.2 {

View File

@ -687,6 +687,7 @@ public func readCGFloat(_ index: inout UnsafePointer<UInt8>, end: UnsafePointer<
public func drawSvgPath(_ context: CGContext, path: StaticString, strokeOnMove: Bool = false) throws { public func drawSvgPath(_ context: CGContext, path: StaticString, strokeOnMove: Bool = false) throws {
var index: UnsafePointer<UInt8> = path.utf8Start var index: UnsafePointer<UInt8> = path.utf8Start
let end = path.utf8Start.advanced(by: path.utf8CodeUnitCount) let end = path.utf8Start.advanced(by: path.utf8CodeUnitCount)
var currentPoint = CGPoint()
while index < end { while index < end {
let c = index.pointee let c = index.pointee
index = index.successor() index = index.successor()
@ -696,18 +697,32 @@ public func drawSvgPath(_ context: CGContext, path: StaticString, strokeOnMove:
let y = try readCGFloat(&index, end: end, separator: 32) let y = try readCGFloat(&index, end: end, separator: 32)
//print("Move to \(x), \(y)") //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 } else if c == 76 { // L
let x = try readCGFloat(&index, end: end, separator: 44) let x = try readCGFloat(&index, end: end, separator: 44)
let y = try readCGFloat(&index, end: end, separator: 32) let y = try readCGFloat(&index, end: end, separator: 32)
//print("Line to \(x), \(y)") //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 { if strokeOnMove {
context.strokePath() 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 } else if c == 67 { // C
let x1 = try readCGFloat(&index, end: end, separator: 44) let x1 = try readCGFloat(&index, end: end, separator: 44)
let y1 = try readCGFloat(&index, end: end, separator: 32) 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 y2 = try readCGFloat(&index, end: end, separator: 32)
let x = try readCGFloat(&index, end: end, separator: 44) let x = try readCGFloat(&index, end: end, separator: 44)
let y = try readCGFloat(&index, end: end, separator: 32) 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)") //print("Line to \(x), \(y)")
if strokeOnMove { if strokeOnMove {
context.strokePath() context.strokePath()
context.move(to: CGPoint(x: x, y: y)) context.move(to: currentPoint)
} }
} else if c == 90 { // Z } else if c == 90 { // Z
if index != end && index.pointee != 32 { if index != end && index.pointee != 32 {

View File

@ -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] = [] var entries: [InviteLinksEditEntry] = []
entries.append(.requestApproval(presentationData.theme, presentationData.strings.InviteLink_Create_RequestApproval, state.requestApproval)) entries.append(.requestApproval(presentationData.theme, presentationData.strings.InviteLink_Create_RequestApproval, state.requestApproval))
var requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel var requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOffInfoChannel
if state.requestApproval { if state.requestApproval {
requestApprovalInfoText = presentationData.strings.InviteLink_Create_RequestApprovalOnInfoChannel requestApprovalInfoText = isGroup ? presentationData.strings.InviteLink_Create_RequestApprovalOnInfoGroup : presentationData.strings.InviteLink_Create_RequestApprovalOnInfoChannel
} else { } 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)) entries.append(.requestApprovalInfo(presentationData.theme, requestApprovalInfoText))
@ -460,9 +460,14 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
let previousState = Atomic<InviteLinkEditControllerState?>(value: nil) let previousState = Atomic<InviteLinkEditControllerState?>(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 |> 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: { let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
dismissImpl?() dismissImpl?()
}) })
@ -524,8 +529,15 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
animateChanges = true 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 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)) return (controllerState, (listState, arguments))
} }

View File

@ -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) presentInGlobalOverlayImpl?(contextController)
}, openAdmin: { admin in }, openAdmin: { admin in
let controller = inviteLinkListController(context: context, peerId: peerId, admin: admin) let controller = inviteLinkListController(context: context, peerId: peerId, admin: admin)
@ -957,10 +957,10 @@ final class InviteLinkContextExtractedContentSource: ContextExtractedContentSour
private let controller: ViewController private let controller: ViewController
private let sourceNode: ContextExtractedContentContainingNode private let sourceNode: ContextExtractedContentContainingNode
init(controller: ViewController, sourceNode: ContextExtractedContentContainingNode, blurBackground: Bool) { init(controller: ViewController, sourceNode: ContextExtractedContentContainingNode, keepInPlace: Bool, blurBackground: Bool) {
self.controller = controller self.controller = controller
self.sourceNode = sourceNode self.sourceNode = sourceNode
self.keepInPlace = true self.keepInPlace = keepInPlace
self.blurBackground = blurBackground self.blurBackground = blurBackground
} }

View File

@ -808,17 +808,19 @@ public final class InviteLinkViewController: ViewController {
} }
let navigationController = parentController.navigationController as? NavigationController let navigationController = parentController.navigationController as? NavigationController
self.controller?.dismiss()
let invitationsContext = parentController.invitationsContext let invitationsContext = parentController.invitationsContext
let revokedInvitationsContext = parentController.revokedInvitationsContext let revokedInvitationsContext = parentController.revokedInvitationsContext
if let navigationController = navigationController { if let navigationController = navigationController {
let updatedPresentationData = (self.presentationData, parentController.presentationDataPromise.get()) 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 let invite = invite {
if invite.isRevoked { if invite.isRevoked {
invitationsContext?.remove(invite) invitationsContext?.remove(invite)
revokedInvitationsContext?.add(invite.withUpdated(isRevoked: true)) revokedInvitationsContext?.add(invite.withUpdated(isRevoked: true))
self?.controller?.dismiss()
} else { } else {
invitationsContext?.update(invite) invitationsContext?.update(invite)
} }
@ -934,7 +936,6 @@ public final class InviteLinkViewController: ViewController {
var titleText = self.presentationData.strings.InviteLink_InviteLink var titleText = self.presentationData.strings.InviteLink_InviteLink
var subtitleText = "" var subtitleText = ""
var subtitleColor = self.presentationData.theme.list.itemSecondaryTextColor var subtitleColor = self.presentationData.theme.list.itemSecondaryTextColor
if self.invite.isRevoked { if self.invite.isRevoked {
@ -981,11 +982,11 @@ public final class InviteLinkViewController: ViewController {
transition.updateFrame(node: self.titleNode, frame: titleFrame) transition.updateFrame(node: self.titleNode, frame: titleFrame)
let editSize = self.editButton.measure(CGSize(width: layout.size.width, height: headerHeight)) 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) transition.updateFrame(node: self.editButton, frame: editFrame)
let doneSize = self.doneButton.measure(CGSize(width: layout.size.width, height: headerHeight)) 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) transition.updateFrame(node: self.doneButton, frame: doneFrame)
} }

View File

@ -160,6 +160,7 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
var presentInGlobalOverlayImpl: ((ViewController) -> Void)? var presentInGlobalOverlayImpl: ((ViewController) -> Void)?
var navigateToProfileImpl: ((EnginePeer) -> Void)? var navigateToProfileImpl: ((EnginePeer) -> Void)?
var navigateToChatImpl: ((EnginePeer) -> Void)?
var dismissInputImpl: (() -> Void)? var dismissInputImpl: (() -> Void)?
var dismissTooltipsImpl: (() -> Void)? var dismissTooltipsImpl: (() -> Void)?
@ -214,33 +215,56 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio
guard let node = node as? ContextExtractedContentContainingNode else { guard let node = node as? ContextExtractedContentContainingNode else {
return 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 items.append(.action(ContextMenuActionItem(text: addString, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor)
}, action: { _, f in }, action: { _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
approveRequestImpl(peer)
})))
approveRequestImpl(peer) 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
items.append(.action(ContextMenuActionItem(text: presentationData.strings.MemberRequests_Dismiss, textColor: .destructive, icon: { theme in f(.dismissWithoutContent)
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor)
}, action: { _, f in navigateToChatImpl?(peer)
f(.dismissWithoutContent) })))
denyRequestImpl(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
let dismissPromise = ValuePromise<Bool>(false) f(.dismissWithoutContent)
let source = InviteRequestsContextExtractedContentSource(sourceNode: node, keepInPlace: false, blurBackground: true, centerVertically: true, shouldBeDismissed: dismissPromise.get())
// sourceNode.requestDismiss = { denyRequestImpl(peer)
// dismissPromise.set(true) })))
// }
let dismissPromise = ValuePromise<Bool>(false)
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(source), items: .single(ContextController.Items(items: items)), gesture: gesture) let source = InviteRequestsContextExtractedContentSource(sourceNode: node, keepInPlace: false, blurBackground: true, centerVertically: true, shouldBeDismissed: dismissPromise.get())
presentInGlobalOverlayImpl?(contextController) // 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: []) let previousEntries = Atomic<[InviteRequestsEntry]>(value: [])
@ -298,10 +322,14 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio
arguments.approveRequest(peer) arguments.approveRequest(peer)
}, denyRequest: { peer in }, denyRequest: { peer in
arguments.denyRequest(peer) arguments.denyRequest(peer)
}, navigateToChat: { peer in
navigateToChatImpl?(peer)
}, pushController: { c in }, pushController: { c in
pushControllerImpl?(c) pushControllerImpl?(c)
}, dismissInput: { }, dismissInput: {
dismissInputImpl?() dismissInputImpl?()
}, presentInGlobalOverlay: { c in
presentInGlobalOverlayImpl?(c)
}) })
} }
@ -347,6 +375,11 @@ public func inviteRequestsController(context: AccountContext, updatedPresentatio
navigationController.pushViewController(controller) 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 dismissInputImpl = { [weak controller] in
controller?.view.endEditing(true) 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 var keepInPlace: Bool
let ignoreContentTouches: Bool = false let ignoreContentTouches: Bool = false
let blurBackground: Bool let blurBackground: Bool

View File

@ -15,6 +15,7 @@ import MergeLists
import ChatListSearchItemHeader import ChatListSearchItemHeader
import ItemListUI import ItemListUI
import SearchUI import SearchUI
import ContextUI
private let searchBarFont = Font.regular(17.0) private let searchBarFont = Font.regular(17.0)
@ -101,22 +102,26 @@ final class InviteRequestsSearchItem: ItemListControllerSearch {
let openPeer: (EnginePeer) -> Void let openPeer: (EnginePeer) -> Void
let approveRequest: (EnginePeer) -> Void let approveRequest: (EnginePeer) -> Void
let denyRequest: (EnginePeer) -> Void let denyRequest: (EnginePeer) -> Void
let navigateToChat: (EnginePeer) -> Void
let pushController: (ViewController) -> Void let pushController: (ViewController) -> Void
let presentInGlobalOverlay: (ViewController) -> Void
let dismissInput: () -> Void let dismissInput: () -> Void
private var updateActivity: ((Bool) -> Void)? private var updateActivity: ((Bool) -> Void)?
private var activity: ValuePromise<Bool> = ValuePromise(ignoreRepeated: false) private var activity: ValuePromise<Bool> = ValuePromise(ignoreRepeated: false)
private let activityDisposable = MetaDisposable() 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.context = context
self.peerId = peerId self.peerId = peerId
self.cancel = cancel self.cancel = cancel
self.openPeer = openPeer self.openPeer = openPeer
self.approveRequest = approveRequest self.approveRequest = approveRequest
self.denyRequest = denyRequest self.denyRequest = denyRequest
self.navigateToChat = navigateToChat
self.pushController = pushController self.pushController = pushController
self.dismissInput = dismissInput self.dismissInput = dismissInput
self.presentInGlobalOverlay = presentInGlobalOverlay
self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal<Bool, NoError> in self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal<Bool, NoError> in
if value { if value {
return .single(value) |> delay(0.2, queue: Queue.mainQueue()) 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 { 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) self?.activity.set(value)
}, pushController: { [weak self] c in }, pushController: { [weak self] c in
self?.pushController(c) self?.pushController(c)
}, dismissInput: self.dismissInput) }, dismissInput: self.dismissInput, presentInGlobalOverlay: self.presentInGlobalOverlay)
} }
} }
private final class InviteRequestsSearchItemNode: ItemListControllerSearchNode { private final class InviteRequestsSearchItemNode: ItemListControllerSearchNode {
private let containerNode: InviteRequestsSearchContainerNode 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 self.containerNode = InviteRequestsSearchContainerNode(context: context, forceTheme: nil, peerId: peerId, openPeer: { peer in
openPeer(peer) openPeer(peer)
}, approveRequest: { peer in }, approveRequest: { peer in
approveRequest(peer) approveRequest(peer)
}, denyRequest: { peer in }, denyRequest: { peer in
denyRequest(peer) denyRequest(peer)
}, updateActivity: updateActivity, pushController: pushController) }, navigateToChat: { peer in
navigateToChat(peer)
}, updateActivity: updateActivity, pushController: pushController, presentInGlobalOverlay: presentInGlobalOverlay)
self.containerNode.cancel = { self.containerNode.cancel = {
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.context = context
self.openPeer = openPeer self.openPeer = openPeer
@ -391,8 +398,62 @@ public final class InviteRequestsSearchContainerNode: SearchDisplayControllerCon
}, denyRequest: { [weak self] peer in }, denyRequest: { [weak self] peer in
denyRequest(peer) denyRequest(peer)
self?.processedPeerIds.insert(peer.id) 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<Bool>(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 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)) let foundItems = combineLatest(searchQuery, context.account.postbox.peerView(id: peerId) |> take(1))
|> mapToSignal { query, peerView -> Signal<[InviteRequestsSearchEntry]?, NoError> in |> 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) return .single(nil)
} }
updateActivity(true) updateActivity(true)
let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: query)) let requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .requests(query: query))
let _ = previousRequestsContext.swap(requestsContext) 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()) return combineLatest(requestsContext.state, presentationDataPromise.get(), processedPeerIds.get())
|> mapToSignal { state, presentationData, processedPeerIds -> Signal<[InviteRequestsSearchEntry]?, NoError> in |> mapToSignal { state, presentationData, processedPeerIds -> Signal<[InviteRequestsSearchEntry]?, NoError> in
if !state.hasLoadedOnce { if !state.hasLoadedOnce {
@ -431,7 +499,7 @@ public final class InviteRequestsSearchContainerNode: SearchDisplayControllerCon
if processedPeerIds.contains(importer.peer.peerId) { if processedPeerIds.contains(importer.peer.peerId) {
continue 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 index += 1
} }
return .single(entries) return .single(entries)

View File

@ -198,6 +198,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
self.subtitleNode.contentsScale = UIScreen.main.scale self.subtitleNode.contentsScale = UIScreen.main.scale
self.expandedSubtitleNode = TextNode() self.expandedSubtitleNode = TextNode()
self.expandedSubtitleNode.alpha = 0.0
self.expandedSubtitleNode.isUserInteractionEnabled = false self.expandedSubtitleNode.isUserInteractionEnabled = false
self.expandedSubtitleNode.contentMode = .left self.expandedSubtitleNode.contentMode = .left
self.expandedSubtitleNode.contentsScale = UIScreen.main.scale self.expandedSubtitleNode.contentsScale = UIScreen.main.scale
@ -517,7 +518,7 @@ public class ItemListInviteRequestItemNode: ListViewItemNode, ItemListItemNode {
let rightInset: CGFloat = 16.0 + params.rightInset let rightInset: CGFloat = 16.0 + params.rightInset
let verticalInset: CGFloat = 9.0 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 (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 (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())) 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()))

View File

@ -307,10 +307,10 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
mutableDescriptionText.append(NSAttributedString(string: text + "\n", font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)) 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() let urlString = NSMutableAttributedString()
urlString.append(plainUrlString) 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 linkText = urlString
descriptionText = mutableDescriptionText descriptionText = mutableDescriptionText
@ -395,7 +395,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
} }
let urlAttributedString = NSMutableAttributedString() 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) { 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)) 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() 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) { 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)) 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 (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? var instantViewImage: UIImage?
if isInstantView { if isInstantView {
instantViewImage = PresentationResourcesChat.sharedMediaInstantViewIcon(item.presentationData.theme.theme) instantViewImage = PresentationResourcesChat.sharedMediaInstantViewIcon(item.presentationData.theme.theme)

View File

@ -38,6 +38,7 @@ private struct LocationViewTransaction {
let insertions: [ListViewInsertItem] let insertions: [ListViewInsertItem]
let updates: [ListViewUpdateItem] let updates: [ListViewUpdateItem]
let gotTravelTimes: Bool let gotTravelTimes: Bool
let count: Int
} }
private enum LocationViewEntryId: Hashable { 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 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) } 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 { enum LocationViewLocation: Equatable {
@ -453,7 +454,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
var drivingTime: Double? var drivingTime: Double?
var transitTime: Double? var transitTime: Double?
var walkingTime: Double? var walkingTime: Double?
if !isLocationView { if !isLocationView && message.author?.id != context.account.peerId {
if let (previousTimestamp, maybeDrivingTime, maybeTransitTime, maybeWalkingTime) = travelTimes[message.id] { if let (previousTimestamp, maybeDrivingTime, maybeTransitTime, maybeWalkingTime) = travelTimes[message.id] {
drivingTime = maybeDrivingTime drivingTime = maybeDrivingTime
transitTime = maybeTransitTime transitTime = maybeTransitTime
@ -704,7 +705,11 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
var index: Int = 0 var index: Int = 0
var offset: CGFloat = 0.0 var offset: CGFloat = 0.0
if transition.gotTravelTimes { if transition.gotTravelTimes {
index = 1 if transition.count > 1 {
index = 1
} else {
index = 0
}
offset = 0.0 offset = 0.0
} else if transition.insertions.count > 2 { } else if transition.insertions.count > 2 {
index = 2 index = 2

View File

@ -363,7 +363,7 @@ private final class ThemeCarouselThemeItemIconNode : ListViewItemNode {
var string: String? var string: String?
if let _ = item.themeReference.emoticon { if let _ = item.themeReference.emoticon {
} else { } else {
string = "⚙️" string = "🎨"
} }
let emojiTitle = NSAttributedString(string: string ?? "", font: Font.regular(20.0), textColor: .black) let emojiTitle = NSAttributedString(string: string ?? "", font: Font.regular(20.0), textColor: .black)

View File

@ -22,9 +22,9 @@ import AnimationUI
private final class ThemePickerControllerArguments { private final class ThemePickerControllerArguments {
let context: AccountContext let context: AccountContext
let selectTheme: (PresentationThemeReference) -> Void let selectTheme: (TelegramBaseTheme?, PresentationThemeReference) -> Void
let previewTheme: (PresentationThemeReference) -> Void let previewTheme: (PresentationThemeReference) -> Void
let selectAccentColor: (PresentationThemeAccentColor?) -> Void let selectAccentColor: (TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void
let openAccentColorPicker: (PresentationThemeReference, Bool) -> Void let openAccentColorPicker: (PresentationThemeReference, Bool) -> Void
let editTheme: (PresentationCloudTheme) -> Void let editTheme: (PresentationCloudTheme) -> Void
let editCurrentTheme: () -> Void let editCurrentTheme: () -> Void
@ -32,7 +32,7 @@ private final class ThemePickerControllerArguments {
let themeContextAction: (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void let themeContextAction: (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void
let colorContextAction: (Bool, PresentationThemeReference, ThemeSettingsColorOption?, 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.context = context
self.selectTheme = selectTheme self.selectTheme = selectTheme
self.previewTheme = previewTheme self.previewTheme = previewTheme
@ -57,7 +57,7 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry {
case themes(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, Bool, [String: [StickerPackItem]]) case themes(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, Bool, [String: [StickerPackItem]])
case customHeader(PresentationTheme, String) case customHeader(PresentationTheme, String)
case chatPreview(PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationChatBubbleCorners, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, [ChatPreviewMessageItem]) 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 accentColor(PresentationTheme, PresentationThemeReference, PresentationThemeReference, [PresentationThemeReference], ThemeSettingsColorOption?)
case editTheme(PresentationTheme, String) case editTheme(PresentationTheme, String)
case createTheme(PresentationTheme, String) case createTheme(PresentationTheme, String)
@ -120,8 +120,8 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .theme(lhsTheme, lhsStrings, lhsThemes, lhsAllThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeSpecificChatWallpapers, lhsCurrentColor): case let .theme(lhsTheme, lhsStrings, lhsThemes, lhsAllThemes, lhsCurrentTheme, lhsThemeAccentColors, lhsThemeSpecificChatWallpapers, lhsCurrentColor, lhsThemePreferredBaseTheme):
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 { 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 return true
} else { } else {
return false return false
@ -166,14 +166,14 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry {
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .chatPreview(theme, wallpaper, fontSize, chatBubbleCorners, strings, dateTimeFormat, nameDisplayOrder, items): 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) 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, _): 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, currentTheme: currentTheme, updatedTheme: { theme in 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 case let .cloud(theme) = theme, theme.theme.file == nil && theme.theme.settings == nil {
if theme.theme.isCreator { if theme.theme.isCreator {
arguments.editTheme(theme) arguments.editTheme(theme)
} }
} else { } else {
arguments.selectTheme(theme) arguments.selectTheme(nil, theme)
} }
}, contextAction: { theme, node, gesture in }, contextAction: { theme, node, gesture in
arguments.themeContextAction(theme.index == currentTheme.index, theme, node, gesture) 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 return ThemeSettingsAccentColorItem(theme: theme, sectionId: self.section, generalThemeReference: generalThemeReference, themeReference: currentTheme, colors: colorItems, currentColor: currentColor, updated: { color in
if let color = color { if let color = color {
switch color { switch color {
case let .accentColor(color): case let .accentColor(color):
arguments.selectAccentColor(color) arguments.selectAccentColor(baseTheme, color)
case let .theme(theme): case let .theme(theme):
arguments.selectTheme(theme) arguments.selectTheme(baseTheme, theme)
} }
} else { } else {
arguments.selectAccentColor(nil) arguments.selectAccentColor(nil, nil)
} }
}, contextAction: { isCurrent, theme, color, node, gesture in }, contextAction: { isCurrent, theme, color, node, gesture in
arguments.colorContextAction(isCurrent, theme, color, node, gesture) arguments.colorContextAction(isCurrent, theme, color, node, gesture)
@ -263,7 +271,7 @@ private enum ThemePickerControllerEntry: ItemListNodeEntry {
arguments.openAccentColorPicker(currentTheme, create) arguments.openAccentColorPicker(currentTheme, create)
}, tag: ThemeSettingsEntryTag.accentColor) }, tag: ThemeSettingsEntryTag.accentColor)
case let .editTheme(theme, text): 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() arguments.editCurrentTheme()
}) })
case let .createTheme(theme, text): case let .createTheme(theme, text):
@ -292,17 +300,23 @@ private func themePickerControllerEntries(presentationData: PresentationData, pr
} }
let generalThemeReference: PresentationThemeReference let generalThemeReference: PresentationThemeReference
if case let .cloud(theme) = themeReference, let settings = theme.theme.settings?.first { if case let .cloud(theme) = themeReference, let settings = theme.theme.settings {
generalThemeReference = .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)) 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 { } else {
generalThemeReference = themeReference 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 { if case let .builtin(builtinTheme) = generalThemeReference {
let colorThemes = availableThemes.filter { reference in 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 return true
} else { } else {
return false return false
@ -344,8 +358,8 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
var getNavigationControllerImpl: (() -> NavigationController?)? var getNavigationControllerImpl: (() -> NavigationController?)?
var presentCrossfadeControllerImpl: ((Bool) -> Void)? var presentCrossfadeControllerImpl: ((Bool) -> Void)?
var selectThemeImpl: ((PresentationThemeReference) -> Void)? var selectThemeImpl: ((TelegramBaseTheme?, PresentationThemeReference) -> Void)?
var selectAccentColorImpl: ((PresentationThemeAccentColor?) -> Void)? var selectAccentColorImpl: ((TelegramBaseTheme?, PresentationThemeAccentColor?) -> Void)?
var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)? var openAccentColorPickerImpl: ((PresentationThemeReference, Bool) -> Void)?
let _ = telegramWallpapers(postbox: context.account.postbox, network: context.account.network).start() 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<Bool>(false) let nightModePreviewPromise = ValuePromise<Bool>(false)
let arguments = ThemePickerControllerArguments(context: context, selectTheme: { theme in let arguments = ThemePickerControllerArguments(context: context, selectTheme: { baseTheme, theme in
selectThemeImpl?(theme) selectThemeImpl?(baseTheme, theme)
}, previewTheme: { themeReference in }, previewTheme: { themeReference in
if let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference) { if let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference) {
let controller = ThemePreviewController(context: context, previewTheme: theme, source: .settings(themeReference, nil, false)) let controller = ThemePreviewController(context: context, previewTheme: theme, source: .settings(themeReference, nil, false))
pushControllerImpl?(controller) pushControllerImpl?(controller)
} }
}, selectAccentColor: { accentColor in }, selectAccentColor: { currentBaseTheme, accentColor in
selectAccentColorImpl?(accentColor) selectAccentColorImpl?(currentBaseTheme, accentColor)
}, openAccentColorPicker: { themeReference, create in }, openAccentColorPicker: { themeReference, create in
openAccentColorPickerImpl?(themeReference, create) openAccentColorPickerImpl?(themeReference, create)
}, editTheme: { theme in }, editTheme: { theme in
@ -398,7 +412,30 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
}) })
pushControllerImpl?(controller) pushControllerImpl?(controller)
}, editCurrentTheme: { }, 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: { }, createNewTheme: {
let _ = (context.sharedContext.accountManager.transaction { transaction -> PresentationThemeReference in let _ = (context.sharedContext.accountManager.transaction { transaction -> PresentationThemeReference in
let settings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.presentationThemeSettings)?.get(PresentationThemeSettings.self) ?? PresentationThemeSettings.defaultSettings 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 isCurrent, let currentThemeIndex = themes.firstIndex(where: { $0.id == theme.theme.id }) {
if let settings = theme.theme.settings?.first { if let settings = theme.theme.settings?.first {
if settings.baseTheme == .night { if settings.baseTheme == .night {
selectAccentColorImpl?(PresentationThemeAccentColor(baseColor: .blue)) selectAccentColorImpl?(nil, PresentationThemeAccentColor(baseColor: .blue))
} else { } else {
selectAccentColorImpl?(nil) selectAccentColorImpl?(nil, nil)
} }
} else { } else {
let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil }) let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil })
@ -571,7 +608,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
} else { } else {
newTheme = .builtin(.nightAccent) 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 }) let previousThemeIndex = themes.prefix(upTo: currentThemeIndex).reversed().firstIndex(where: { $0.file != nil })
if let previousThemeIndex = previousThemeIndex { if let previousThemeIndex = previousThemeIndex {
let theme = themes[themes.index(before: previousThemeIndex.base)] 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 { } else {
if settings.baseTheme == .night { if settings.baseTheme == .night {
selectAccentColorImpl?(PresentationThemeAccentColor(baseColor: .blue)) selectAccentColorImpl?(nil, PresentationThemeAccentColor(baseColor: .blue))
} else { } else {
selectAccentColorImpl?(nil) selectAccentColorImpl?(nil, nil)
} }
} }
} }
@ -863,10 +900,10 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
themeReference = settings.theme themeReference = settings.theme
// } // }
let rightNavigationButton = ItemListNavigationButton(content: .node(switchNode), style: .regular, enabled: true, action: { let rightNavigationButton = ItemListNavigationButton(content: .node(switchNode), style: .regular, enabled: true, action: { [weak switchNode] in
// nightModePreviewPromise.set(!nightModePreview) nightModePreviewPromise.set(!nightModePreview)
// switchNode?.play(isDark: presentationData.theme.overallDarkAppearance, theme: presentationData.theme) switchNode?.play(isDark: presentationData.theme.overallDarkAppearance, theme: presentationData.theme)
// presentCrossfadeControllerImpl?(false) presentCrossfadeControllerImpl?(false)
}) })
var defaultThemes: [PresentationThemeReference] = [] var defaultThemes: [PresentationThemeReference] = []
@ -985,7 +1022,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
context.sharedContext.presentGlobalController(crossfadeController, nil) context.sharedContext.presentGlobalController(crossfadeController, nil)
} }
} }
selectThemeImpl = { theme in selectThemeImpl = { baseTheme, theme in
guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme) else { guard let presentationTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: theme) else {
return return
} }
@ -1029,9 +1066,14 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
var baseThemeIndex: Int64? var baseThemeIndex: Int64?
var updatedThemeBaseIndex: Int64? var updatedThemeBaseIndex: Int64?
var updatedBaseTheme: TelegramBaseTheme?
if case let .cloud(info) = theme { if case let .cloud(info) = theme {
updatedTheme = .cloud(PresentationCloudTheme(theme: info.theme, resolvedWallpaper: resolvedWallpaper, creatorAccountId: info.theme.isCreator ? context.account.id : nil)) 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 baseThemeIndex = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)).index
updatedThemeBaseIndex = baseThemeIndex updatedThemeBaseIndex = baseThemeIndex
} }
@ -1040,6 +1082,10 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
} }
let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
var updatedThemePreferredBaseTheme = current.themePreferredBaseTheme
if let updatedBaseTheme = updatedBaseTheme {
updatedThemePreferredBaseTheme[updatedTheme.index] = updatedBaseTheme
}
var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting var updatedAutomaticThemeSwitchSetting = current.automaticThemeSwitchSetting
if case let .cloud(info) = updatedTheme, info.theme.settings?.contains(where: { $0.baseTheme == .night || $0.baseTheme == .tinted }) ?? false { if case let .cloud(info) = updatedTheme, info.theme.settings?.contains(where: { $0.baseTheme == .night || $0.baseTheme == .tinted }) ?? false {
updatedAutomaticThemeSwitchSetting.theme = updatedTheme updatedAutomaticThemeSwitchSetting.theme = updatedTheme
@ -1050,7 +1096,7 @@ public func themePickerController(context: AccountContext, focusOnItemTag: Theme
updatedAutomaticThemeSwitchSetting.theme = updatedTheme updatedAutomaticThemeSwitchSetting.theme = updatedTheme
} }
} }
return current.withUpdatedTheme(updatedTheme).withUpdatedAutomaticThemeSwitchSetting(updatedAutomaticThemeSwitchSetting) return current.withUpdatedTheme(updatedTheme).withUpdatedThemePreferredBaseTheme(updatedThemePreferredBaseTheme).withUpdatedAutomaticThemeSwitchSetting(updatedAutomaticThemeSwitchSetting)
// var updatedThemeSpecificAccentColors = current.themeSpecificAccentColors // var updatedThemeSpecificAccentColors = current.themeSpecificAccentColors
// if let baseThemeIndex = baseThemeIndex { // if let baseThemeIndex = baseThemeIndex {
// updatedThemeSpecificAccentColors[baseThemeIndex] = PresentationThemeAccentColor(themeIndex: updatedTheme.index) // 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)) let controller = ThemeAccentColorController(context: context, mode: .colors(themeReference: themeReference, create: create))
pushControllerImpl?(controller) pushControllerImpl?(controller)
} }
selectAccentColorImpl = { accentColor in selectAccentColorImpl = { currentBaseTheme, accentColor in
var wallpaperSignal: Signal<TelegramWallpaper?, NoError> = .single(nil) let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
if let colorWallpaper = accentColor?.wallpaper, case let .file(file) = colorWallpaper { return current
wallpaperSignal = cachedWallpaper(account: context.account, slug: file.slug, settings: colorWallpaper.settings) // var currentTheme = current.theme
|> mapToSignal { cachedWallpaper in // let currentPreferredBaseTheme = currentBaseTheme
if let wallpaper = cachedWallpaper?.wallpaper, case let .file(file) = wallpaper { // if case let .cloud(theme) = currentTheme, let _ = theme.theme.settings, currentBaseTheme != nil {
let _ = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource)).start() //
// }
return .single(wallpaper) //
// 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)
} else { }).start()
return .single(nil)
}
}
}
let _ = (wallpaperSignal presentCrossfadeControllerImpl?(true)
|> 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)
})
} }
// var wallpaperSignal: Signal<TelegramWallpaper?, NoError> = .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 return controller
} }

View File

@ -288,11 +288,11 @@ private func editThemeControllerEntries(presentationData: PresentationData, stat
entries.append(.changeColors(presentationData.theme, presentationData.strings.EditTheme_ChangeColors)) entries.append(.changeColors(presentationData.theme, presentationData.strings.EditTheme_ChangeColors))
if hasSettings { if hasSettings {
if previewTheme.overallDarkAppearance { if previewTheme.overallDarkAppearance {
entries.append(.toggleDark(presentationData.theme, "Toggle Base Theme")) // entries.append(.toggleDark(presentationData.theme, "Toggle Base Theme"))
} }
} else { } else {
if !isCreate { 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(.uploadTheme(presentationData.theme, uploadText))
entries.append(.uploadInfo(presentationData.theme, uploadInfo)) entries.append(.uploadInfo(presentationData.theme, uploadInfo))
@ -643,7 +643,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
themeSpecificChatWallpapers[themeReference.index] = nil 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: { }) |> deliverOnMainQueue).start(completed: {
if !hasCustomFile { if !hasCustomFile {
saveThemeTemplateFile(state.title, themeResource, { saveThemeTemplateFile(state.title, themeResource, {
@ -677,7 +677,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
themeSpecificChatWallpapers[themeReference.index] = nil 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: { }) |> deliverOnMainQueue).start(completed: {
if let themeResource = themeResource, !hasCustomFile { if let themeResource = themeResource, !hasCustomFile {
saveThemeTemplateFile(state.title, themeResource, { saveThemeTemplateFile(state.title, themeResource, {

View File

@ -249,13 +249,14 @@ final class ThemeAccentColorController: ViewController {
updatedTheme = themeReference updatedTheme = themeReference
} }
let themePreferredBaseTheme = current.themePreferredBaseTheme
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
themeSpecificChatWallpapers[themeReference.index] = nil themeSpecificChatWallpapers[themeReference.index] = nil
var themeSpecificAccentColors = current.themeSpecificAccentColors var themeSpecificAccentColors = current.themeSpecificAccentColors
themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) 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) |> castError(CreateThemeError.self)
} else { } else {
@ -278,13 +279,14 @@ final class ThemeAccentColorController: ViewController {
updatedTheme = themeReference updatedTheme = themeReference
} }
let themePreferredBaseTheme = current.themePreferredBaseTheme
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
themeSpecificChatWallpapers[themeReference.index] = nil themeSpecificChatWallpapers[themeReference.index] = nil
var themeSpecificAccentColors = current.themeSpecificAccentColors var themeSpecificAccentColors = current.themeSpecificAccentColors
themeSpecificAccentColors[baseThemeReference.index] = PresentationThemeAccentColor(themeIndex: themeReference.index) 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) |> castError(CreateThemeError.self)
} else { } else {

View File

@ -245,7 +245,7 @@ private enum ThemeAutoNightSettingsControllerEntry: ItemListNodeEntry {
case let .themeHeader(_, title): case let .themeHeader(_, title):
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
case let .themeItem(theme, strings, themes, allThemes, currentTheme, themeSpecificAccentColors, themeSpecificChatWallpapers): 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) arguments.updateTheme(theme)
}, contextAction: nil) }, contextAction: nil)
} }

View File

@ -1230,6 +1230,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
return current return current
} }
let themePreferredBaseTheme = current.themePreferredBaseTheme
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
var themeSpecificAccentColors = current.themeSpecificAccentColors var themeSpecificAccentColors = current.themeSpecificAccentColors
themeSpecificAccentColors[generalThemeReference.index] = accentColor?.withUpdatedWallpaper(presetWallpaper) 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() }).start()
presentCrossfadeControllerImpl?(true) presentCrossfadeControllerImpl?(true)

View File

@ -358,12 +358,13 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem {
let displayUnsupported: Bool let displayUnsupported: Bool
let themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] let themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]
let themeSpecificChatWallpapers: [Int64: TelegramWallpaper] let themeSpecificChatWallpapers: [Int64: TelegramWallpaper]
let themePreferredBaseTheme: [Int64: TelegramBaseTheme]
let currentTheme: PresentationThemeReference let currentTheme: PresentationThemeReference
let updatedTheme: (PresentationThemeReference) -> Void let updatedTheme: (PresentationThemeReference) -> Void
let contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)? let contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?
let tag: ItemListItemTag? 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.context = context
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
@ -372,6 +373,7 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem {
self.displayUnsupported = displayUnsupported self.displayUnsupported = displayUnsupported
self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificAccentColors = themeSpecificAccentColors
self.themeSpecificChatWallpapers = themeSpecificChatWallpapers self.themeSpecificChatWallpapers = themeSpecificChatWallpapers
self.themePreferredBaseTheme = themePreferredBaseTheme
self.currentTheme = currentTheme self.currentTheme = currentTheme
self.updatedTheme = updatedTheme self.updatedTheme = updatedTheme
self.contextAction = contextAction self.contextAction = contextAction
@ -636,7 +638,12 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode {
let wallpaper = accentColor?.wallpaper ?? customWallpaper ?? themeWallpaper 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)) entries.append(ThemeSettingsThemeEntry(index: index, themeReference: theme, title: title, accentColor: accentColor, selected: selected, theme: item.theme, wallpaper: wallpaper))
index += 1 index += 1
} }

View File

@ -155,7 +155,10 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
self.isUserInteractionEnabled = false 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() let progressNode = ASImageNode()
progressNode.displaysAsynchronously = false progressNode.displaysAsynchronously = false
progressNode.frame = progressFrame progressNode.frame = progressFrame

View File

@ -1,7 +1,7 @@
import Foundation import Foundation
import Postbox import Postbox
public enum TelegramBaseTheme: Int32 { public enum TelegramBaseTheme: Int32, Codable {
case classic case classic
case day case day
case night case night

View File

@ -9,6 +9,10 @@ public extension TelegramEngine {
self.account = account self.account = account
} }
// public func getThemes(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<[TelegramTheme], NoError> {
// return _internal_getThemes(accountManager: accountManager, postbox: self.account.postbox, network: self.account.network)
// }
public func getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> { public func getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> {
return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached) return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached)
} }

View File

@ -623,9 +623,16 @@ public func updatedPresentationData(accountManager: AccountManager<TelegramAccou
switchedToNightModeWallpaper = true switchedToNightModeWallpaper = true
} }
effectiveTheme = automaticTheme effectiveTheme = automaticTheme
preferredBaseTheme = .night if let baseTheme = themeSettings.themePreferredBaseTheme[effectiveTheme.index], [.night, .tinted].contains(baseTheme) {
preferredBaseTheme = baseTheme
} else {
preferredBaseTheme = .night
}
} else { } else {
effectiveTheme = themeSettings.theme effectiveTheme = themeSettings.theme
if let baseTheme = themeSettings.themePreferredBaseTheme[effectiveTheme.index], [.classic, .day].contains(baseTheme) {
preferredBaseTheme = baseTheme
}
} }
if let colors = effectiveColors, colors.baseColor == .theme { if let colors = effectiveColors, colors.baseColor == .theme {

View File

@ -55,6 +55,7 @@ public enum PresentationResourceKey: Int32 {
case itemListCloseIconImage case itemListCloseIconImage
case itemListMakeVisibleIcon case itemListMakeVisibleIcon
case itemListMakeInvisibleIcon case itemListMakeInvisibleIcon
case itemListEditThemeIcon
case itemListCornersTop case itemListCornersTop
case itemListCornersBottom case itemListCornersBottom
case itemListCornersBoth case itemListCornersBoth

View File

@ -181,6 +181,12 @@ public struct PresentationResourcesItemList {
}) })
} }
public static func makeEditThemeIcon(_ theme: PresentationTheme) -> 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? { public static func cornersImage(_ theme: PresentationTheme, top: Bool, bottom: Bool) -> UIImage? {
if !top && !bottom { if !top && !bottom {
return nil return nil

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "colors_30.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

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

View File

@ -138,7 +138,7 @@ final class ThemeUpdateManagerImpl: ThemeUpdateManager {
theme = updatedTheme 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() }).start()
} }

View File

@ -129,7 +129,7 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager {
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
themeSpecificChatWallpapers[themeReference.index] = updatedWallpaper themeSpecificChatWallpapers[themeReference.index] = updatedWallpaper
themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: current.themeSpecificAccentColors[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() })).start()
} }

View File

@ -591,6 +591,7 @@ public struct PresentationThemeSettings: Codable {
} }
public var theme: PresentationThemeReference public var theme: PresentationThemeReference
public var themePreferredBaseTheme: [Int64: TelegramBaseTheme]
public var themeSpecificAccentColors: [Int64: PresentationThemeAccentColor] public var themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]
public var themeSpecificChatWallpapers: [Int64: TelegramWallpaper] public var themeSpecificChatWallpapers: [Int64: TelegramWallpaper]
public var useSystemFont: Bool public var useSystemFont: Bool
@ -637,11 +638,12 @@ public struct PresentationThemeSettings: Codable {
} }
public static var defaultSettings: PresentationThemeSettings { 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.theme = theme
self.themePreferredBaseTheme = themePreferredBaseTheme
self.themeSpecificAccentColors = themeSpecificAccentColors self.themeSpecificAccentColors = themeSpecificAccentColors
self.themeSpecificChatWallpapers = themeSpecificChatWallpapers self.themeSpecificChatWallpapers = themeSpecificChatWallpapers
self.useSystemFont = useSystemFont self.useSystemFont = useSystemFont
@ -661,6 +663,15 @@ public struct PresentationThemeSettings: Codable {
} else { } else {
self.theme = .builtin(.dayClassic) 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") let themeSpecificChatWallpapersDict = try container.decode([DictionaryKey: TelegramWallpaperNativeCodable].self, forKey: "themeSpecificChatWallpapers")
var mappedThemeSpecificChatWallpapers: [Int64: TelegramWallpaper] = [:] var mappedThemeSpecificChatWallpapers: [Int64: TelegramWallpaper] = [:]
@ -695,6 +706,12 @@ public struct PresentationThemeSettings: Codable {
try container.encode(PostboxEncoder().encodeObjectToRawData(self.theme), forKey: "t") 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] = [:] var mappedThemeSpecificAccentColors: [DictionaryKey: AdaptedPostboxEncoder.RawObjectData] = [:]
for (key, value) in self.themeSpecificAccentColors { for (key, value) in self.themeSpecificAccentColors {
mappedThemeSpecificAccentColors[DictionaryKey(key)] = PostboxEncoder().encodeObjectToRawData(value) mappedThemeSpecificAccentColors[DictionaryKey(key)] = PostboxEncoder().encodeObjectToRawData(value)
@ -717,43 +734,47 @@ public struct PresentationThemeSettings: Codable {
} }
public static func ==(lhs: PresentationThemeSettings, rhs: PresentationThemeSettings) -> Bool { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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)
} }
} }

View File

@ -1308,7 +1308,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
} }
let themeSignal: Signal<PresentationTheme?, NoError> let themeSignal: Signal<PresentationTheme?, NoError>
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)) themeSignal = .single(makePresentationTheme(cloudTheme: theme.theme, dark: nightMode))
} else if case let .builtin(theme) = theme { } else if case let .builtin(theme) = theme {
themeSignal = .single(makeDefaultPresentationTheme(reference: theme, serviceBackgroundColor: nil)) themeSignal = .single(makeDefaultPresentationTheme(reference: theme, serviceBackgroundColor: nil))
@ -1485,12 +1485,12 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
if large { if large {
c.saveGState() c.saveGState()
c.translateBy(x: 5.0, y: 25.0) c.translateBy(x: 7.0, y: 27.0)
c.translateBy(x: 114.0, y: 32.0) c.translateBy(x: 114.0, y: 32.0)
c.scaleBy(x: 1.0, y: -1.0) c.scaleBy(x: 1.0, y: -1.0)
c.translateBy(x: -114.0, y: -32.0) c.translateBy(x: -114.0, y: -32.0)
let _ = try? drawSvgPath(c, path: "M98.0061174,0 C106.734138,0 113.82927,6.99200411 113.996965,15.6850616 L114,16 C114,24.836556 106.830179,32 98.0061174,32 L21.9938826,32 C18.2292665,32 14.7684355,30.699197 12.0362474,28.5221601 C8.56516444,32.1765452 -1.77635684e-15,31.9985981 -1.77635684e-15,31.9985981 C5.69252399,28.6991366 5.98604874,24.4421608 5.99940747,24.1573436 L6,24.1422468 L6,16 C6,7.163444 13.1698213,0 21.9938826,0 L98.0061174,0 ") let _ = try? drawSvgPath(c, path: "M12.8304,29.8712 C10.0551,31.8416 6.6628,33 2.99998,33 C1.98426,33 0.989361,32.9109 0.022644,32.7402 C2.97318,31.9699 5.24596,29.5785 5.84625,26.5607 C5.99996,25.7879 5.99996,24.8586 5.99996,23 V16.0 H6.00743 C6.27176,7.11861 13.5546,0 22.5,0 H61.5 C70.6127,0 78,7.3873 78,16.5 C78,25.6127 70.6127,33 61.5,33 H22.5 C18.8883,33 15.5476,31.8396 12.8304,29.8712 ")
if Set(incomingColors.map(\.rgb)).count > 1 { if Set(incomingColors.map(\.rgb)).count > 1 {
c.clip() c.clip()
@ -1504,7 +1504,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
let colorSpace = CGColorSpaceCreateDeviceRGB() let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)! let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)!
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 32.0), options: CGGradientDrawingOptions()) c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 34.0), options: CGGradientDrawingOptions())
} else { } else {
c.setFillColor(incomingColors[0].cgColor) c.setFillColor(incomingColors[0].cgColor)
c.fillPath() c.fillPath()
@ -1517,7 +1517,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
c.clip() c.clip()
if incomingColors.count >= 2 { if incomingColors.count >= 2 {
let gradientColors = incomingColors.map { $0.cgColor } as CFArray let gradientColors = incomingColors.reversed().map { $0.cgColor } as CFArray
var locations: [CGFloat] = [] var locations: [CGFloat] = []
for i in 0 ..< incomingColors.count { for i in 0 ..< incomingColors.count {
@ -1551,12 +1551,12 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
if large { if large {
c.saveGState() c.saveGState()
c.translateBy(x: drawingRect.width - 114.0 - 5.0, y: 65.0) c.translateBy(x: -71.0, y: 66.0)
c.translateBy(x: 114.0, y: 32.0) c.translateBy(x: 114.0, y: 32.0)
c.scaleBy(x: -1.0, y: -1.0) c.scaleBy(x: 1.0, y: -1.0)
c.translateBy(x: 0, y: -32.0) c.translateBy(x: 0.0, y: -32.0)
let _ = try? drawSvgPath(c, path: "M98.0061174,0 C106.734138,0 113.82927,6.99200411 113.996965,15.6850616 L114,16 C114,24.836556 106.830179,32 98.0061174,32 L21.9938826,32 C18.2292665,32 14.7684355,30.699197 12.0362474,28.5221601 C8.56516444,32.1765452 -1.77635684e-15,31.9985981 -1.77635684e-15,31.9985981 C5.69252399,28.6991366 5.98604874,24.4421608 5.99940747,24.1573436 L6,24.1422468 L6,16 C6,7.163444 13.1698213,0 21.9938826,0 L98.0061174,0 ") let _ = try? drawSvgPath(c, path: "M57.1696,29.8712 C59.9449,31.8416 63.3372,33 67,33 C68.0157,33 69.0106,32.9109 69.9773,32.7402 C67.0268,31.9699 64.754,29.5786 64.1537,26.5607 C64,25.7879 64,24.8586 64,23 V16.5 V16 H63.9926 C63.7282,7.11861 56.4454,0 47.5,0 H16.5 C7.3873,0 0,7.3873 0,16.5 C0,25.6127 7.3873,33 16.5,33 H47.5 C51.1117,33 54.4524,31.8396 57.1696,29.8712 ")
if Set(outgoingColors.map(\.rgb)).count > 1 { if Set(outgoingColors.map(\.rgb)).count > 1 {
c.clip() c.clip()
@ -1570,7 +1570,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
let colorSpace = CGColorSpaceCreateDeviceRGB() let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)! let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)!
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 32.0), options: CGGradientDrawingOptions()) c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 34.0), options: CGGradientDrawingOptions())
} else { } else {
c.setFillColor(outgoingColors[0].cgColor) c.setFillColor(outgoingColors[0].cgColor)
c.fillPath() c.fillPath()
@ -1583,7 +1583,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
c.clip() c.clip()
if outgoingColors.count >= 2 { if outgoingColors.count >= 2 {
let gradientColors = outgoingColors.map { $0.cgColor } as CFArray let gradientColors = outgoingColors.reversed().map { $0.cgColor } as CFArray
var locations: [CGFloat] = [] var locations: [CGFloat] = []
for i in 0 ..< outgoingColors.count { for i in 0 ..< outgoingColors.count {