mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Initial peer custom wallpapers implementation
This commit is contained in:
parent
c851ec3046
commit
330fcfa5cd
@ -9118,3 +9118,7 @@ Sorry for the inconvenience.";
|
|||||||
"Premium.MaxSharedFolderLinksFinalText" = "Sorry, you can only create **%1$@** invite links";
|
"Premium.MaxSharedFolderLinksFinalText" = "Sorry, you can only create **%1$@** invite links";
|
||||||
|
|
||||||
"Premium.GiftedTitle.Someone" = "Someone";
|
"Premium.GiftedTitle.Someone" = "Someone";
|
||||||
|
|
||||||
|
"Notification.ChangedWallpaper" = "%1$@ set a new background for this chat";
|
||||||
|
"Notification.YouChangedWallpaper" = "You set a new background for this chat";
|
||||||
|
"Notification.Wallpaper.View" = "View Background";
|
||||||
|
|||||||
@ -87,6 +87,10 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture
|
|||||||
|
|
||||||
self.pager.dismiss = { [weak self] in
|
self.pager.dismiss = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
if let galleryController = strongSelf.galleryController(), galleryController.navigationController != nil {
|
||||||
|
galleryController.dismiss(animated: true)
|
||||||
|
return
|
||||||
|
}
|
||||||
var interfaceAnimationCompleted = false
|
var interfaceAnimationCompleted = false
|
||||||
var contentAnimationCompleted = true
|
var contentAnimationCompleted = true
|
||||||
|
|
||||||
|
|||||||
@ -25,14 +25,16 @@ final class MediaPickerGridItem: GridItem {
|
|||||||
let content: MediaPickerGridItemContent
|
let content: MediaPickerGridItemContent
|
||||||
let interaction: MediaPickerInteraction
|
let interaction: MediaPickerInteraction
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
|
let selectable: Bool
|
||||||
let enableAnimations: Bool
|
let enableAnimations: Bool
|
||||||
|
|
||||||
let section: GridSection? = nil
|
let section: GridSection? = nil
|
||||||
|
|
||||||
init(content: MediaPickerGridItemContent, interaction: MediaPickerInteraction, theme: PresentationTheme, enableAnimations: Bool) {
|
init(content: MediaPickerGridItemContent, interaction: MediaPickerInteraction, theme: PresentationTheme, selectable: Bool, enableAnimations: Bool) {
|
||||||
self.content = content
|
self.content = content
|
||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.selectable = selectable
|
||||||
self.enableAnimations = enableAnimations
|
self.enableAnimations = enableAnimations
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,11 +42,11 @@ final class MediaPickerGridItem: GridItem {
|
|||||||
switch self.content {
|
switch self.content {
|
||||||
case let .asset(fetchResult, index):
|
case let .asset(fetchResult, index):
|
||||||
let node = MediaPickerGridItemNode()
|
let node = MediaPickerGridItemNode()
|
||||||
node.setup(interaction: self.interaction, fetchResult: fetchResult, index: index, theme: self.theme, enableAnimations: self.enableAnimations)
|
node.setup(interaction: self.interaction, fetchResult: fetchResult, index: index, theme: self.theme, selectable: self.selectable, enableAnimations: self.enableAnimations)
|
||||||
return node
|
return node
|
||||||
case let .media(media, index):
|
case let .media(media, index):
|
||||||
let node = MediaPickerGridItemNode()
|
let node = MediaPickerGridItemNode()
|
||||||
node.setup(interaction: self.interaction, media: media, index: index, theme: self.theme, enableAnimations: self.enableAnimations)
|
node.setup(interaction: self.interaction, media: media, index: index, theme: self.theme, selectable: self.selectable, enableAnimations: self.enableAnimations)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,13 +58,13 @@ final class MediaPickerGridItem: GridItem {
|
|||||||
assertionFailure()
|
assertionFailure()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
node.setup(interaction: self.interaction, fetchResult: fetchResult, index: index, theme: self.theme, enableAnimations: self.enableAnimations)
|
node.setup(interaction: self.interaction, fetchResult: fetchResult, index: index, theme: self.theme, selectable: self.selectable, enableAnimations: self.enableAnimations)
|
||||||
case let .media(media, index):
|
case let .media(media, index):
|
||||||
guard let node = node as? MediaPickerGridItemNode else {
|
guard let node = node as? MediaPickerGridItemNode else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
node.setup(interaction: self.interaction, media: media, index: index, theme: self.theme, enableAnimations: self.enableAnimations)
|
node.setup(interaction: self.interaction, media: media, index: index, theme: self.theme, selectable: self.selectable, enableAnimations: self.enableAnimations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,6 +86,7 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||||||
var currentMediaState: (TGMediaSelectableItem, Int)?
|
var currentMediaState: (TGMediaSelectableItem, Int)?
|
||||||
var currentState: (PHFetchResult<PHAsset>, Int)?
|
var currentState: (PHFetchResult<PHAsset>, Int)?
|
||||||
var enableAnimations: Bool = true
|
var enableAnimations: Bool = true
|
||||||
|
private var selectable: Bool = false
|
||||||
|
|
||||||
private let imageNode: ImageNode
|
private let imageNode: ImageNode
|
||||||
private var checkNode: InteractiveCheckNode?
|
private var checkNode: InteractiveCheckNode?
|
||||||
@ -171,7 +174,7 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateSelectionState(animated: Bool = false) {
|
func updateSelectionState(animated: Bool = false) {
|
||||||
if self.checkNode == nil, let _ = self.interaction?.selectionState, let theme = self.theme {
|
if self.checkNode == nil, let _ = self.interaction?.selectionState, self.selectable, let theme = self.theme {
|
||||||
let checkNode = InteractiveCheckNode(theme: CheckNodeTheme(theme: theme, style: .overlay))
|
let checkNode = InteractiveCheckNode(theme: CheckNodeTheme(theme: theme, style: .overlay))
|
||||||
checkNode.valueChanged = { [weak self] value in
|
checkNode.valueChanged = { [weak self] value in
|
||||||
if let strongSelf = self, let interaction = strongSelf.interaction, let selectableItem = strongSelf.selectableItem {
|
if let strongSelf = self, let interaction = strongSelf.interaction, let selectableItem = strongSelf.selectableItem {
|
||||||
@ -223,9 +226,10 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||||||
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
|
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(interaction: MediaPickerInteraction, media: MediaPickerScreen.Subject.Media, index: Int, theme: PresentationTheme, enableAnimations: Bool) {
|
func setup(interaction: MediaPickerInteraction, media: MediaPickerScreen.Subject.Media, index: Int, theme: PresentationTheme, selectable: Bool, enableAnimations: Bool) {
|
||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.selectable = selectable
|
||||||
self.enableAnimations = enableAnimations
|
self.enableAnimations = enableAnimations
|
||||||
|
|
||||||
self.backgroundColor = theme.list.mediaPlaceholderColor
|
self.backgroundColor = theme.list.mediaPlaceholderColor
|
||||||
@ -239,9 +243,10 @@ final class MediaPickerGridItemNode: GridItemNode {
|
|||||||
self.updateHiddenMedia()
|
self.updateHiddenMedia()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(interaction: MediaPickerInteraction, fetchResult: PHFetchResult<PHAsset>, index: Int, theme: PresentationTheme, enableAnimations: Bool) {
|
func setup(interaction: MediaPickerInteraction, fetchResult: PHFetchResult<PHAsset>, index: Int, theme: PresentationTheme, selectable: Bool, enableAnimations: Bool) {
|
||||||
self.interaction = interaction
|
self.interaction = interaction
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.selectable = selectable
|
||||||
self.enableAnimations = enableAnimations
|
self.enableAnimations = enableAnimations
|
||||||
|
|
||||||
self.backgroundColor = theme.list.mediaPlaceholderColor
|
self.backgroundColor = theme.list.mediaPlaceholderColor
|
||||||
|
|||||||
@ -48,13 +48,14 @@ final class MediaPickerInteraction {
|
|||||||
private struct MediaPickerGridEntry: Comparable, Identifiable {
|
private struct MediaPickerGridEntry: Comparable, Identifiable {
|
||||||
let stableId: Int
|
let stableId: Int
|
||||||
let content: MediaPickerGridItemContent
|
let content: MediaPickerGridItemContent
|
||||||
|
let selectable: Bool
|
||||||
|
|
||||||
static func <(lhs: MediaPickerGridEntry, rhs: MediaPickerGridEntry) -> Bool {
|
static func <(lhs: MediaPickerGridEntry, rhs: MediaPickerGridEntry) -> Bool {
|
||||||
return lhs.stableId < rhs.stableId
|
return lhs.stableId < rhs.stableId
|
||||||
}
|
}
|
||||||
|
|
||||||
func item(context: AccountContext, interaction: MediaPickerInteraction, theme: PresentationTheme) -> MediaPickerGridItem {
|
func item(context: AccountContext, interaction: MediaPickerInteraction, theme: PresentationTheme) -> MediaPickerGridItem {
|
||||||
return MediaPickerGridItem(content: self.content, interaction: interaction, theme: theme, enableAnimations: context.sharedContext.energyUsageSettings.fullTranslucency)
|
return MediaPickerGridItem(content: self.content, interaction: interaction, theme: theme, selectable: self.selectable, enableAnimations: context.sharedContext.energyUsageSettings.fullTranslucency)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case assets(PHAssetCollection?)
|
case assets(PHAssetCollection?, Bool)
|
||||||
case media([Media])
|
case media([Media])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +158,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
public var presentWebSearch: (MediaGroupsScreen, Bool) -> Void = { _, _ in }
|
public var presentWebSearch: (MediaGroupsScreen, Bool) -> Void = { _, _ in }
|
||||||
public var getCaptionPanelView: () -> TGCaptionPanelView? = { return nil }
|
public var getCaptionPanelView: () -> TGCaptionPanelView? = { return nil }
|
||||||
|
|
||||||
|
public var customSelection: ((PHAsset) -> Void)? = nil
|
||||||
|
|
||||||
private var completed = false
|
private var completed = false
|
||||||
public var legacyCompletion: (_ signals: [Any], _ silently: Bool, _ scheduleTime: Int32?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void = { _, _, _, _, _ in }
|
public var legacyCompletion: (_ signals: [Any], _ silently: Bool, _ scheduleTime: Int32?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void = { _, _, _, _, _ in }
|
||||||
|
|
||||||
@ -250,7 +253,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
if case .assets(nil) = controller.subject {
|
if case .assets(nil, false) = controller.subject {
|
||||||
} else {
|
} else {
|
||||||
self.preloadPromise.set(false)
|
self.preloadPromise.set(false)
|
||||||
}
|
}
|
||||||
@ -263,7 +266,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
let preloadPromise = self.preloadPromise
|
let preloadPromise = self.preloadPromise
|
||||||
let updatedState: Signal<State, NoError>
|
let updatedState: Signal<State, NoError>
|
||||||
switch controller.subject {
|
switch controller.subject {
|
||||||
case let .assets(collection):
|
case let .assets(collection, _):
|
||||||
updatedState = combineLatest(mediaAssetsContext.mediaAccess(), mediaAssetsContext.cameraAccess())
|
updatedState = combineLatest(mediaAssetsContext.mediaAccess(), mediaAssetsContext.cameraAccess())
|
||||||
|> mapToSignal { mediaAccess, cameraAccess -> Signal<State, NoError> in
|
|> mapToSignal { mediaAccess, cameraAccess -> Signal<State, NoError> in
|
||||||
if case .notDetermined = mediaAccess {
|
if case .notDetermined = mediaAccess {
|
||||||
@ -400,7 +403,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.gridNode.view.addGestureRecognizer(selectionGesture)
|
self.gridNode.view.addGestureRecognizer(selectionGesture)
|
||||||
self.selectionGesture = selectionGesture
|
self.selectionGesture = selectionGesture
|
||||||
|
|
||||||
if let controller = self.controller, case let .assets(collection) = controller.subject, collection != nil {
|
if let controller = self.controller, case let .assets(collection, _) = controller.subject, collection != nil {
|
||||||
self.gridNode.view.interactiveTransitionGestureRecognizerTest = { point -> Bool in
|
self.gridNode.view.interactiveTransitionGestureRecognizerTest = { point -> Bool in
|
||||||
return point.x > 44.0
|
return point.x > 44.0
|
||||||
}
|
}
|
||||||
@ -451,7 +454,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if let controller = self.controller, case .assets(nil) = controller.subject {
|
if let controller = self.controller, case .assets(nil, false) = controller.subject {
|
||||||
let enableAnimations = self.controller?.context.sharedContext.energyUsageSettings.fullTranslucency ?? true
|
let enableAnimations = self.controller?.context.sharedContext.energyUsageSettings.fullTranslucency ?? true
|
||||||
|
|
||||||
let cameraView = TGAttachmentCameraView(forSelfPortrait: false, videoModeByDefault: controller.bannedSendPhotos != nil && controller.bannedSendVideos == nil)!
|
let cameraView = TGAttachmentCameraView(forSelfPortrait: false, videoModeByDefault: controller.bannedSendPhotos != nil && controller.bannedSendVideos == nil)!
|
||||||
@ -552,6 +555,11 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
var updateLayout = false
|
var updateLayout = false
|
||||||
|
|
||||||
|
var selectable = true
|
||||||
|
if case let .assets(_, isStandalone) = controller.subject, isStandalone {
|
||||||
|
selectable = false
|
||||||
|
}
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case let .noAccess(cameraAccess):
|
case let .noAccess(cameraAccess):
|
||||||
if case .assets = previousState {
|
if case .assets = previousState {
|
||||||
@ -570,12 +578,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
for i in 0 ..< count {
|
for i in 0 ..< count {
|
||||||
let index: Int
|
let index: Int
|
||||||
if case let .assets(collection) = controller.subject, let _ = collection {
|
if case let .assets(collection, _) = controller.subject, let _ = collection {
|
||||||
index = i
|
index = i
|
||||||
} else {
|
} else {
|
||||||
index = totalCount - i - 1
|
index = totalCount - i - 1
|
||||||
}
|
}
|
||||||
entries.append(MediaPickerGridEntry(stableId: stableId, content: .asset(fetchResult, index)))
|
entries.append(MediaPickerGridEntry(stableId: stableId, content: .asset(fetchResult, index), selectable: selectable))
|
||||||
stableId += 1
|
stableId += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +602,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
case let .media(media):
|
case let .media(media):
|
||||||
let count = media.count
|
let count = media.count
|
||||||
for i in 0 ..< count {
|
for i in 0 ..< count {
|
||||||
entries.append(MediaPickerGridEntry(stableId: stableId, content: .media(media[i], i)))
|
entries.append(MediaPickerGridEntry(stableId: stableId, content: .media(media[i], i), selectable: true))
|
||||||
stableId += 1
|
stableId += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -603,7 +611,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.currentEntries = entries
|
self.currentEntries = entries
|
||||||
|
|
||||||
var scrollToItem: GridNodeScrollToItem?
|
var scrollToItem: GridNodeScrollToItem?
|
||||||
if case let .assets(collection) = controller.subject, let _ = collection, previousEntries.isEmpty && !entries.isEmpty {
|
if case let .assets(collection, _) = controller.subject, let _ = collection, previousEntries.isEmpty && !entries.isEmpty {
|
||||||
scrollToItem = GridNodeScrollToItem(index: entries.count - 1, position: .bottom(0.0), transition: .immediate, directionHint: .down, adjustForSection: false)
|
scrollToItem = GridNodeScrollToItem(index: entries.count - 1, position: .bottom(0.0), transition: .immediate, directionHint: .down, adjustForSection: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,6 +731,19 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.dismissInput()
|
self.dismissInput()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let customSelection = controller.customSelection {
|
||||||
|
customSelection(fetchResult[index])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let reversed: Bool
|
||||||
|
if case .assets(nil, _) = controller.subject {
|
||||||
|
reversed = true
|
||||||
|
} else {
|
||||||
|
reversed = false
|
||||||
|
}
|
||||||
|
let index = reversed ? fetchResult.count - index - 1 : index
|
||||||
|
|
||||||
var hasTimer = false
|
var hasTimer = false
|
||||||
if controller.chatLocation?.peerId != controller.context.account.peerId && controller.chatLocation?.peerId?.namespace == Namespaces.Peer.CloudUser {
|
if controller.chatLocation?.peerId != controller.context.account.peerId && controller.chatLocation?.peerId?.namespace == Namespaces.Peer.CloudUser {
|
||||||
hasTimer = true
|
hasTimer = true
|
||||||
@ -732,13 +753,6 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
self.openingMedia = true
|
self.openingMedia = true
|
||||||
|
|
||||||
let reversed: Bool
|
|
||||||
if case .assets(nil) = controller.subject {
|
|
||||||
reversed = true
|
|
||||||
} else {
|
|
||||||
reversed = false
|
|
||||||
}
|
|
||||||
let index = reversed ? fetchResult.count - index - 1 : index
|
|
||||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||||
self?.hiddenMediaId.set(.single(id))
|
self?.hiddenMediaId.set(.single(id))
|
||||||
}, initialLayout: layout, transitionHostView: { [weak self] in
|
}, initialLayout: layout, transitionHostView: { [weak self] in
|
||||||
@ -1233,7 +1247,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
self.titleView = MediaPickerTitleView(theme: self.presentationData.theme, segments: [self.presentationData.strings.Attachment_AllMedia, self.presentationData.strings.Attachment_SelectedMedia(1)], selectedIndex: 0)
|
self.titleView = MediaPickerTitleView(theme: self.presentationData.theme, segments: [self.presentationData.strings.Attachment_AllMedia, self.presentationData.strings.Attachment_SelectedMedia(1)], selectedIndex: 0)
|
||||||
|
|
||||||
if case let .assets(collection) = subject, let collection = collection {
|
if case let .assets(collection, _) = subject, let collection = collection {
|
||||||
self.titleView.title = collection.localizedTitle ?? presentationData.strings.Attachment_Gallery
|
self.titleView.title = collection.localizedTitle ?? presentationData.strings.Attachment_Gallery
|
||||||
} else {
|
} else {
|
||||||
self.titleView.title = presentationData.strings.Attachment_Gallery
|
self.titleView.title = presentationData.strings.Attachment_Gallery
|
||||||
@ -1302,8 +1316,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
self.navigationItem.titleView = self.titleView
|
self.navigationItem.titleView = self.titleView
|
||||||
|
|
||||||
if case let .assets(collection) = self.subject, collection != nil {
|
if case let .assets(collection, isStandalone) = self.subject {
|
||||||
|
if !isStandalone {
|
||||||
|
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||||
|
} else if collection != nil {
|
||||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed))
|
self.navigationItem.leftBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||||
|
|
||||||
@ -1658,7 +1676,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.requestAttachmentMenuExpansion()
|
self.requestAttachmentMenuExpansion()
|
||||||
self.presentWebSearch(MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, openGroup: { [weak self] collection in
|
self.presentWebSearch(MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, openGroup: { [weak self] collection in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let mediaPicker = MediaPickerScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: strongSelf.peer, threadTitle: strongSelf.threadTitle, chatLocation: strongSelf.chatLocation, bannedSendPhotos: strongSelf.bannedSendPhotos, bannedSendVideos: strongSelf.bannedSendVideos, subject: .assets(collection), editingContext: strongSelf.interaction?.editingState, selectionContext: strongSelf.interaction?.selectionState)
|
let mediaPicker = MediaPickerScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: strongSelf.peer, threadTitle: strongSelf.threadTitle, chatLocation: strongSelf.chatLocation, bannedSendPhotos: strongSelf.bannedSendPhotos, bannedSendVideos: strongSelf.bannedSendVideos, subject: .assets(collection, false), editingContext: strongSelf.interaction?.editingState, selectionContext: strongSelf.interaction?.selectionState)
|
||||||
|
|
||||||
mediaPicker.presentSchedulePicker = strongSelf.presentSchedulePicker
|
mediaPicker.presentSchedulePicker = strongSelf.presentSchedulePicker
|
||||||
mediaPicker.presentTimerPicker = strongSelf.presentTimerPicker
|
mediaPicker.presentTimerPicker = strongSelf.presentTimerPicker
|
||||||
|
|||||||
@ -110,6 +110,8 @@ swift_library(
|
|||||||
"//submodules/AnimatedAvatarSetNode",
|
"//submodules/AnimatedAvatarSetNode",
|
||||||
"//submodules/TelegramUI/Components/StorageUsageScreen",
|
"//submodules/TelegramUI/Components/StorageUsageScreen",
|
||||||
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
||||||
|
"//submodules/MediaPickerUI:MediaPickerUI",
|
||||||
|
"//submodules/ImageBlur:ImageBlur",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import AccountContext
|
|||||||
import LegacyUI
|
import LegacyUI
|
||||||
import LegacyMediaPickerUI
|
import LegacyMediaPickerUI
|
||||||
import LocalMediaResources
|
import LocalMediaResources
|
||||||
|
import ImageBlur
|
||||||
|
|
||||||
func presentCustomWallpaperPicker(context: AccountContext, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void) {
|
func presentCustomWallpaperPicker(context: AccountContext, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void) {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
@ -194,3 +195,131 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE
|
|||||||
return croppedImage
|
return croppedImage
|
||||||
}).start()
|
}).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, peerId: PeerId, completion: @escaping () -> Void) {
|
||||||
|
let imageSignal: Signal<UIImage, NoError>
|
||||||
|
switch wallpaper {
|
||||||
|
case let .wallpaper(wallpaper, _):
|
||||||
|
switch wallpaper {
|
||||||
|
case let .file(file):
|
||||||
|
if let path = context.account.postbox.mediaBox.completedResourcePath(file.file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
||||||
|
context.sharedContext.accountManager.mediaBox.storeResourceData(file.file.resource.id, data: data)
|
||||||
|
let _ = context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start()
|
||||||
|
let _ = context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true).start()
|
||||||
|
}
|
||||||
|
case let .image(representations, _):
|
||||||
|
for representation in representations {
|
||||||
|
let resource = representation.resource
|
||||||
|
if let path = context.account.postbox.mediaBox.completedResourcePath(resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
||||||
|
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
|
let _ = context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
imageSignal = .complete()
|
||||||
|
completion()
|
||||||
|
case let .asset(asset):
|
||||||
|
imageSignal = fetchPhotoLibraryImage(localIdentifier: asset.localIdentifier, thumbnail: false)
|
||||||
|
|> filter { value in
|
||||||
|
return !(value?.1 ?? true)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<UIImage, NoError> in
|
||||||
|
if let result = result {
|
||||||
|
return .single(result.0)
|
||||||
|
} else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case let .contextResult(result):
|
||||||
|
var imageResource: TelegramMediaResource?
|
||||||
|
switch result {
|
||||||
|
case let .externalReference(externalReference):
|
||||||
|
if let content = externalReference.content {
|
||||||
|
imageResource = content.resource
|
||||||
|
}
|
||||||
|
case let .internalReference(internalReference):
|
||||||
|
if let image = internalReference.image {
|
||||||
|
if let imageRepresentation = imageRepresentationLargerThan(image.representations, size: PixelDimensions(width: 1000, height: 800)) {
|
||||||
|
imageResource = imageRepresentation.resource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let imageResource = imageResource {
|
||||||
|
imageSignal = .single(context.account.postbox.mediaBox.completedResourcePath(imageResource))
|
||||||
|
|> mapToSignal { path -> Signal<UIImage, NoError> in
|
||||||
|
if let path = path, let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedIfSafe]), let image = UIImage(data: data) {
|
||||||
|
return .single(image)
|
||||||
|
} else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
imageSignal = .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = (imageSignal
|
||||||
|
|> map { image -> UIImage in
|
||||||
|
var croppedImage = UIImage()
|
||||||
|
|
||||||
|
let finalCropRect: CGRect
|
||||||
|
if let cropRect = cropRect {
|
||||||
|
finalCropRect = cropRect
|
||||||
|
} else {
|
||||||
|
let screenSize = TGScreenSize()
|
||||||
|
let fittedSize = TGScaleToFit(screenSize, image.size)
|
||||||
|
finalCropRect = CGRect(x: (image.size.width - fittedSize.width) / 2.0, y: (image.size.height - fittedSize.height) / 2.0, width: fittedSize.width, height: fittedSize.height)
|
||||||
|
}
|
||||||
|
croppedImage = TGPhotoEditorCrop(image, nil, .up, 0.0, finalCropRect, false, CGSize(width: 1440.0, height: 2960.0), image.size, true)
|
||||||
|
|
||||||
|
if mode.contains(.blur) {
|
||||||
|
croppedImage = blurredImage(croppedImage, radius: 45.0)!
|
||||||
|
}
|
||||||
|
|
||||||
|
let thumbnailDimensions = finalCropRect.size.fitted(CGSize(width: 320.0, height: 320.0))
|
||||||
|
let thumbnailImage = generateScaledImage(image: croppedImage, size: thumbnailDimensions, scale: 1.0)
|
||||||
|
|
||||||
|
if let data = croppedImage.jpegData(compressionQuality: 0.8), let thumbnailImage = thumbnailImage, let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||||
|
let thumbnailResource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||||
|
context.sharedContext.accountManager.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData)
|
||||||
|
context.account.postbox.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData)
|
||||||
|
|
||||||
|
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||||
|
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
|
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||||
|
|
||||||
|
let settings = WallpaperSettings(blur: mode.contains(.blur), motion: mode.contains(.motion), colors: [], intensity: nil)
|
||||||
|
let temporaryWallpaper: TelegramWallpaper = .image([TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailDimensions), resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false), TelegramMediaImageRepresentation(dimensions: PixelDimensions(croppedImage.size), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)], settings)
|
||||||
|
|
||||||
|
let _ = context.account.postbox.transaction({ transaction in
|
||||||
|
transaction.updatePeerCachedData(peerIds: Set([peerId])) { _, cachedData in
|
||||||
|
if let cachedData = cachedData as? CachedUserData {
|
||||||
|
return cachedData.withUpdatedWallpaper(temporaryWallpaper)
|
||||||
|
} else {
|
||||||
|
return cachedData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start()
|
||||||
|
|
||||||
|
Queue.mainQueue().async {
|
||||||
|
completion()
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = uploadWallpaper(account: context.account, resource: resource, settings: WallpaperSettings(blur: false, motion: mode.contains(.motion), colors: [], intensity: nil)).start(next: { status in
|
||||||
|
if case let .complete(wallpaper) = status {
|
||||||
|
if case let .file(file) = wallpaper {
|
||||||
|
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: file.file.resource.id, synchronous: true)
|
||||||
|
for representation in file.file.previewRepresentations {
|
||||||
|
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: representation.resource.id, synchronous: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = context.engine.themes.setChatWallpaper(peerId: peerId, wallpaper: wallpaper).start()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return croppedImage
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
|
|||||||
@ -14,8 +14,23 @@ import ShareController
|
|||||||
import SearchUI
|
import SearchUI
|
||||||
import HexColor
|
import HexColor
|
||||||
import PresentationDataUtils
|
import PresentationDataUtils
|
||||||
|
import MediaPickerUI
|
||||||
|
|
||||||
public final class ThemeGridController: ViewController {
|
public final class ThemeGridController: ViewController {
|
||||||
|
public enum Mode: Equatable {
|
||||||
|
case `default`
|
||||||
|
case peer(EnginePeer.Id, TelegramWallpaper?)
|
||||||
|
|
||||||
|
var galleryMode: WallpaperGalleryController.Mode {
|
||||||
|
switch self {
|
||||||
|
case .default:
|
||||||
|
return .default
|
||||||
|
case let .peer(peerId, _):
|
||||||
|
return .peer(peerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var controllerNode: ThemeGridControllerNode {
|
private var controllerNode: ThemeGridControllerNode {
|
||||||
return self.displayNode as! ThemeGridControllerNode
|
return self.displayNode as! ThemeGridControllerNode
|
||||||
}
|
}
|
||||||
@ -26,6 +41,7 @@ public final class ThemeGridController: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
private let mode: Mode
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private let presentationDataPromise = Promise<PresentationData>()
|
private let presentationDataPromise = Promise<PresentationData>()
|
||||||
@ -44,8 +60,9 @@ public final class ThemeGridController: ViewController {
|
|||||||
|
|
||||||
private var previousContentOffset: GridNodeVisibleContentOffset?
|
private var previousContentOffset: GridNodeVisibleContentOffset?
|
||||||
|
|
||||||
public init(context: AccountContext) {
|
public init(context: AccountContext, mode: Mode = .default) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.mode = mode
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
self.presentationDataPromise.set(.single(self.presentationData))
|
self.presentationDataPromise.set(.single(self.presentationData))
|
||||||
|
|
||||||
@ -116,12 +133,25 @@ public final class ThemeGridController: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override func loadDisplayNode() {
|
public override func loadDisplayNode() {
|
||||||
self.displayNode = ThemeGridControllerNode(context: self.context, presentationData: self.presentationData, presentPreviewController: { [weak self] source in
|
let dismissControllers = { [weak self] in
|
||||||
|
if let self, let navigationController = self.navigationController as? NavigationController {
|
||||||
|
let controllers = navigationController.viewControllers.filter({ controller in
|
||||||
|
if controller is ThemeGridController || controller is WallpaperGalleryController || controller is MediaPickerScreen {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.displayNode = ThemeGridControllerNode(context: self.context, presentationData: self.presentationData, mode: self.mode, presentPreviewController: { [weak self] source in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: source)
|
let controller = WallpaperGalleryController(context: strongSelf.context, source: source, mode: strongSelf.mode.galleryMode)
|
||||||
controller.apply = { [weak self, weak controller] wallpaper, mode, cropRect in
|
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self, case let .wallpaper(wallpaperValue, _) = wallpaper {
|
||||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: mode, cropRect: cropRect, completion: { [weak self, weak controller] in
|
switch strongSelf.mode {
|
||||||
|
case .default:
|
||||||
|
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak self, weak controller] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.deactivateSearch(animated: false)
|
strongSelf.deactivateSearch(animated: false)
|
||||||
strongSelf.controllerNode.scrollToTop(animated: false)
|
strongSelf.controllerNode.scrollToTop(animated: false)
|
||||||
@ -129,70 +159,55 @@ public final class ThemeGridController: ViewController {
|
|||||||
if let controller = controller {
|
if let controller = controller {
|
||||||
switch wallpaper {
|
switch wallpaper {
|
||||||
case .asset, .contextResult:
|
case .asset, .contextResult:
|
||||||
controller.dismiss(forceAway: true)
|
controller.dismiss(animated: true)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
case let .peer(peerId, _):
|
||||||
|
let _ = (strongSelf.context.engine.themes.setChatWallpaper(peerId: peerId, wallpaper: wallpaperValue)
|
||||||
|
|> deliverOnMainQueue).start(completed: {
|
||||||
|
dismissControllers()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self?.push(controller)
|
self?.push(controller)
|
||||||
}
|
}
|
||||||
}, presentGallery: { [weak self] in
|
}, presentGallery: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
presentCustomWallpaperPicker(context: strongSelf.context, present: { [weak self] controller in
|
let controller = MediaPickerScreen(context: strongSelf.context, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, true))
|
||||||
self?.present(controller, in: .window(.root), with: nil, blockInteraction: true)
|
controller.customSelection = { [weak self] asset in
|
||||||
}, push: { [weak self] controller in
|
guard let strongSelf = self else {
|
||||||
self?.push(controller)
|
return
|
||||||
|
}
|
||||||
|
let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: strongSelf.mode.galleryMode)
|
||||||
|
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in
|
||||||
|
if let strongSelf = self, let controller = controller {
|
||||||
|
switch strongSelf.mode {
|
||||||
|
case .default:
|
||||||
|
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak controller] in
|
||||||
|
if let controller = controller {
|
||||||
|
controller.dismiss(forceAway: true)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
case let .peer(peerId, _):
|
||||||
|
uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, peerId: peerId, completion: {
|
||||||
|
dismissControllers()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strongSelf.push(controller)
|
||||||
|
}
|
||||||
|
self?.push(controller)
|
||||||
}
|
}
|
||||||
}, presentColors: { [weak self] in
|
}, presentColors: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let controller = ThemeColorsGridController(context: strongSelf.context)
|
let controller = ThemeColorsGridController(context: strongSelf.context)
|
||||||
(strongSelf.navigationController as? NavigationController)?.pushViewController(controller)
|
(strongSelf.navigationController as? NavigationController)?.pushViewController(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if let strongSelf = self {
|
|
||||||
let _ = (strongSelf.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings])
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] sharedData in
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings) ?? PresentationThemeSettings.defaultSettings
|
|
||||||
|
|
||||||
let autoNightModeTriggered = strongSelf.presentationData.autoNightModeTriggered
|
|
||||||
let themeReference: PresentationThemeReference
|
|
||||||
if autoNightModeTriggered {
|
|
||||||
themeReference = settings.automaticThemeSwitchSetting.theme
|
|
||||||
} else {
|
|
||||||
themeReference = settings.theme
|
|
||||||
}
|
|
||||||
|
|
||||||
let controller = ThemeAccentColorController(context: strongSelf.context, mode: .background(themeReference: themeReference))
|
|
||||||
controller.completion = { [weak self] in
|
|
||||||
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
|
||||||
var controllers = navigationController.viewControllers
|
|
||||||
controllers = controllers.filter { controller in
|
|
||||||
if controller is ThemeColorsGridController {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
navigationController.setViewControllers(controllers, animated: false)
|
|
||||||
controllers = controllers.filter { controller in
|
|
||||||
if controller is ThemeAccentColorController {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
strongSelf.push(controller)
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
}, emptyStateUpdated: { [weak self] empty in
|
}, emptyStateUpdated: { [weak self] empty in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if empty != strongSelf.isEmpty {
|
if empty != strongSelf.isEmpty {
|
||||||
|
|||||||
@ -141,6 +141,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
|
private let mode: ThemeGridController.Mode
|
||||||
private var controllerInteraction: ThemeGridControllerInteraction?
|
private var controllerInteraction: ThemeGridControllerInteraction?
|
||||||
|
|
||||||
private let presentPreviewController: (WallpaperListSource) -> Void
|
private let presentPreviewController: (WallpaperListSource) -> Void
|
||||||
@ -192,8 +193,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var disposable: Disposable?
|
private var disposable: Disposable?
|
||||||
|
|
||||||
init(context: AccountContext, presentationData: PresentationData, presentPreviewController: @escaping (WallpaperListSource) -> Void, presentGallery: @escaping () -> Void, presentColors: @escaping () -> Void, emptyStateUpdated: @escaping (Bool) -> Void, deleteWallpapers: @escaping ([TelegramWallpaper], @escaping () -> Void) -> Void, shareWallpapers: @escaping ([TelegramWallpaper]) -> Void, resetWallpapers: @escaping () -> Void, popViewController: @escaping () -> Void) {
|
init(context: AccountContext, presentationData: PresentationData, mode: ThemeGridController.Mode, presentPreviewController: @escaping (WallpaperListSource) -> Void, presentGallery: @escaping () -> Void, presentColors: @escaping () -> Void, emptyStateUpdated: @escaping (Bool) -> Void, deleteWallpapers: @escaping ([TelegramWallpaper], @escaping () -> Void) -> Void, shareWallpapers: @escaping ([TelegramWallpaper]) -> Void, resetWallpapers: @escaping () -> Void, popViewController: @escaping () -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.mode = mode
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.presentPreviewController = presentPreviewController
|
self.presentPreviewController = presentPreviewController
|
||||||
self.presentGallery = presentGallery
|
self.presentGallery = presentGallery
|
||||||
@ -338,12 +340,19 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
self.controllerInteraction = interaction
|
self.controllerInteraction = interaction
|
||||||
|
|
||||||
|
var selectFirst = true
|
||||||
|
if case .peer = self.mode {
|
||||||
|
selectFirst = false
|
||||||
|
}
|
||||||
|
|
||||||
let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperIdsPromise.get(), context.sharedContext.presentationData)
|
let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperIdsPromise.get(), context.sharedContext.presentationData)
|
||||||
|> map { wallpapers, deletedWallpaperIds, presentationData -> (ThemeGridEntryTransition, Bool) in
|
|> map { wallpapers, deletedWallpaperIds, presentationData -> (ThemeGridEntryTransition, Bool) in
|
||||||
var entries: [ThemeGridControllerEntry] = []
|
var entries: [ThemeGridControllerEntry] = []
|
||||||
var index = 1
|
var index = 1
|
||||||
|
|
||||||
|
if selectFirst {
|
||||||
entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: false, isSelected: true), at: 0)
|
entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: false, isSelected: true), at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
var defaultWallpaper: TelegramWallpaper?
|
var defaultWallpaper: TelegramWallpaper?
|
||||||
if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
||||||
|
|||||||
@ -165,12 +165,17 @@ private func updatedFileWallpaper(id: Int64? = nil, accessHash: Int64? = nil, sl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class WallpaperGalleryController: ViewController {
|
public class WallpaperGalleryController: ViewController {
|
||||||
|
public enum Mode {
|
||||||
|
case `default`
|
||||||
|
case peer(EnginePeer.Id)
|
||||||
|
}
|
||||||
private var galleryNode: GalleryControllerNode {
|
private var galleryNode: GalleryControllerNode {
|
||||||
return self.displayNode as! GalleryControllerNode
|
return self.displayNode as! GalleryControllerNode
|
||||||
}
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let source: WallpaperListSource
|
private let source: WallpaperListSource
|
||||||
|
private let mode: Mode
|
||||||
public var apply: ((WallpaperGalleryEntry, WallpaperPresentationOptions, CGRect?) -> Void)?
|
public var apply: ((WallpaperGalleryEntry, WallpaperPresentationOptions, CGRect?) -> Void)?
|
||||||
|
|
||||||
private let _ready = Promise<Bool>()
|
private let _ready = Promise<Bool>()
|
||||||
@ -211,9 +216,10 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
private var savedPatternWallpaper: TelegramWallpaper?
|
private var savedPatternWallpaper: TelegramWallpaper?
|
||||||
private var savedPatternIntensity: Int32?
|
private var savedPatternIntensity: Int32?
|
||||||
|
|
||||||
public init(context: AccountContext, source: WallpaperListSource) {
|
public init(context: AccountContext, source: WallpaperListSource, mode: Mode = .default) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.source = source
|
self.source = source
|
||||||
|
self.mode = mode
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
@ -378,6 +384,9 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
|
|
||||||
(self.displayNode as? WallpaperGalleryControllerNode)?.nativeStatusBar = self.statusBar
|
(self.displayNode as? WallpaperGalleryControllerNode)?.nativeStatusBar = self.statusBar
|
||||||
|
|
||||||
|
self.galleryNode.galleryController = { [weak self] in
|
||||||
|
return self
|
||||||
|
}
|
||||||
self.galleryNode.navigationBar = self.navigationBar
|
self.galleryNode.navigationBar = self.navigationBar
|
||||||
self.galleryNode.dismiss = { [weak self] in
|
self.galleryNode.dismiss = { [weak self] in
|
||||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||||
@ -423,6 +432,9 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if case .peer = self.mode {
|
||||||
|
doneButtonType = .setPeer
|
||||||
|
}
|
||||||
|
|
||||||
let toolbarNode = WallpaperGalleryToolbarNode(theme: presentationData.theme, strings: presentationData.strings, doneButtonType: doneButtonType)
|
let toolbarNode = WallpaperGalleryToolbarNode(theme: presentationData.theme, strings: presentationData.strings, doneButtonType: doneButtonType)
|
||||||
self.toolbarNode = toolbarNode
|
self.toolbarNode = toolbarNode
|
||||||
@ -439,6 +451,13 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
let options = centralItemNode.options
|
let options = centralItemNode.options
|
||||||
if !strongSelf.entries.isEmpty {
|
if !strongSelf.entries.isEmpty {
|
||||||
let entry = strongSelf.entries[centralItemNode.index]
|
let entry = strongSelf.entries[centralItemNode.index]
|
||||||
|
|
||||||
|
if case .peer = strongSelf.mode {
|
||||||
|
strongSelf.apply?(entry, options, centralItemNode.cropRect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .wallpaper(wallpaper, _):
|
case let .wallpaper(wallpaper, _):
|
||||||
var resource: MediaResource?
|
var resource: MediaResource?
|
||||||
@ -1044,15 +1063,3 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension GalleryControllerNode {
|
|
||||||
func modalAnimateIn(completion: (() -> Void)? = nil) {
|
|
||||||
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
|
||||||
}
|
|
||||||
|
|
||||||
func modalAnimateOut(completion: (() -> Void)? = nil) {
|
|
||||||
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
|
|
||||||
completion?()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -658,9 +658,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
strongSelf.colorsButtonNode.buttonColor = color
|
strongSelf.colorsButtonNode.buttonColor = color
|
||||||
|
|
||||||
if color == UIColor(rgb: 0x000000, alpha: 0.3) {
|
if color == UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||||
strongSelf.playButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45), transition: .immediate)
|
strongSelf.playButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
|
||||||
strongSelf.cancelButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45), transition: .immediate)
|
strongSelf.cancelButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
|
||||||
strongSelf.shareButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45), transition: .immediate)
|
strongSelf.shareButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.playButtonBackgroundNode.updateColor(color: color, transition: .immediate)
|
strongSelf.playButtonBackgroundNode.updateColor(color: color, transition: .immediate)
|
||||||
strongSelf.cancelButtonBackgroundNode.updateColor(color: color, transition: .immediate)
|
strongSelf.cancelButtonBackgroundNode.updateColor(color: color, transition: .immediate)
|
||||||
|
|||||||
@ -11,6 +11,7 @@ enum WallpaperGalleryToolbarCancelButtonType {
|
|||||||
|
|
||||||
enum WallpaperGalleryToolbarDoneButtonType {
|
enum WallpaperGalleryToolbarDoneButtonType {
|
||||||
case set
|
case set
|
||||||
|
case setPeer
|
||||||
case proceed
|
case proceed
|
||||||
case apply
|
case apply
|
||||||
case none
|
case none
|
||||||
@ -48,7 +49,7 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
|
|||||||
self.cancelButtonType = cancelButtonType
|
self.cancelButtonType = cancelButtonType
|
||||||
self.doneButtonType = doneButtonType
|
self.doneButtonType = doneButtonType
|
||||||
|
|
||||||
self.doneButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45))
|
self.doneButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55))
|
||||||
self.doneButtonBackgroundNode.cornerRadius = 14.0
|
self.doneButtonBackgroundNode.cornerRadius = 14.0
|
||||||
|
|
||||||
let blurEffect: UIBlurEffect
|
let blurEffect: UIBlurEffect
|
||||||
@ -152,6 +153,8 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
|
|||||||
switch self.doneButtonType {
|
switch self.doneButtonType {
|
||||||
case .set:
|
case .set:
|
||||||
doneTitle = strings.Wallpaper_ApplyForAll
|
doneTitle = strings.Wallpaper_ApplyForAll
|
||||||
|
case .setPeer:
|
||||||
|
doneTitle = strings.Wallpaper_ApplyForChat
|
||||||
case .proceed:
|
case .proceed:
|
||||||
doneTitle = strings.Theme_Colors_Proceed
|
doneTitle = strings.Theme_Colors_Proceed
|
||||||
case .apply:
|
case .apply:
|
||||||
|
|||||||
@ -141,7 +141,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
|||||||
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||||
didSet {
|
didSet {
|
||||||
if self.buttonColor == UIColor(rgb: 0x000000, alpha: 0.3) {
|
if self.buttonColor == UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||||
self.backgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45), transition: .immediate)
|
self.backgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
|
||||||
} else {
|
} else {
|
||||||
self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
|
self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -476,6 +476,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-648257196] = { return Api.MessageAction.parse_messageActionSecureValuesSent($0) }
|
dict[-648257196] = { return Api.MessageAction.parse_messageActionSecureValuesSent($0) }
|
||||||
dict[455635795] = { return Api.MessageAction.parse_messageActionSecureValuesSentMe($0) }
|
dict[455635795] = { return Api.MessageAction.parse_messageActionSecureValuesSentMe($0) }
|
||||||
dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
|
dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
|
||||||
|
dict[-1136350937] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
|
||||||
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
|
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
|
||||||
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
|
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
|
||||||
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
|
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
|
||||||
@ -913,7 +914,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
|
dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
|
||||||
dict[-1885878744] = { return Api.User.parse_user($0) }
|
dict[-1885878744] = { return Api.User.parse_user($0) }
|
||||||
dict[-742634630] = { return Api.User.parse_userEmpty($0) }
|
dict[-742634630] = { return Api.User.parse_userEmpty($0) }
|
||||||
dict[-120378643] = { return Api.UserFull.parse_userFull($0) }
|
dict[-1813324973] = { return Api.UserFull.parse_userFull($0) }
|
||||||
dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
||||||
dict[1326562017] = { return Api.UserProfilePhoto.parse_userProfilePhotoEmpty($0) }
|
dict[1326562017] = { return Api.UserProfilePhoto.parse_userProfilePhotoEmpty($0) }
|
||||||
dict[164646985] = { return Api.UserStatus.parse_userStatusEmpty($0) }
|
dict[164646985] = { return Api.UserStatus.parse_userStatusEmpty($0) }
|
||||||
|
|||||||
@ -261,6 +261,7 @@ public extension Api {
|
|||||||
case messageActionSecureValuesSent(types: [Api.SecureValueType])
|
case messageActionSecureValuesSent(types: [Api.SecureValueType])
|
||||||
case messageActionSecureValuesSentMe(values: [Api.SecureValue], credentials: Api.SecureCredentialsEncrypted)
|
case messageActionSecureValuesSentMe(values: [Api.SecureValue], credentials: Api.SecureCredentialsEncrypted)
|
||||||
case messageActionSetChatTheme(emoticon: String)
|
case messageActionSetChatTheme(emoticon: String)
|
||||||
|
case messageActionSetChatWallPaper(wallpaper: Api.WallPaper)
|
||||||
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
|
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
|
||||||
case messageActionSuggestProfilePhoto(photo: Api.Photo)
|
case messageActionSuggestProfilePhoto(photo: Api.Photo)
|
||||||
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
|
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
|
||||||
@ -506,6 +507,12 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||||
break
|
break
|
||||||
|
case .messageActionSetChatWallPaper(let wallpaper):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1136350937)
|
||||||
|
}
|
||||||
|
wallpaper.serialize(buffer, true)
|
||||||
|
break
|
||||||
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
|
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1007897979)
|
buffer.appendInt32(1007897979)
|
||||||
@ -619,6 +626,8 @@ public extension Api {
|
|||||||
return ("messageActionSecureValuesSentMe", [("values", values as Any), ("credentials", credentials as Any)])
|
return ("messageActionSecureValuesSentMe", [("values", values as Any), ("credentials", credentials as Any)])
|
||||||
case .messageActionSetChatTheme(let emoticon):
|
case .messageActionSetChatTheme(let emoticon):
|
||||||
return ("messageActionSetChatTheme", [("emoticon", emoticon as Any)])
|
return ("messageActionSetChatTheme", [("emoticon", emoticon as Any)])
|
||||||
|
case .messageActionSetChatWallPaper(let wallpaper):
|
||||||
|
return ("messageActionSetChatWallPaper", [("wallpaper", wallpaper as Any)])
|
||||||
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
|
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
|
||||||
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
|
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
|
||||||
case .messageActionSuggestProfilePhoto(let photo):
|
case .messageActionSuggestProfilePhoto(let photo):
|
||||||
@ -1043,6 +1052,19 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_messageActionSetChatWallPaper(_ reader: BufferReader) -> MessageAction? {
|
||||||
|
var _1: Api.WallPaper?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
_1 = Api.parse(reader, signature: signature) as? Api.WallPaper
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.MessageAction.messageActionSetChatWallPaper(wallpaper: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
public static func parse_messageActionSetMessagesTTL(_ reader: BufferReader) -> MessageAction? {
|
public static func parse_messageActionSetMessagesTTL(_ reader: BufferReader) -> MessageAction? {
|
||||||
var _1: Int32?
|
var _1: Int32?
|
||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
|
|||||||
@ -586,13 +586,13 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum UserFull: TypeConstructorDescription {
|
enum UserFull: TypeConstructorDescription {
|
||||||
case userFull(flags: Int32, id: Int64, about: String?, settings: Api.PeerSettings, personalPhoto: Api.Photo?, profilePhoto: Api.Photo?, fallbackPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?, privateForwardName: String?, botGroupAdminRights: Api.ChatAdminRights?, botBroadcastAdminRights: Api.ChatAdminRights?, premiumGifts: [Api.PremiumGiftOption]?)
|
case userFull(flags: Int32, id: Int64, about: String?, settings: Api.PeerSettings, personalPhoto: Api.Photo?, profilePhoto: Api.Photo?, fallbackPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?, privateForwardName: String?, botGroupAdminRights: Api.ChatAdminRights?, botBroadcastAdminRights: Api.ChatAdminRights?, premiumGifts: [Api.PremiumGiftOption]?, wallpaper: Api.WallPaper?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .userFull(let flags, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let premiumGifts):
|
case .userFull(let flags, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let premiumGifts, let wallpaper):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-120378643)
|
buffer.appendInt32(-1813324973)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt64(id, buffer: buffer, boxed: false)
|
serializeInt64(id, buffer: buffer, boxed: false)
|
||||||
@ -616,14 +616,15 @@ public extension Api {
|
|||||||
for item in premiumGifts! {
|
for item in premiumGifts! {
|
||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}}
|
}}
|
||||||
|
if Int(flags) & Int(1 << 24) != 0 {wallpaper!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .userFull(let flags, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let premiumGifts):
|
case .userFull(let flags, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let premiumGifts, let wallpaper):
|
||||||
return ("userFull", [("flags", flags as Any), ("id", id as Any), ("about", about as Any), ("settings", settings as Any), ("personalPhoto", personalPhoto as Any), ("profilePhoto", profilePhoto as Any), ("fallbackPhoto", fallbackPhoto as Any), ("notifySettings", notifySettings as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("commonChatsCount", commonChatsCount as Any), ("folderId", folderId as Any), ("ttlPeriod", ttlPeriod as Any), ("themeEmoticon", themeEmoticon as Any), ("privateForwardName", privateForwardName as Any), ("botGroupAdminRights", botGroupAdminRights as Any), ("botBroadcastAdminRights", botBroadcastAdminRights as Any), ("premiumGifts", premiumGifts as Any)])
|
return ("userFull", [("flags", flags as Any), ("id", id as Any), ("about", about as Any), ("settings", settings as Any), ("personalPhoto", personalPhoto as Any), ("profilePhoto", profilePhoto as Any), ("fallbackPhoto", fallbackPhoto as Any), ("notifySettings", notifySettings as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("commonChatsCount", commonChatsCount as Any), ("folderId", folderId as Any), ("ttlPeriod", ttlPeriod as Any), ("themeEmoticon", themeEmoticon as Any), ("privateForwardName", privateForwardName as Any), ("botGroupAdminRights", botGroupAdminRights as Any), ("botBroadcastAdminRights", botBroadcastAdminRights as Any), ("premiumGifts", premiumGifts as Any), ("wallpaper", wallpaper as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,6 +683,10 @@ public extension Api {
|
|||||||
if Int(_1!) & Int(1 << 19) != 0 {if let _ = reader.readInt32() {
|
if Int(_1!) & Int(1 << 19) != 0 {if let _ = reader.readInt32() {
|
||||||
_18 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PremiumGiftOption.self)
|
_18 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PremiumGiftOption.self)
|
||||||
} }
|
} }
|
||||||
|
var _19: Api.WallPaper?
|
||||||
|
if Int(_1!) & Int(1 << 24) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_19 = Api.parse(reader, signature: signature) as? Api.WallPaper
|
||||||
|
} }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||||
@ -700,8 +705,9 @@ public extension Api {
|
|||||||
let _c16 = (Int(_1!) & Int(1 << 17) == 0) || _16 != nil
|
let _c16 = (Int(_1!) & Int(1 << 17) == 0) || _16 != nil
|
||||||
let _c17 = (Int(_1!) & Int(1 << 18) == 0) || _17 != nil
|
let _c17 = (Int(_1!) & Int(1 << 18) == 0) || _17 != nil
|
||||||
let _c18 = (Int(_1!) & Int(1 << 19) == 0) || _18 != nil
|
let _c18 = (Int(_1!) & Int(1 << 19) == 0) || _18 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 {
|
let _c19 = (Int(_1!) & Int(1 << 24) == 0) || _19 != nil
|
||||||
return Api.UserFull.userFull(flags: _1!, id: _2!, about: _3, settings: _4!, personalPhoto: _5, profilePhoto: _6, fallbackPhoto: _7, notifySettings: _8!, botInfo: _9, pinnedMsgId: _10, commonChatsCount: _11!, folderId: _12, ttlPeriod: _13, themeEmoticon: _14, privateForwardName: _15, botGroupAdminRights: _16, botBroadcastAdminRights: _17, premiumGifts: _18)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 {
|
||||||
|
return Api.UserFull.userFull(flags: _1!, id: _2!, about: _3, settings: _4!, personalPhoto: _5, profilePhoto: _6, fallbackPhoto: _7, notifySettings: _8!, botInfo: _9, pinnedMsgId: _10, commonChatsCount: _11!, folderId: _12, ttlPeriod: _13, themeEmoticon: _14, privateForwardName: _15, botGroupAdminRights: _16, botBroadcastAdminRights: _17, premiumGifts: _18, wallpaper: _19)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -3057,6 +3057,21 @@ public extension Api.functions.communities {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.communities {
|
||||||
|
static func getLeaveCommunitySuggestions(community: Api.InputCommunity) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.Peer]>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-296838430)
|
||||||
|
community.serialize(buffer, true)
|
||||||
|
return (FunctionDescription(name: "communities.getLeaveCommunitySuggestions", parameters: [("community", String(describing: community))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.Peer]? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: [Api.Peer]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
result = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.communities {
|
public extension Api.functions.communities {
|
||||||
static func hideCommunityUpdates(community: Api.InputCommunity) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
static func hideCommunityUpdates(community: Api.InputCommunity) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
@ -6865,6 +6880,23 @@ public extension Api.functions.messages {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.messages {
|
||||||
|
static func setChatWallPaper(peer: Api.InputPeer, wallpaper: Api.InputWallPaper, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1109557590)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
wallpaper.serialize(buffer, true)
|
||||||
|
settings.serialize(buffer, true)
|
||||||
|
return (FunctionDescription(name: "messages.setChatWallPaper", parameters: [("peer", String(describing: peer)), ("wallpaper", String(describing: wallpaper)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.Updates?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func setDefaultHistoryTTL(period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
static func setDefaultHistoryTTL(period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
|||||||
@ -205,7 +205,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto:
|
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper:
|
||||||
break
|
break
|
||||||
case let .messageActionChannelMigrateFrom(_, chatId):
|
case let .messageActionChannelMigrateFrom(_, chatId):
|
||||||
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))
|
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))
|
||||||
|
|||||||
@ -108,6 +108,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||||||
return TelegramMediaAction(action: .suggestedProfilePhoto(image: telegramMediaImageFromApiPhoto(photo)))
|
return TelegramMediaAction(action: .suggestedProfilePhoto(image: telegramMediaImageFromApiPhoto(photo)))
|
||||||
case let .messageActionRequestedPeer(buttonId, peer):
|
case let .messageActionRequestedPeer(buttonId, peer):
|
||||||
return TelegramMediaAction(action: .requestedPeer(buttonId: buttonId, peerId: peer.peerId))
|
return TelegramMediaAction(action: .requestedPeer(buttonId: buttonId, peerId: peer.peerId))
|
||||||
|
case let .messageActionSetChatWallPaper(wallpaper):
|
||||||
|
return TelegramMediaAction(action: .setChatWallpaper(wallpaper: TelegramWallpaper(apiWallpaper: wallpaper)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -95,7 +95,7 @@ extension TelegramWallpaper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiInputWallpaperAndSettings: (Api.InputWallPaper?, Api.WallPaperSettings)? {
|
var apiInputWallpaperAndSettings: (Api.InputWallPaper, Api.WallPaperSettings)? {
|
||||||
switch self {
|
switch self {
|
||||||
case .builtin:
|
case .builtin:
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -199,6 +199,7 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
public let fallbackPhoto: CachedPeerProfilePhoto
|
public let fallbackPhoto: CachedPeerProfilePhoto
|
||||||
public let premiumGiftOptions: [CachedPremiumGiftOption]
|
public let premiumGiftOptions: [CachedPremiumGiftOption]
|
||||||
public let voiceMessagesAvailable: Bool
|
public let voiceMessagesAvailable: Bool
|
||||||
|
public let wallpaper: TelegramWallpaper?
|
||||||
public let flags: CachedUserFlags
|
public let flags: CachedUserFlags
|
||||||
|
|
||||||
public let peerIds: Set<PeerId>
|
public let peerIds: Set<PeerId>
|
||||||
@ -224,12 +225,13 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
self.fallbackPhoto = .unknown
|
self.fallbackPhoto = .unknown
|
||||||
self.premiumGiftOptions = []
|
self.premiumGiftOptions = []
|
||||||
self.voiceMessagesAvailable = true
|
self.voiceMessagesAvailable = true
|
||||||
|
self.wallpaper = nil
|
||||||
self.flags = CachedUserFlags()
|
self.flags = CachedUserFlags()
|
||||||
self.peerIds = Set()
|
self.peerIds = Set()
|
||||||
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, themeEmoticon: String?, photo: CachedPeerProfilePhoto, personalPhoto: CachedPeerProfilePhoto, fallbackPhoto: CachedPeerProfilePhoto, premiumGiftOptions: [CachedPremiumGiftOption], voiceMessagesAvailable: Bool, flags: CachedUserFlags) {
|
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?, photo: CachedPeerProfilePhoto, personalPhoto: CachedPeerProfilePhoto, fallbackPhoto: CachedPeerProfilePhoto, premiumGiftOptions: [CachedPremiumGiftOption], voiceMessagesAvailable: Bool, wallpaper: TelegramWallpaper?, flags: CachedUserFlags) {
|
||||||
self.about = about
|
self.about = about
|
||||||
self.botInfo = botInfo
|
self.botInfo = botInfo
|
||||||
self.peerStatusSettings = peerStatusSettings
|
self.peerStatusSettings = peerStatusSettings
|
||||||
@ -248,6 +250,7 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
self.fallbackPhoto = fallbackPhoto
|
self.fallbackPhoto = fallbackPhoto
|
||||||
self.premiumGiftOptions = premiumGiftOptions
|
self.premiumGiftOptions = premiumGiftOptions
|
||||||
self.voiceMessagesAvailable = voiceMessagesAvailable
|
self.voiceMessagesAvailable = voiceMessagesAvailable
|
||||||
|
self.wallpaper = wallpaper
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
|
|
||||||
self.peerIds = Set<PeerId>()
|
self.peerIds = Set<PeerId>()
|
||||||
@ -290,6 +293,7 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
|
|
||||||
self.premiumGiftOptions = decoder.decodeObjectArrayWithDecoderForKey("pgo") as [CachedPremiumGiftOption]
|
self.premiumGiftOptions = decoder.decodeObjectArrayWithDecoderForKey("pgo") as [CachedPremiumGiftOption]
|
||||||
self.voiceMessagesAvailable = decoder.decodeInt32ForKey("vma", orElse: 0) != 0
|
self.voiceMessagesAvailable = decoder.decodeInt32ForKey("vma", orElse: 0) != 0
|
||||||
|
self.wallpaper = decoder.decode(TelegramWallpaperNativeCodable.self, forKey: "wp")?.value
|
||||||
self.flags = CachedUserFlags(rawValue: decoder.decodeInt32ForKey("fl", orElse: 0))
|
self.flags = CachedUserFlags(rawValue: decoder.decodeInt32ForKey("fl", orElse: 0))
|
||||||
|
|
||||||
self.peerIds = Set<PeerId>()
|
self.peerIds = Set<PeerId>()
|
||||||
@ -346,6 +350,13 @@ public final class CachedUserData: CachedPeerData {
|
|||||||
|
|
||||||
encoder.encodeObjectArray(self.premiumGiftOptions, forKey: "pgo")
|
encoder.encodeObjectArray(self.premiumGiftOptions, forKey: "pgo")
|
||||||
encoder.encodeInt32(self.voiceMessagesAvailable ? 1 : 0, forKey: "vma")
|
encoder.encodeInt32(self.voiceMessagesAvailable ? 1 : 0, forKey: "vma")
|
||||||
|
|
||||||
|
if let wallpaper = self.wallpaper {
|
||||||
|
encoder.encode(TelegramWallpaperNativeCodable(wallpaper), forKey: "wp")
|
||||||
|
} else {
|
||||||
|
encoder.encodeNil(forKey: "wp")
|
||||||
|
}
|
||||||
|
|
||||||
encoder.encodeInt32(self.flags.rawValue, forKey: "fl")
|
encoder.encodeInt32(self.flags.rawValue, forKey: "fl")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -361,82 +372,86 @@ 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 && self.themeEmoticon == other.themeEmoticon && self.photo == other.photo && self.personalPhoto == other.personalPhoto && self.fallbackPhoto == other.fallbackPhoto && self.premiumGiftOptions == other.premiumGiftOptions && self.voiceMessagesAvailable == other.voiceMessagesAvailable && self.flags == other.flags
|
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 && self.photo == other.photo && self.personalPhoto == other.personalPhoto && self.fallbackPhoto == other.fallbackPhoto && self.premiumGiftOptions == other.premiumGiftOptions && self.voiceMessagesAvailable == other.voiceMessagesAvailable && self.flags == other.flags && self.wallpaper == other.wallpaper
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
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, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedUserData {
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPhoto(_ photo: CachedPeerProfilePhoto) -> CachedUserData {
|
public func withUpdatedPhoto(_ photo: CachedPeerProfilePhoto) -> 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: self.themeEmoticon, photo: photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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: self.themeEmoticon, photo: photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPersonalPhoto(_ personalPhoto: CachedPeerProfilePhoto) -> CachedUserData {
|
public func withUpdatedPersonalPhoto(_ personalPhoto: CachedPeerProfilePhoto) -> 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: self.themeEmoticon, photo: self.photo, personalPhoto: personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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: self.themeEmoticon, photo: self.photo, personalPhoto: personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedFallbackPhoto(_ fallbackPhoto: CachedPeerProfilePhoto) -> CachedUserData {
|
public func withUpdatedFallbackPhoto(_ fallbackPhoto: CachedPeerProfilePhoto) -> 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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedPremiumGiftOptions(_ premiumGiftOptions: [CachedPremiumGiftOption]) -> CachedUserData {
|
public func withUpdatedPremiumGiftOptions(_ premiumGiftOptions: [CachedPremiumGiftOption]) -> 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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: self.flags)
|
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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedVoiceMessagesAvailable(_ voiceMessagesAvailable: Bool) -> CachedUserData {
|
public func withUpdatedVoiceMessagesAvailable(_ voiceMessagesAvailable: 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: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: voiceMessagesAvailable, flags: self.flags)
|
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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: voiceMessagesAvailable, wallpaper: self.wallpaper, flags: self.flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func withUpdatedWallpaper(_ wallpaper: TelegramWallpaper?) -> 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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: wallpaper, flags: self.flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedFlags(_ flags: CachedUserFlags) -> CachedUserData {
|
public func withUpdatedFlags(_ flags: CachedUserFlags) -> 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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: flags)
|
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: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -101,6 +101,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
case suggestedProfilePhoto(image: TelegramMediaImage?)
|
case suggestedProfilePhoto(image: TelegramMediaImage?)
|
||||||
case attachMenuBotAllowed
|
case attachMenuBotAllowed
|
||||||
case requestedPeer(buttonId: Int32, peerId: PeerId)
|
case requestedPeer(buttonId: Int32, peerId: PeerId)
|
||||||
|
case setChatWallpaper(wallpaper: TelegramWallpaper)
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||||
@ -181,6 +182,12 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
self = .attachMenuBotAllowed
|
self = .attachMenuBotAllowed
|
||||||
case 32:
|
case 32:
|
||||||
self = .requestedPeer(buttonId: decoder.decodeInt32ForKey("b", orElse: 0), peerId: PeerId(decoder.decodeInt64ForKey("pi", orElse: 0)))
|
self = .requestedPeer(buttonId: decoder.decodeInt32ForKey("b", orElse: 0), peerId: PeerId(decoder.decodeInt64ForKey("pi", orElse: 0)))
|
||||||
|
case 33:
|
||||||
|
if let wallpaper = decoder.decode(TelegramWallpaperNativeCodable.self, forKey: "wallpaper")?.value {
|
||||||
|
self = .setChatWallpaper(wallpaper: wallpaper)
|
||||||
|
} else {
|
||||||
|
self = .unknown
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
self = .unknown
|
self = .unknown
|
||||||
}
|
}
|
||||||
@ -342,6 +349,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
encoder.encodeInt32(32, forKey: "_rawValue")
|
encoder.encodeInt32(32, forKey: "_rawValue")
|
||||||
encoder.encodeInt32(buttonId, forKey: "b")
|
encoder.encodeInt32(buttonId, forKey: "b")
|
||||||
encoder.encodeInt64(peerId.toInt64(), forKey: "pi")
|
encoder.encodeInt64(peerId.toInt64(), forKey: "pi")
|
||||||
|
case let .setChatWallpaper(wallpaper):
|
||||||
|
encoder.encodeInt32(33, forKey: "_rawValue")
|
||||||
|
encoder.encode(TelegramWallpaperNativeCodable(wallpaper), forKey: "wallpaper")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -237,7 +237,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch fullUser {
|
switch fullUser {
|
||||||
case let .userFull(_, _, _, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _, _):
|
case let .userFull(_, _, _, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
updatePeers(transaction: transaction, peers: peers, update: { previous, updated -> Peer in
|
updatePeers(transaction: transaction, peers: peers, update: { previous, updated -> Peer in
|
||||||
if previous?.id == accountPeerId, let accountUser = accountUser, let user = TelegramUser.merge(previous as? TelegramUser, rhs: accountUser) {
|
if previous?.id == accountPeerId, let accountUser = accountUser, let user = TelegramUser.merge(previous as? TelegramUser, rhs: accountUser) {
|
||||||
return user
|
return user
|
||||||
@ -255,7 +255,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
previous = CachedUserData()
|
previous = CachedUserData()
|
||||||
}
|
}
|
||||||
switch fullUser {
|
switch fullUser {
|
||||||
case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, personalPhoto, profilePhoto, fallbackPhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions):
|
case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, personalPhoto, profilePhoto, fallbackPhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions, userWallpaper):
|
||||||
let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:))
|
let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:))
|
||||||
let isBlocked = (userFullFlags & (1 << 0)) != 0
|
let isBlocked = (userFullFlags & (1 << 0)) != 0
|
||||||
let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0
|
let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0
|
||||||
@ -290,6 +290,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
premiumGiftOptions = []
|
premiumGiftOptions = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let wallpaper = userWallpaper.flatMap { TelegramWallpaper(apiWallpaper: $0) }
|
||||||
|
|
||||||
return previous.withUpdatedAbout(userFullAbout)
|
return previous.withUpdatedAbout(userFullAbout)
|
||||||
.withUpdatedBotInfo(botInfo)
|
.withUpdatedBotInfo(botInfo)
|
||||||
.withUpdatedCommonGroupCount(userFullCommonChatsCount)
|
.withUpdatedCommonGroupCount(userFullCommonChatsCount)
|
||||||
@ -308,6 +310,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
.withUpdatedFallbackPhoto(.known(fallbackPhoto))
|
.withUpdatedFallbackPhoto(.known(fallbackPhoto))
|
||||||
.withUpdatedPremiumGiftOptions(premiumGiftOptions)
|
.withUpdatedPremiumGiftOptions(premiumGiftOptions)
|
||||||
.withUpdatedVoiceMessagesAvailable(voiceMessagesAvailable)
|
.withUpdatedVoiceMessagesAvailable(voiceMessagesAvailable)
|
||||||
|
.withUpdatedWallpaper(wallpaper)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,14 +78,14 @@ func _internal_getChatThemes(accountManager: AccountManager<TelegramAccountManag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_setChatTheme(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
func _internal_setChatTheme(account: Account, peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
||||||
return postbox.loadedPeerWithId(peerId)
|
return account.postbox.loadedPeerWithId(peerId)
|
||||||
|> mapToSignal { peer in
|
|> mapToSignal { peer in
|
||||||
guard let inputPeer = apiInputPeer(peer) else {
|
guard let inputPeer = apiInputPeer(peer) else {
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||||
if let current = current as? CachedUserData {
|
if let current = current as? CachedUserData {
|
||||||
return current.withUpdatedThemeEmoticon(emoticon)
|
return current.withUpdatedThemeEmoticon(emoticon)
|
||||||
@ -98,12 +98,12 @@ func _internal_setChatTheme(postbox: Postbox, network: Network, stateManager: Ac
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return network.request(Api.functions.messages.setChatTheme(peer: inputPeer, emoticon: emoticon ?? ""))
|
return account.network.request(Api.functions.messages.setChatTheme(peer: inputPeer, emoticon: emoticon ?? ""))
|
||||||
|> `catch` { error in
|
|> `catch` { error in
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|> mapToSignal { updates -> Signal<Void, NoError> in
|
|> mapToSignal { updates -> Signal<Void, NoError> in
|
||||||
stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
} |> switchToLatest
|
} |> switchToLatest
|
||||||
@ -117,3 +117,38 @@ func managedChatThemesUpdates(accountManager: AccountManager<TelegramAccountMana
|
|||||||
}
|
}
|
||||||
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_setChatWallpaper(account: Account, peerId: PeerId, wallpaper: TelegramWallpaper?) -> Signal<Void, NoError> {
|
||||||
|
return account.postbox.loadedPeerWithId(peerId)
|
||||||
|
|> mapToSignal { peer in
|
||||||
|
guard let inputPeer = apiInputPeer(peer) else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||||
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||||
|
if let current = current as? CachedUserData {
|
||||||
|
return current.withUpdatedWallpaper(wallpaper)
|
||||||
|
} else {
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var inputWallpaper: Api.InputWallPaper?
|
||||||
|
var inputSettings: Api.WallPaperSettings?
|
||||||
|
if let inputWallpaperAndInputSettings = wallpaper?.apiInputWallpaperAndSettings {
|
||||||
|
inputWallpaper = inputWallpaperAndInputSettings.0
|
||||||
|
inputSettings = inputWallpaperAndInputSettings.1
|
||||||
|
}
|
||||||
|
|
||||||
|
return account.network.request(Api.functions.messages.setChatWallPaper(peer: inputPeer, wallpaper: inputWallpaper ?? .inputWallPaperNoFile(id: 0), settings: inputSettings ?? apiWallpaperSettings(WallpaperSettings())))
|
||||||
|
|> `catch` { error in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|> mapToSignal { updates -> Signal<Void, NoError> in
|
||||||
|
account.stateManager.addUpdates(updates)
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
} |> switchToLatest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -9,16 +9,16 @@ public extension TelegramEngine {
|
|||||||
self.account = account
|
self.account = account
|
||||||
}
|
}
|
||||||
|
|
||||||
// public func getThemes(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<[TelegramTheme], NoError> {
|
|
||||||
// return _internal_getThemes(accountManager: accountManager, postbox: self.account.postbox, network: self.account.network)
|
|
||||||
// }
|
|
||||||
|
|
||||||
public func getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> {
|
public func getChatThemes(accountManager: AccountManager<TelegramAccountManagerTypes>, forceUpdate: Bool = false, onlyCached: Bool = false) -> Signal<[TelegramTheme], NoError> {
|
||||||
return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached)
|
return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setChatTheme(peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
public func setChatTheme(peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
||||||
return _internal_setChatTheme(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, emoticon: emoticon)
|
return _internal_setChatTheme(account: self.account, peerId: peerId, emoticon: emoticon)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func setChatWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?) -> Signal<Void, NoError> {
|
||||||
|
return _internal_setChatWallpaper(account: self.account, peerId: peerId, wallpaper: wallpaper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -873,6 +873,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
let botName = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""
|
let botName = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""
|
||||||
let peerName = message.peers[peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""
|
let peerName = message.peers[peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""
|
||||||
attributedString = addAttributesToStringWithRanges(strings.Notification_RequestedPeer(peerName, botName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, peerId), (1, message.id.peerId)]))
|
attributedString = addAttributesToStringWithRanges(strings.Notification_RequestedPeer(peerName, botName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, peerId), (1, message.id.peerId)]))
|
||||||
|
case .setChatWallpaper:
|
||||||
|
if message.author?.id == accountPeerId {
|
||||||
|
attributedString = NSAttributedString(string: strings.Notification_YouChangedWallpaper, font: titleFont, textColor: primaryTextColor)
|
||||||
|
} else {
|
||||||
|
let resultTitleString = strings.Notification_ChangedWallpaper(authorName)
|
||||||
|
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
||||||
|
}
|
||||||
case .unknown:
|
case .unknown:
|
||||||
attributedString = nil
|
attributedString = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -262,7 +262,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return self.presentationInterfaceState.interfaceState.selectionState?.selectedIds
|
return self.presentationInterfaceState.interfaceState.selectionState?.selectedIds
|
||||||
}
|
}
|
||||||
|
|
||||||
private var themeEmoticonPromise = Promise<String?>()
|
private let chatThemeEmoticonPromise = Promise<String?>()
|
||||||
|
private let chatWallpaperPromise = Promise<TelegramWallpaper?>()
|
||||||
|
|
||||||
private var chatTitleView: ChatTitleView?
|
private var chatTitleView: ChatTitleView?
|
||||||
private var leftNavigationButton: ChatNavigationButton?
|
private var leftNavigationButton: ChatNavigationButton?
|
||||||
@ -837,7 +838,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
case .setChatTheme:
|
case .setChatTheme:
|
||||||
strongSelf.presentThemeSelection()
|
strongSelf.presentThemeSelection()
|
||||||
return true
|
return true
|
||||||
|
case let .setChatWallpaper(wallpaper):
|
||||||
|
strongSelf.chatDisplayNode.dismissInput()
|
||||||
|
let wallpaperPreviewController = WallpaperGalleryController(context: strongSelf.context, source: .wallpaper(wallpaper, nil, [], nil, nil, nil))
|
||||||
|
strongSelf.push(wallpaperPreviewController)
|
||||||
|
return true
|
||||||
case let .giftPremium(_, _, duration, _, _):
|
case let .giftPremium(_, _, duration, _, _):
|
||||||
|
strongSelf.chatDisplayNode.dismissInput()
|
||||||
let fromPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? strongSelf.context.account.peerId : message.id.peerId
|
let fromPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? strongSelf.context.account.peerId : message.id.peerId
|
||||||
let toPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? message.id.peerId : strongSelf.context.account.peerId
|
let toPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? message.id.peerId : strongSelf.context.account.peerId
|
||||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .gift(from: fromPeerId, to: toPeerId, duration: duration))
|
let controller = PremiumIntroScreen(context: strongSelf.context, source: .gift(from: fromPeerId, to: toPeerId, duration: duration))
|
||||||
@ -5785,7 +5792,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let themeEmoticon: Signal<String?, NoError> = self.themeEmoticonPromise.get()
|
let themeEmoticon: Signal<String?, NoError> = self.chatThemeEmoticonPromise.get()
|
||||||
|
|> distinctUntilChanged
|
||||||
|
|
||||||
|
let chatWallpaper: Signal<TelegramWallpaper?, NoError> = self.chatWallpaperPromise.get()
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
let themeSettings = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings])
|
let themeSettings = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings])
|
||||||
@ -5801,7 +5811,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
let accountManager = context.sharedContext.accountManager
|
let accountManager = context.sharedContext.accountManager
|
||||||
let currentThemeEmoticon = Atomic<(String?, Bool)?>(value: nil)
|
let currentThemeEmoticon = Atomic<(String?, Bool)?>(value: nil)
|
||||||
self.presentationDataDisposable = combineLatest(queue: Queue.mainQueue(), context.sharedContext.presentationData, themeSettings, context.engine.themes.getChatThemes(accountManager: accountManager, onlyCached: true), themeEmoticon, self.themeEmoticonAndDarkAppearancePreviewPromise.get()).start(next: { [weak self] presentationData, themeSettings, chatThemes, themeEmoticon, themeEmoticonAndDarkAppearance in
|
self.presentationDataDisposable = combineLatest(
|
||||||
|
queue: Queue.mainQueue(),
|
||||||
|
context.sharedContext.presentationData,
|
||||||
|
themeSettings,
|
||||||
|
context.engine.themes.getChatThemes(accountManager: accountManager, onlyCached: true),
|
||||||
|
themeEmoticon,
|
||||||
|
self.themeEmoticonAndDarkAppearancePreviewPromise.get(),
|
||||||
|
chatWallpaper
|
||||||
|
).start(next: { [weak self] presentationData, themeSettings, chatThemes, themeEmoticon, themeEmoticonAndDarkAppearance, chatWallpaper in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
|
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
|
||||||
|
|
||||||
@ -5905,6 +5923,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
presentationData = presentationData.withUpdated(theme: lightTheme).withUpdated(chatWallpaper: lightWallpaper)
|
presentationData = presentationData.withUpdated(theme: lightTheme).withUpdated(chatWallpaper: lightWallpaper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let chatWallpaper {
|
||||||
|
presentationData = presentationData.withUpdated(chatWallpaper: chatWallpaper)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let isFirstTime = !strongSelf.didSetPresentationData
|
let isFirstTime = !strongSelf.didSetPresentationData
|
||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
strongSelf.didSetPresentationData = true
|
strongSelf.didSetPresentationData = true
|
||||||
@ -6820,9 +6844,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let peerId = self.chatLocation.peerId {
|
if let peerId = self.chatLocation.peerId {
|
||||||
self.themeEmoticonPromise.set(self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.ThemeEmoticon(id: peerId)))
|
self.chatThemeEmoticonPromise.set(self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.ThemeEmoticon(id: peerId)))
|
||||||
|
let chatWallpaper = self.context.account.viewTracker.peerView(peerId)
|
||||||
|
|> take(1)
|
||||||
|
|> map { view -> TelegramWallpaper? in
|
||||||
|
if let cachedUserData = view.cachedData as? CachedUserData {
|
||||||
|
return cachedUserData.wallpaper
|
||||||
} else {
|
} else {
|
||||||
self.themeEmoticonPromise.set(.single(nil))
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.chatWallpaperPromise.set(chatWallpaper)
|
||||||
|
} else {
|
||||||
|
self.chatThemeEmoticonPromise.set(.single(nil))
|
||||||
|
self.chatWallpaperPromise.set(.single(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let peerId = self.chatLocation.peerId {
|
if let peerId = self.chatLocation.peerId {
|
||||||
@ -6961,15 +6996,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
if cachedData != nil {
|
if cachedData != nil {
|
||||||
var themeEmoticon: String? = nil
|
var themeEmoticon: String? = nil
|
||||||
|
var chatWallpaper: TelegramWallpaper?
|
||||||
if let cachedData = cachedData as? CachedUserData {
|
if let cachedData = cachedData as? CachedUserData {
|
||||||
themeEmoticon = cachedData.themeEmoticon
|
themeEmoticon = cachedData.themeEmoticon
|
||||||
|
chatWallpaper = cachedData.wallpaper
|
||||||
} else if let cachedData = cachedData as? CachedGroupData {
|
} else if let cachedData = cachedData as? CachedGroupData {
|
||||||
themeEmoticon = cachedData.themeEmoticon
|
themeEmoticon = cachedData.themeEmoticon
|
||||||
} else if let cachedData = cachedData as? CachedChannelData {
|
} else if let cachedData = cachedData as? CachedChannelData {
|
||||||
themeEmoticon = cachedData.themeEmoticon
|
themeEmoticon = cachedData.themeEmoticon
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.themeEmoticonPromise.set(.single(themeEmoticon))
|
strongSelf.chatThemeEmoticonPromise.set(.single(themeEmoticon))
|
||||||
|
strongSelf.chatWallpaperPromise.set(.single(chatWallpaper))
|
||||||
}
|
}
|
||||||
|
|
||||||
var pinnedMessageId: MessageId?
|
var pinnedMessageId: MessageId?
|
||||||
@ -13771,7 +13809,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.present(actionSheet, in: .window(.root))
|
self.present(actionSheet, in: .window(.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentMediaPicker(subject: MediaPickerScreen.Subject = .assets(nil), saveEditedPhotos: Bool, bannedSendPhotos: (Int32, Bool)?, bannedSendVideos: (Int32, Bool)?, present: @escaping (MediaPickerScreen, AttachmentMediaPickerContext?) -> Void, updateMediaPickerContext: @escaping (AttachmentMediaPickerContext?) -> Void, completion: @escaping ([Any], Bool, Int32?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void) {
|
private func presentMediaPicker(subject: MediaPickerScreen.Subject = .assets(nil, false), saveEditedPhotos: Bool, bannedSendPhotos: (Int32, Bool)?, bannedSendVideos: (Int32, Bool)?, present: @escaping (MediaPickerScreen, AttachmentMediaPickerContext?) -> Void, updateMediaPickerContext: @escaping (AttachmentMediaPickerContext?) -> Void, completion: @escaping ([Any], Bool, Int32?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void) {
|
||||||
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -18424,7 +18462,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return animatedEmojiStickers
|
return animatedEmojiStickers
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = (combineLatest(queue: Queue.mainQueue(), self.themeEmoticonPromise.get(), animatedEmojiStickers)
|
let _ = (combineLatest(queue: Queue.mainQueue(), self.chatThemeEmoticonPromise.get(), animatedEmojiStickers)
|
||||||
|> take(1)).start(next: { [weak self] themeEmoticon, animatedEmojiStickers in
|
|> take(1)).start(next: { [weak self] themeEmoticon, animatedEmojiStickers in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -18445,19 +18483,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeWallpaper: {
|
changeWallpaper: {
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self, let peerId else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let themeController = strongSelf.themeScreen {
|
if let themeController = strongSelf.themeScreen {
|
||||||
strongSelf.themeScreen = nil
|
strongSelf.themeScreen = nil
|
||||||
themeController.dimTapped()
|
themeController.dimTapped()
|
||||||
}
|
}
|
||||||
let controller = ThemeGridController(context: strongSelf.context)
|
let controller = ThemeGridController(context: strongSelf.context, mode: .peer(peerId, strongSelf.presentationData.chatWallpaper))
|
||||||
controller.navigationPresentation = .modal
|
controller.navigationPresentation = .modal
|
||||||
strongSelf.push(controller)
|
strongSelf.push(controller)
|
||||||
},
|
},
|
||||||
completion: { [weak self] emoticon in
|
completion: { [weak self] emoticon in
|
||||||
guard let strongSelf = self, let peerId = peerId else {
|
guard let strongSelf = self, let peerId else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.themeEmoticonAndDarkAppearancePreviewPromise.set(.single((emoticon ?? "", nil)))
|
strongSelf.themeEmoticonAndDarkAppearancePreviewPromise.set(.single((emoticon ?? "", nil)))
|
||||||
|
|||||||
@ -182,7 +182,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let isGeneralThreadClosed = chatPresentationInterfaceState.isGeneralThreadClosed, isGeneralThreadClosed {
|
} else if let isGeneralThreadClosed = chatPresentationInterfaceState.isGeneralThreadClosed, isGeneralThreadClosed && chatPresentationInterfaceState.interfaceState.replyMessageId == nil {
|
||||||
if !canManage {
|
if !canManage {
|
||||||
if let currentPanel = (currentPanel as? ChatRestrictedInputPanelNode) ?? (currentSecondaryPanel as? ChatRestrictedInputPanelNode) {
|
if let currentPanel = (currentPanel as? ChatRestrictedInputPanelNode) ?? (currentSecondaryPanel as? ChatRestrictedInputPanelNode) {
|
||||||
return (currentPanel, nil)
|
return (currentPanel, nil)
|
||||||
|
|||||||
@ -157,6 +157,8 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
|
|||||||
result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
||||||
} else if case .suggestedProfilePhoto = action.action {
|
} else if case .suggestedProfilePhoto = action.action {
|
||||||
result.append((message, ChatMessageProfilePhotoSuggestionContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
result.append((message, ChatMessageProfilePhotoSuggestionContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
||||||
|
} else if case .setChatWallpaper = action.action {
|
||||||
|
result.append((message, ChatMessageWallpaperBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
||||||
} else {
|
} else {
|
||||||
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,312 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import AsyncDisplayKit
|
||||||
|
import Display
|
||||||
|
import SwiftSignalKit
|
||||||
|
import Postbox
|
||||||
|
import TelegramCore
|
||||||
|
import AccountContext
|
||||||
|
import TelegramPresentationData
|
||||||
|
import TelegramUIPreferences
|
||||||
|
import TextFormat
|
||||||
|
import LocalizedPeerData
|
||||||
|
import TelegramStringFormatting
|
||||||
|
import WallpaperBackgroundNode
|
||||||
|
import PhotoResources
|
||||||
|
import WallpaperResources
|
||||||
|
import Markdown
|
||||||
|
|
||||||
|
class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode {
|
||||||
|
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
|
private let mediaBackgroundNode: NavigationBackgroundNode
|
||||||
|
private let subtitleNode: TextNode
|
||||||
|
private let imageNode: TransformImageNode
|
||||||
|
|
||||||
|
private let buttonNode: HighlightTrackingButtonNode
|
||||||
|
private let buttonTitleNode: TextNode
|
||||||
|
|
||||||
|
private var absoluteRect: (CGRect, CGSize)?
|
||||||
|
|
||||||
|
private let fetchDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
required init() {
|
||||||
|
self.mediaBackgroundNode = NavigationBackgroundNode(color: .clear)
|
||||||
|
self.mediaBackgroundNode.clipsToBounds = true
|
||||||
|
self.mediaBackgroundNode.cornerRadius = 24.0
|
||||||
|
|
||||||
|
self.subtitleNode = TextNode()
|
||||||
|
self.subtitleNode.isUserInteractionEnabled = false
|
||||||
|
self.subtitleNode.displaysAsynchronously = false
|
||||||
|
|
||||||
|
self.imageNode = TransformImageNode()
|
||||||
|
|
||||||
|
self.buttonNode = HighlightTrackingButtonNode()
|
||||||
|
self.buttonNode.clipsToBounds = true
|
||||||
|
self.buttonNode.cornerRadius = 17.0
|
||||||
|
|
||||||
|
self.buttonTitleNode = TextNode()
|
||||||
|
self.buttonTitleNode.isUserInteractionEnabled = false
|
||||||
|
self.buttonTitleNode.displaysAsynchronously = false
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.addSubnode(self.mediaBackgroundNode)
|
||||||
|
self.addSubnode(self.subtitleNode)
|
||||||
|
self.addSubnode(self.imageNode)
|
||||||
|
|
||||||
|
self.addSubnode(self.buttonNode)
|
||||||
|
self.addSubnode(self.buttonTitleNode)
|
||||||
|
|
||||||
|
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||||
|
if let strongSelf = self {
|
||||||
|
if highlighted {
|
||||||
|
strongSelf.buttonNode.layer.removeAnimation(forKey: "opacity")
|
||||||
|
strongSelf.buttonNode.alpha = 0.4
|
||||||
|
strongSelf.buttonTitleNode.layer.removeAnimation(forKey: "opacity")
|
||||||
|
strongSelf.buttonTitleNode.alpha = 0.4
|
||||||
|
} else {
|
||||||
|
strongSelf.buttonNode.alpha = 1.0
|
||||||
|
strongSelf.buttonNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||||
|
strongSelf.buttonTitleNode.alpha = 1.0
|
||||||
|
strongSelf.buttonTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.fetchDisposable.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
|
if self.item?.message.id == messageId {
|
||||||
|
return (self.imageNode, self.imageNode.bounds, { [weak self] in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return (nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
let resultView = strongSelf.imageNode.view.snapshotContentTree(unhide: true)
|
||||||
|
return (resultView, nil)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func updateHiddenMedia(_ media: [Media]?) -> Bool {
|
||||||
|
var mediaHidden = false
|
||||||
|
var currentMedia: Media?
|
||||||
|
if let item = item {
|
||||||
|
mediaLoop: for media in item.message.media {
|
||||||
|
if let media = media as? TelegramMediaAction {
|
||||||
|
switch media.action {
|
||||||
|
case let .suggestedProfilePhoto(image):
|
||||||
|
currentMedia = image
|
||||||
|
break mediaLoop
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let currentMedia = currentMedia, let media = media {
|
||||||
|
for item in media {
|
||||||
|
if item.isSemanticallyEqual(to: currentMedia) {
|
||||||
|
mediaHidden = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.imageNode.isHidden = mediaHidden
|
||||||
|
return mediaHidden
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func buttonPressed() {
|
||||||
|
guard let item = self.item else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
|
let makeImageLayout = self.imageNode.asyncLayout()
|
||||||
|
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
|
||||||
|
let makeButtonTitleLayout = TextNode.asyncLayout(self.buttonTitleNode)
|
||||||
|
|
||||||
|
let currentItem = self.item
|
||||||
|
|
||||||
|
return { item, layoutConstants, _, _, _, _ in
|
||||||
|
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center)
|
||||||
|
|
||||||
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
|
let width: CGFloat = 220.0
|
||||||
|
let imageSize = CGSize(width: 100.0, height: 100.0)
|
||||||
|
|
||||||
|
let primaryTextColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText
|
||||||
|
|
||||||
|
var wallpaper: TelegramWallpaper?
|
||||||
|
if let media = item.message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .setChatWallpaper(wallpaperValue) = media.action {
|
||||||
|
wallpaper = wallpaperValue
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaUpdated = true
|
||||||
|
if let wallpaper = wallpaper, let media = currentItem?.message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .setChatWallpaper(currentWallpaper) = media.action {
|
||||||
|
mediaUpdated = wallpaper != currentWallpaper
|
||||||
|
}
|
||||||
|
|
||||||
|
var media: WallpaperPreviewMedia?
|
||||||
|
if let wallpaper {
|
||||||
|
media = WallpaperPreviewMedia(wallpaper: wallpaper)
|
||||||
|
}
|
||||||
|
|
||||||
|
let fromYou = item.message.author?.id == item.context.account.peerId
|
||||||
|
|
||||||
|
let peerName = item.message.peers[item.message.id.peerId].flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
||||||
|
let text: String
|
||||||
|
if fromYou {
|
||||||
|
text = item.presentationData.strings.Notification_YouChangedWallpaper
|
||||||
|
} else {
|
||||||
|
text = item.presentationData.strings.Notification_ChangedWallpaper(peerName).string
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: primaryTextColor)
|
||||||
|
let bold = MarkdownAttributeSet(font: Font.semibold(13.0), textColor: primaryTextColor)
|
||||||
|
|
||||||
|
let subtitle = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in
|
||||||
|
return nil
|
||||||
|
}), textAlignment: .center)
|
||||||
|
|
||||||
|
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Notification_Wallpaper_View, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
let backgroundSize = CGSize(width: width, height: subtitleLayout.size.height + 145.0 + (fromYou ? 0.0 : 37.0))
|
||||||
|
|
||||||
|
return (backgroundSize.width, { boundingWidth in
|
||||||
|
return (backgroundSize, { [weak self] animation, synchronousLoads, _ in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.item = item
|
||||||
|
|
||||||
|
strongSelf.buttonNode.isHidden = fromYou
|
||||||
|
strongSelf.buttonTitleNode.isHidden = fromYou
|
||||||
|
|
||||||
|
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
|
||||||
|
if let media {
|
||||||
|
if mediaUpdated {
|
||||||
|
// strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(context: item.context, userLocation: .peer(item.message.id.peerId), photoReference: .message(message: MessageReference(item.message), media: photo), displayAtSize: nil, storeToDownloadsPeerId: nil).start())
|
||||||
|
}
|
||||||
|
|
||||||
|
let boundingSize = imageSize
|
||||||
|
var imageSize = boundingSize
|
||||||
|
let updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
||||||
|
switch media.content {
|
||||||
|
case let .file(file, _, _, _, _, _):
|
||||||
|
var representations: [ImageRepresentationWithReference] = file.previewRepresentations.map({ ImageRepresentationWithReference(representation: $0, reference: AnyMediaReference.message(message: MessageReference(item.message), media: file).resourceReference($0.resource)) })
|
||||||
|
if file.mimeType == "image/svg+xml" || file.mimeType == "application/x-tgwallpattern" {
|
||||||
|
representations.append(ImageRepresentationWithReference(representation: .init(dimensions: PixelDimensions(width: 1440, height: 2960), resource: file.resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false), reference: AnyMediaReference.message(message: MessageReference(item.message), media: file).resourceReference(file.resource)))
|
||||||
|
}
|
||||||
|
if ["image/png", "image/svg+xml", "application/x-tgwallpattern"].contains(file.mimeType) {
|
||||||
|
updateImageSignal = patternWallpaperImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, representations: representations, mode: .screen)
|
||||||
|
|> mapToSignal { value -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
|
||||||
|
if let value {
|
||||||
|
return .single(value)
|
||||||
|
} else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let dimensions = file.dimensions?.cgSize {
|
||||||
|
imageSize = dimensions.aspectFilled(boundingSize)
|
||||||
|
}
|
||||||
|
updateImageSignal = wallpaperImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, fileReference: FileMediaReference.message(message: MessageReference(item.message), media: file), representations: representations, alwaysShowThumbnailFirst: true, thumbnail: true, autoFetchFullSize: true)
|
||||||
|
}
|
||||||
|
case let .color(color):
|
||||||
|
updateImageSignal = solidColorImage(color)
|
||||||
|
case let .gradient(colors, rotation):
|
||||||
|
updateImageSignal = gradientImage(colors.map(UIColor.init(rgb:)), rotation: rotation ?? 0)
|
||||||
|
case .themeSettings:
|
||||||
|
updateImageSignal = .complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.imageNode.setSignal(updateImageSignal, attemptSynchronously: synchronousLoads)
|
||||||
|
|
||||||
|
let arguments = TransformImageArguments(corners: ImageCorners(radius: boundingSize.width / 2.0), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets())
|
||||||
|
let apply = makeImageLayout(arguments)
|
||||||
|
apply()
|
||||||
|
|
||||||
|
strongSelf.imageNode.frame = imageFrame
|
||||||
|
}
|
||||||
|
|
||||||
|
let mediaBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize)
|
||||||
|
strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame
|
||||||
|
|
||||||
|
strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)
|
||||||
|
strongSelf.mediaBackgroundNode.update(size: mediaBackgroundFrame.size, transition: .immediate)
|
||||||
|
strongSelf.buttonNode.backgroundColor = item.presentationData.theme.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12)
|
||||||
|
|
||||||
|
let _ = subtitleApply()
|
||||||
|
let _ = buttonTitleApply()
|
||||||
|
|
||||||
|
let subtitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 127.0), size: subtitleLayout.size)
|
||||||
|
strongSelf.subtitleNode.frame = subtitleFrame
|
||||||
|
|
||||||
|
let buttonTitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonTitleLayout.size.width) / 2.0), y: subtitleFrame.maxY + 18.0), size: buttonTitleLayout.size)
|
||||||
|
strongSelf.buttonTitleNode.frame = buttonTitleFrame
|
||||||
|
|
||||||
|
let buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0)
|
||||||
|
strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: subtitleFrame.maxY + 10.0), size: buttonSize)
|
||||||
|
|
||||||
|
if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true {
|
||||||
|
if strongSelf.mediaBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||||
|
strongSelf.mediaBackgroundNode.isHidden = true
|
||||||
|
backgroundContent.clipsToBounds = true
|
||||||
|
backgroundContent.allowsGroupOpacity = true
|
||||||
|
backgroundContent.cornerRadius = 24.0
|
||||||
|
|
||||||
|
strongSelf.mediaBackgroundContent = backgroundContent
|
||||||
|
strongSelf.insertSubnode(backgroundContent, at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.mediaBackgroundContent?.frame = mediaBackgroundFrame
|
||||||
|
} else {
|
||||||
|
strongSelf.mediaBackgroundNode.isHidden = false
|
||||||
|
strongSelf.mediaBackgroundContent?.removeFromSupernode()
|
||||||
|
strongSelf.mediaBackgroundContent = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (rect, size) = strongSelf.absoluteRect {
|
||||||
|
strongSelf.updateAbsoluteRect(rect, within: size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.absoluteRect = (rect, containerSize)
|
||||||
|
|
||||||
|
if let mediaBackgroundContent = self.mediaBackgroundContent {
|
||||||
|
var backgroundFrame = mediaBackgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
mediaBackgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||||
|
if self.mediaBackgroundNode.frame.contains(point) {
|
||||||
|
return .openMessage
|
||||||
|
} else {
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1406,7 +1406,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
items[.peerSettings]!.append(PeerInfoScreenActionItem(id: ItemIntro, text: "Edit Intro", icon: UIImage(bundleImageName: "Peer Info/BotIntro"), action: {
|
items[.peerSettings]!.append(PeerInfoScreenActionItem(id: ItemIntro, text: "Edit Intro", icon: UIImage(bundleImageName: "Peer Info/BotIntro"), action: {
|
||||||
interaction.openPeerMention("botfather", .withBotStartPayload(ChatControllerInitialBotStart(payload: user.addressName ?? "", behavior: .interactive)))
|
interaction.openPeerMention("botfather", .withBotStartPayload(ChatControllerInitialBotStart(payload: "\(user.addressName ?? "")-intro", behavior: .interactive)))
|
||||||
}))
|
}))
|
||||||
items[.peerSettings]!.append(PeerInfoScreenActionItem(id: ItemCommands, text: "Edit Commands", icon: UIImage(bundleImageName: "Peer Info/BotCommands"), action: {
|
items[.peerSettings]!.append(PeerInfoScreenActionItem(id: ItemCommands, text: "Edit Commands", icon: UIImage(bundleImageName: "Peer Info/BotCommands"), action: {
|
||||||
interaction.openPeerMention("botfather", .withBotStartPayload(ChatControllerInitialBotStart(payload: "\(user.addressName ?? "")-commands", behavior: .interactive)))
|
interaction.openPeerMention("botfather", .withBotStartPayload(ChatControllerInitialBotStart(payload: "\(user.addressName ?? "")-commands", behavior: .interactive)))
|
||||||
@ -4132,7 +4132,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .withBotStartPayload(startPayload):
|
case let .withBotStartPayload(startPayload):
|
||||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), botStart: startPayload))
|
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), botStart: startPayload, keepStack: .always))
|
||||||
case let .withAttachBot(attachBotStart):
|
case let .withAttachBot(attachBotStart):
|
||||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), attachBotStart: attachBotStart))
|
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), attachBotStart: attachBotStart))
|
||||||
case let .withBotApp(botAppStart):
|
case let .withBotApp(botAppStart):
|
||||||
|
|||||||
@ -45,3 +45,18 @@ final class WallpaperPreviewMedia: Media {
|
|||||||
return self.isEqual(to: other)
|
return self.isEqual(to: other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension WallpaperPreviewMedia {
|
||||||
|
convenience init?(wallpaper: TelegramWallpaper) {
|
||||||
|
switch wallpaper {
|
||||||
|
case let .color(color):
|
||||||
|
self.init(content: .color(UIColor(rgb: color)))
|
||||||
|
case let .gradient(gradient):
|
||||||
|
self.init(content: .gradient(gradient.colors, gradient.settings.rotation))
|
||||||
|
case let .file(file):
|
||||||
|
self.init(content: .file(file: file.file, colors: file.settings.colors, rotation: file.settings.rotation, intensity: file.settings.intensity, false, false))
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user