mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various Improvements
This commit is contained in:
parent
6c38a5a68f
commit
d60588b3f1
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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()))
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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, {
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
12
submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "colors_30.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
212
submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/colors_30.pdf
vendored
Normal file
212
submodules/TelegramUI/Images.xcassets/Settings/EditTheme.imageset/colors_30.pdf
vendored
Normal 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
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user