mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Implemented chat-specific themes
This commit is contained in:
parent
c7fe52fd72
commit
d423f90681
@ -6,6 +6,8 @@ load("@build_bazel_rules_apple//apple:ios.bzl",
|
|||||||
"ios_application",
|
"ios_application",
|
||||||
"ios_extension",
|
"ios_extension",
|
||||||
"ios_framework",
|
"ios_framework",
|
||||||
|
"ios_unit_test",
|
||||||
|
"ios_ui_test",
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_apple//apple:resources.bzl",
|
load("@build_bazel_rules_apple//apple:resources.bzl",
|
||||||
@ -1853,6 +1855,23 @@ ios_application(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "UITestsLib",
|
||||||
|
module_name = "UITestsLib",
|
||||||
|
srcs = glob(["UITests/**/*.swift"]),
|
||||||
|
deps = [
|
||||||
|
"//submodules/TelegramUI:TelegramUI",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_ui_test(
|
||||||
|
name = "UITests",
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
deps = [":UITestsLib"],
|
||||||
|
infoplists = [":UITestsLib/Info.plist"],
|
||||||
|
test_host = ":Telegram",
|
||||||
|
)
|
||||||
|
|
||||||
# Temporary targets used to simplify webrtc build tests
|
# Temporary targets used to simplify webrtc build tests
|
||||||
|
|
||||||
ios_application(
|
ios_application(
|
||||||
|
@ -6622,6 +6622,21 @@ Sorry for the inconvenience.";
|
|||||||
"Group.Username.InvalidStartsWithUnderscore" = "Group names can't start with an underscore.";
|
"Group.Username.InvalidStartsWithUnderscore" = "Group names can't start with an underscore.";
|
||||||
"Group.Username.InvalidEndsWithUnderscore" = "Group names can't end with an underscore.";
|
"Group.Username.InvalidEndsWithUnderscore" = "Group names can't end with an underscore.";
|
||||||
|
|
||||||
|
"UserInfo.ChangeColors" = "Change Colors";
|
||||||
|
|
||||||
|
"Conversation.Theme.Title" = "Select Theme";
|
||||||
|
"Conversation.Theme.Apply" = "Apply Theme";
|
||||||
|
"Conversation.Theme.NoTheme" = "No\nTheme";
|
||||||
|
"Conversation.Theme.Reset" = "Reset Theme for This Chat";
|
||||||
|
"Conversation.Theme.SwitchToDark" = "Switch to dark appearance";
|
||||||
|
"Conversation.Theme.SwitchToLight" = "Switch to light appearance";
|
||||||
|
|
||||||
|
"Notification.ChangedTheme" = "%1$@ changed chat theme to %2$@";
|
||||||
|
"Notification.DisabledTheme" = "%@ disabled chat theme";
|
||||||
|
|
||||||
|
"Notification.YouChangedTheme" = "You changed chat theme to %@";
|
||||||
|
"Notification.YouDisabledTheme" = "You disabled chat theme";
|
||||||
|
|
||||||
"Appstore.Cloud" = "**Cloud-based**\nUnlimited storage for chats,\nmedia and documents.";
|
"Appstore.Cloud" = "**Cloud-based**\nUnlimited storage for chats,\nmedia and documents.";
|
||||||
"Appstore.Cloud.Profile" = "**Jennifer**\n23 y.o. designer from San Francisco.";
|
"Appstore.Cloud.Profile" = "**Jennifer**\n23 y.o. designer from San Francisco.";
|
||||||
"Appstore.Creative" = "**Creative**\nColor themes, stickers, GIFs,\nvideo messages and more.";
|
"Appstore.Creative" = "**Creative**\nColor themes, stickers, GIFs,\nvideo messages and more.";
|
||||||
|
@ -290,9 +290,10 @@ public final class NavigateToChatControllerParams {
|
|||||||
public let options: NavigationAnimationOptions
|
public let options: NavigationAnimationOptions
|
||||||
public let parentGroupId: PeerGroupId?
|
public let parentGroupId: PeerGroupId?
|
||||||
public let chatListFilter: Int32?
|
public let chatListFilter: Int32?
|
||||||
|
public let changeColors: Bool
|
||||||
public let completion: (ChatController) -> Void
|
public let completion: (ChatController) -> Void
|
||||||
|
|
||||||
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, completion: @escaping (ChatController) -> Void = { _ in }) {
|
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, changeColors: Bool = false, completion: @escaping (ChatController) -> Void = { _ in }) {
|
||||||
self.navigationController = navigationController
|
self.navigationController = navigationController
|
||||||
self.chatController = chatController
|
self.chatController = chatController
|
||||||
self.chatLocationContextHolder = chatLocationContextHolder
|
self.chatLocationContextHolder = chatLocationContextHolder
|
||||||
@ -314,6 +315,7 @@ public final class NavigateToChatControllerParams {
|
|||||||
self.options = options
|
self.options = options
|
||||||
self.parentGroupId = parentGroupId
|
self.parentGroupId = parentGroupId
|
||||||
self.chatListFilter = chatListFilter
|
self.chatListFilter = chatListFilter
|
||||||
|
self.changeColors = changeColors
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,6 +578,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
var activeAccountsWithInfo: Signal<(primary: AccountRecordId?, accounts: [AccountWithInfo]), NoError> { get }
|
var activeAccountsWithInfo: Signal<(primary: AccountRecordId?, accounts: [AccountWithInfo]), NoError> { get }
|
||||||
|
|
||||||
var presentGlobalController: (ViewController, Any?) -> Void { get }
|
var presentGlobalController: (ViewController, Any?) -> Void { get }
|
||||||
|
var presentCrossfadeController: () -> Void { get }
|
||||||
|
|
||||||
func makeTempAccountContext(account: Account) -> AccountContext
|
func makeTempAccountContext(account: Account) -> AccountContext
|
||||||
|
|
||||||
@ -587,7 +590,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func openChatMessage(_ params: OpenChatMessageParams) -> Bool
|
func openChatMessage(_ params: OpenChatMessageParams) -> Bool
|
||||||
func messageFromPreloadedChatHistoryViewForLocation(id: MessageId, location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?) -> Signal<(MessageIndex?, Bool), NoError>
|
func messageFromPreloadedChatHistoryViewForLocation(id: MessageId, location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?) -> Signal<(MessageIndex?, Bool), NoError>
|
||||||
func makeOverlayAudioPlayerController(context: AccountContext, peerId: PeerId, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController
|
func makeOverlayAudioPlayerController(context: AccountContext, peerId: PeerId, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController
|
||||||
func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool) -> ViewController?
|
func makePeerInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool) -> ViewController?
|
||||||
func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController?
|
func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController?
|
||||||
func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController
|
func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController
|
||||||
func makePeersNearbyController(context: AccountContext) -> ViewController
|
func makePeersNearbyController(context: AccountContext) -> ViewController
|
||||||
|
@ -44,6 +44,8 @@ public final class AnimationNode : ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view.logHierarchyKeypaths()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
} else {
|
} else {
|
||||||
return LOTAnimationView()
|
return LOTAnimationView()
|
||||||
|
@ -208,7 +208,7 @@ public final class CallListController: TelegramBaseController {
|
|||||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
|
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
|
||||||
)
|
)
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
if let strongSelf = self, let peer = peer, let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer._asPeer(), mode: .calls(messages: messages.map({ $0._asMessage() })), avatarInitiallyExpanded: false, fromChat: false) {
|
if let strongSelf = self, let peer = peer, let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .calls(messages: messages.map({ $0._asMessage() })), avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(controller)
|
(strongSelf.navigationController as? NavigationController)?.pushViewController(controller)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -487,7 +487,7 @@ public class ContactsController: ViewController {
|
|||||||
}
|
}
|
||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
|
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,9 @@ public final class ListViewReorderingGestureRecognizer: UIGestureRecognizer {
|
|||||||
self.startLongPressTimer()
|
self.startLongPressTimer()
|
||||||
} else {
|
} else {
|
||||||
self.state = .began
|
self.state = .began
|
||||||
|
if let itemNode = self.itemNode {
|
||||||
|
self.began(itemNode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.state = .failed
|
self.state = .failed
|
||||||
|
@ -8,7 +8,7 @@ private var backArrowImageCache: [Int32: UIImage] = [:]
|
|||||||
public final class SparseNode: ASDisplayNode {
|
public final class SparseNode: ASDisplayNode {
|
||||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
for view in self.view.subviews {
|
for view in self.view.subviews {
|
||||||
if let result = view.hitTest(self.view.convert(point, to: view), with: event) {
|
if let result = view.hitTest(self.view.convert(point, to: view), with: event), result.isUserInteractionEnabled {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1221,7 +1221,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peerId)
|
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let controller = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
strongSelf.getNavigationController()?.pushViewController(controller)
|
strongSelf.getNavigationController()?.pushViewController(controller)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ public func legacyMediaEditor(context: AccountContext, peer: Peer, media: AnyMed
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocation: ChatLocation, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, ((String) -> UIView?)?, @escaping () -> Void) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController {
|
public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocation: ChatLocation, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, presentationData: PresentationData, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, ((String) -> UIView?)?, @escaping () -> Void) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController {
|
||||||
let defaultVideoPreset = defaultVideoPresetForContext(context)
|
let defaultVideoPreset = defaultVideoPresetForContext(context)
|
||||||
UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0")
|
UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0")
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, chatLocati
|
|||||||
|
|
||||||
legacyController.enableSizeClassSignal = true
|
legacyController.enableSizeClassSignal = true
|
||||||
|
|
||||||
let presentationDisposable = context.sharedContext.presentationData.start(next: { [weak legacyController] presentationData in
|
let presentationDisposable = updatedPresentationData.signal.start(next: { [weak legacyController] presentationData in
|
||||||
if let legacyController = legacyController, let controller = legacyController.legacyController as? TGMenuSheetController {
|
if let legacyController = legacyController, let controller = legacyController.legacyController as? TGMenuSheetController {
|
||||||
controller.pallete = legacyMenuPaletteFromTheme(presentationData.theme, forceDark: false)
|
controller.pallete = legacyMenuPaletteFromTheme(presentationData.theme, forceDark: false)
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ public final class SecureIdAuthController: ViewController, StandalonePresentable
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
|
(strongSelf.navigationController as? NavigationController)?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -371,7 +371,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
|||||||
if let navigationController = getNavigationControllerImpl?() {
|
if let navigationController = getNavigationControllerImpl?() {
|
||||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(participant.peer.id)))
|
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(participant.peer.id)))
|
||||||
}
|
}
|
||||||
} else if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: participant.peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
} else if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: participant.peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(infoController)
|
pushControllerImpl?(infoController)
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
@ -423,7 +423,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}, openPeer: { peer in
|
}, openPeer: { peer in
|
||||||
if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
}, inviteViaLink: {
|
}, inviteViaLink: {
|
||||||
@ -483,7 +483,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
|
|||||||
return state.withUpdatedSearchingMembers(false)
|
return state.withUpdatedSearchingMembers(false)
|
||||||
}
|
}
|
||||||
}, openPeer: { peer, _ in
|
}, openPeer: { peer, _ in
|
||||||
if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(infoController)
|
pushControllerImpl?(infoController)
|
||||||
}
|
}
|
||||||
}, pushController: { c in
|
}, pushController: { c in
|
||||||
|
@ -698,7 +698,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
|
|||||||
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||||
})
|
})
|
||||||
}, openPeerInfo: { peer in
|
}, openPeerInfo: { peer in
|
||||||
if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
}, openKicked: {
|
}, openKicked: {
|
||||||
|
@ -598,7 +598,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|
|||||||
controller?.clearItemNodesHighlight(animated: true)
|
controller?.clearItemNodesHighlight(animated: true)
|
||||||
}
|
}
|
||||||
navigateToProfileImpl = { [weak controller] peer, distance in
|
navigateToProfileImpl = { [weak controller] peer, distance in
|
||||||
if let navigationController = controller?.navigationController as? NavigationController, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .nearbyPeer(distance: distance), avatarInitiallyExpanded: peer.largeProfileImage != nil, fromChat: false) {
|
if let navigationController = controller?.navigationController as? NavigationController, let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .nearbyPeer(distance: distance), avatarInitiallyExpanded: peer.largeProfileImage != nil, fromChat: false) {
|
||||||
navigationController.pushViewController(controller)
|
navigationController.pushViewController(controller)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ public func blockedPeersController(context: AccountContext, blockedPeersContext:
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}, openPeer: { peer in
|
}, openPeer: { peer in
|
||||||
if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -319,7 +319,7 @@ public func selectivePrivacyPeersController(context: AccountContext, title: Stri
|
|||||||
return transaction.getPeer(peerId)
|
return transaction.getPeer(peerId)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
guard let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) else {
|
guard let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
|
@ -873,7 +873,7 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
|||||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
navigationController.pushViewController(controller)
|
navigationController.pushViewController(controller)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -181,6 +181,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[608050278] = { return Api.SendMessageAction.parse_sendMessageUploadRoundAction($0) }
|
dict[608050278] = { return Api.SendMessageAction.parse_sendMessageUploadRoundAction($0) }
|
||||||
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
||||||
dict[-606432698] = { return Api.SendMessageAction.parse_sendMessageHistoryImportAction($0) }
|
dict[-606432698] = { return Api.SendMessageAction.parse_sendMessageHistoryImportAction($0) }
|
||||||
|
dict[-1336228175] = { return Api.SendMessageAction.parse_sendMessageChooseStickerAction($0) }
|
||||||
dict[-1137792208] = { return Api.PrivacyKey.parse_privacyKeyStatusTimestamp($0) }
|
dict[-1137792208] = { return Api.PrivacyKey.parse_privacyKeyStatusTimestamp($0) }
|
||||||
dict[1343122938] = { return Api.PrivacyKey.parse_privacyKeyChatInvite($0) }
|
dict[1343122938] = { return Api.PrivacyKey.parse_privacyKeyChatInvite($0) }
|
||||||
dict[1030105979] = { return Api.PrivacyKey.parse_privacyKeyPhoneCall($0) }
|
dict[1030105979] = { return Api.PrivacyKey.parse_privacyKeyPhoneCall($0) }
|
||||||
|
@ -4281,6 +4281,7 @@ public extension Api {
|
|||||||
case sendMessageUploadRoundAction(progress: Int32)
|
case sendMessageUploadRoundAction(progress: Int32)
|
||||||
case speakingInGroupCallAction
|
case speakingInGroupCallAction
|
||||||
case sendMessageHistoryImportAction(progress: Int32)
|
case sendMessageHistoryImportAction(progress: Int32)
|
||||||
|
case sendMessageChooseStickerAction
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -4373,6 +4374,12 @@ public extension Api {
|
|||||||
buffer.appendInt32(-606432698)
|
buffer.appendInt32(-606432698)
|
||||||
}
|
}
|
||||||
serializeInt32(progress, buffer: buffer, boxed: false)
|
serializeInt32(progress, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
|
case .sendMessageChooseStickerAction:
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1336228175)
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4409,6 +4416,8 @@ public extension Api {
|
|||||||
return ("speakingInGroupCallAction", [])
|
return ("speakingInGroupCallAction", [])
|
||||||
case .sendMessageHistoryImportAction(let progress):
|
case .sendMessageHistoryImportAction(let progress):
|
||||||
return ("sendMessageHistoryImportAction", [("progress", progress)])
|
return ("sendMessageHistoryImportAction", [("progress", progress)])
|
||||||
|
case .sendMessageChooseStickerAction:
|
||||||
|
return ("sendMessageChooseStickerAction", [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4505,6 +4514,9 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_sendMessageChooseStickerAction(_ reader: BufferReader) -> SendMessageAction? {
|
||||||
|
return Api.SendMessageAction.sendMessageChooseStickerAction
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum PrivacyKey: TypeConstructorDescription {
|
public enum PrivacyKey: TypeConstructorDescription {
|
||||||
|
@ -6160,17 +6160,6 @@ public final class VoiceChatController: ViewController {
|
|||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func displayToggleVideoSourceTooltip(screencast: Bool) {
|
|
||||||
// guard let videoContainerNode = self.mainStageVideoContainerNode else {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// let location = videoContainerNode.view.convert(videoContainerNode.otherVideoWrapperNode.frame, to: nil)
|
|
||||||
// self.controller?.present(TooltipScreen(text: screencast ? self.presentationData.strings.VoiceChat_TapToViewCameraVideo : self.presentationData.strings.VoiceChat_TapToViewScreenVideo, icon: nil, location: .point(location.offsetBy(dx: -9.0, dy: 0.0), .right), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
|
||||||
// return .dismiss(consume: false)
|
|
||||||
// }), in: .window(.root))
|
|
||||||
}
|
|
||||||
|
|
||||||
private var isScheduled: Bool {
|
private var isScheduled: Bool {
|
||||||
return self.isScheduling || self.callState?.scheduleTimestamp != nil
|
return self.isScheduling || self.callState?.scheduleTimestamp != nil
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,8 @@ private var declaredEncodables: Void = {
|
|||||||
declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) })
|
declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) })
|
||||||
declareEncodable(WallpaperDataResource.self, f: { WallpaperDataResource(decoder: $0) })
|
declareEncodable(WallpaperDataResource.self, f: { WallpaperDataResource(decoder: $0) })
|
||||||
declareEncodable(ForwardHideSendersNamesMessageAttribute.self, f: { ForwardHideSendersNamesMessageAttribute(decoder: $0) })
|
declareEncodable(ForwardHideSendersNamesMessageAttribute.self, f: { ForwardHideSendersNamesMessageAttribute(decoder: $0) })
|
||||||
|
declareEncodable(ChatTheme.self, f: { ChatTheme(decoder: $0) })
|
||||||
|
declareEncodable(ChatThemes.self, f: { ChatThemes(decoder: $0) })
|
||||||
|
|
||||||
return
|
return
|
||||||
}()
|
}()
|
||||||
|
@ -77,8 +77,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||||||
case let .inputGroupCall(id, accessHash):
|
case let .inputGroupCall(id, accessHash):
|
||||||
return TelegramMediaAction(action: .groupPhoneCall(callId: id, accessHash: accessHash, scheduleDate: scheduleDate, duration: nil))
|
return TelegramMediaAction(action: .groupPhoneCall(callId: id, accessHash: accessHash, scheduleDate: scheduleDate, duration: nil))
|
||||||
}
|
}
|
||||||
case .messageActionSetChatTheme:
|
case let .messageActionSetChatTheme(emoji):
|
||||||
return nil
|
return TelegramMediaAction(action: .setChatTheme(emoji: emoji))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import TelegramApi
|
|||||||
|
|
||||||
|
|
||||||
extension TelegramTheme {
|
extension TelegramTheme {
|
||||||
convenience init?(apiTheme: Api.Theme) {
|
convenience init(apiTheme: Api.Theme) {
|
||||||
switch apiTheme {
|
switch apiTheme {
|
||||||
case let .theme(flags, id, accessHash, slug, title, document, settings, installCount):
|
case let .theme(flags, id, accessHash, slug, title, document, settings, installCount):
|
||||||
self.init(id: id, accessHash: accessHash, slug: slug, title: title, file: document.flatMap(telegramMediaFileFromApiDocument), settings: settings.flatMap(TelegramThemeSettings.init(apiThemeSettings:)), isCreator: (flags & 1 << 0) != 0, isDefault: (flags & 1 << 1) != 0, installCount: installCount)
|
self.init(id: id, accessHash: accessHash, slug: slug, title: title, file: document.flatMap(telegramMediaFileFromApiDocument), settings: settings.flatMap(TelegramThemeSettings.init(apiThemeSettings:)), isCreator: (flags & 1 << 0) != 0, isDefault: (flags & 1 << 1) != 0, installCount: installCount)
|
||||||
|
@ -1412,9 +1412,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
|||||||
}
|
}
|
||||||
updatedState.deleteMessages(messageIds)
|
updatedState.deleteMessages(messageIds)
|
||||||
case let .updateTheme(theme):
|
case let .updateTheme(theme):
|
||||||
if let theme = TelegramTheme(apiTheme: theme) {
|
updatedState.updateTheme(TelegramTheme(apiTheme: theme))
|
||||||
updatedState.updateTheme(theme)
|
|
||||||
}
|
|
||||||
case let .updateMessageID(id, randomId):
|
case let .updateMessageID(id, randomId):
|
||||||
updatedState.updatedOutgoingUniqueMessageIds[randomId] = id
|
updatedState.updatedOutgoingUniqueMessageIds[randomId] = id
|
||||||
case .updateDialogFilters:
|
case .updateDialogFilters:
|
||||||
|
@ -130,7 +130,7 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa
|
|||||||
case .speakingInGroupCall:
|
case .speakingInGroupCall:
|
||||||
return .speakingInGroupCallAction
|
return .speakingInGroupCallAction
|
||||||
case .choosingSticker:
|
case .choosingSticker:
|
||||||
return .sendMessageGamePlayAction
|
return .sendMessageChooseStickerAction
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return .sendMessageCancelAction
|
return .sendMessageCancelAction
|
||||||
|
@ -66,6 +66,8 @@ extension PeerInputActivity {
|
|||||||
self = .uploadingInstantVideo(progress: progress)
|
self = .uploadingInstantVideo(progress: progress)
|
||||||
case .speakingInGroupCallAction:
|
case .speakingInGroupCallAction:
|
||||||
self = .speakingInGroupCall(timestamp: timestamp)
|
self = .speakingInGroupCall(timestamp: timestamp)
|
||||||
|
case .sendMessageChooseStickerAction:
|
||||||
|
self = .choosingSticker
|
||||||
case let .sendMessageHistoryImportAction:
|
case let .sendMessageHistoryImportAction:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -224,6 +224,7 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
public let activeCall: ActiveCall?
|
public let activeCall: ActiveCall?
|
||||||
public let callJoinPeerId: PeerId?
|
public let callJoinPeerId: PeerId?
|
||||||
public let pendingSuggestions: [String]
|
public let pendingSuggestions: [String]
|
||||||
|
public let themeEmoticon: String?
|
||||||
|
|
||||||
public let peerIds: Set<PeerId>
|
public let peerIds: Set<PeerId>
|
||||||
public let messageIds: Set<MessageId>
|
public let messageIds: Set<MessageId>
|
||||||
@ -257,9 +258,10 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
self.activeCall = nil
|
self.activeCall = nil
|
||||||
self.callJoinPeerId = nil
|
self.callJoinPeerId = nil
|
||||||
self.pendingSuggestions = []
|
self.pendingSuggestions = []
|
||||||
|
self.themeEmoticon = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(isNotAccessible: Bool, flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?, migrationReference: ChannelMigrationReference?, linkedDiscussionPeerId: LinkedDiscussionPeerId, peerGeoLocation: PeerGeoLocation?, slowModeTimeout: Int32?, slowModeValidUntilTimestamp: Int32?, hasScheduledMessages: Bool, statsDatacenterId: Int32, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: ActiveCall?, callJoinPeerId: PeerId?, autoremoveTimeout: CachedPeerAutoremoveTimeout, pendingSuggestions: [String]) {
|
public init(isNotAccessible: Bool, flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?, migrationReference: ChannelMigrationReference?, linkedDiscussionPeerId: LinkedDiscussionPeerId, peerGeoLocation: PeerGeoLocation?, slowModeTimeout: Int32?, slowModeValidUntilTimestamp: Int32?, hasScheduledMessages: Bool, statsDatacenterId: Int32, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: ActiveCall?, callJoinPeerId: PeerId?, autoremoveTimeout: CachedPeerAutoremoveTimeout, pendingSuggestions: [String], themeEmoticon: String?) {
|
||||||
self.isNotAccessible = isNotAccessible
|
self.isNotAccessible = isNotAccessible
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.about = about
|
self.about = about
|
||||||
@ -283,6 +285,7 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
self.callJoinPeerId = callJoinPeerId
|
self.callJoinPeerId = callJoinPeerId
|
||||||
self.autoremoveTimeout = autoremoveTimeout
|
self.autoremoveTimeout = autoremoveTimeout
|
||||||
self.pendingSuggestions = pendingSuggestions
|
self.pendingSuggestions = pendingSuggestions
|
||||||
|
self.themeEmoticon = themeEmoticon
|
||||||
|
|
||||||
var peerIds = Set<PeerId>()
|
var peerIds = Set<PeerId>()
|
||||||
for botInfo in botInfos {
|
for botInfo in botInfos {
|
||||||
@ -310,95 +313,99 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedIsNotAccessible(_ isNotAccessible: Bool) -> CachedChannelData {
|
public func withUpdatedIsNotAccessible(_ isNotAccessible: Bool) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData {
|
public func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedAbout(_ about: String?) -> CachedChannelData {
|
public func withUpdatedAbout(_ about: String?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData {
|
public func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData {
|
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData {
|
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedChannelData {
|
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData {
|
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedStickerPack(_ stickerPack: StickerPackCollectionInfo?) -> CachedChannelData {
|
public func withUpdatedStickerPack(_ stickerPack: StickerPackCollectionInfo?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedMinAvailableMessageId(_ minAvailableMessageId: MessageId?) -> CachedChannelData {
|
public func withUpdatedMinAvailableMessageId(_ minAvailableMessageId: MessageId?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedMigrationReference(_ migrationReference: ChannelMigrationReference?) -> CachedChannelData {
|
public func withUpdatedMigrationReference(_ migrationReference: ChannelMigrationReference?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedLinkedDiscussionPeerId(_ linkedDiscussionPeerId: LinkedDiscussionPeerId) -> CachedChannelData {
|
public func withUpdatedLinkedDiscussionPeerId(_ linkedDiscussionPeerId: LinkedDiscussionPeerId) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> CachedChannelData {
|
public func withUpdatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedSlowModeTimeout(_ slowModeTimeout: Int32?) -> CachedChannelData {
|
public func withUpdatedSlowModeTimeout(_ slowModeTimeout: Int32?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedSlowModeValidUntilTimestamp(_ slowModeValidUntilTimestamp: Int32?) -> CachedChannelData {
|
public func withUpdatedSlowModeValidUntilTimestamp(_ slowModeValidUntilTimestamp: Int32?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedChannelData {
|
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedStatsDatacenterId(_ statsDatacenterId: Int32) -> CachedChannelData {
|
public func withUpdatedStatsDatacenterId(_ statsDatacenterId: Int32) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedChannelData {
|
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedChannelData {
|
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedActiveCall(_ activeCall: ActiveCall?) -> CachedChannelData {
|
public func withUpdatedActiveCall(_ activeCall: ActiveCall?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedChannelData {
|
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedChannelData {
|
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: autoremoveTimeout, pendingSuggestions: self.pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: autoremoveTimeout, pendingSuggestions: self.pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPendingSuggestions(_ pendingSuggestions: [String]) -> CachedChannelData {
|
public func withUpdatedPendingSuggestions(_ pendingSuggestions: [String]) -> CachedChannelData {
|
||||||
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions)
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: self.themeEmoticon)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedChannelData {
|
||||||
|
return CachedChannelData(isNotAccessible: self.isNotAccessible, flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId, migrationReference: self.migrationReference, linkedDiscussionPeerId: self.linkedDiscussionPeerId, peerGeoLocation: self.peerGeoLocation, slowModeTimeout: self.slowModeTimeout, slowModeValidUntilTimestamp: self.slowModeValidUntilTimestamp, hasScheduledMessages: self.hasScheduledMessages, statsDatacenterId: self.statsDatacenterId, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, callJoinPeerId: self.callJoinPeerId, autoremoveTimeout: self.autoremoveTimeout, pendingSuggestions: pendingSuggestions, themeEmoticon: themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
@ -475,6 +482,8 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
|
|
||||||
self.pendingSuggestions = decoder.decodeStringArrayForKey("sug")
|
self.pendingSuggestions = decoder.decodeStringArrayForKey("sug")
|
||||||
|
|
||||||
|
self.themeEmoticon = decoder.decodeOptionalStringForKey("te")
|
||||||
|
|
||||||
if let photo = decoder.decodeObjectForKey("ph", decoder: { TelegramMediaImage(decoder: $0) }) as? TelegramMediaImage {
|
if let photo = decoder.decodeObjectForKey("ph", decoder: { TelegramMediaImage(decoder: $0) }) as? TelegramMediaImage {
|
||||||
self.photo = photo
|
self.photo = photo
|
||||||
} else {
|
} else {
|
||||||
@ -600,6 +609,12 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
encoder.encodeStringArray(self.pendingSuggestions, forKey: "sug")
|
encoder.encodeStringArray(self.pendingSuggestions, forKey: "sug")
|
||||||
|
|
||||||
|
if let themeEmoticon = self.themeEmoticon, !themeEmoticon.isEmpty {
|
||||||
|
encoder.encodeString(themeEmoticon, forKey: "te")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "te")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isEqual(to: CachedPeerData) -> Bool {
|
public func isEqual(to: CachedPeerData) -> Bool {
|
||||||
@ -699,6 +714,10 @@ public final class CachedChannelData: CachedPeerData {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if other.themeEmoticon != self.themeEmoticon {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,14 +51,14 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
public let invitedBy: PeerId?
|
public let invitedBy: PeerId?
|
||||||
public let photo: TelegramMediaImage?
|
public let photo: TelegramMediaImage?
|
||||||
public let autoremoveTimeout: CachedPeerAutoremoveTimeout
|
public let autoremoveTimeout: CachedPeerAutoremoveTimeout
|
||||||
|
public let activeCall: CachedChannelData.ActiveCall?
|
||||||
|
public let callJoinPeerId: PeerId?
|
||||||
|
public let themeEmoticon: String?
|
||||||
|
|
||||||
public let peerIds: Set<PeerId>
|
public let peerIds: Set<PeerId>
|
||||||
public let messageIds: Set<MessageId>
|
public let messageIds: Set<MessageId>
|
||||||
public let associatedHistoryMessageId: MessageId? = nil
|
public let associatedHistoryMessageId: MessageId? = nil
|
||||||
|
|
||||||
public let activeCall: CachedChannelData.ActiveCall?
|
|
||||||
public let callJoinPeerId: PeerId?
|
|
||||||
|
|
||||||
public init() {
|
public init() {
|
||||||
self.participants = nil
|
self.participants = nil
|
||||||
self.exportedInvitation = nil
|
self.exportedInvitation = nil
|
||||||
@ -73,12 +73,12 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
self.invitedBy = nil
|
self.invitedBy = nil
|
||||||
self.photo = nil
|
self.photo = nil
|
||||||
self.autoremoveTimeout = .unknown
|
self.autoremoveTimeout = .unknown
|
||||||
|
|
||||||
self.activeCall = nil
|
self.activeCall = nil
|
||||||
self.callJoinPeerId = nil
|
self.callJoinPeerId = nil
|
||||||
|
self.themeEmoticon = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, about: String?, flags: CachedGroupFlags, hasScheduledMessages: Bool, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: CachedChannelData.ActiveCall?, autoremoveTimeout: CachedPeerAutoremoveTimeout, callJoinPeerId: PeerId?) {
|
public init(participants: CachedGroupParticipants?, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, about: String?, flags: CachedGroupFlags, hasScheduledMessages: Bool, invitedBy: PeerId?, photo: TelegramMediaImage?, activeCall: CachedChannelData.ActiveCall?, autoremoveTimeout: CachedPeerAutoremoveTimeout, callJoinPeerId: PeerId?, themeEmoticon: String?) {
|
||||||
self.participants = participants
|
self.participants = participants
|
||||||
self.exportedInvitation = exportedInvitation
|
self.exportedInvitation = exportedInvitation
|
||||||
self.botInfos = botInfos
|
self.botInfos = botInfos
|
||||||
@ -92,6 +92,7 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
self.activeCall = activeCall
|
self.activeCall = activeCall
|
||||||
self.autoremoveTimeout = autoremoveTimeout
|
self.autoremoveTimeout = autoremoveTimeout
|
||||||
self.callJoinPeerId = callJoinPeerId
|
self.callJoinPeerId = callJoinPeerId
|
||||||
|
self.themeEmoticon = themeEmoticon
|
||||||
|
|
||||||
var messageIds = Set<MessageId>()
|
var messageIds = Set<MessageId>()
|
||||||
if let pinnedMessageId = self.pinnedMessageId {
|
if let pinnedMessageId = self.pinnedMessageId {
|
||||||
@ -152,6 +153,8 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
|
|
||||||
self.callJoinPeerId = decoder.decodeOptionalInt64ForKey("callJoinPeerId").flatMap(PeerId.init)
|
self.callJoinPeerId = decoder.decodeOptionalInt64ForKey("callJoinPeerId").flatMap(PeerId.init)
|
||||||
|
|
||||||
|
self.themeEmoticon = decoder.decodeOptionalStringForKey("te")
|
||||||
|
|
||||||
var messageIds = Set<MessageId>()
|
var messageIds = Set<MessageId>()
|
||||||
if let pinnedMessageId = self.pinnedMessageId {
|
if let pinnedMessageId = self.pinnedMessageId {
|
||||||
messageIds.insert(pinnedMessageId)
|
messageIds.insert(pinnedMessageId)
|
||||||
@ -229,6 +232,12 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "callJoinPeerId")
|
encoder.encodeNil(forKey: "callJoinPeerId")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let themeEmoticon = self.themeEmoticon, !themeEmoticon.isEmpty {
|
||||||
|
encoder.encodeString(themeEmoticon, forKey: "te")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "te")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isEqual(to: CachedPeerData) -> Bool {
|
public func isEqual(to: CachedPeerData) -> Bool {
|
||||||
@ -244,58 +253,62 @@ public final class CachedGroupData: CachedPeerData {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.participants == other.participants && self.exportedInvitation == other.exportedInvitation && self.botInfos == other.botInfos && self.peerStatusSettings == other.peerStatusSettings && self.pinnedMessageId == other.pinnedMessageId && self.about == other.about && self.flags == other.flags && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.invitedBy == other.invitedBy
|
return self.participants == other.participants && self.exportedInvitation == other.exportedInvitation && self.botInfos == other.botInfos && self.peerStatusSettings == other.peerStatusSettings && self.pinnedMessageId == other.pinnedMessageId && self.about == other.about && self.flags == other.flags && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.invitedBy == other.invitedBy && self.themeEmoticon == other.themeEmoticon
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedParticipants(_ participants: CachedGroupParticipants?) -> CachedGroupData {
|
public func withUpdatedParticipants(_ participants: CachedGroupParticipants?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedGroupData {
|
public func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedGroupData {
|
public func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedGroupData {
|
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedGroupData {
|
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedAbout(_ about: String?) -> CachedGroupData {
|
public func withUpdatedAbout(_ about: String?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedFlags(_ flags: CachedGroupFlags) -> CachedGroupData {
|
public func withUpdatedFlags(_ flags: CachedGroupFlags) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedGroupData {
|
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedGroupData {
|
public func withUpdatedInvitedBy(_ invitedBy: PeerId?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedGroupData {
|
public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedActiveCall(_ activeCall: CachedChannelData.ActiveCall?) -> CachedGroupData {
|
public func withUpdatedActiveCall(_ activeCall: CachedChannelData.ActiveCall?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedGroupData {
|
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: autoremoveTimeout, callJoinPeerId: self.callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: autoremoveTimeout, callJoinPeerId: self.callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedGroupData {
|
public func withUpdatedCallJoinPeerId(_ callJoinPeerId: PeerId?) -> CachedGroupData {
|
||||||
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: callJoinPeerId)
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: callJoinPeerId, themeEmoticon: self.themeEmoticon)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedGroupData {
|
||||||
|
return CachedGroupData(participants: self.participants, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, about: self.about, flags: self.flags, hasScheduledMessages: self.hasScheduledMessages, invitedBy: self.invitedBy, photo: self.photo, activeCall: self.activeCall, autoremoveTimeout: self.autoremoveTimeout, callJoinPeerId: callJoinPeerId, themeEmoticon: themeEmoticon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
public let canPinMessages: Bool
|
public let canPinMessages: Bool
|
||||||
public let hasScheduledMessages: Bool
|
public let hasScheduledMessages: Bool
|
||||||
public let autoremoveTimeout: CachedPeerAutoremoveTimeout
|
public let autoremoveTimeout: CachedPeerAutoremoveTimeout
|
||||||
|
public let themeEmoticon: String?
|
||||||
|
|
||||||
public let peerIds = Set<PeerId>()
|
public let peerIds = Set<PeerId>()
|
||||||
public let messageIds: Set<MessageId>
|
public let messageIds: Set<MessageId>
|
||||||
@ -80,10 +81,11 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
self.canPinMessages = false
|
self.canPinMessages = false
|
||||||
self.hasScheduledMessages = false
|
self.hasScheduledMessages = false
|
||||||
self.autoremoveTimeout = .unknown
|
self.autoremoveTimeout = .unknown
|
||||||
|
self.themeEmoticon = nil
|
||||||
self.messageIds = Set()
|
self.messageIds = Set()
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(about: String?, botInfo: BotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout) {
|
public init(about: String?, botInfo: BotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?) {
|
||||||
self.about = about
|
self.about = about
|
||||||
self.botInfo = botInfo
|
self.botInfo = botInfo
|
||||||
self.peerStatusSettings = peerStatusSettings
|
self.peerStatusSettings = peerStatusSettings
|
||||||
@ -96,6 +98,8 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
self.canPinMessages = canPinMessages
|
self.canPinMessages = canPinMessages
|
||||||
self.hasScheduledMessages = hasScheduledMessages
|
self.hasScheduledMessages = hasScheduledMessages
|
||||||
self.autoremoveTimeout = autoremoveTimeout
|
self.autoremoveTimeout = autoremoveTimeout
|
||||||
|
self.themeEmoticon = themeEmoticon
|
||||||
|
|
||||||
var messageIds = Set<MessageId>()
|
var messageIds = Set<MessageId>()
|
||||||
if let pinnedMessageId = self.pinnedMessageId {
|
if let pinnedMessageId = self.pinnedMessageId {
|
||||||
messageIds.insert(pinnedMessageId)
|
messageIds.insert(pinnedMessageId)
|
||||||
@ -126,6 +130,7 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
self.canPinMessages = decoder.decodeInt32ForKey("cpm", orElse: 0) != 0
|
self.canPinMessages = decoder.decodeInt32ForKey("cpm", orElse: 0) != 0
|
||||||
self.hasScheduledMessages = decoder.decodeBoolForKey("hsm", orElse: false)
|
self.hasScheduledMessages = decoder.decodeBoolForKey("hsm", orElse: false)
|
||||||
self.autoremoveTimeout = decoder.decodeObjectForKey("artv", decoder: CachedPeerAutoremoveTimeout.init(decoder:)) as? CachedPeerAutoremoveTimeout ?? .unknown
|
self.autoremoveTimeout = decoder.decodeObjectForKey("artv", decoder: CachedPeerAutoremoveTimeout.init(decoder:)) as? CachedPeerAutoremoveTimeout ?? .unknown
|
||||||
|
self.themeEmoticon = decoder.decodeOptionalStringForKey("te")
|
||||||
|
|
||||||
var messageIds = Set<MessageId>()
|
var messageIds = Set<MessageId>()
|
||||||
if let pinnedMessageId = self.pinnedMessageId {
|
if let pinnedMessageId = self.pinnedMessageId {
|
||||||
@ -167,6 +172,11 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
encoder.encodeInt32(self.canPinMessages ? 1 : 0, forKey: "cpm")
|
encoder.encodeInt32(self.canPinMessages ? 1 : 0, forKey: "cpm")
|
||||||
encoder.encodeBool(self.hasScheduledMessages, forKey: "hsm")
|
encoder.encodeBool(self.hasScheduledMessages, forKey: "hsm")
|
||||||
encoder.encodeObject(self.autoremoveTimeout, forKey: "artv")
|
encoder.encodeObject(self.autoremoveTimeout, forKey: "artv")
|
||||||
|
if let themeEmoticon = self.themeEmoticon, !themeEmoticon.isEmpty {
|
||||||
|
encoder.encodeString(themeEmoticon, forKey: "te")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "te")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isEqual(to: CachedPeerData) -> Bool {
|
public func isEqual(to: CachedPeerData) -> Bool {
|
||||||
@ -181,54 +191,58 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return other.about == self.about && other.botInfo == self.botInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.voiceCallsAvailable == other.voiceCallsAvailable && self.videoCallsAvailable == other.videoCallsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout
|
return other.about == self.about && other.botInfo == self.botInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.voiceCallsAvailable == other.voiceCallsAvailable && self.videoCallsAvailable == other.videoCallsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.themeEmoticon == other.themeEmoticon
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedAbout(_ about: String?) -> CachedUserData {
|
public func withUpdatedAbout(_ about: String?) -> CachedUserData {
|
||||||
return CachedUserData(about: about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedBotInfo(_ botInfo: BotInfo?) -> CachedUserData {
|
public func withUpdatedBotInfo(_ botInfo: BotInfo?) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings) -> CachedUserData {
|
public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedUserData {
|
public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedIsBlocked(_ isBlocked: Bool) -> CachedUserData {
|
public func withUpdatedIsBlocked(_ isBlocked: Bool) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedCommonGroupCount(_ commonGroupCount: Int32) -> CachedUserData {
|
public func withUpdatedCommonGroupCount(_ commonGroupCount: Int32) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedVoiceCallsAvailable(_ voiceCallsAvailable: Bool) -> CachedUserData {
|
public func withUpdatedVoiceCallsAvailable(_ voiceCallsAvailable: Bool) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedVideoCallsAvailable(_ videoCallsAvailable: Bool) -> CachedUserData {
|
public func withUpdatedVideoCallsAvailable(_ videoCallsAvailable: Bool) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedCallsPrivate(_ callsPrivate: Bool) -> CachedUserData {
|
public func withUpdatedCallsPrivate(_ callsPrivate: Bool) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedCanPinMessages(_ canPinMessages: Bool) -> CachedUserData {
|
public func withUpdatedCanPinMessages(_ canPinMessages: Bool) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedUserData {
|
public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedUserData {
|
public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedUserData {
|
||||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout)
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, themeEmoticon: self.themeEmoticon)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedUserData {
|
||||||
|
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: themeEmoticon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,6 +350,7 @@ private enum SharedDataKeyValues: Int32 {
|
|||||||
case themeSettings = 6
|
case themeSettings = 6
|
||||||
case countriesList = 7
|
case countriesList = 7
|
||||||
case wallapersState = 8
|
case wallapersState = 8
|
||||||
|
case chatThemes = 9
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SharedDataKeys {
|
public struct SharedDataKeys {
|
||||||
@ -400,6 +401,12 @@ public struct SharedDataKeys {
|
|||||||
key.setInt32(0, value: SharedDataKeyValues.wallapersState.rawValue)
|
key.setInt32(0, value: SharedDataKeyValues.wallapersState.rawValue)
|
||||||
return key
|
return key
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
public static let chatThemes: ValueBoxKey = {
|
||||||
|
let key = ValueBoxKey(length: 4)
|
||||||
|
key.setInt32(0, value: SharedDataKeyValues.chatThemes.rawValue)
|
||||||
|
return key
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 {
|
public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 {
|
||||||
|
@ -48,6 +48,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
case geoProximityReached(from: PeerId, to: PeerId, distance: Int32)
|
case geoProximityReached(from: PeerId, to: PeerId, distance: Int32)
|
||||||
case groupPhoneCall(callId: Int64, accessHash: Int64, scheduleDate: Int32?, duration: Int32?)
|
case groupPhoneCall(callId: Int64, accessHash: Int64, scheduleDate: Int32?, duration: Int32?)
|
||||||
case inviteToGroupPhoneCall(callId: Int64, accessHash: Int64, peerIds: [PeerId])
|
case inviteToGroupPhoneCall(callId: Int64, accessHash: Int64, peerIds: [PeerId])
|
||||||
|
case setChatTheme(emoji: String)
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||||
@ -110,6 +111,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
peerIds = decoder.decodeInt64ArrayForKey("peerIds").map(PeerId.init)
|
peerIds = decoder.decodeInt64ArrayForKey("peerIds").map(PeerId.init)
|
||||||
}
|
}
|
||||||
self = .inviteToGroupPhoneCall(callId: decoder.decodeInt64ForKey("callId", orElse: 0), accessHash: decoder.decodeInt64ForKey("accessHash", orElse: 0), peerIds: peerIds)
|
self = .inviteToGroupPhoneCall(callId: decoder.decodeInt64ForKey("callId", orElse: 0), accessHash: decoder.decodeInt64ForKey("accessHash", orElse: 0), peerIds: peerIds)
|
||||||
|
case 24:
|
||||||
|
self = .setChatTheme(emoji: decoder.decodeStringForKey("emoji", orElse: ""))
|
||||||
default:
|
default:
|
||||||
self = .unknown
|
self = .unknown
|
||||||
}
|
}
|
||||||
@ -219,6 +222,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
encoder.encodeInt64(callId, forKey: "callId")
|
encoder.encodeInt64(callId, forKey: "callId")
|
||||||
encoder.encodeInt64(accessHash, forKey: "accessHash")
|
encoder.encodeInt64(accessHash, forKey: "accessHash")
|
||||||
encoder.encodeInt64Array(peerIds.map { $0.toInt64() }, forKey: "peerIds")
|
encoder.encodeInt64Array(peerIds.map { $0.toInt64() }, forKey: "peerIds")
|
||||||
|
case let .setChatTheme(emoji):
|
||||||
|
encoder.encodeInt32(24, forKey: "_rawValue")
|
||||||
|
encoder.encodeString(emoji, forKey: "emoji")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ import Postbox
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramApi
|
import TelegramApi
|
||||||
|
|
||||||
|
|
||||||
public struct Country: PostboxCoding, Equatable {
|
public struct Country: PostboxCoding, Equatable {
|
||||||
public static func == (lhs: Country, rhs: Country) -> Bool {
|
public static func == (lhs: Country, rhs: Country) -> Bool {
|
||||||
return lhs.id == rhs.id && lhs.name == rhs.name && lhs.localizedName == rhs.localizedName && lhs.countryCodes == rhs.countryCodes && lhs.hidden == rhs.hidden
|
return lhs.id == rhs.id && lhs.name == rhs.name && lhs.localizedName == rhs.localizedName && lhs.countryCodes == rhs.countryCodes && lhs.hidden == rhs.hidden
|
||||||
|
@ -210,6 +210,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
|
|
||||||
return previous.withUpdatedAbout(userFull.about).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFull.commonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedVoiceCallsAvailable(voiceCallsAvailable).withUpdatedVideoCallsAvailable(videoCallsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages)
|
return previous.withUpdatedAbout(userFull.about).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFull.commonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedVoiceCallsAvailable(voiceCallsAvailable).withUpdatedVideoCallsAvailable(videoCallsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages)
|
||||||
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
||||||
|
.withUpdatedThemeEmoticon(userFull.themeEmoticon)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
@ -320,6 +321,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
.withUpdatedPhoto(photo)
|
.withUpdatedPhoto(photo)
|
||||||
.withUpdatedActiveCall(updatedActiveCall)
|
.withUpdatedActiveCall(updatedActiveCall)
|
||||||
.withUpdatedCallJoinPeerId(groupCallDefaultJoinAs?.peerId)
|
.withUpdatedCallJoinPeerId(groupCallDefaultJoinAs?.peerId)
|
||||||
|
.withUpdatedThemeEmoticon(chatFull.themeEmoticon)
|
||||||
})
|
})
|
||||||
case .channelFull:
|
case .channelFull:
|
||||||
break
|
break
|
||||||
@ -540,6 +542,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
.withUpdatedCallJoinPeerId(groupcallDefaultJoinAs?.peerId)
|
.withUpdatedCallJoinPeerId(groupcallDefaultJoinAs?.peerId)
|
||||||
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
.withUpdatedAutoremoveTimeout(autoremoveTimeout)
|
||||||
.withUpdatedPendingSuggestions(pendingSuggestions ?? [])
|
.withUpdatedPendingSuggestions(pendingSuggestions ?? [])
|
||||||
|
.withUpdatedThemeEmoticon(themeEmoticon)
|
||||||
})
|
})
|
||||||
|
|
||||||
if let minAvailableMessageId = minAvailableMessageId, minAvailableMessageIdUpdated {
|
if let minAvailableMessageId = minAvailableMessageId, minAvailableMessageIdUpdated {
|
||||||
|
@ -39,6 +39,10 @@ public final class TelegramEngine {
|
|||||||
public lazy var localization: Localization = {
|
public lazy var localization: Localization = {
|
||||||
return Localization(account: self.account)
|
return Localization(account: self.account)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
public lazy var themes: Themes = {
|
||||||
|
return Themes(account: self.account)
|
||||||
|
}()
|
||||||
|
|
||||||
public lazy var messages: Messages = {
|
public lazy var messages: Messages = {
|
||||||
return Messages(account: self.account)
|
return Messages(account: self.account)
|
||||||
|
@ -0,0 +1,153 @@
|
|||||||
|
import Foundation
|
||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramApi
|
||||||
|
|
||||||
|
public struct ChatTheme: PostboxCoding, Equatable {
|
||||||
|
public static func == (lhs: ChatTheme, rhs: ChatTheme) -> Bool {
|
||||||
|
return lhs.emoji == rhs.emoji && lhs.theme == rhs.theme && lhs.darkTheme == rhs.darkTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
public let emoji: String
|
||||||
|
public let theme: TelegramTheme
|
||||||
|
public let darkTheme: TelegramTheme
|
||||||
|
|
||||||
|
public init(emoji: String, theme: TelegramTheme, darkTheme: TelegramTheme) {
|
||||||
|
self.emoji = emoji
|
||||||
|
self.theme = theme
|
||||||
|
self.darkTheme = darkTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
self.emoji = decoder.decodeStringForKey("e", orElse: "")
|
||||||
|
self.theme = decoder.decodeObjectForKey("t") as! TelegramTheme
|
||||||
|
self.darkTheme = decoder.decodeObjectForKey("dt") as! TelegramTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
encoder.encodeString(self.emoji, forKey: "e")
|
||||||
|
encoder.encodeObject(self.theme, forKey: "t")
|
||||||
|
encoder.encodeObject(self.darkTheme, forKey: "dt")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final class ChatThemes: PreferencesEntry, Equatable {
|
||||||
|
public let chatThemes: [ChatTheme]
|
||||||
|
public let hash: Int32
|
||||||
|
|
||||||
|
public init(chatThemes: [ChatTheme], hash: Int32) {
|
||||||
|
self.chatThemes = chatThemes
|
||||||
|
self.hash = hash
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
self.chatThemes = decoder.decodeObjectArrayForKey("c").map { $0 as! ChatTheme }
|
||||||
|
self.hash = decoder.decodeInt32ForKey("h", orElse: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
encoder.encodeObjectArray(self.chatThemes, forKey: "c")
|
||||||
|
encoder.encodeInt32(self.hash, forKey: "h")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||||
|
if let to = to as? ChatThemes {
|
||||||
|
return self == to
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func ==(lhs: ChatThemes, rhs: ChatThemes) -> Bool {
|
||||||
|
return lhs.chatThemes == rhs.chatThemes && lhs.hash == rhs.hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, network: Network, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[ChatTheme], NoError> {
|
||||||
|
let fetch: ([ChatTheme]?, Int32?) -> Signal<[ChatTheme], NoError> = { current, hash in
|
||||||
|
return network.request(Api.functions.account.getChatThemes(hash: hash ?? 0))
|
||||||
|
|> retryRequest
|
||||||
|
|> mapToSignal { result -> Signal<[ChatTheme], NoError> in
|
||||||
|
switch result {
|
||||||
|
case let .chatThemes(hash, apiThemes):
|
||||||
|
let result = apiThemes.compactMap { ChatTheme(apiChatTheme: $0) }
|
||||||
|
if result == current {
|
||||||
|
return .complete()
|
||||||
|
} else {
|
||||||
|
let _ = accountManager.transaction { transaction in
|
||||||
|
transaction.updateSharedData(SharedDataKeys.chatThemes, { _ in
|
||||||
|
return ChatThemes(chatThemes: result, hash: hash)
|
||||||
|
})
|
||||||
|
}.start()
|
||||||
|
return .single(result)
|
||||||
|
}
|
||||||
|
case .chatThemesNotModified:
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if forceUpdate {
|
||||||
|
return fetch(nil, nil)
|
||||||
|
} else {
|
||||||
|
return accountManager.sharedData(keys: [SharedDataKeys.chatThemes])
|
||||||
|
|> take(1)
|
||||||
|
|> map { sharedData -> ([ChatTheme], Int32) in
|
||||||
|
if let chatThemes = sharedData.entries[SharedDataKeys.chatThemes] as? ChatThemes {
|
||||||
|
return (chatThemes.chatThemes, chatThemes.hash)
|
||||||
|
} else {
|
||||||
|
return ([], 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> mapToSignal { current, hash -> Signal<[ChatTheme], NoError> in
|
||||||
|
if onlyCached {
|
||||||
|
return .single(current)
|
||||||
|
} else {
|
||||||
|
return .single(current)
|
||||||
|
|> then(fetch(current, hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func _internal_setChatTheme(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, emoji: String?) -> Signal<Void, NoError> {
|
||||||
|
return postbox.loadedPeerWithId(peerId)
|
||||||
|
|> mapToSignal { peer in
|
||||||
|
guard let inputPeer = apiInputPeer(peer) else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||||
|
if let current = current as? CachedUserData {
|
||||||
|
return current.withUpdatedThemeEmoticon(emoji)
|
||||||
|
} else if let current = current as? CachedGroupData {
|
||||||
|
return current.withUpdatedThemeEmoticon(emoji)
|
||||||
|
} else if let current = current as? CachedChannelData {
|
||||||
|
return current.withUpdatedThemeEmoticon(emoji)
|
||||||
|
} else {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return network.request(Api.functions.messages.setChatTheme(peer: inputPeer, emoticon: emoji ?? ""))
|
||||||
|
|> `catch` { error in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|> mapToSignal { updates -> Signal<Void, NoError> in
|
||||||
|
stateManager.addUpdates(updates)
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
} |> switchToLatest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ChatTheme {
|
||||||
|
init(apiChatTheme: Api.ChatTheme) {
|
||||||
|
switch apiChatTheme {
|
||||||
|
case let .chatTheme(emoticon, theme, darkTheme):
|
||||||
|
self.init(emoji: emoticon, theme: TelegramTheme(apiTheme: theme), darkTheme: TelegramTheme(apiTheme: darkTheme))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import SwiftSignalKit
|
||||||
|
import Postbox
|
||||||
|
|
||||||
|
public extension TelegramEngine {
|
||||||
|
final class Themes {
|
||||||
|
private let account: Account
|
||||||
|
|
||||||
|
init(account: Account) {
|
||||||
|
self.account = account
|
||||||
|
}
|
||||||
|
|
||||||
|
public func getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[ChatTheme], NoError> {
|
||||||
|
return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func setChatTheme(peerId: PeerId, emoji: String?) -> Signal<Void, NoError> {
|
||||||
|
return _internal_setChatTheme(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, emoji: emoji)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ import Postbox
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramApi
|
import TelegramApi
|
||||||
|
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
let telegramThemeFormat = "macos"
|
let telegramThemeFormat = "macos"
|
||||||
let telegramThemeFileExtension = "palette"
|
let telegramThemeFileExtension = "palette"
|
||||||
@ -101,11 +100,7 @@ public func getTheme(account: Account, slug: String) -> Signal<TelegramTheme, Ge
|
|||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { theme -> Signal<TelegramTheme, GetThemeError> in
|
|> mapToSignal { theme -> Signal<TelegramTheme, GetThemeError> in
|
||||||
if let theme = TelegramTheme(apiTheme: theme) {
|
return .single(TelegramTheme(apiTheme: theme))
|
||||||
return .single(theme)
|
|
||||||
} else {
|
|
||||||
return .fail(.generic)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,11 +117,7 @@ private func checkThemeUpdated(network: Network, theme: TelegramTheme) -> Signal
|
|||||||
return network.request(Api.functions.account.getTheme(format: telegramThemeFormat, theme: .inputTheme(id: theme.id, accessHash: theme.accessHash), documentId: documentId))
|
return network.request(Api.functions.account.getTheme(format: telegramThemeFormat, theme: .inputTheme(id: theme.id, accessHash: theme.accessHash), documentId: documentId))
|
||||||
|> mapError { _ -> GetThemeError in return .generic }
|
|> mapError { _ -> GetThemeError in return .generic }
|
||||||
|> map { theme -> ThemeUpdatedResult in
|
|> map { theme -> ThemeUpdatedResult in
|
||||||
if let theme = TelegramTheme(apiTheme: theme) {
|
return .updated(TelegramTheme(apiTheme: theme))
|
||||||
return .updated(theme)
|
|
||||||
} else {
|
|
||||||
return .notModified
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,24 +301,21 @@ public func createTheme(account: Account, title: String, resource: MediaResource
|
|||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
||||||
if let theme = TelegramTheme(apiTheme: apiTheme) {
|
let theme = TelegramTheme(apiTheme: apiTheme)
|
||||||
return account.postbox.transaction { transaction -> CreateThemeResult in
|
return account.postbox.transaction { transaction -> CreateThemeResult in
|
||||||
let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes)
|
let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes)
|
||||||
var items = entries.map { $0.contents as! TelegramTheme }
|
var items = entries.map { $0.contents as! TelegramTheme }
|
||||||
items.insert(theme, at: 0)
|
items.insert(theme, at: 0)
|
||||||
var updatedEntries: [OrderedItemListEntry] = []
|
var updatedEntries: [OrderedItemListEntry] = []
|
||||||
for item in items {
|
for item in items {
|
||||||
var intValue = Int32(updatedEntries.count)
|
var intValue = Int32(updatedEntries.count)
|
||||||
let id = MemoryBuffer(data: Data(bytes: &intValue, count: 4))
|
let id = MemoryBuffer(data: Data(bytes: &intValue, count: 4))
|
||||||
updatedEntries.append(OrderedItemListEntry(id: id, contents: item))
|
updatedEntries.append(OrderedItemListEntry(id: id, contents: item))
|
||||||
}
|
|
||||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
|
||||||
return .result(theme)
|
|
||||||
}
|
}
|
||||||
|> castError(CreateThemeError.self)
|
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
||||||
} else {
|
return .result(theme)
|
||||||
return .fail(.generic)
|
|
||||||
}
|
}
|
||||||
|
|> castError(CreateThemeError.self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -348,26 +336,23 @@ public func createTheme(account: Account, title: String, resource: MediaResource
|
|||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
||||||
if var theme = TelegramTheme(apiTheme: apiTheme) {
|
var theme = TelegramTheme(apiTheme: apiTheme)
|
||||||
theme = TelegramTheme(id: theme.id, accessHash: theme.accessHash, slug: theme.slug, title: theme.title, file: theme.file, settings: settings, isCreator: theme.isCreator, isDefault: theme.isDefault, installCount: theme.installCount)
|
theme = TelegramTheme(id: theme.id, accessHash: theme.accessHash, slug: theme.slug, title: theme.title, file: theme.file, settings: settings, isCreator: theme.isCreator, isDefault: theme.isDefault, installCount: theme.installCount)
|
||||||
|
|
||||||
return account.postbox.transaction { transaction -> CreateThemeResult in
|
return account.postbox.transaction { transaction -> CreateThemeResult in
|
||||||
let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes)
|
let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes)
|
||||||
var items = entries.map { $0.contents as! TelegramTheme }
|
var items = entries.map { $0.contents as! TelegramTheme }
|
||||||
items.insert(theme, at: 0)
|
items.insert(theme, at: 0)
|
||||||
var updatedEntries: [OrderedItemListEntry] = []
|
var updatedEntries: [OrderedItemListEntry] = []
|
||||||
for item in items {
|
for item in items {
|
||||||
var intValue = Int32(updatedEntries.count)
|
var intValue = Int32(updatedEntries.count)
|
||||||
let id = MemoryBuffer(data: Data(bytes: &intValue, count: 4))
|
let id = MemoryBuffer(data: Data(bytes: &intValue, count: 4))
|
||||||
updatedEntries.append(OrderedItemListEntry(id: id, contents: item))
|
updatedEntries.append(OrderedItemListEntry(id: id, contents: item))
|
||||||
}
|
}
|
||||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
||||||
return .result(theme)
|
return .result(theme)
|
||||||
}
|
|
||||||
|> castError(CreateThemeError.self)
|
|
||||||
} else {
|
|
||||||
return .fail(.generic)
|
|
||||||
}
|
}
|
||||||
|
|> castError(CreateThemeError.self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,41 +414,38 @@ public func updateTheme(account: Account, accountManager: AccountManager<Telegra
|
|||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> in
|
||||||
if let theme = TelegramTheme(apiTheme: apiTheme) {
|
let theme = TelegramTheme(apiTheme: apiTheme)
|
||||||
let updatedTheme = TelegramTheme(id: theme.id, accessHash: theme.accessHash, slug: theme.slug, title: theme.title, file: theme.file, settings: settings, isCreator: theme.isCreator, isDefault: theme.isDefault, installCount: theme.installCount)
|
let updatedTheme = TelegramTheme(id: theme.id, accessHash: theme.accessHash, slug: theme.slug, title: theme.title, file: theme.file, settings: settings, isCreator: theme.isCreator, isDefault: theme.isDefault, installCount: theme.installCount)
|
||||||
|
|
||||||
let _ = accountManager.transaction { transaction in
|
let _ = accountManager.transaction { transaction in
|
||||||
transaction.updateSharedData(SharedDataKeys.themeSettings, { current in
|
transaction.updateSharedData(SharedDataKeys.themeSettings, { current in
|
||||||
var updated = current as? ThemeSettings ?? ThemeSettings(currentTheme: nil)
|
var updated = current as? ThemeSettings ?? ThemeSettings(currentTheme: nil)
|
||||||
if updatedTheme.id == updated.currentTheme?.id {
|
if updatedTheme.id == updated.currentTheme?.id {
|
||||||
updated = ThemeSettings(currentTheme: updatedTheme)
|
updated = ThemeSettings(currentTheme: updatedTheme)
|
||||||
}
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
}.start()
|
|
||||||
return account.postbox.transaction { transaction -> CreateThemeResult in
|
|
||||||
let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes)
|
|
||||||
let items = entries.map { entry -> TelegramTheme in
|
|
||||||
let theme = entry.contents as! TelegramTheme
|
|
||||||
if theme.id == updatedTheme.id {
|
|
||||||
return updatedTheme
|
|
||||||
} else {
|
|
||||||
return theme
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var updatedEntries: [OrderedItemListEntry] = []
|
return updated
|
||||||
for item in items {
|
})
|
||||||
var intValue = Int32(updatedEntries.count)
|
}.start()
|
||||||
let id = MemoryBuffer(data: Data(bytes: &intValue, count: 4))
|
return account.postbox.transaction { transaction -> CreateThemeResult in
|
||||||
updatedEntries.append(OrderedItemListEntry(id: id, contents: item))
|
let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes)
|
||||||
|
let items = entries.map { entry -> TelegramTheme in
|
||||||
|
let theme = entry.contents as! TelegramTheme
|
||||||
|
if theme.id == updatedTheme.id {
|
||||||
|
return updatedTheme
|
||||||
|
} else {
|
||||||
|
return theme
|
||||||
}
|
}
|
||||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
|
||||||
return .result(updatedTheme)
|
|
||||||
}
|
}
|
||||||
|> castError(CreateThemeError.self)
|
var updatedEntries: [OrderedItemListEntry] = []
|
||||||
} else {
|
for item in items {
|
||||||
return .fail(.generic)
|
var intValue = Int32(updatedEntries.count)
|
||||||
|
let id = MemoryBuffer(data: Data(bytes: &intValue, count: 4))
|
||||||
|
updatedEntries.append(OrderedItemListEntry(id: id, contents: item))
|
||||||
|
}
|
||||||
|
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.CloudThemes, items: updatedEntries)
|
||||||
|
return .result(updatedTheme)
|
||||||
}
|
}
|
||||||
|
|> castError(CreateThemeError.self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -752,7 +752,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio
|
|||||||
dimColor: UIColor(white: 0.0, alpha: 0.4),
|
dimColor: UIColor(white: 0.0, alpha: 0.4),
|
||||||
backgroundType: .light,
|
backgroundType: .light,
|
||||||
opaqueItemBackgroundColor: UIColor(rgb: 0xffffff),
|
opaqueItemBackgroundColor: UIColor(rgb: 0xffffff),
|
||||||
itemBackgroundColor: UIColor(white: 1.0, alpha: 0.87),
|
itemBackgroundColor: UIColor(white: 1.0, alpha: 0.8),
|
||||||
opaqueItemHighlightedBackgroundColor: UIColor(white: 0.9, alpha: 1.0),
|
opaqueItemHighlightedBackgroundColor: UIColor(white: 0.9, alpha: 1.0),
|
||||||
itemHighlightedBackgroundColor: UIColor(white: 0.9, alpha: 0.7),
|
itemHighlightedBackgroundColor: UIColor(white: 0.9, alpha: 0.7),
|
||||||
opaqueItemSeparatorColor: UIColor(white: 0.9, alpha: 1.0),
|
opaqueItemSeparatorColor: UIColor(white: 0.9, alpha: 1.0),
|
||||||
|
@ -108,6 +108,10 @@ public final class PresentationData: Equatable {
|
|||||||
return PresentationData(strings: self.strings, theme: theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: self.chatFontSize, chatBubbleCorners: self.chatBubbleCorners, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, reduceMotion: self.reduceMotion, largeEmoji: self.largeEmoji)
|
return PresentationData(strings: self.strings, theme: theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: self.chatWallpaper, chatFontSize: self.chatFontSize, chatBubbleCorners: self.chatBubbleCorners, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, reduceMotion: self.reduceMotion, largeEmoji: self.largeEmoji)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func withUpdated(chatWallpaper: TelegramWallpaper) -> PresentationData {
|
||||||
|
return PresentationData(strings: self.strings, theme: self.theme, autoNightModeTriggered: self.autoNightModeTriggered, chatWallpaper: chatWallpaper, chatFontSize: self.chatFontSize, chatBubbleCorners: self.chatBubbleCorners, listsFontSize: self.listsFontSize, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, nameSortOrder: self.nameSortOrder, reduceMotion: self.reduceMotion, largeEmoji: self.largeEmoji)
|
||||||
|
}
|
||||||
|
|
||||||
public static func ==(lhs: PresentationData, rhs: PresentationData) -> Bool {
|
public static func ==(lhs: PresentationData, rhs: PresentationData) -> Bool {
|
||||||
return lhs.strings === rhs.strings && lhs.theme === rhs.theme && lhs.autoNightModeTriggered == rhs.autoNightModeTriggered && lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatFontSize == rhs.chatFontSize && lhs.chatBubbleCorners == rhs.chatBubbleCorners && lhs.listsFontSize == rhs.listsFontSize && lhs.dateTimeFormat == rhs.dateTimeFormat && lhs.reduceMotion == rhs.reduceMotion && lhs.largeEmoji == rhs.largeEmoji
|
return lhs.strings === rhs.strings && lhs.theme === rhs.theme && lhs.autoNightModeTriggered == rhs.autoNightModeTriggered && lhs.chatWallpaper == rhs.chatWallpaper && lhs.chatFontSize == rhs.chatFontSize && lhs.chatBubbleCorners == rhs.chatBubbleCorners && lhs.listsFontSize == rhs.listsFontSize && lhs.dateTimeFormat == rhs.dateTimeFormat && lhs.reduceMotion == rhs.reduceMotion && lhs.largeEmoji == rhs.largeEmoji
|
||||||
}
|
}
|
||||||
|
@ -528,6 +528,24 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
}
|
}
|
||||||
|
|
||||||
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||||
|
case let .setChatTheme(emoji):
|
||||||
|
if emoji.isEmpty {
|
||||||
|
if message.author?.id == accountPeerId {
|
||||||
|
attributedString = NSAttributedString(string: strings.Notification_YouDisabledTheme, font: titleFont, textColor: primaryTextColor)
|
||||||
|
} else {
|
||||||
|
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
|
||||||
|
let resultTitleString = strings.Notification_DisabledTheme(authorName)
|
||||||
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if message.author?.id == accountPeerId {
|
||||||
|
attributedString = NSAttributedString(string: strings.Notification_YouChangedTheme(emoji).string, font: titleFont, textColor: primaryTextColor)
|
||||||
|
} else {
|
||||||
|
let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)]
|
||||||
|
let resultTitleString = strings.Notification_ChangedTheme(authorName, emoji)
|
||||||
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||||
|
}
|
||||||
|
}
|
||||||
case .unknown:
|
case .unknown:
|
||||||
attributedString = nil
|
attributedString = nil
|
||||||
}
|
}
|
||||||
|
1
submodules/TelegramUI/Resources/Animations/anim_sun.json
Normal file
1
submodules/TelegramUI/Resources/Animations/anim_sun.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -243,6 +243,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
private var presentationInterfaceState: ChatPresentationInterfaceState
|
private var presentationInterfaceState: ChatPresentationInterfaceState
|
||||||
private var presentationInterfaceStatePromise: ValuePromise<ChatPresentationInterfaceState>
|
private var presentationInterfaceStatePromise: ValuePromise<ChatPresentationInterfaceState>
|
||||||
|
|
||||||
|
private var cachedDataPromise = Promise<CachedPeerData?>(nil)
|
||||||
|
|
||||||
private var chatTitleView: ChatTitleView?
|
private var chatTitleView: ChatTitleView?
|
||||||
private var leftNavigationButton: ChatNavigationButton?
|
private var leftNavigationButton: ChatNavigationButton?
|
||||||
private var rightNavigationButton: ChatNavigationButton?
|
private var rightNavigationButton: ChatNavigationButton?
|
||||||
@ -345,8 +347,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
private var canReadHistoryValue = false
|
private var canReadHistoryValue = false
|
||||||
private var canReadHistoryDisposable: Disposable?
|
private var canReadHistoryDisposable: Disposable?
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
private var themeEmoticonPreviewPromise = ValuePromise<String?>(nil)
|
||||||
|
private var themeDarkAppearancePreviewPromise = ValuePromise<Bool?>(nil)
|
||||||
|
private var presentationDataPromise = Promise<PresentationData>()
|
||||||
|
private var presentationData: PresentationData {
|
||||||
|
didSet {
|
||||||
|
self.presentationDataPromise.set(.single(self.presentationData))
|
||||||
|
}
|
||||||
|
}
|
||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
var updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) {
|
||||||
|
return (self.presentationData, self.presentationDataPromise.get())
|
||||||
|
}
|
||||||
|
|
||||||
private var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
private var automaticMediaDownloadSettings: MediaAutoDownloadSettings
|
||||||
private var automaticMediaDownloadSettingsDisposable: Disposable?
|
private var automaticMediaDownloadSettingsDisposable: Disposable?
|
||||||
@ -700,6 +712,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
return true
|
return true
|
||||||
|
case .setChatTheme:
|
||||||
|
strongSelf.presentThemeSelection()
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -2835,7 +2850,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.chatTitleView?.pressed = { [weak self] in
|
self.chatTitleView?.pressed = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if strongSelf.chatLocation == .peer(strongSelf.context.account.peerId) {
|
if strongSelf.chatLocation == .peer(strongSelf.context.account.peerId) {
|
||||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true) {
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true) {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3740,13 +3755,48 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
let themeEmoticon: Signal<String?, NoError> = self.cachedDataPromise.get()
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
|> map { cachedData -> String? in
|
||||||
|
if let cachedData = cachedData as? CachedUserData {
|
||||||
|
return cachedData.themeEmoticon
|
||||||
|
} else if let cachedData = cachedData as? CachedUserData {
|
||||||
|
return cachedData.themeEmoticon
|
||||||
|
} else if let cachedData = cachedData as? CachedUserData {
|
||||||
|
return cachedData.themeEmoticon
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
|
|
||||||
|
self.presentationDataDisposable = combineLatest(queue: Queue.mainQueue(), context.sharedContext.presentationData, context.engine.themes.getChatThemes(accountManager: context.sharedContext.accountManager, onlyCached: true), themeEmoticon, self.themeEmoticonPreviewPromise.get(), self.themeDarkAppearancePreviewPromise.get()).start(next: { [weak self] presentationData, chatThemes, themeEmoticon, themeEmoticonPreview, darkAppearancePreview in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let previousTheme = strongSelf.presentationData.theme
|
let previousTheme = strongSelf.presentationData.theme
|
||||||
let previousStrings = strongSelf.presentationData.strings
|
let previousStrings = strongSelf.presentationData.strings
|
||||||
let previousChatWallpaper = strongSelf.presentationData.chatWallpaper
|
let previousChatWallpaper = strongSelf.presentationData.chatWallpaper
|
||||||
|
|
||||||
|
var themeEmoticon = themeEmoticon
|
||||||
|
if let themeEmoticonPreview = themeEmoticonPreview {
|
||||||
|
if !themeEmoticonPreview.isEmpty {
|
||||||
|
themeEmoticon = themeEmoticonPreview
|
||||||
|
} else {
|
||||||
|
themeEmoticon = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isDarkAppearance = presentationData.theme.overallDarkAppearance
|
||||||
|
if let darkAppearancePreview = darkAppearancePreview {
|
||||||
|
isDarkAppearance = darkAppearancePreview
|
||||||
|
}
|
||||||
|
|
||||||
|
var presentationData = presentationData
|
||||||
|
if let themeEmoticon = themeEmoticon, let theme = chatThemes.first(where: { $0.emoji == themeEmoticon }) {
|
||||||
|
let customTheme = isDarkAppearance ? theme.darkTheme : theme.theme
|
||||||
|
if let settings = customTheme.settings, let theme = makePresentationTheme(settings: settings) {
|
||||||
|
presentationData = presentationData.withUpdated(theme: theme)
|
||||||
|
presentationData = presentationData.withUpdated(chatWallpaper: theme.chat.defaultWallpaper)
|
||||||
|
}
|
||||||
|
}
|
||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
|
|
||||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings || presentationData.chatWallpaper != previousChatWallpaper {
|
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings || presentationData.chatWallpaper != previousChatWallpaper {
|
||||||
@ -4471,6 +4521,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let (cachedData, messages) = cachedDataAndMessages
|
let (cachedData, messages) = cachedDataAndMessages
|
||||||
|
|
||||||
|
strongSelf.cachedDataPromise.set(.single(cachedData))
|
||||||
|
|
||||||
var pinnedMessageId: MessageId?
|
var pinnedMessageId: MessageId?
|
||||||
var peerIsBlocked: Bool = false
|
var peerIsBlocked: Bool = false
|
||||||
var callsAvailable: Bool = false
|
var callsAvailable: Bool = false
|
||||||
@ -8425,7 +8477,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|> deliverOnMainQueue).start(next: { [weak self] peerView in
|
|> deliverOnMainQueue).start(next: { [weak self] peerView in
|
||||||
if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && !strongSelf.presentationInterfaceState.isNotAccessible {
|
if let strongSelf = self, let peer = peerView.peers[peerView.peerId], peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil && !strongSelf.presentationInterfaceState.isNotAccessible {
|
||||||
if peer.id == strongSelf.context.account.peerId {
|
if peer.id == strongSelf.context.account.peerId {
|
||||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true) {
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer, let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: true) {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -8436,7 +8488,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let validLayout = strongSelf.validLayout, validLayout.deviceMetrics.type == .tablet {
|
if let validLayout = strongSelf.validLayout, validLayout.deviceMetrics.type == .tablet {
|
||||||
expandAvatar = false
|
expandAvatar = false
|
||||||
}
|
}
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: expandAvatar, fromChat: true) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: expandAvatar, fromChat: true) {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8799,7 +8851,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
slowModeEnabled = true
|
slowModeEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let controller = legacyAttachmentMenu(context: strongSelf.context, peer: peer, chatLocation: strongSelf.chatLocation, editMediaOptions: menuEditMediaOptions, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, canSendPolls: canSendPolls, presentationData: strongSelf.presentationData, parentController: legacyController, recentlyUsedInlineBots: strongSelf.recentlyUsedInlineBotsValue, initialCaption: inputText.string, openGallery: {
|
let controller = legacyAttachmentMenu(context: strongSelf.context, peer: peer, chatLocation: strongSelf.chatLocation, editMediaOptions: menuEditMediaOptions, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, canSendPolls: canSendPolls, presentationData: strongSelf.presentationData, updatedPresentationData: strongSelf.updatedPresentationData, parentController: legacyController, recentlyUsedInlineBots: strongSelf.recentlyUsedInlineBotsValue, initialCaption: inputText.string, openGallery: {
|
||||||
self?.presentMediaPicker(fileMode: false, editingMedia: editMediaOptions != nil, completion: { signals, silentPosting, scheduleTime in
|
self?.presentMediaPicker(fileMode: false, editingMedia: editMediaOptions != nil, completion: { signals, silentPosting, scheduleTime in
|
||||||
if !inputText.string.isEmpty {
|
if !inputText.string.isEmpty {
|
||||||
//strongSelf.clearInputText()
|
//strongSelf.clearInputText()
|
||||||
@ -11322,7 +11374,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let validLayout = strongSelf.validLayout, validLayout.deviceMetrics.type == .tablet {
|
if let validLayout = strongSelf.validLayout, validLayout.deviceMetrics.type == .tablet {
|
||||||
expandAvatar = false
|
expandAvatar = false
|
||||||
}
|
}
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: mode, avatarInitiallyExpanded: expandAvatar, fromChat: false) {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11775,7 +11827,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil {
|
if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil {
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
strongSelf.effectiveNavigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12834,6 +12886,73 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.push(controller)
|
self.push(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func presentCrossfadeSnapshot() {
|
||||||
|
guard let snapshotView = self.view.snapshotView(afterScreenUpdates: false) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.view.addSubview(snapshotView)
|
||||||
|
|
||||||
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||||
|
snapshotView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public func presentThemeSelection() {
|
||||||
|
let context = self.context
|
||||||
|
let peerId = self.chatLocation.peerId
|
||||||
|
|
||||||
|
self.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
|
||||||
|
var updated = state
|
||||||
|
updated = updated.updatedInputMode({ _ in
|
||||||
|
return .none
|
||||||
|
})
|
||||||
|
updated = updated.updatedShowCommands(false)
|
||||||
|
return updated
|
||||||
|
})
|
||||||
|
|
||||||
|
let _ = (self.cachedDataPromise.get()
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] cachedData in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedEmoticon: String?
|
||||||
|
if let cachedData = cachedData as? CachedUserData {
|
||||||
|
selectedEmoticon = cachedData.themeEmoticon
|
||||||
|
} else if let cachedData = cachedData as? CachedGroupData {
|
||||||
|
selectedEmoticon = cachedData.themeEmoticon
|
||||||
|
} else if let cachedData = cachedData as? CachedChannelData {
|
||||||
|
selectedEmoticon = cachedData.themeEmoticon
|
||||||
|
} else {
|
||||||
|
selectedEmoticon = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let controller = ChatThemeScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, initiallySelectedEmoticon: selectedEmoticon, previewTheme: { [weak self] emoticon in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.presentCrossfadeSnapshot()
|
||||||
|
strongSelf.themeEmoticonPreviewPromise.set(emoticon)
|
||||||
|
if emoticon == nil {
|
||||||
|
strongSelf.themeDarkAppearancePreviewPromise.set(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, previewDarkTheme: { dark in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.presentCrossfadeSnapshot()
|
||||||
|
strongSelf.themeDarkAppearancePreviewPromise.set(dark)
|
||||||
|
}
|
||||||
|
}, completion: { [weak self] emoticon in
|
||||||
|
strongSelf.themeDarkAppearancePreviewPromise.set(nil)
|
||||||
|
let _ = context.engine.themes.setChatTheme(peerId: peerId, emoji: emoticon).start(completed: { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.themeEmoticonPreviewPromise.set(nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
strongSelf.present(controller, in: .window(.root))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private var effectiveNavigationController: NavigationController? {
|
private var effectiveNavigationController: NavigationController? {
|
||||||
if let navigationController = self.navigationController as? NavigationController {
|
if let navigationController = self.navigationController as? NavigationController {
|
||||||
return navigationController
|
return navigationController
|
||||||
|
@ -247,7 +247,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.inputContextPanelContainer = ChatControllerTitlePanelNodeContainer()
|
self.inputContextPanelContainer = ChatControllerTitlePanelNodeContainer()
|
||||||
|
|
||||||
var getMessageTransitionNode: (() -> ChatMessageTransitionNode?)?
|
var getMessageTransitionNode: (() -> ChatMessageTransitionNode?)?
|
||||||
self.historyNode = ChatHistoryListNode(context: context, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tagMask: nil, subject: subject, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), messageTransitionNode: {
|
self.historyNode = ChatHistoryListNode(context: context, updatedPresentationData: controller?.updatedPresentationData ?? (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tagMask: nil, subject: subject, controllerInteraction: controllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), messageTransitionNode: {
|
||||||
return getMessageTransitionNode?()
|
return getMessageTransitionNode?()
|
||||||
})
|
})
|
||||||
self.historyNode.rotated = true
|
self.historyNode.rotated = true
|
||||||
|
@ -559,7 +559,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
private let clientId: Atomic<Int32>
|
private let clientId: Atomic<Int32>
|
||||||
|
|
||||||
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles, messageTransitionNode: @escaping () -> ChatMessageTransitionNode? = { nil }) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tagMask: MessageTags?, source: ChatHistoryListSource = .default, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, selectedMessages: Signal<Set<MessageId>?, NoError>, mode: ChatHistoryListMode = .bubbles, messageTransitionNode: @escaping () -> ChatMessageTransitionNode? = { nil }) {
|
||||||
var tagMask = tagMask
|
var tagMask = tagMask
|
||||||
var appendMessagesFromTheSameGroup = false
|
var appendMessagesFromTheSameGroup = false
|
||||||
if case .pinnedMessages = subject {
|
if case .pinnedMessages = subject {
|
||||||
@ -575,7 +575,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = updatedPresentationData.initial
|
||||||
self.currentPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners, animatedEmojiScale: 1.0)
|
self.currentPresentationData = ChatPresentationData(theme: ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper), fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners, animatedEmojiScale: 1.0)
|
||||||
|
|
||||||
self.chatPresentationDataPromise = Promise(self.currentPresentationData)
|
self.chatPresentationDataPromise = Promise(self.currentPresentationData)
|
||||||
@ -1088,7 +1088,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
self.presentationDataDisposable = (
|
self.presentationDataDisposable = (
|
||||||
combineLatest(queue: .mainQueue(),
|
combineLatest(queue: .mainQueue(),
|
||||||
context.sharedContext.presentationData,
|
updatedPresentationData.signal,
|
||||||
appConfiguration)
|
appConfiguration)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData, appConfiguration in
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData, appConfiguration in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
@ -225,13 +225,15 @@ final class ChatMediaInputStickerPackItemNode: ListViewItemNode {
|
|||||||
self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: resource, animated: true, nilIfEmpty: true))
|
self.imageNode.setSignal(chatMessageStickerPackThumbnail(postbox: account.postbox, resource: resource, animated: true, nilIfEmpty: true))
|
||||||
|
|
||||||
let loopAnimatedStickers = self.inputNodeInteraction?.stickerSettings?.loopAnimatedStickers ?? false
|
let loopAnimatedStickers = self.inputNodeInteraction?.stickerSettings?.loopAnimatedStickers ?? false
|
||||||
self.imageNode.isHidden = loopAnimatedStickers
|
|
||||||
|
|
||||||
let animatedStickerNode: AnimatedStickerNode
|
let animatedStickerNode: AnimatedStickerNode
|
||||||
if let current = self.animatedStickerNode {
|
if let current = self.animatedStickerNode {
|
||||||
animatedStickerNode = current
|
animatedStickerNode = current
|
||||||
} else {
|
} else {
|
||||||
animatedStickerNode = AnimatedStickerNode()
|
animatedStickerNode = AnimatedStickerNode()
|
||||||
|
animatedStickerNode.started = { [weak self] in
|
||||||
|
self?.imageNode.isHidden = true
|
||||||
|
}
|
||||||
self.animatedStickerNode = animatedStickerNode
|
self.animatedStickerNode = animatedStickerNode
|
||||||
if let placeholderNode = self.placeholderNode {
|
if let placeholderNode = self.placeholderNode {
|
||||||
self.scalingNode.insertSubnode(animatedStickerNode, belowSubnode: placeholderNode)
|
self.scalingNode.insertSubnode(animatedStickerNode, belowSubnode: placeholderNode)
|
||||||
|
@ -228,11 +228,11 @@ class ChatMessageBackground: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if transition.isAnimated {
|
} else if transition.isAnimated {
|
||||||
if let previousContents = self.imageNode.layer.contents, let image = image {
|
// if let previousContents = self.imageNode.layer.contents, let image = image {
|
||||||
if (previousContents as AnyObject) !== image.cgImage {
|
// if (previousContents as AnyObject) !== image.cgImage {
|
||||||
self.imageNode.layer.animate(from: previousContents as AnyObject, to: image.cgImage! as AnyObject, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.42)
|
// self.imageNode.layer.animate(from: previousContents as AnyObject, to: image.cgImage! as AnyObject, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.42)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
self.imageNode.image = image
|
self.imageNode.image = image
|
||||||
|
@ -772,7 +772,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
if peer is TelegramChannel, let navigationController = strongSelf.getNavigationController() {
|
if peer is TelegramChannel, let navigationController = strongSelf.getNavigationController() {
|
||||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), peekData: peekData, animated: true))
|
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), peekData: peekData, animated: true))
|
||||||
} else {
|
} else {
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
strongSelf.pushController(infoController)
|
strongSelf.pushController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -786,7 +786,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
strongSelf.pushController(infoController)
|
strongSelf.pushController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
918
submodules/TelegramUI/Sources/ChatThemeScreen.swift
Normal file
918
submodules/TelegramUI/Sources/ChatThemeScreen.swift
Normal file
@ -0,0 +1,918 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import Display
|
||||||
|
import AsyncDisplayKit
|
||||||
|
import Postbox
|
||||||
|
import TelegramCore
|
||||||
|
import SwiftSignalKit
|
||||||
|
import AccountContext
|
||||||
|
import SolidRoundedButtonNode
|
||||||
|
import TelegramPresentationData
|
||||||
|
import TelegramUIPreferences
|
||||||
|
import PresentationDataUtils
|
||||||
|
import AnimationUI
|
||||||
|
import MergeLists
|
||||||
|
import WallpaperResources
|
||||||
|
import TooltipUI
|
||||||
|
|
||||||
|
private func closeButtonImage(theme: PresentationTheme) -> UIImage? {
|
||||||
|
return generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setFillColor(theme.actionSheet.inputBackgroundColor.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setLineWidth(2.0)
|
||||||
|
context.setLineCap(.round)
|
||||||
|
context.setStrokeColor(theme.actionSheet.inputClearButtonColor.cgColor)
|
||||||
|
|
||||||
|
context.move(to: CGPoint(x: 10.0, y: 10.0))
|
||||||
|
context.addLine(to: CGPoint(x: 20.0, y: 20.0))
|
||||||
|
context.strokePath()
|
||||||
|
|
||||||
|
context.move(to: CGPoint(x: 20.0, y: 10.0))
|
||||||
|
context.addLine(to: CGPoint(x: 10.0, y: 20.0))
|
||||||
|
context.strokePath()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ThemeSettingsThemeEntry: Comparable, Identifiable {
|
||||||
|
let index: Int
|
||||||
|
let emoticon: String?
|
||||||
|
let themeReference: PresentationThemeReference?
|
||||||
|
var selected: Bool
|
||||||
|
let theme: PresentationTheme
|
||||||
|
let wallpaper: TelegramWallpaper?
|
||||||
|
|
||||||
|
var stableId: Int {
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: ThemeSettingsThemeEntry, rhs: ThemeSettingsThemeEntry) -> Bool {
|
||||||
|
if lhs.index != rhs.index {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.emoticon != rhs.emoticon {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.themeReference?.index != rhs.themeReference?.index {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.selected != rhs.selected {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.theme !== rhs.theme {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.wallpaper != rhs.wallpaper {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
static func <(lhs: ThemeSettingsThemeEntry, rhs: ThemeSettingsThemeEntry) -> Bool {
|
||||||
|
return lhs.index < rhs.index
|
||||||
|
}
|
||||||
|
|
||||||
|
func item(context: AccountContext, action: @escaping (String?) -> Void) -> ListViewItem {
|
||||||
|
return ThemeSettingsThemeIconItem(context: context, emoticon: self.emoticon, themeReference: self.themeReference, selected: self.selected, theme: self.theme, wallpaper: self.wallpaper, action: action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class ThemeSettingsThemeIconItem: ListViewItem {
|
||||||
|
let context: AccountContext
|
||||||
|
let emoticon: String?
|
||||||
|
let themeReference: PresentationThemeReference?
|
||||||
|
let selected: Bool
|
||||||
|
let theme: PresentationTheme
|
||||||
|
let wallpaper: TelegramWallpaper?
|
||||||
|
let action: (String?) -> Void
|
||||||
|
|
||||||
|
public init(context: AccountContext, emoticon: String?, themeReference: PresentationThemeReference?, selected: Bool, theme: PresentationTheme, wallpaper: TelegramWallpaper?, action: @escaping (String?) -> Void) {
|
||||||
|
self.context = context
|
||||||
|
self.emoticon = emoticon
|
||||||
|
self.themeReference = themeReference
|
||||||
|
self.selected = selected
|
||||||
|
self.theme = theme
|
||||||
|
self.wallpaper = wallpaper
|
||||||
|
self.action = action
|
||||||
|
}
|
||||||
|
|
||||||
|
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||||
|
async {
|
||||||
|
let node = ThemeSettingsThemeItemIconNode()
|
||||||
|
let (nodeLayout, apply) = node.asyncLayout()(self, params)
|
||||||
|
node.insets = nodeLayout.insets
|
||||||
|
node.contentSize = nodeLayout.contentSize
|
||||||
|
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(node, {
|
||||||
|
return (nil, { _ in
|
||||||
|
apply(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
assert(node() is ThemeSettingsThemeItemIconNode)
|
||||||
|
if let nodeValue = node() as? ThemeSettingsThemeItemIconNode {
|
||||||
|
let layout = nodeValue.asyncLayout()
|
||||||
|
async {
|
||||||
|
let (nodeLayout, apply) = layout(self, params)
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion(nodeLayout, { _ in
|
||||||
|
apply(animation.isAnimated)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var selectable = true
|
||||||
|
public func selected(listView: ListView) {
|
||||||
|
self.action(self.emoticon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ThemeSettingsThemeItemNodeTransition {
|
||||||
|
let deletions: [ListViewDeleteItem]
|
||||||
|
let insertions: [ListViewInsertItem]
|
||||||
|
let updates: [ListViewUpdateItem]
|
||||||
|
let crossfade: Bool
|
||||||
|
let entries: [ThemeSettingsThemeEntry]
|
||||||
|
}
|
||||||
|
|
||||||
|
private func ensureThemeVisible(listNode: ListView, emoticon: String?, animated: Bool) -> Bool {
|
||||||
|
var resultNode: ThemeSettingsThemeItemIconNode?
|
||||||
|
listNode.forEachItemNode { node in
|
||||||
|
if resultNode == nil, let node = node as? ThemeSettingsThemeItemIconNode {
|
||||||
|
if node.item?.emoticon == emoticon {
|
||||||
|
resultNode = node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let resultNode = resultNode {
|
||||||
|
listNode.ensureItemNodeVisible(resultNode, animated: animated, overflow: 57.0)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func preparedTransition(context: AccountContext, action: @escaping (String?) -> Void, from fromEntries: [ThemeSettingsThemeEntry], to toEntries: [ThemeSettingsThemeEntry], crossfade: Bool) -> ThemeSettingsThemeItemNodeTransition {
|
||||||
|
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||||
|
|
||||||
|
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||||
|
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, action: action), directionHint: .Down) }
|
||||||
|
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, action: action), directionHint: nil) }
|
||||||
|
|
||||||
|
return ThemeSettingsThemeItemNodeTransition(deletions: deletions, insertions: insertions, updates: updates, crossfade: crossfade, entries: toEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var cachedBorderImages: [String: UIImage] = [:]
|
||||||
|
private func generateBorderImage(theme: PresentationTheme, bordered: Bool, selected: Bool) -> UIImage? {
|
||||||
|
let key = "\(theme.list.itemBlocksBackgroundColor.hexString)_\(selected ? "s" + theme.list.itemAccentColor.hexString : theme.list.disclosureArrowColor.hexString)"
|
||||||
|
if let image = cachedBorderImages[key] {
|
||||||
|
return image
|
||||||
|
} else {
|
||||||
|
let image = generateImage(CGSize(width: 18.0, height: 18.0), rotatedContext: { size, context in
|
||||||
|
let bounds = CGRect(origin: CGPoint(), size: size)
|
||||||
|
context.clear(bounds)
|
||||||
|
|
||||||
|
let lineWidth: CGFloat
|
||||||
|
if selected {
|
||||||
|
lineWidth = 2.0
|
||||||
|
context.setLineWidth(lineWidth)
|
||||||
|
context.setStrokeColor(theme.list.itemBlocksBackgroundColor.cgColor)
|
||||||
|
|
||||||
|
context.strokeEllipse(in: bounds.insetBy(dx: 3.0 + lineWidth / 2.0, dy: 3.0 + lineWidth / 2.0))
|
||||||
|
|
||||||
|
var accentColor = theme.list.itemAccentColor
|
||||||
|
if accentColor.rgb == 0xffffff {
|
||||||
|
accentColor = UIColor(rgb: 0x999999)
|
||||||
|
}
|
||||||
|
context.setStrokeColor(accentColor.cgColor)
|
||||||
|
} else {
|
||||||
|
context.setStrokeColor(theme.list.disclosureArrowColor.withAlphaComponent(0.4).cgColor)
|
||||||
|
lineWidth = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
if bordered || selected {
|
||||||
|
context.setLineWidth(lineWidth)
|
||||||
|
context.strokeEllipse(in: bounds.insetBy(dx: 1.0 + lineWidth / 2.0, dy: 1.0 + lineWidth / 2.0))
|
||||||
|
}
|
||||||
|
})?.stretchableImage(withLeftCapWidth: 9, topCapHeight: 9)
|
||||||
|
cachedBorderImages[key] = image
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class ThemeSettingsThemeItemIconNode : ListViewItemNode {
|
||||||
|
private let containerNode: ASDisplayNode
|
||||||
|
private let imageNode: TransformImageNode
|
||||||
|
private let overlayNode: ASImageNode
|
||||||
|
private let textNode: TextNode
|
||||||
|
private let emojiNode: TextNode
|
||||||
|
var snapshotView: UIView?
|
||||||
|
|
||||||
|
var item: ThemeSettingsThemeIconItem?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self.containerNode = ASDisplayNode()
|
||||||
|
|
||||||
|
self.imageNode = TransformImageNode()
|
||||||
|
self.imageNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 82.0, height: 108.0))
|
||||||
|
self.imageNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.overlayNode = ASImageNode()
|
||||||
|
self.overlayNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 84.0, height: 110.0))
|
||||||
|
self.overlayNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.textNode = TextNode()
|
||||||
|
self.textNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
self.emojiNode = TextNode()
|
||||||
|
self.emojiNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
super.init(layerBacked: false, dynamicBounce: false, rotated: false, seeThrough: false)
|
||||||
|
|
||||||
|
self.addSubnode(self.containerNode)
|
||||||
|
self.containerNode.addSubnode(self.imageNode)
|
||||||
|
self.containerNode.addSubnode(self.overlayNode)
|
||||||
|
self.containerNode.addSubnode(self.textNode)
|
||||||
|
self.containerNode.addSubnode(self.emojiNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func asyncLayout() -> (ThemeSettingsThemeIconItem, ListViewItemLayoutParams) -> (ListViewItemNodeLayout, (Bool) -> Void) {
|
||||||
|
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||||
|
let makeEmojiLayout = TextNode.asyncLayout(self.emojiNode)
|
||||||
|
let makeImageLayout = self.imageNode.asyncLayout()
|
||||||
|
|
||||||
|
let currentItem = self.item
|
||||||
|
|
||||||
|
return { [weak self] item, params in
|
||||||
|
var updatedThemeReference = false
|
||||||
|
var updatedTheme = false
|
||||||
|
var updatedWallpaper = false
|
||||||
|
var updatedSelected = false
|
||||||
|
|
||||||
|
if currentItem?.themeReference != item.themeReference {
|
||||||
|
updatedThemeReference = true
|
||||||
|
}
|
||||||
|
if currentItem?.wallpaper != item.wallpaper {
|
||||||
|
updatedWallpaper = true
|
||||||
|
}
|
||||||
|
if currentItem?.theme !== item.theme {
|
||||||
|
updatedTheme = true
|
||||||
|
}
|
||||||
|
if currentItem?.selected != item.selected {
|
||||||
|
updatedSelected = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = NSAttributedString(string: "No\nTheme", font: Font.semibold(15.0), textColor: item.theme.actionSheet.controlAccentColor)
|
||||||
|
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: text, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
let title = NSAttributedString(string: item.emoticon ?? "❌", font: Font.regular(22.0), textColor: .black)
|
||||||
|
let (_, emojiApply) = makeEmojiLayout(TextNodeLayoutArguments(attributedString: title, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
let itemLayout = ListViewItemNodeLayout(contentSize: CGSize(width: 120.0, height: 90.0), insets: UIEdgeInsets())
|
||||||
|
return (itemLayout, { animated in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.item = item
|
||||||
|
|
||||||
|
if updatedThemeReference || updatedWallpaper {
|
||||||
|
if let themeReference = item.themeReference {
|
||||||
|
strongSelf.imageNode.cornerRadius = 0.0
|
||||||
|
strongSelf.imageNode.setSignal(themeIconImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, theme: themeReference, color: nil, wallpaper: item.wallpaper, emoticon: true))
|
||||||
|
strongSelf.imageNode.backgroundColor = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if item.themeReference == nil {
|
||||||
|
strongSelf.imageNode.cornerRadius = 9.0
|
||||||
|
strongSelf.imageNode.backgroundColor = item.theme.actionSheet.opaqueItemBackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
if updatedTheme || updatedSelected {
|
||||||
|
strongSelf.overlayNode.image = generateBorderImage(theme: item.theme, bordered: false, selected: item.selected)
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((90.0 - textLayout.size.width) / 2.0), y: 24.0), size: textLayout.size)
|
||||||
|
strongSelf.textNode.isHidden = item.emoticon != nil
|
||||||
|
|
||||||
|
strongSelf.containerNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||||
|
strongSelf.containerNode.frame = CGRect(origin: CGPoint(x: 15.0, y: -15.0), size: CGSize(width: 90.0, height: 120.0))
|
||||||
|
|
||||||
|
let _ = textApply()
|
||||||
|
let _ = emojiApply()
|
||||||
|
|
||||||
|
let imageSize = CGSize(width: 82.0, height: 108.0)
|
||||||
|
strongSelf.imageNode.frame = CGRect(origin: CGPoint(x: 4.0, y: 6.0), size: imageSize)
|
||||||
|
let applyLayout = makeImageLayout(TransformImageArguments(corners: ImageCorners(radius: 9.0), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: .clear))
|
||||||
|
applyLayout()
|
||||||
|
|
||||||
|
strongSelf.overlayNode.frame = strongSelf.imageNode.frame.insetBy(dx: -1.0, dy: -1.0)
|
||||||
|
strongSelf.emojiNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 79.0), size: CGSize(width: 90.0, height: 30.0))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func crossfade() {
|
||||||
|
if let snapshotView = self.view.snapshotView(afterScreenUpdates: false) {
|
||||||
|
self.view.addSubview(snapshotView)
|
||||||
|
|
||||||
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||||
|
snapshotView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||||
|
super.animateInsertion(currentTimestamp, duration: duration, short: short)
|
||||||
|
|
||||||
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||||
|
super.animateRemoved(currentTimestamp, duration: duration)
|
||||||
|
|
||||||
|
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||||
|
super.animateAdded(currentTimestamp, duration: duration)
|
||||||
|
|
||||||
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ChatThemeScreen: ViewController {
|
||||||
|
private var controllerNode: ChatThemeScreenNode {
|
||||||
|
return self.displayNode as! ChatThemeScreenNode
|
||||||
|
}
|
||||||
|
|
||||||
|
private var animatedIn = false
|
||||||
|
|
||||||
|
private let context: AccountContext
|
||||||
|
private let initiallySelectedEmoticon: String?
|
||||||
|
private let dismissByTapOutside: Bool
|
||||||
|
private let previewTheme: (String?) -> Void
|
||||||
|
private let previewDarkTheme: (Bool) -> Void
|
||||||
|
private let completion: (String?) -> Void
|
||||||
|
|
||||||
|
private var presentationData: PresentationData
|
||||||
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
|
init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), initiallySelectedEmoticon: String?, dismissByTapOutside: Bool = true, previewTheme: @escaping (String?) -> Void, previewDarkTheme: @escaping (Bool) -> Void, completion: @escaping (String?) -> Void) {
|
||||||
|
self.context = context
|
||||||
|
self.presentationData = updatedPresentationData.initial
|
||||||
|
self.initiallySelectedEmoticon = initiallySelectedEmoticon
|
||||||
|
self.dismissByTapOutside = dismissByTapOutside
|
||||||
|
self.previewTheme = previewTheme
|
||||||
|
self.previewDarkTheme = previewDarkTheme
|
||||||
|
self.completion = completion
|
||||||
|
|
||||||
|
super.init(navigationBarPresentationData: nil)
|
||||||
|
|
||||||
|
self.statusBar.statusBarStyle = .Ignore
|
||||||
|
|
||||||
|
self.blocksBackgroundWhenInOverlay = true
|
||||||
|
|
||||||
|
self.presentationDataDisposable = (updatedPresentationData.signal
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.presentationData = presentationData
|
||||||
|
strongSelf.controllerNode.updatePresentationData(presentationData)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
self.statusBar.statusBarStyle = .Ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
required init(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.presentationDataDisposable?.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func loadDisplayNode() {
|
||||||
|
self.displayNode = ChatThemeScreenNode(context: self.context, presentationData: self.presentationData, initiallySelectedEmoticon: self.initiallySelectedEmoticon, dismissByTapOutside: self.dismissByTapOutside)
|
||||||
|
self.controllerNode.previewTheme = { [weak self] emoticon in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.previewTheme(emoticon ?? "")
|
||||||
|
}
|
||||||
|
self.controllerNode.present = { [weak self] c in
|
||||||
|
self?.present(c, in: .window(.root))
|
||||||
|
}
|
||||||
|
self.controllerNode.previewDarkTheme = { [weak self] dark in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.previewDarkTheme(dark)
|
||||||
|
}
|
||||||
|
self.controllerNode.completion = { [weak self] emoticon in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.completion(emoticon)
|
||||||
|
strongSelf.dismiss()
|
||||||
|
}
|
||||||
|
self.controllerNode.dismiss = { [weak self] in
|
||||||
|
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||||
|
}
|
||||||
|
self.controllerNode.cancel = { [weak self] in
|
||||||
|
self?.previewTheme(nil)
|
||||||
|
self?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func loadView() {
|
||||||
|
super.loadView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
if !self.animatedIn {
|
||||||
|
self.animatedIn = true
|
||||||
|
self.controllerNode.animateIn()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func dismiss(completion: (() -> Void)? = nil) {
|
||||||
|
self.forEachController({ controller in
|
||||||
|
if let controller = controller as? TooltipScreen {
|
||||||
|
controller.dismiss()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
self.controllerNode.animateOut(completion: completion)
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||||
|
super.containerLayoutUpdated(layout, transition: transition)
|
||||||
|
|
||||||
|
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelegate {
|
||||||
|
private let context: AccountContext
|
||||||
|
private var presentationData: PresentationData
|
||||||
|
private let dismissByTapOutside: Bool
|
||||||
|
|
||||||
|
private let dimNode: ASDisplayNode
|
||||||
|
private let wrappingScrollNode: ASScrollNode
|
||||||
|
private let contentContainerNode: ASDisplayNode
|
||||||
|
private let topContentContainerNode: SparseNode
|
||||||
|
private let effectNode: ASDisplayNode
|
||||||
|
private let backgroundNode: ASDisplayNode
|
||||||
|
private let contentBackgroundNode: ASDisplayNode
|
||||||
|
private let titleNode: ASTextNode
|
||||||
|
private let textNode: ImmediateTextNode
|
||||||
|
private let cancelButton: HighlightableButtonNode
|
||||||
|
private let switchThemeButton: HighlightTrackingButtonNode
|
||||||
|
private let animationNode: AnimationNode
|
||||||
|
private let doneButton: SolidRoundedButtonNode
|
||||||
|
|
||||||
|
private let listNode: ListView
|
||||||
|
private var entries: [ThemeSettingsThemeEntry]?
|
||||||
|
private var enqueuedTransitions: [ThemeSettingsThemeItemNodeTransition] = []
|
||||||
|
private var initialized = false
|
||||||
|
|
||||||
|
private let initiallySelectedEmoticon: String?
|
||||||
|
private var selectedEmoticon: String? {
|
||||||
|
didSet {
|
||||||
|
self.selectedEmoticonPromise.set(self.selectedEmoticon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private var selectedEmoticonPromise: ValuePromise<String?>
|
||||||
|
private var isDarkAppearancePromise: ValuePromise<Bool>
|
||||||
|
|
||||||
|
private var containerLayout: (ContainerViewLayout, CGFloat)?
|
||||||
|
|
||||||
|
private let disposable = MetaDisposable()
|
||||||
|
|
||||||
|
var present: ((ViewController) -> Void)?
|
||||||
|
var previewTheme: ((String?) -> Void)?
|
||||||
|
var previewDarkTheme: ((Bool) -> Void)?
|
||||||
|
var completion: ((String?) -> Void)?
|
||||||
|
var dismiss: (() -> Void)?
|
||||||
|
var cancel: (() -> Void)?
|
||||||
|
|
||||||
|
init(context: AccountContext, presentationData: PresentationData, initiallySelectedEmoticon: String?, dismissByTapOutside: Bool) {
|
||||||
|
self.context = context
|
||||||
|
self.initiallySelectedEmoticon = initiallySelectedEmoticon
|
||||||
|
self.selectedEmoticon = initiallySelectedEmoticon
|
||||||
|
self.selectedEmoticonPromise = ValuePromise(initiallySelectedEmoticon)
|
||||||
|
self.presentationData = presentationData
|
||||||
|
self.dismissByTapOutside = dismissByTapOutside
|
||||||
|
|
||||||
|
self.wrappingScrollNode = ASScrollNode()
|
||||||
|
self.wrappingScrollNode.view.alwaysBounceVertical = true
|
||||||
|
self.wrappingScrollNode.view.delaysContentTouches = false
|
||||||
|
self.wrappingScrollNode.view.canCancelContentTouches = true
|
||||||
|
|
||||||
|
self.dimNode = ASDisplayNode()
|
||||||
|
self.dimNode.backgroundColor = .clear
|
||||||
|
|
||||||
|
self.contentContainerNode = ASDisplayNode()
|
||||||
|
self.contentContainerNode.isOpaque = false
|
||||||
|
|
||||||
|
self.topContentContainerNode = SparseNode()
|
||||||
|
self.topContentContainerNode.isOpaque = false
|
||||||
|
|
||||||
|
self.backgroundNode = ASDisplayNode()
|
||||||
|
self.backgroundNode.clipsToBounds = true
|
||||||
|
self.backgroundNode.cornerRadius = 16.0
|
||||||
|
|
||||||
|
self.isDarkAppearancePromise = ValuePromise(self.presentationData.theme.overallDarkAppearance)
|
||||||
|
|
||||||
|
let backgroundColor = self.presentationData.theme.actionSheet.itemBackgroundColor
|
||||||
|
let textColor = self.presentationData.theme.actionSheet.primaryTextColor
|
||||||
|
let blurStyle: UIBlurEffect.Style = self.presentationData.theme.actionSheet.backgroundType == .light ? .light : .dark
|
||||||
|
|
||||||
|
self.effectNode = ASDisplayNode(viewBlock: {
|
||||||
|
return UIVisualEffectView(effect: UIBlurEffect(style: blurStyle))
|
||||||
|
})
|
||||||
|
|
||||||
|
self.contentBackgroundNode = ASDisplayNode()
|
||||||
|
self.contentBackgroundNode.backgroundColor = backgroundColor
|
||||||
|
|
||||||
|
let title = self.presentationData.strings.Conversation_Theme_Title
|
||||||
|
self.titleNode = ASTextNode()
|
||||||
|
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(17.0), textColor: textColor)
|
||||||
|
|
||||||
|
self.textNode = ImmediateTextNode()
|
||||||
|
|
||||||
|
self.cancelButton = HighlightableButtonNode()
|
||||||
|
self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal)
|
||||||
|
|
||||||
|
var colors: [String: UIColor] = [:]
|
||||||
|
let accentColor = self.presentationData.theme.actionSheet.controlAccentColor
|
||||||
|
colors["Sunny.Path 14.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 15.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Path.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 39.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 24.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 25.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 18.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 41.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 43.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Path 10.Path.Fill 1"] = accentColor
|
||||||
|
colors["Path 11.Path.Fill 1"] = accentColor
|
||||||
|
|
||||||
|
self.switchThemeButton = HighlightTrackingButtonNode()
|
||||||
|
self.animationNode = AnimationNode(animation: self.presentationData.theme.overallDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: colors, scale: 1.0)
|
||||||
|
self.animationNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
self.doneButton = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 52.0, cornerRadius: 11.0, gloss: false)
|
||||||
|
self.doneButton.title = self.presentationData.strings.Conversation_Theme_Apply
|
||||||
|
|
||||||
|
self.listNode = ListView()
|
||||||
|
self.listNode.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0)
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.backgroundColor = nil
|
||||||
|
self.isOpaque = false
|
||||||
|
|
||||||
|
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:))))
|
||||||
|
self.addSubnode(self.dimNode)
|
||||||
|
|
||||||
|
self.wrappingScrollNode.view.delegate = self
|
||||||
|
self.addSubnode(self.wrappingScrollNode)
|
||||||
|
|
||||||
|
self.wrappingScrollNode.addSubnode(self.backgroundNode)
|
||||||
|
self.wrappingScrollNode.addSubnode(self.contentContainerNode)
|
||||||
|
self.wrappingScrollNode.addSubnode(self.topContentContainerNode)
|
||||||
|
|
||||||
|
self.backgroundNode.addSubnode(self.effectNode)
|
||||||
|
self.backgroundNode.addSubnode(self.contentBackgroundNode)
|
||||||
|
self.contentContainerNode.addSubnode(self.titleNode)
|
||||||
|
self.contentContainerNode.addSubnode(self.textNode)
|
||||||
|
self.contentContainerNode.addSubnode(self.cancelButton)
|
||||||
|
self.contentContainerNode.addSubnode(self.doneButton)
|
||||||
|
|
||||||
|
self.topContentContainerNode.addSubnode(self.animationNode)
|
||||||
|
self.topContentContainerNode.addSubnode(self.switchThemeButton)
|
||||||
|
self.topContentContainerNode.addSubnode(self.listNode)
|
||||||
|
|
||||||
|
self.switchThemeButton.addTarget(self, action: #selector(self.switchThemePressed), forControlEvents: .touchUpInside)
|
||||||
|
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
||||||
|
self.doneButton.pressed = { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.doneButton.isUserInteractionEnabled = false
|
||||||
|
strongSelf.completion?(strongSelf.selectedEmoticon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.disposable.set(combineLatest(queue: Queue.mainQueue(), self.context.engine.themes.getChatThemes(accountManager: self.context.sharedContext.accountManager), self.selectedEmoticonPromise.get(), self.isDarkAppearancePromise.get()).start(next: { [weak self] themes, selectedEmoticon, isDarkAppearance in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let presentationData = strongSelf.presentationData
|
||||||
|
|
||||||
|
var entries: [ThemeSettingsThemeEntry] = []
|
||||||
|
if strongSelf.initiallySelectedEmoticon != nil {
|
||||||
|
entries.append(ThemeSettingsThemeEntry(index: 0, emoticon: nil, themeReference: nil, selected: selectedEmoticon == nil, theme: presentationData.theme, wallpaper: nil))
|
||||||
|
}
|
||||||
|
for theme in themes {
|
||||||
|
entries.append(ThemeSettingsThemeEntry(index: entries.count, emoticon: theme.emoji, themeReference: .cloud(PresentationCloudTheme(theme: isDarkAppearance ? theme.darkTheme : theme.theme, resolvedWallpaper: nil, creatorAccountId: nil)), selected: selectedEmoticon == theme.emoji, theme: presentationData.theme, wallpaper: nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
let action: (String?) -> Void = { [weak self] emoticon in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.crossfade()
|
||||||
|
|
||||||
|
strongSelf.selectedEmoticon = emoticon
|
||||||
|
strongSelf.previewTheme?(emoticon)
|
||||||
|
let _ = ensureThemeVisible(listNode: strongSelf.listNode, emoticon: emoticon, animated: true)
|
||||||
|
|
||||||
|
strongSelf.doneButton.title = emoticon == nil ? strongSelf.presentationData.strings.Conversation_Theme_Reset : strongSelf.presentationData.strings.Conversation_Theme_Apply
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let previousEntries = strongSelf.entries ?? []
|
||||||
|
let crossfade = previousEntries.count != entries.count
|
||||||
|
let transition = preparedTransition(context: strongSelf.context, action: action, from: previousEntries, to: entries, crossfade: crossfade)
|
||||||
|
strongSelf.enqueueTransition(transition)
|
||||||
|
|
||||||
|
strongSelf.entries = entries
|
||||||
|
}))
|
||||||
|
|
||||||
|
self.switchThemeButton.highligthedChanged = { [weak self] highlighted in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if highlighted {
|
||||||
|
strongSelf.animationNode.layer.removeAnimation(forKey: "opacity")
|
||||||
|
strongSelf.animationNode.alpha = 0.4
|
||||||
|
} else {
|
||||||
|
strongSelf.animationNode.alpha = 1.0
|
||||||
|
strongSelf.animationNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func enqueueTransition(_ transition: ThemeSettingsThemeItemNodeTransition) {
|
||||||
|
self.enqueuedTransitions.append(transition)
|
||||||
|
|
||||||
|
while !self.enqueuedTransitions.isEmpty {
|
||||||
|
self.dequeueTransition()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func dequeueTransition() {
|
||||||
|
guard let transition = self.enqueuedTransitions.first else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.enqueuedTransitions.remove(at: 0)
|
||||||
|
|
||||||
|
var options = ListViewDeleteAndInsertOptions()
|
||||||
|
if self.initialized && transition.crossfade {
|
||||||
|
options.insert(.AnimateCrossfade)
|
||||||
|
}
|
||||||
|
options.insert(.Synchronous)
|
||||||
|
|
||||||
|
var scrollToItem: ListViewScrollToItem?
|
||||||
|
if !self.initialized {
|
||||||
|
if let index = transition.entries.firstIndex(where: { entry in
|
||||||
|
return entry.emoticon == self.initiallySelectedEmoticon
|
||||||
|
}) {
|
||||||
|
scrollToItem = ListViewScrollToItem(index: index, position: .bottom(-57.0), animated: false, curve: .Default(duration: 0.0), directionHint: .Down)
|
||||||
|
self.initialized = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.listNode.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, scrollToItem: scrollToItem, updateSizeAndInsets: nil, updateOpaqueState: nil, completion: { _ in
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func updatePresentationData(_ presentationData: PresentationData) {
|
||||||
|
let previousTheme = self.presentationData.theme
|
||||||
|
self.presentationData = presentationData
|
||||||
|
|
||||||
|
self.isDarkAppearancePromise.set(presentationData.theme.overallDarkAppearance)
|
||||||
|
|
||||||
|
if let effectView = self.effectNode.view as? UIVisualEffectView {
|
||||||
|
effectView.effect = UIBlurEffect(style: presentationData.theme.actionSheet.backgroundType == .light ? .light : .dark)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.contentBackgroundNode.backgroundColor = self.presentationData.theme.actionSheet.itemBackgroundColor
|
||||||
|
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
|
||||||
|
|
||||||
|
if previousTheme !== presentationData.theme, let (layout, navigationBarHeight) = self.containerLayout {
|
||||||
|
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal)
|
||||||
|
self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme))
|
||||||
|
}
|
||||||
|
|
||||||
|
override func didLoad() {
|
||||||
|
super.didLoad()
|
||||||
|
|
||||||
|
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
||||||
|
self.wrappingScrollNode.view.contentInsetAdjustmentBehavior = .never
|
||||||
|
}
|
||||||
|
|
||||||
|
self.listNode.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func cancelButtonPressed() {
|
||||||
|
self.cancel?()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func switchThemePressed() {
|
||||||
|
var colors: [String: UIColor] = [:]
|
||||||
|
let accentColor = self.presentationData.theme.actionSheet.controlAccentColor
|
||||||
|
colors["Sunny.Path 14.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 15.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Path.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 39.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 24.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 25.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 18.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 41.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Sunny.Path 43.Path.Stroke 1"] = accentColor
|
||||||
|
colors["Path 10.Path.Fill 1"] = accentColor
|
||||||
|
colors["Path 11.Path.Fill 1"] = accentColor
|
||||||
|
|
||||||
|
self.crossfade()
|
||||||
|
self.animationNode.setAnimation(name: self.presentationData.theme.overallDarkAppearance ? "anim_sun_reverse" : "anim_sun", colors: colors)
|
||||||
|
self.animationNode.playOnce()
|
||||||
|
self.previewDarkTheme?(!self.presentationData.theme.overallDarkAppearance)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||||
|
if self.dismissByTapOutside, case .ended = recognizer.state {
|
||||||
|
self.cancelButtonPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func crossfade() {
|
||||||
|
if let snapshotView = self.backgroundNode.view.snapshotView(afterScreenUpdates: false) {
|
||||||
|
snapshotView.frame = self.backgroundNode.frame
|
||||||
|
self.backgroundNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.backgroundNode.view)
|
||||||
|
|
||||||
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||||
|
snapshotView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if let snapshotView = self.contentContainerNode.view.snapshotView(afterScreenUpdates: false) {
|
||||||
|
snapshotView.frame = self.contentContainerNode.frame
|
||||||
|
self.contentContainerNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.contentContainerNode.view)
|
||||||
|
|
||||||
|
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||||
|
snapshotView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
self.listNode.forEachVisibleItemNode { node in
|
||||||
|
if let node = node as? ThemeSettingsThemeItemIconNode {
|
||||||
|
node.crossfade()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var animatedOut = false
|
||||||
|
func animateIn() {
|
||||||
|
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||||
|
|
||||||
|
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||||
|
let dimPosition = self.dimNode.layer.position
|
||||||
|
|
||||||
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)
|
||||||
|
let targetBounds = self.bounds
|
||||||
|
self.bounds = self.bounds.offsetBy(dx: 0.0, dy: -offset)
|
||||||
|
self.dimNode.position = CGPoint(x: dimPosition.x, y: dimPosition.y - offset)
|
||||||
|
transition.animateView({
|
||||||
|
self.bounds = targetBounds
|
||||||
|
self.dimNode.position = dimPosition
|
||||||
|
})
|
||||||
|
|
||||||
|
let frame = self.switchThemeButton.view.convert(self.switchThemeButton.bounds, to: self.view)
|
||||||
|
|
||||||
|
Queue.mainQueue().after(1.0) {
|
||||||
|
if !self.animatedOut {
|
||||||
|
self.present?(TooltipScreen(text: self.presentationData.theme.overallDarkAppearance ? self.presentationData.strings.Conversation_Theme_SwitchToLight : self.presentationData.strings.Conversation_Theme_SwitchToDark, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 3.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in
|
||||||
|
return .dismiss(consume: false)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateOut(completion: (() -> Void)? = nil) {
|
||||||
|
self.animatedOut = true
|
||||||
|
|
||||||
|
var dimCompleted = false
|
||||||
|
var offsetCompleted = false
|
||||||
|
|
||||||
|
let internalCompletion: () -> Void = { [weak self] in
|
||||||
|
if let strongSelf = self, dimCompleted && offsetCompleted {
|
||||||
|
strongSelf.dismiss?()
|
||||||
|
}
|
||||||
|
completion?()
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in
|
||||||
|
dimCompleted = true
|
||||||
|
internalCompletion()
|
||||||
|
})
|
||||||
|
|
||||||
|
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||||
|
let dimPosition = self.dimNode.layer.position
|
||||||
|
self.dimNode.layer.animatePosition(from: dimPosition, to: CGPoint(x: dimPosition.x, y: dimPosition.y - offset), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
|
self.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||||
|
offsetCompleted = true
|
||||||
|
internalCompletion()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||||
|
if self.bounds.contains(point) {
|
||||||
|
if !self.contentBackgroundNode.bounds.contains(self.convert(point, to: self.contentBackgroundNode)) {
|
||||||
|
return self.dimNode.view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.hitTest(point, with: event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
||||||
|
let contentOffset = scrollView.contentOffset
|
||||||
|
let additionalTopHeight = max(0.0, -contentOffset.y)
|
||||||
|
|
||||||
|
if additionalTopHeight >= 30.0 {
|
||||||
|
self.cancelButtonPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
self.containerLayout = (layout, navigationBarHeight)
|
||||||
|
|
||||||
|
var insets = layout.insets(options: [.statusBar, .input])
|
||||||
|
let cleanInsets = layout.insets(options: [.statusBar])
|
||||||
|
insets.top = max(10.0, insets.top)
|
||||||
|
|
||||||
|
let bottomInset: CGFloat = 10.0 + cleanInsets.bottom
|
||||||
|
let titleHeight: CGFloat = 54.0
|
||||||
|
let contentHeight = titleHeight + bottomInset + 188.0
|
||||||
|
|
||||||
|
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
|
||||||
|
|
||||||
|
let sideInset = floor((layout.size.width - width) / 2.0)
|
||||||
|
let contentContainerFrame = CGRect(origin: CGPoint(x: sideInset, y: layout.size.height - contentHeight), size: CGSize(width: width, height: contentHeight))
|
||||||
|
let contentFrame = contentContainerFrame
|
||||||
|
|
||||||
|
var backgroundFrame = CGRect(origin: CGPoint(x: contentFrame.minX, y: contentFrame.minY), size: CGSize(width: contentFrame.width, height: contentFrame.height + 2000.0))
|
||||||
|
if backgroundFrame.minY < contentFrame.minY {
|
||||||
|
backgroundFrame.origin.y = contentFrame.minY
|
||||||
|
}
|
||||||
|
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
|
||||||
|
transition.updateFrame(node: self.effectNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||||
|
transition.updateFrame(node: self.contentBackgroundNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||||
|
transition.updateFrame(node: self.wrappingScrollNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||||
|
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||||
|
|
||||||
|
let titleSize = self.titleNode.measure(CGSize(width: width, height: titleHeight))
|
||||||
|
let titleFrame = CGRect(origin: CGPoint(x: floor((contentFrame.width - titleSize.width) / 2.0), y: 18.0), size: titleSize)
|
||||||
|
transition.updateFrame(node: self.titleNode, frame: titleFrame)
|
||||||
|
|
||||||
|
let switchThemeSize = CGSize(width: 44.0, height: 44.0)
|
||||||
|
let switchThemeFrame = CGRect(origin: CGPoint(x: 3.0, y: 6.0), size: switchThemeSize)
|
||||||
|
transition.updateFrame(node: self.switchThemeButton, frame: switchThemeFrame)
|
||||||
|
transition.updateFrame(node: self.animationNode, frame: switchThemeFrame.insetBy(dx: 9.0, dy: 9.0))
|
||||||
|
|
||||||
|
let cancelSize = CGSize(width: 44.0, height: 44.0)
|
||||||
|
let cancelFrame = CGRect(origin: CGPoint(x: contentFrame.width - cancelSize.width - 3.0, y: 6.0), size: cancelSize)
|
||||||
|
transition.updateFrame(node: self.cancelButton, frame: cancelFrame)
|
||||||
|
|
||||||
|
let buttonInset: CGFloat = 16.0
|
||||||
|
let doneButtonHeight = self.doneButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
|
||||||
|
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 6.0, width: contentFrame.width, height: doneButtonHeight))
|
||||||
|
|
||||||
|
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame)
|
||||||
|
transition.updateFrame(node: self.topContentContainerNode, frame: contentContainerFrame)
|
||||||
|
|
||||||
|
var listInsets = UIEdgeInsets()
|
||||||
|
listInsets.top += layout.safeInsets.left + 12.0
|
||||||
|
listInsets.bottom += layout.safeInsets.right + 12.0
|
||||||
|
|
||||||
|
let contentSize = CGSize(width: contentFrame.width, height: 120.0)
|
||||||
|
|
||||||
|
self.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: contentSize.height, height: contentSize.width)
|
||||||
|
self.listNode.position = CGPoint(x: contentSize.width / 2.0, y: contentSize.height / 2.0 + titleHeight + 6.0)
|
||||||
|
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: CGSize(width: contentSize.height, height: contentSize.width), insets: listInsets, duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,9 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
if params.activateInput {
|
if params.activateInput {
|
||||||
controller.activateInput()
|
controller.activateInput()
|
||||||
}
|
}
|
||||||
|
if params.changeColors {
|
||||||
|
controller.presentThemeSelection()
|
||||||
|
}
|
||||||
if let botStart = params.botStart {
|
if let botStart = params.botStart {
|
||||||
controller.updateChatPresentationInterfaceState(interactive: false, { state -> ChatPresentationInterfaceState in
|
controller.updateChatPresentationInterfaceState(interactive: false, { state -> ChatPresentationInterfaceState in
|
||||||
return state.updatedBotStartPayload(botStart.payload)
|
return state.updatedBotStartPayload(botStart.payload)
|
||||||
@ -116,6 +119,9 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
if params.activateInput {
|
if params.activateInput {
|
||||||
controller.activateInput()
|
controller.activateInput()
|
||||||
}
|
}
|
||||||
|
if params.changeColors {
|
||||||
|
controller.presentThemeSelection()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params.navigationController.currentWindow?.forEachController { controller in
|
params.navigationController.currentWindow?.forEachController { controller in
|
||||||
|
@ -17,7 +17,7 @@ func openAddContactImpl(context: AccountContext, firstName: String = "", lastNam
|
|||||||
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: label, value: phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
|
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: label, value: phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
|
||||||
present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
|
present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
|
||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushController(infoController)
|
pushController(infoController)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,7 +192,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
|
|||||||
case .info:
|
case .info:
|
||||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
context.sharedContext.applicationBindings.dismissNativeController()
|
context.sharedContext.applicationBindings.dismissNativeController()
|
||||||
navigationController?.pushViewController(infoController)
|
navigationController?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
|
|||||||
return transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt32Value(idValue)))
|
return transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt32Value(idValue)))
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
if let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
navigationController?.pushViewController(controller)
|
navigationController?.pushViewController(controller)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -186,7 +186,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
self.isGlobalSearch = false
|
self.isGlobalSearch = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self.historyNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, source: source, subject: .message(id: initialMessageId, highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch))
|
self.historyNode = ChatHistoryListNode(context: context, updatedPresentationData: (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, source: source, subject: .message(id: initialMessageId, highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch))
|
||||||
self.historyNode.clipsToBounds = true
|
self.historyNode.clipsToBounds = true
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -528,7 +528,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||||
let historyNode = ChatHistoryListNode(context: self.context, chatLocation: .peer(self.peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: .message(id: messageId, highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch))
|
let historyNode = ChatHistoryListNode(context: self.context, updatedPresentationData: (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData), chatLocation: .peer(self.peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: .message(id: messageId, highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch))
|
||||||
historyNode.clipsToBounds = true
|
historyNode.clipsToBounds = true
|
||||||
historyNode.preloadPages = true
|
historyNode.preloadPages = true
|
||||||
historyNode.stackFromBottom = true
|
historyNode.stackFromBottom = true
|
||||||
|
@ -59,7 +59,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
|||||||
self.selectedMessagesPromise.set(.single(self.selectedMessages))
|
self.selectedMessagesPromise.set(.single(self.selectedMessages))
|
||||||
|
|
||||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||||
self.listNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: nil, controllerInteraction: chatControllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(search: false, reversed: false, displayHeaders: .allButLast, hintLinks: tagMask == .webPage, isGlobalSearch: false))
|
self.listNode = ChatHistoryListNode(context: context, updatedPresentationData: (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: nil, controllerInteraction: chatControllerInteraction, selectedMessages: self.selectedMessagesPromise.get(), mode: .list(search: false, reversed: false, displayHeaders: .allButLast, hintLinks: tagMask == .webPage, isGlobalSearch: false))
|
||||||
self.listNode.clipsToBounds = true
|
self.listNode.clipsToBounds = true
|
||||||
self.listNode.defaultToSynchronousTransactionWhileScrolling = true
|
self.listNode.defaultToSynchronousTransactionWhileScrolling = true
|
||||||
self.listNode.scroller.bounces = false
|
self.listNode.scroller.bounces = false
|
||||||
|
@ -348,7 +348,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
|||||||
let separatorNode: ASDisplayNode
|
let separatorNode: ASDisplayNode
|
||||||
let backgroundNode: NavigationBackgroundNode
|
let backgroundNode: NavigationBackgroundNode
|
||||||
|
|
||||||
init(context: AccountContext, peerId: PeerId, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, reportMessages: @escaping () -> Void) {
|
init(context: AccountContext, presentationData: PresentationData, peerId: PeerId, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, reportMessages: @escaping () -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.deleteMessages = deleteMessages
|
self.deleteMessages = deleteMessages
|
||||||
@ -356,7 +356,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
|||||||
self.forwardMessages = forwardMessages
|
self.forwardMessages = forwardMessages
|
||||||
self.reportMessages = reportMessages
|
self.reportMessages = reportMessages
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = presentationData
|
||||||
|
|
||||||
self.separatorNode = ASDisplayNode()
|
self.separatorNode = ASDisplayNode()
|
||||||
self.backgroundNode = NavigationBackgroundNode(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
self.backgroundNode = NavigationBackgroundNode(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||||
@ -1571,7 +1571,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.isOpenedFromChat = isOpenedFromChat
|
self.isOpenedFromChat = isOpenedFromChat
|
||||||
self.videoCallsEnabled = VideoCallsConfiguration(appConfiguration: context.currentAppConfiguration.with { $0 }).areVideoCallsEnabled
|
self.videoCallsEnabled = VideoCallsConfiguration(appConfiguration: context.currentAppConfiguration.with { $0 }).areVideoCallsEnabled
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = controller.presentationData
|
||||||
self.nearbyPeerDistance = nearbyPeerDistance
|
self.nearbyPeerDistance = nearbyPeerDistance
|
||||||
self.callMessages = callMessages
|
self.callMessages = callMessages
|
||||||
self.isSettings = isSettings
|
self.isSettings = isSettings
|
||||||
@ -3146,7 +3146,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil {
|
if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil {
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
strongSelf.controller?.push(infoController)
|
strongSelf.controller?.push(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3220,7 +3220,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||||
if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil {
|
if let strongSelf = self, peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil {
|
||||||
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = strongSelf.context.sharedContext.makePeerInfoController(context: strongSelf.context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
(strongSelf.controller?.navigationController as? NavigationController)?.pushViewController(infoController)
|
(strongSelf.controller?.navigationController as? NavigationController)?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3484,6 +3484,24 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
let headerButtons = Set(peerInfoHeaderButtons(peer: peer, cachedData: data.cachedData, isOpenedFromChat: self.isOpenedFromChat, isExpanded: self.headerNode.isAvatarExpanded, videoCallsEnabled: self.videoCallsEnabled, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false))
|
let headerButtons = Set(peerInfoHeaderButtons(peer: peer, cachedData: data.cachedData, isOpenedFromChat: self.isOpenedFromChat, isExpanded: self.headerNode.isAvatarExpanded, videoCallsEnabled: self.videoCallsEnabled, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false))
|
||||||
|
|
||||||
let filteredButtons = allHeaderButtons.subtracting(headerButtons)
|
let filteredButtons = allHeaderButtons.subtracting(headerButtons)
|
||||||
|
|
||||||
|
var canChangeColors = true
|
||||||
|
if let peer = peer as? TelegramChannel {
|
||||||
|
canChangeColors = peer.hasPermission(.changeInfo)
|
||||||
|
} else if let peer = peer as? TelegramGroup, case .member = peer.role {
|
||||||
|
canChangeColors = !peer.hasBannedPermission(.banChangeInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
if canChangeColors {
|
||||||
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ChangeColors, icon: { theme in
|
||||||
|
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor)
|
||||||
|
}, action: { [weak self] _, f in
|
||||||
|
f(.dismissWithoutContent)
|
||||||
|
|
||||||
|
self?.openChatForThemeChange()
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
if filteredButtons.contains(.addMember) {
|
if filteredButtons.contains(.addMember) {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.PeerInfo_ButtonAddMember, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.PeerInfo_ButtonAddMember, icon: { theme in
|
||||||
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor)
|
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor)
|
||||||
@ -3609,7 +3627,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.peerId.namespace == Namespaces.Peer.CloudUser && user.botInfo == nil && !user.flags.contains(.isSupport) {
|
if self.peerId.namespace == Namespaces.Peer.CloudUser && user.botInfo == nil && !user.flags.contains(.isSupport) {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_StartSecretChat, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_StartSecretChat, icon: { theme in
|
||||||
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor)
|
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor)
|
||||||
@ -3794,6 +3812,13 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func openChatForThemeChange() {
|
||||||
|
if let navigationController = (self.controller?.navigationController as? NavigationController) {
|
||||||
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(self.peerId), keepStack: .default, changeColors: true, completion: { _ in
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func openStartSecretChat() {
|
private func openStartSecretChat() {
|
||||||
let peerId = self.peerId
|
let peerId = self.peerId
|
||||||
let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, PeerId?) in
|
let _ = (self.context.account.postbox.transaction { transaction -> (Peer?, PeerId?) in
|
||||||
@ -4776,7 +4801,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
if isMember {
|
if isMember {
|
||||||
mode = .group(self.peerId)
|
mode = .group(self.peerId)
|
||||||
}
|
}
|
||||||
if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, peer: peer, mode: mode, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: nil, peer: peer, mode: mode, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
(self.controller?.navigationController as? NavigationController)?.pushViewController(infoController)
|
(self.controller?.navigationController as? NavigationController)?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5497,7 +5522,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func switchToAccount(id: AccountRecordId) {
|
fileprivate func switchToAccount(id: AccountRecordId) {
|
||||||
self.accountsAndPeers.set(.never())
|
self.accountsAndPeers.set(.never())
|
||||||
self.context.sharedContext.switchToAccount(id: id, fromSettingsController: nil, withChatListController: nil)
|
self.context.sharedContext.switchToAccount(id: id, fromSettingsController: nil, withChatListController: nil)
|
||||||
@ -6054,7 +6079,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
selectionPanelNode = current
|
selectionPanelNode = current
|
||||||
} else {
|
} else {
|
||||||
wasAdded = true
|
wasAdded = true
|
||||||
selectionPanelNode = PeerInfoSelectionPanelNode(context: self.context, peerId: self.peerId, deleteMessages: { [weak self] in
|
selectionPanelNode = PeerInfoSelectionPanelNode(context: self.context, presentationData: self.presentationData, peerId: self.peerId, deleteMessages: { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -6452,7 +6477,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
|
|||||||
private let isSettings: Bool
|
private let isSettings: Bool
|
||||||
private let ignoreGroupInCommon: PeerId?
|
private let ignoreGroupInCommon: PeerId?
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
fileprivate var presentationData: PresentationData
|
||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
private let accountsAndPeers = Promise<((AccountContext, Peer)?, [(AccountContext, Peer, Int32)])>()
|
private let accountsAndPeers = Promise<((AccountContext, Peer)?, [(AccountContext, Peer, Int32)])>()
|
||||||
@ -6474,7 +6499,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
|
|||||||
|
|
||||||
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
||||||
|
|
||||||
public init(context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, callMessages: [Message], isSettings: Bool = false, ignoreGroupInCommon: PeerId? = nil) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, callMessages: [Message], isSettings: Bool = false, ignoreGroupInCommon: PeerId? = nil) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.avatarInitiallyExpanded = avatarInitiallyExpanded
|
self.avatarInitiallyExpanded = avatarInitiallyExpanded
|
||||||
@ -6484,7 +6509,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
|
|||||||
self.isSettings = isSettings
|
self.isSettings = isSettings
|
||||||
self.ignoreGroupInCommon = ignoreGroupInCommon
|
self.ignoreGroupInCommon = ignoreGroupInCommon
|
||||||
|
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = updatedPresentationData?.0 ?? context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData)
|
let baseNavigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData)
|
||||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(
|
super.init(navigationBarPresentationData: NavigationBarPresentationData(
|
||||||
@ -6707,7 +6732,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
|
|||||||
self?.controllerNode.scrollToTop()
|
self?.controllerNode.scrollToTop()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
self.presentationDataDisposable = ((updatedPresentationData?.signal ?? context.sharedContext.presentationData)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let previousTheme = strongSelf.presentationData.theme
|
let previousTheme = strongSelf.presentationData.theme
|
||||||
|
@ -349,7 +349,7 @@ public func pollResultsController(context: AccountContext, messageId: MessageId,
|
|||||||
})
|
})
|
||||||
}, openPeer: { peer in
|
}, openPeer: { peer in
|
||||||
if let peer = peer.peers[peer.peerId] {
|
if let peer = peer.peers[peer.peerId] {
|
||||||
if let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1103,8 +1103,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
handleTextLinkActionImpl(context: context, peerId: peerId, navigateDisposable: navigateDisposable, controller: controller, action: action, itemLink: itemLink)
|
handleTextLinkActionImpl(context: context, peerId: peerId, navigateDisposable: navigateDisposable, controller: controller, action: action, itemLink: itemLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makePeerInfoController(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool) -> ViewController? {
|
public func makePeerInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool) -> ViewController? {
|
||||||
let controller = peerInfoControllerImpl(context: context, peer: peer, mode: mode, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: fromChat)
|
let controller = peerInfoControllerImpl(context: context, updatedPresentationData: updatedPresentationData, peer: peer, mode: mode, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: fromChat)
|
||||||
controller?.navigationPresentation = .modalInLargeLayout
|
controller?.navigationPresentation = .modalInLargeLayout
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
@ -1419,11 +1419,11 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
|
|
||||||
private let defaultChatControllerInteraction = ChatControllerInteraction.default
|
private let defaultChatControllerInteraction = ChatControllerInteraction.default
|
||||||
|
|
||||||
private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool) -> ViewController? {
|
private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool) -> ViewController? {
|
||||||
if let _ = peer as? TelegramGroup {
|
if let _ = peer as? TelegramGroup {
|
||||||
return PeerInfoScreenImpl(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, callMessages: [])
|
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, callMessages: [])
|
||||||
} else if let _ = peer as? TelegramChannel {
|
} else if let _ = peer as? TelegramChannel {
|
||||||
return PeerInfoScreenImpl(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, callMessages: [])
|
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, callMessages: [])
|
||||||
} else if peer is TelegramUser {
|
} else if peer is TelegramUser {
|
||||||
var nearbyPeerDistance: Int32?
|
var nearbyPeerDistance: Int32?
|
||||||
var callMessages: [Message] = []
|
var callMessages: [Message] = []
|
||||||
@ -1438,9 +1438,9 @@ private func peerInfoControllerImpl(context: AccountContext, peer: Peer, mode: P
|
|||||||
case let .group(id):
|
case let .group(id):
|
||||||
ignoreGroupInCommon = id
|
ignoreGroupInCommon = id
|
||||||
}
|
}
|
||||||
return PeerInfoScreenImpl(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nearbyPeerDistance, callMessages: callMessages, ignoreGroupInCommon: ignoreGroupInCommon)
|
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nearbyPeerDistance, callMessages: callMessages, ignoreGroupInCommon: ignoreGroupInCommon)
|
||||||
} else if peer is TelegramSecretChat {
|
} else if peer is TelegramSecretChat {
|
||||||
return PeerInfoScreenImpl(context: context, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, callMessages: [])
|
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, callMessages: [])
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ public final class TelegramRootController: NavigationController {
|
|||||||
sharedContext.switchingData = (nil, nil, nil)
|
sharedContext.switchingData = (nil, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
let accountSettingsController = PeerInfoScreenImpl(context: self.context, peerId: self.context.account.peerId, avatarInitiallyExpanded: false, isOpenedFromChat: false, nearbyPeerDistance: nil, callMessages: [], isSettings: true)
|
let accountSettingsController = PeerInfoScreenImpl(context: self.context, updatedPresentationData: nil, peerId: self.context.account.peerId, avatarInitiallyExpanded: false, isOpenedFromChat: false, nearbyPeerDistance: nil, callMessages: [], isSettings: true)
|
||||||
accountSettingsController.tabBarItemDebugTapAction = { [weak self, weak accountSettingsController] in
|
accountSettingsController.tabBarItemDebugTapAction = { [weak self, weak accountSettingsController] in
|
||||||
guard let strongSelf = self, let accountSettingsController = accountSettingsController else {
|
guard let strongSelf = self, let accountSettingsController = accountSettingsController else {
|
||||||
return
|
return
|
||||||
|
@ -34,7 +34,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
|
|||||||
peerSignal = context.account.postbox.loadedPeerWithId(peerId) |> map(Optional.init)
|
peerSignal = context.account.postbox.loadedPeerWithId(peerId) |> map(Optional.init)
|
||||||
navigateDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).start(next: { peer in
|
navigateDisposable.set((peerSignal |> take(1) |> deliverOnMainQueue).start(next: { peer in
|
||||||
if let controller = controller, let peer = peer {
|
if let controller = controller, let peer = peer {
|
||||||
if let infoController = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) {
|
||||||
(controller.navigationController as? NavigationController)?.pushViewController(infoController)
|
(controller.navigationController as? NavigationController)?.pushViewController(infoController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,14 +53,17 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
|
|
||||||
private var isArrowInverted: Bool = false
|
private var isArrowInverted: Bool = false
|
||||||
|
|
||||||
|
private let inset: CGFloat
|
||||||
|
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
init(text: String, textEntities: [MessageTextEntity], style: TooltipScreen.Style, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: TooltipScreen.DisplayDuration, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?) {
|
init(text: String, textEntities: [MessageTextEntity], style: TooltipScreen.Style, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: TooltipScreen.DisplayDuration, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?) {
|
||||||
self.tooltipStyle = style
|
self.tooltipStyle = style
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.customContentNode = customContentNode
|
self.customContentNode = customContentNode
|
||||||
self.location = location
|
self.location = location
|
||||||
self.displayDuration = displayDuration
|
self.displayDuration = displayDuration
|
||||||
|
self.inset = inset
|
||||||
self.shouldDismissOnTouch = shouldDismissOnTouch
|
self.shouldDismissOnTouch = shouldDismissOnTouch
|
||||||
self.requestDismiss = requestDismiss
|
self.requestDismiss = requestDismiss
|
||||||
self.openActiveTextItem = openActiveTextItem
|
self.openActiveTextItem = openActiveTextItem
|
||||||
@ -295,7 +298,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
|
|
||||||
self.scrollingContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
self.scrollingContainer.frame = CGRect(origin: CGPoint(), size: layout.size)
|
||||||
|
|
||||||
let sideInset: CGFloat = 13.0 + layout.safeInsets.left
|
let sideInset: CGFloat = self.inset + layout.safeInsets.left
|
||||||
let bottomInset: CGFloat = 10.0
|
let bottomInset: CGFloat = 10.0
|
||||||
let contentInset: CGFloat = 11.0
|
let contentInset: CGFloat = 11.0
|
||||||
let contentVerticalInset: CGFloat = 11.0
|
let contentVerticalInset: CGFloat = 11.0
|
||||||
@ -563,6 +566,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
private let customContentNode: TooltipCustomContentNode?
|
private let customContentNode: TooltipCustomContentNode?
|
||||||
private let location: TooltipScreen.Location
|
private let location: TooltipScreen.Location
|
||||||
private let displayDuration: DisplayDuration
|
private let displayDuration: DisplayDuration
|
||||||
|
private let inset: CGFloat
|
||||||
private let shouldDismissOnTouch: (CGPoint) -> TooltipScreen.DismissOnTouch
|
private let shouldDismissOnTouch: (CGPoint) -> TooltipScreen.DismissOnTouch
|
||||||
private let openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?
|
private let openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?
|
||||||
|
|
||||||
@ -578,7 +582,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
|
|
||||||
private var dismissTimer: Foundation.Timer?
|
private var dismissTimer: Foundation.Timer?
|
||||||
|
|
||||||
public init(text: String, textEntities: [MessageTextEntity] = [], style: TooltipScreen.Style = .default, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)? = nil) {
|
public init(text: String, textEntities: [MessageTextEntity] = [], style: TooltipScreen.Style = .default, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)? = nil) {
|
||||||
self.text = text
|
self.text = text
|
||||||
self.textEntities = textEntities
|
self.textEntities = textEntities
|
||||||
self.style = style
|
self.style = style
|
||||||
@ -586,6 +590,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
self.customContentNode = customContentNode
|
self.customContentNode = customContentNode
|
||||||
self.location = location
|
self.location = location
|
||||||
self.displayDuration = displayDuration
|
self.displayDuration = displayDuration
|
||||||
|
self.inset = inset
|
||||||
self.shouldDismissOnTouch = shouldDismissOnTouch
|
self.shouldDismissOnTouch = shouldDismissOnTouch
|
||||||
self.openActiveTextItem = openActiveTextItem
|
self.openActiveTextItem = openActiveTextItem
|
||||||
|
|
||||||
@ -642,7 +647,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
override public func loadDisplayNode() {
|
||||||
self.displayNode = TooltipScreenNode(text: self.text, textEntities: self.textEntities, style: self.style, icon: self.icon, customContentNode: self.customContentNode, location: self.location, displayDuration: self.displayDuration, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
self.displayNode = TooltipScreenNode(text: self.text, textEntities: self.textEntities, style: self.style, icon: self.icon, customContentNode: self.customContentNode, location: self.location, displayDuration: self.displayDuration, inset: self.inset, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1291,7 +1291,7 @@ public func themeImage(account: Account, accountManager: AccountManager<Telegram
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func themeIconImage(account: Account, accountManager: AccountManager<TelegramAccountManagerTypes>, theme: PresentationThemeReference, color: PresentationThemeAccentColor?, wallpaper: TelegramWallpaper? = nil) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
public func themeIconImage(account: Account, accountManager: AccountManager<TelegramAccountManagerTypes>, theme: PresentationThemeReference, color: PresentationThemeAccentColor?, wallpaper: TelegramWallpaper? = nil, emoticon: Bool = false) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||||
let colorsSignal: Signal<((UIColor, UIColor?, [UInt32]), [UIColor], [UIColor], UIImage?, Int32?), NoError>
|
let colorsSignal: Signal<((UIColor, UIColor?, [UInt32]), [UIColor], [UIColor], UIImage?, Int32?), NoError>
|
||||||
|
|
||||||
var reference: MediaResourceReference?
|
var reference: MediaResourceReference?
|
||||||
@ -1468,21 +1468,71 @@ public func themeIconImage(account: Account, accountManager: AccountManager<Tele
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let incomingColors = colors.1
|
|
||||||
let incoming = generateGradientTintedImage(image: UIImage(bundleImageName: "Settings/ThemeBubble"), colors: incomingColors)
|
|
||||||
|
|
||||||
let outgoingColors = colors.2
|
|
||||||
let outgoing = generateGradientTintedImage(image: UIImage(bundleImageName: "Settings/ThemeBubble"), colors: outgoingColors)
|
|
||||||
|
|
||||||
c.translateBy(x: drawingRect.width / 2.0, y: drawingRect.height / 2.0)
|
c.translateBy(x: drawingRect.width / 2.0, y: drawingRect.height / 2.0)
|
||||||
c.scaleBy(x: 1.0, y: -1.0)
|
c.scaleBy(x: 1.0, y: -1.0)
|
||||||
c.translateBy(x: -drawingRect.width / 2.0, y: -drawingRect.height / 2.0)
|
c.translateBy(x: -drawingRect.width / 2.0, y: -drawingRect.height / 2.0)
|
||||||
c.draw(incoming!.cgImage!, in: CGRect(x: 9.0, y: 34.0, width: 57.0, height: 16.0))
|
|
||||||
|
let incomingColors = colors.1
|
||||||
|
if emoticon {
|
||||||
|
let rect = CGRect(x: 8.0, y: 44.0, width: 48.0, height: 24.0)
|
||||||
|
c.addPath(UIBezierPath(roundedRect: rect, cornerRadius: 12.0).cgPath)
|
||||||
|
c.clip()
|
||||||
|
|
||||||
|
if incomingColors.count >= 2 {
|
||||||
|
let gradientColors = incomingColors.map { $0.cgColor } as CFArray
|
||||||
|
|
||||||
|
var locations: [CGFloat] = []
|
||||||
|
for i in 0 ..< incomingColors.count {
|
||||||
|
let t = CGFloat(i) / CGFloat(incomingColors.count - 1)
|
||||||
|
locations.append(t)
|
||||||
|
}
|
||||||
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||||
|
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
||||||
|
|
||||||
|
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: rect.minY), end: CGPoint(x: 0.0, y: rect.maxY), options: CGGradientDrawingOptions())
|
||||||
|
} else if !incomingColors.isEmpty {
|
||||||
|
c.setFillColor(incomingColors[0].cgColor)
|
||||||
|
c.fill(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.resetClip()
|
||||||
|
} else {
|
||||||
|
let incoming = generateGradientTintedImage(image: UIImage(bundleImageName: "Settings/ThemeBubble"), colors: incomingColors)
|
||||||
|
c.draw(incoming!.cgImage!, in: CGRect(x: 9.0, y: 34.0, width: 57.0, height: 16.0))
|
||||||
|
}
|
||||||
|
|
||||||
c.translateBy(x: drawingRect.width / 2.0, y: drawingRect.height / 2.0)
|
c.translateBy(x: drawingRect.width / 2.0, y: drawingRect.height / 2.0)
|
||||||
c.scaleBy(x: -1.0, y: 1.0)
|
c.scaleBy(x: -1.0, y: 1.0)
|
||||||
c.translateBy(x: -drawingRect.width / 2.0, y: -drawingRect.height / 2.0)
|
c.translateBy(x: -drawingRect.width / 2.0, y: -drawingRect.height / 2.0)
|
||||||
c.draw(outgoing!.cgImage!, in: CGRect(x: 9.0, y: 12.0, width: 57.0, height: 16.0))
|
|
||||||
|
let outgoingColors = colors.2
|
||||||
|
if emoticon {
|
||||||
|
let rect = CGRect(x: 8.0, y: 72.0, width: 48.0, height: 24.0)
|
||||||
|
c.addPath(UIBezierPath(roundedRect: rect, cornerRadius: 12.0).cgPath)
|
||||||
|
c.clip()
|
||||||
|
|
||||||
|
if outgoingColors.count >= 2 {
|
||||||
|
let gradientColors = outgoingColors.map { $0.cgColor } as CFArray
|
||||||
|
|
||||||
|
var locations: [CGFloat] = []
|
||||||
|
for i in 0 ..< outgoingColors.count {
|
||||||
|
let t = CGFloat(i) / CGFloat(outgoingColors.count - 1)
|
||||||
|
locations.append(t)
|
||||||
|
}
|
||||||
|
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||||
|
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
|
||||||
|
|
||||||
|
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: rect.minY), end: CGPoint(x: 0.0, y: rect.maxY), options: CGGradientDrawingOptions())
|
||||||
|
} else if !outgoingColors.isEmpty {
|
||||||
|
c.setFillColor(outgoingColors[0].cgColor)
|
||||||
|
c.fill(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.resetClip()
|
||||||
|
} else {
|
||||||
|
let outgoing = generateGradientTintedImage(image: UIImage(bundleImageName: "Settings/ThemeBubble"), colors: outgoingColors)
|
||||||
|
c.draw(outgoing!.cgImage!, in: CGRect(x: 9.0, y: 12.0, width: 57.0, height: 16.0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
addCorners(context, arguments: arguments)
|
addCorners(context, arguments: arguments)
|
||||||
return context
|
return context
|
||||||
|
@ -269,7 +269,7 @@ public func widgetSetupScreen(context: AccountContext) -> ViewController {
|
|||||||
return transaction.getPeer(peerId)
|
return transaction.getPeer(peerId)
|
||||||
}
|
}
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
guard let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) else {
|
guard let peer = peer, let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user