Initial peer custom wallpapers implementation

This commit is contained in:
Ilya Laktyushin 2023-03-31 23:44:19 +04:00
parent c851ec3046
commit 330fcfa5cd
31 changed files with 863 additions and 167 deletions

View File

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

View File

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

View File

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

View File

@ -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)
} }
@ -722,6 +730,19 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
Queue.mainQueue().justDispatch { Queue.mainQueue().justDispatch {
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 {
@ -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 {
self.navigationItem.leftBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed)) 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))
}
} 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

View File

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

View File

@ -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()
}

View File

@ -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,83 +133,81 @@ 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 {
if let strongSelf = self { case .default:
strongSelf.deactivateSearch(animated: false) uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak self, weak controller] in
strongSelf.controllerNode.scrollToTop(animated: false) if let strongSelf = self {
} strongSelf.deactivateSearch(animated: false)
if let controller = controller { strongSelf.controllerNode.scrollToTop(animated: false)
switch wallpaper { }
if let controller = controller {
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 {

View File

@ -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
entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: false, isSelected: true), at: 0) if selectFirst {
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) {

View File

@ -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?()
})
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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")
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -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 {
return nil
}
}
self.chatWallpaperPromise.set(chatWallpaper)
} else { } else {
self.themeEmoticonPromise.set(.single(nil)) 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)))

View File

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

View File

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

View File

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

View File

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

View File

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