mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '6f4f3817a9c6387d8554ac8c0054e161c6446e05'
This commit is contained in:
commit
ebdc6a921e
@ -9119,6 +9119,10 @@ Sorry for the inconvenience.";
|
||||
|
||||
"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";
|
||||
|
||||
"Channel.AdminLog.JoinedViaFolderInviteLink" = "%1$@ joined via invite link %2$@ (community)";
|
||||
|
||||
"Conversation.OpenChatFolder" = "Open Shared Folder";
|
||||
|
@ -87,6 +87,10 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture
|
||||
|
||||
self.pager.dismiss = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if let galleryController = strongSelf.galleryController(), galleryController.navigationController != nil {
|
||||
galleryController.dismiss(animated: true)
|
||||
return
|
||||
}
|
||||
var interfaceAnimationCompleted = false
|
||||
var contentAnimationCompleted = true
|
||||
|
||||
|
@ -25,14 +25,16 @@ final class MediaPickerGridItem: GridItem {
|
||||
let content: MediaPickerGridItemContent
|
||||
let interaction: MediaPickerInteraction
|
||||
let theme: PresentationTheme
|
||||
let selectable: Bool
|
||||
let enableAnimations: Bool
|
||||
|
||||
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.interaction = interaction
|
||||
self.theme = theme
|
||||
self.selectable = selectable
|
||||
self.enableAnimations = enableAnimations
|
||||
}
|
||||
|
||||
@ -40,11 +42,11 @@ final class MediaPickerGridItem: GridItem {
|
||||
switch self.content {
|
||||
case let .asset(fetchResult, index):
|
||||
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
|
||||
case let .media(media, index):
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -56,13 +58,13 @@ final class MediaPickerGridItem: GridItem {
|
||||
assertionFailure()
|
||||
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):
|
||||
guard let node = node as? MediaPickerGridItemNode else {
|
||||
assertionFailure()
|
||||
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 currentState: (PHFetchResult<PHAsset>, Int)?
|
||||
var enableAnimations: Bool = true
|
||||
private var selectable: Bool = false
|
||||
|
||||
private let imageNode: ImageNode
|
||||
private var checkNode: InteractiveCheckNode?
|
||||
@ -171,7 +174,7 @@ final class MediaPickerGridItemNode: GridItemNode {
|
||||
}
|
||||
|
||||
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))
|
||||
checkNode.valueChanged = { [weak self] value in
|
||||
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(_:))))
|
||||
}
|
||||
|
||||
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.theme = theme
|
||||
self.selectable = selectable
|
||||
self.enableAnimations = enableAnimations
|
||||
|
||||
self.backgroundColor = theme.list.mediaPlaceholderColor
|
||||
@ -239,9 +243,10 @@ final class MediaPickerGridItemNode: GridItemNode {
|
||||
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.theme = theme
|
||||
self.selectable = selectable
|
||||
self.enableAnimations = enableAnimations
|
||||
|
||||
self.backgroundColor = theme.list.mediaPlaceholderColor
|
||||
|
@ -48,13 +48,14 @@ final class MediaPickerInteraction {
|
||||
private struct MediaPickerGridEntry: Comparable, Identifiable {
|
||||
let stableId: Int
|
||||
let content: MediaPickerGridItemContent
|
||||
let selectable: Bool
|
||||
|
||||
static func <(lhs: MediaPickerGridEntry, rhs: MediaPickerGridEntry) -> Bool {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
|
||||
@ -157,6 +158,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
public var presentWebSearch: (MediaGroupsScreen, Bool) -> Void = { _, _ in }
|
||||
public var getCaptionPanelView: () -> TGCaptionPanelView? = { return nil }
|
||||
|
||||
public var customSelection: ((PHAsset) -> Void)? = nil
|
||||
|
||||
private var completed = false
|
||||
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()
|
||||
|
||||
if case .assets(nil) = controller.subject {
|
||||
if case .assets(nil, false) = controller.subject {
|
||||
} else {
|
||||
self.preloadPromise.set(false)
|
||||
}
|
||||
@ -263,7 +266,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
let preloadPromise = self.preloadPromise
|
||||
let updatedState: Signal<State, NoError>
|
||||
switch controller.subject {
|
||||
case let .assets(collection):
|
||||
case let .assets(collection, _):
|
||||
updatedState = combineLatest(mediaAssetsContext.mediaAccess(), mediaAssetsContext.cameraAccess())
|
||||
|> mapToSignal { mediaAccess, cameraAccess -> Signal<State, NoError> in
|
||||
if case .notDetermined = mediaAccess {
|
||||
@ -400,7 +403,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
self.gridNode.view.addGestureRecognizer(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
|
||||
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 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 selectable = true
|
||||
if case let .assets(_, isStandalone) = controller.subject, isStandalone {
|
||||
selectable = false
|
||||
}
|
||||
|
||||
switch state {
|
||||
case let .noAccess(cameraAccess):
|
||||
if case .assets = previousState {
|
||||
@ -570,12 +578,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
|
||||
for i in 0 ..< count {
|
||||
let index: Int
|
||||
if case let .assets(collection) = controller.subject, let _ = collection {
|
||||
if case let .assets(collection, _) = controller.subject, let _ = collection {
|
||||
index = i
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
@ -594,7 +602,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
case let .media(media):
|
||||
let count = media.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
|
||||
}
|
||||
}
|
||||
@ -603,7 +611,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
self.currentEntries = entries
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@ -722,6 +730,19 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
Queue.mainQueue().justDispatch {
|
||||
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
|
||||
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
|
||||
|
||||
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?.hiddenMediaId.set(.single(id))
|
||||
}, 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)
|
||||
|
||||
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
|
||||
} else {
|
||||
self.titleView.title = presentationData.strings.Attachment_Gallery
|
||||
@ -1302,8 +1316,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
|
||||
self.navigationItem.titleView = self.titleView
|
||||
|
||||
if case let .assets(collection) = self.subject, collection != nil {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed))
|
||||
if case let .assets(collection, isStandalone) = self.subject {
|
||||
if !isStandalone {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||
} else if collection != nil {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed))
|
||||
}
|
||||
} else {
|
||||
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.presentWebSearch(MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, openGroup: { [weak self] collection in
|
||||
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.presentTimerPicker = strongSelf.presentTimerPicker
|
||||
|
@ -110,6 +110,8 @@ swift_library(
|
||||
"//submodules/AnimatedAvatarSetNode",
|
||||
"//submodules/TelegramUI/Components/StorageUsageScreen",
|
||||
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
||||
"//submodules/MediaPickerUI:MediaPickerUI",
|
||||
"//submodules/ImageBlur:ImageBlur",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -11,6 +11,7 @@ import AccountContext
|
||||
import LegacyUI
|
||||
import LegacyMediaPickerUI
|
||||
import LocalMediaResources
|
||||
import ImageBlur
|
||||
|
||||
func presentCustomWallpaperPicker(context: AccountContext, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -194,3 +195,131 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE
|
||||
return croppedImage
|
||||
}).start()
|
||||
}
|
||||
|
||||
func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, peerId: PeerId, completion: @escaping () -> Void) {
|
||||
let imageSignal: Signal<UIImage, NoError>
|
||||
switch wallpaper {
|
||||
case let .wallpaper(wallpaper, _):
|
||||
switch wallpaper {
|
||||
case let .file(file):
|
||||
if let path = context.account.postbox.mediaBox.completedResourcePath(file.file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(file.file.resource.id, data: data)
|
||||
let _ = context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start()
|
||||
let _ = context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true).start()
|
||||
}
|
||||
case let .image(representations, _):
|
||||
for representation in representations {
|
||||
let resource = representation.resource
|
||||
if let path = context.account.postbox.mediaBox.completedResourcePath(resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
||||
let _ = context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: true, fetch: true).start()
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
imageSignal = .complete()
|
||||
completion()
|
||||
case let .asset(asset):
|
||||
imageSignal = fetchPhotoLibraryImage(localIdentifier: asset.localIdentifier, thumbnail: false)
|
||||
|> filter { value in
|
||||
return !(value?.1 ?? true)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<UIImage, NoError> in
|
||||
if let result = result {
|
||||
return .single(result.0)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
case let .contextResult(result):
|
||||
var imageResource: TelegramMediaResource?
|
||||
switch result {
|
||||
case let .externalReference(externalReference):
|
||||
if let content = externalReference.content {
|
||||
imageResource = content.resource
|
||||
}
|
||||
case let .internalReference(internalReference):
|
||||
if let image = internalReference.image {
|
||||
if let imageRepresentation = imageRepresentationLargerThan(image.representations, size: PixelDimensions(width: 1000, height: 800)) {
|
||||
imageResource = imageRepresentation.resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let imageResource = imageResource {
|
||||
imageSignal = .single(context.account.postbox.mediaBox.completedResourcePath(imageResource))
|
||||
|> mapToSignal { path -> Signal<UIImage, NoError> in
|
||||
if let path = path, let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedIfSafe]), let image = UIImage(data: data) {
|
||||
return .single(image)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
imageSignal = .complete()
|
||||
}
|
||||
}
|
||||
|
||||
let _ = (imageSignal
|
||||
|> map { image -> UIImage in
|
||||
var croppedImage = UIImage()
|
||||
|
||||
let finalCropRect: CGRect
|
||||
if let cropRect = cropRect {
|
||||
finalCropRect = cropRect
|
||||
} else {
|
||||
let screenSize = TGScreenSize()
|
||||
let fittedSize = TGScaleToFit(screenSize, image.size)
|
||||
finalCropRect = CGRect(x: (image.size.width - fittedSize.width) / 2.0, y: (image.size.height - fittedSize.height) / 2.0, width: fittedSize.width, height: fittedSize.height)
|
||||
}
|
||||
croppedImage = TGPhotoEditorCrop(image, nil, .up, 0.0, finalCropRect, false, CGSize(width: 1440.0, height: 2960.0), image.size, true)
|
||||
|
||||
if mode.contains(.blur) {
|
||||
croppedImage = blurredImage(croppedImage, radius: 45.0)!
|
||||
}
|
||||
|
||||
let thumbnailDimensions = finalCropRect.size.fitted(CGSize(width: 320.0, height: 320.0))
|
||||
let thumbnailImage = generateScaledImage(image: croppedImage, size: thumbnailDimensions, scale: 1.0)
|
||||
|
||||
if let data = croppedImage.jpegData(compressionQuality: 0.8), let thumbnailImage = thumbnailImage, let thumbnailData = thumbnailImage.jpegData(compressionQuality: 0.4) {
|
||||
let thumbnailResource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData)
|
||||
context.account.postbox.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData)
|
||||
|
||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data)
|
||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
|
||||
|
||||
let settings = WallpaperSettings(blur: mode.contains(.blur), motion: mode.contains(.motion), colors: [], intensity: nil)
|
||||
let temporaryWallpaper: TelegramWallpaper = .image([TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailDimensions), resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false), TelegramMediaImageRepresentation(dimensions: PixelDimensions(croppedImage.size), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)], settings)
|
||||
|
||||
let _ = context.account.postbox.transaction({ transaction in
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId])) { _, cachedData in
|
||||
if let cachedData = cachedData as? CachedUserData {
|
||||
return cachedData.withUpdatedWallpaper(temporaryWallpaper)
|
||||
} else {
|
||||
return cachedData
|
||||
}
|
||||
}
|
||||
}).start()
|
||||
|
||||
Queue.mainQueue().async {
|
||||
completion()
|
||||
}
|
||||
|
||||
let _ = uploadWallpaper(account: context.account, resource: resource, settings: WallpaperSettings(blur: false, motion: mode.contains(.motion), colors: [], intensity: nil)).start(next: { status in
|
||||
if case let .complete(wallpaper) = status {
|
||||
if case let .file(file) = wallpaper {
|
||||
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: file.file.resource.id, synchronous: true)
|
||||
for representation in file.file.previewRepresentations {
|
||||
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: representation.resource.id, synchronous: true)
|
||||
}
|
||||
}
|
||||
let _ = context.engine.themes.setChatWallpaper(peerId: peerId, wallpaper: wallpaper).start()
|
||||
}
|
||||
})
|
||||
}
|
||||
return croppedImage
|
||||
}).start()
|
||||
}
|
||||
|
@ -14,8 +14,23 @@ import ShareController
|
||||
import SearchUI
|
||||
import HexColor
|
||||
import PresentationDataUtils
|
||||
import MediaPickerUI
|
||||
|
||||
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 {
|
||||
return self.displayNode as! ThemeGridControllerNode
|
||||
}
|
||||
@ -26,6 +41,7 @@ public final class ThemeGridController: ViewController {
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let mode: Mode
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private let presentationDataPromise = Promise<PresentationData>()
|
||||
@ -44,8 +60,9 @@ public final class ThemeGridController: ViewController {
|
||||
|
||||
private var previousContentOffset: GridNodeVisibleContentOffset?
|
||||
|
||||
public init(context: AccountContext) {
|
||||
public init(context: AccountContext, mode: Mode = .default) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationDataPromise.set(.single(self.presentationData))
|
||||
|
||||
@ -116,83 +133,81 @@ public final class ThemeGridController: ViewController {
|
||||
}
|
||||
|
||||
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 {
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: source)
|
||||
controller.apply = { [weak self, weak controller] wallpaper, mode, cropRect in
|
||||
if let strongSelf = self {
|
||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: mode, cropRect: cropRect, completion: { [weak self, weak controller] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.deactivateSearch(animated: false)
|
||||
strongSelf.controllerNode.scrollToTop(animated: false)
|
||||
}
|
||||
if let controller = controller {
|
||||
switch wallpaper {
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: source, mode: strongSelf.mode.galleryMode)
|
||||
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in
|
||||
if let strongSelf = self, case let .wallpaper(wallpaperValue, _) = wallpaper {
|
||||
switch strongSelf.mode {
|
||||
case .default:
|
||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak self, weak controller] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.deactivateSearch(animated: false)
|
||||
strongSelf.controllerNode.scrollToTop(animated: false)
|
||||
}
|
||||
if let controller = controller {
|
||||
switch wallpaper {
|
||||
case .asset, .contextResult:
|
||||
controller.dismiss(forceAway: true)
|
||||
controller.dismiss(animated: true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
case let .peer(peerId, _):
|
||||
let _ = (strongSelf.context.engine.themes.setChatWallpaper(peerId: peerId, wallpaper: wallpaperValue)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
dismissControllers()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
self?.push(controller)
|
||||
}
|
||||
}, presentGallery: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
presentCustomWallpaperPicker(context: strongSelf.context, present: { [weak self] controller in
|
||||
self?.present(controller, in: .window(.root), with: nil, blockInteraction: true)
|
||||
}, push: { [weak self] controller in
|
||||
self?.push(controller)
|
||||
})
|
||||
let controller = MediaPickerScreen(context: strongSelf.context, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, true))
|
||||
controller.customSelection = { [weak self] asset in
|
||||
guard let strongSelf = self else {
|
||||
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
|
||||
if let strongSelf = self {
|
||||
let controller = ThemeColorsGridController(context: strongSelf.context)
|
||||
(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
|
||||
if let strongSelf = self {
|
||||
if empty != strongSelf.isEmpty {
|
||||
|
@ -141,6 +141,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private let mode: ThemeGridController.Mode
|
||||
private var controllerInteraction: ThemeGridControllerInteraction?
|
||||
|
||||
private let presentPreviewController: (WallpaperListSource) -> Void
|
||||
@ -192,8 +193,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
|
||||
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.mode = mode
|
||||
self.presentationData = presentationData
|
||||
self.presentPreviewController = presentPreviewController
|
||||
self.presentGallery = presentGallery
|
||||
@ -338,12 +340,19 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
})
|
||||
self.controllerInteraction = interaction
|
||||
|
||||
var selectFirst = true
|
||||
if case .peer = self.mode {
|
||||
selectFirst = false
|
||||
}
|
||||
|
||||
let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperIdsPromise.get(), context.sharedContext.presentationData)
|
||||
|> map { wallpapers, deletedWallpaperIds, presentationData -> (ThemeGridEntryTransition, Bool) in
|
||||
var entries: [ThemeGridControllerEntry] = []
|
||||
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?
|
||||
if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
||||
|
@ -165,12 +165,17 @@ private func updatedFileWallpaper(id: Int64? = nil, accessHash: Int64? = nil, sl
|
||||
}
|
||||
|
||||
public class WallpaperGalleryController: ViewController {
|
||||
public enum Mode {
|
||||
case `default`
|
||||
case peer(EnginePeer.Id)
|
||||
}
|
||||
private var galleryNode: GalleryControllerNode {
|
||||
return self.displayNode as! GalleryControllerNode
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let source: WallpaperListSource
|
||||
private let mode: Mode
|
||||
public var apply: ((WallpaperGalleryEntry, WallpaperPresentationOptions, CGRect?) -> Void)?
|
||||
|
||||
private let _ready = Promise<Bool>()
|
||||
@ -211,9 +216,10 @@ public class WallpaperGalleryController: ViewController {
|
||||
private var savedPatternWallpaper: TelegramWallpaper?
|
||||
private var savedPatternIntensity: Int32?
|
||||
|
||||
public init(context: AccountContext, source: WallpaperListSource) {
|
||||
public init(context: AccountContext, source: WallpaperListSource, mode: Mode = .default) {
|
||||
self.context = context
|
||||
self.source = source
|
||||
self.mode = mode
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
@ -378,6 +384,9 @@ public class WallpaperGalleryController: ViewController {
|
||||
|
||||
(self.displayNode as? WallpaperGalleryControllerNode)?.nativeStatusBar = self.statusBar
|
||||
|
||||
self.galleryNode.galleryController = { [weak self] in
|
||||
return self
|
||||
}
|
||||
self.galleryNode.navigationBar = self.navigationBar
|
||||
self.galleryNode.dismiss = { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
@ -423,6 +432,9 @@ public class WallpaperGalleryController: ViewController {
|
||||
default:
|
||||
break
|
||||
}
|
||||
if case .peer = self.mode {
|
||||
doneButtonType = .setPeer
|
||||
}
|
||||
|
||||
let toolbarNode = WallpaperGalleryToolbarNode(theme: presentationData.theme, strings: presentationData.strings, doneButtonType: doneButtonType)
|
||||
self.toolbarNode = toolbarNode
|
||||
@ -439,6 +451,13 @@ public class WallpaperGalleryController: ViewController {
|
||||
let options = centralItemNode.options
|
||||
if !strongSelf.entries.isEmpty {
|
||||
let entry = strongSelf.entries[centralItemNode.index]
|
||||
|
||||
if case .peer = strongSelf.mode {
|
||||
strongSelf.apply?(entry, options, centralItemNode.cropRect)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
switch entry {
|
||||
case let .wallpaper(wallpaper, _):
|
||||
var resource: MediaResource?
|
||||
@ -1044,15 +1063,3 @@ public class WallpaperGalleryController: ViewController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension GalleryControllerNode {
|
||||
func modalAnimateIn(completion: (() -> Void)? = nil) {
|
||||
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
|
||||
func modalAnimateOut(completion: (() -> Void)? = nil) {
|
||||
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -658,9 +658,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
strongSelf.colorsButtonNode.buttonColor = color
|
||||
|
||||
if color == UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||
strongSelf.playButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45), transition: .immediate)
|
||||
strongSelf.cancelButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.45), transition: .immediate)
|
||||
strongSelf.shareButtonBackgroundNode.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.55), transition: .immediate)
|
||||
strongSelf.shareButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
|
||||
} else {
|
||||
strongSelf.playButtonBackgroundNode.updateColor(color: color, transition: .immediate)
|
||||
strongSelf.cancelButtonBackgroundNode.updateColor(color: color, transition: .immediate)
|
||||
|
@ -11,6 +11,7 @@ enum WallpaperGalleryToolbarCancelButtonType {
|
||||
|
||||
enum WallpaperGalleryToolbarDoneButtonType {
|
||||
case set
|
||||
case setPeer
|
||||
case proceed
|
||||
case apply
|
||||
case none
|
||||
@ -48,7 +49,7 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
|
||||
self.cancelButtonType = cancelButtonType
|
||||
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
|
||||
|
||||
let blurEffect: UIBlurEffect
|
||||
@ -152,6 +153,8 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
|
||||
switch self.doneButtonType {
|
||||
case .set:
|
||||
doneTitle = strings.Wallpaper_ApplyForAll
|
||||
case .setPeer:
|
||||
doneTitle = strings.Wallpaper_ApplyForChat
|
||||
case .proceed:
|
||||
doneTitle = strings.Theme_Colors_Proceed
|
||||
case .apply:
|
||||
|
@ -141,7 +141,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||
didSet {
|
||||
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 {
|
||||
self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
|
||||
}
|
||||
|
@ -108,8 +108,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
||||
return TelegramMediaAction(action: .suggestedProfilePhoto(image: telegramMediaImageFromApiPhoto(photo)))
|
||||
case let .messageActionRequestedPeer(buttonId, peer):
|
||||
return TelegramMediaAction(action: .requestedPeer(buttonId: buttonId, peerId: peer.peerId))
|
||||
case .messageActionSetChatWallPaper:
|
||||
return nil
|
||||
case let .messageActionSetChatWallPaper(wallpaper):
|
||||
return TelegramMediaAction(action: .setChatWallpaper(wallpaper: TelegramWallpaper(apiWallpaper: wallpaper)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ extension TelegramWallpaper {
|
||||
}
|
||||
}
|
||||
|
||||
var apiInputWallpaperAndSettings: (Api.InputWallPaper?, Api.WallPaperSettings)? {
|
||||
var apiInputWallpaperAndSettings: (Api.InputWallPaper, Api.WallPaperSettings)? {
|
||||
switch self {
|
||||
case .builtin:
|
||||
return nil
|
||||
|
@ -199,6 +199,7 @@ public final class CachedUserData: CachedPeerData {
|
||||
public let fallbackPhoto: CachedPeerProfilePhoto
|
||||
public let premiumGiftOptions: [CachedPremiumGiftOption]
|
||||
public let voiceMessagesAvailable: Bool
|
||||
public let wallpaper: TelegramWallpaper?
|
||||
public let flags: CachedUserFlags
|
||||
|
||||
public let peerIds: Set<PeerId>
|
||||
@ -224,12 +225,13 @@ public final class CachedUserData: CachedPeerData {
|
||||
self.fallbackPhoto = .unknown
|
||||
self.premiumGiftOptions = []
|
||||
self.voiceMessagesAvailable = true
|
||||
self.wallpaper = nil
|
||||
self.flags = CachedUserFlags()
|
||||
self.peerIds = 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.botInfo = botInfo
|
||||
self.peerStatusSettings = peerStatusSettings
|
||||
@ -248,6 +250,7 @@ public final class CachedUserData: CachedPeerData {
|
||||
self.fallbackPhoto = fallbackPhoto
|
||||
self.premiumGiftOptions = premiumGiftOptions
|
||||
self.voiceMessagesAvailable = voiceMessagesAvailable
|
||||
self.wallpaper = wallpaper
|
||||
self.flags = flags
|
||||
|
||||
self.peerIds = Set<PeerId>()
|
||||
@ -290,6 +293,7 @@ public final class CachedUserData: CachedPeerData {
|
||||
|
||||
self.premiumGiftOptions = decoder.decodeObjectArrayWithDecoderForKey("pgo") as [CachedPremiumGiftOption]
|
||||
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.peerIds = Set<PeerId>()
|
||||
@ -346,6 +350,13 @@ public final class CachedUserData: CachedPeerData {
|
||||
|
||||
encoder.encodeObjectArray(self.premiumGiftOptions, forKey: "pgo")
|
||||
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")
|
||||
}
|
||||
|
||||
@ -361,82 +372,86 @@ public final class CachedUserData: CachedPeerData {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, flags: flags)
|
||||
return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, personalPhoto: self.personalPhoto, fallbackPhoto: self.fallbackPhoto, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable, wallpaper: self.wallpaper, flags: flags)
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
case suggestedProfilePhoto(image: TelegramMediaImage?)
|
||||
case attachMenuBotAllowed
|
||||
case requestedPeer(buttonId: Int32, peerId: PeerId)
|
||||
case setChatWallpaper(wallpaper: TelegramWallpaper)
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||
@ -181,6 +182,12 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
self = .attachMenuBotAllowed
|
||||
case 32:
|
||||
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:
|
||||
self = .unknown
|
||||
}
|
||||
@ -342,6 +349,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
encoder.encodeInt32(32, forKey: "_rawValue")
|
||||
encoder.encodeInt32(buttonId, forKey: "b")
|
||||
encoder.encodeInt64(peerId.toInt64(), forKey: "pi")
|
||||
case let .setChatWallpaper(wallpaper):
|
||||
encoder.encodeInt32(33, forKey: "_rawValue")
|
||||
encoder.encode(TelegramWallpaperNativeCodable(wallpaper), forKey: "wallpaper")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +255,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
previous = CachedUserData()
|
||||
}
|
||||
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 isBlocked = (userFullFlags & (1 << 0)) != 0
|
||||
let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0
|
||||
@ -290,6 +290,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
premiumGiftOptions = []
|
||||
}
|
||||
|
||||
let wallpaper = userWallpaper.flatMap { TelegramWallpaper(apiWallpaper: $0) }
|
||||
|
||||
return previous.withUpdatedAbout(userFullAbout)
|
||||
.withUpdatedBotInfo(botInfo)
|
||||
.withUpdatedCommonGroupCount(userFullCommonChatsCount)
|
||||
@ -308,6 +310,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
||||
.withUpdatedFallbackPhoto(.known(fallbackPhoto))
|
||||
.withUpdatedPremiumGiftOptions(premiumGiftOptions)
|
||||
.withUpdatedVoiceMessagesAvailable(voiceMessagesAvailable)
|
||||
.withUpdatedWallpaper(wallpaper)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -78,14 +78,14 @@ func _internal_getChatThemes(accountManager: AccountManager<TelegramAccountManag
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_setChatTheme(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
||||
return postbox.loadedPeerWithId(peerId)
|
||||
func _internal_setChatTheme(account: Account, peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
||||
return account.postbox.loadedPeerWithId(peerId)
|
||||
|> mapToSignal { peer in
|
||||
guard let inputPeer = apiInputPeer(peer) else {
|
||||
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
|
||||
if let current = current as? CachedUserData {
|
||||
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
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<Void, NoError> in
|
||||
stateManager.addUpdates(updates)
|
||||
account.stateManager.addUpdates(updates)
|
||||
return .complete()
|
||||
}
|
||||
} |> 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
|
||||
}
|
||||
|
||||
func _internal_setChatWallpaper(account: Account, peerId: PeerId, wallpaper: TelegramWallpaper?) -> Signal<Void, NoError> {
|
||||
return account.postbox.loadedPeerWithId(peerId)
|
||||
|> mapToSignal { peer in
|
||||
guard let inputPeer = apiInputPeer(peer) else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedUserData {
|
||||
return current.withUpdatedWallpaper(wallpaper)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
|
||||
var inputWallpaper: Api.InputWallPaper?
|
||||
var inputSettings: Api.WallPaperSettings?
|
||||
if let inputWallpaperAndInputSettings = wallpaper?.apiInputWallpaperAndSettings {
|
||||
inputWallpaper = inputWallpaperAndInputSettings.0
|
||||
inputSettings = inputWallpaperAndInputSettings.1
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.messages.setChatWallPaper(peer: inputPeer, wallpaper: inputWallpaper ?? .inputWallPaperNoFile(id: 0), settings: inputSettings ?? apiWallpaperSettings(WallpaperSettings())))
|
||||
|> `catch` { error in
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<Void, NoError> in
|
||||
account.stateManager.addUpdates(updates)
|
||||
return .complete()
|
||||
}
|
||||
} |> switchToLatest
|
||||
}
|
||||
}
|
||||
|
@ -9,16 +9,16 @@ public extension TelegramEngine {
|
||||
self.account = account
|
||||
}
|
||||
|
||||
// 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> {
|
||||
return _internal_getChatThemes(accountManager: accountManager, network: self.account.network, forceUpdate: forceUpdate, onlyCached: onlyCached)
|
||||
}
|
||||
|
||||
public func setChatTheme(peerId: PeerId, emoticon: String?) -> Signal<Void, NoError> {
|
||||
return _internal_setChatTheme(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, emoticon: emoticon)
|
||||
return _internal_setChatTheme(account: self.account, peerId: peerId, emoticon: emoticon)
|
||||
}
|
||||
|
||||
public func setChatWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?) -> Signal<Void, NoError> {
|
||||
return _internal_setChatWallpaper(account: self.account, peerId: peerId, wallpaper: wallpaper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -873,6 +873,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
let botName = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? ""
|
||||
let 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)]))
|
||||
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:
|
||||
attributedString = nil
|
||||
}
|
||||
|
@ -262,7 +262,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
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 leftNavigationButton: ChatNavigationButton?
|
||||
@ -837,7 +838,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
case .setChatTheme:
|
||||
strongSelf.presentThemeSelection()
|
||||
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, _, _):
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
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 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
|
||||
|
||||
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 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 {
|
||||
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
|
||||
|
||||
@ -5905,6 +5923,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
presentationData = presentationData.withUpdated(theme: lightTheme).withUpdated(chatWallpaper: lightWallpaper)
|
||||
}
|
||||
}
|
||||
|
||||
if let chatWallpaper {
|
||||
presentationData = presentationData.withUpdated(chatWallpaper: chatWallpaper)
|
||||
}
|
||||
|
||||
|
||||
let isFirstTime = !strongSelf.didSetPresentationData
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.didSetPresentationData = true
|
||||
@ -6820,9 +6844,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
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 {
|
||||
self.themeEmoticonPromise.set(.single(nil))
|
||||
self.chatThemeEmoticonPromise.set(.single(nil))
|
||||
self.chatWallpaperPromise.set(.single(nil))
|
||||
}
|
||||
|
||||
if let peerId = self.chatLocation.peerId {
|
||||
@ -6961,15 +6996,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
if cachedData != nil {
|
||||
var themeEmoticon: String? = nil
|
||||
var chatWallpaper: TelegramWallpaper?
|
||||
if let cachedData = cachedData as? CachedUserData {
|
||||
themeEmoticon = cachedData.themeEmoticon
|
||||
chatWallpaper = cachedData.wallpaper
|
||||
} else if let cachedData = cachedData as? CachedGroupData {
|
||||
themeEmoticon = cachedData.themeEmoticon
|
||||
} else if let cachedData = cachedData as? CachedChannelData {
|
||||
themeEmoticon = cachedData.themeEmoticon
|
||||
}
|
||||
|
||||
strongSelf.themeEmoticonPromise.set(.single(themeEmoticon))
|
||||
strongSelf.chatThemeEmoticonPromise.set(.single(themeEmoticon))
|
||||
strongSelf.chatWallpaperPromise.set(.single(chatWallpaper))
|
||||
}
|
||||
|
||||
var pinnedMessageId: MessageId?
|
||||
@ -13771,7 +13809,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
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 {
|
||||
return
|
||||
}
|
||||
@ -18424,7 +18462,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
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
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -18445,19 +18483,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
},
|
||||
changeWallpaper: {
|
||||
guard let strongSelf = self else {
|
||||
guard let strongSelf = self, let peerId else {
|
||||
return
|
||||
}
|
||||
if let themeController = strongSelf.themeScreen {
|
||||
strongSelf.themeScreen = nil
|
||||
themeController.dimTapped()
|
||||
}
|
||||
let controller = ThemeGridController(context: strongSelf.context)
|
||||
let controller = ThemeGridController(context: strongSelf.context, mode: .peer(peerId, strongSelf.presentationData.chatWallpaper))
|
||||
controller.navigationPresentation = .modal
|
||||
strongSelf.push(controller)
|
||||
},
|
||||
completion: { [weak self] emoticon in
|
||||
guard let strongSelf = self, let peerId = peerId else {
|
||||
guard let strongSelf = self, let peerId else {
|
||||
return
|
||||
}
|
||||
strongSelf.themeEmoticonAndDarkAppearancePreviewPromise.set(.single((emoticon ?? "", nil)))
|
||||
|
@ -182,7 +182,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let isGeneralThreadClosed = chatPresentationInterfaceState.isGeneralThreadClosed, isGeneralThreadClosed {
|
||||
} else if let isGeneralThreadClosed = chatPresentationInterfaceState.isGeneralThreadClosed, isGeneralThreadClosed && chatPresentationInterfaceState.interfaceState.replyMessageId == nil {
|
||||
if !canManage {
|
||||
if let currentPanel = (currentPanel as? ChatRestrictedInputPanelNode) ?? (currentSecondaryPanel as? ChatRestrictedInputPanelNode) {
|
||||
return (currentPanel, nil)
|
||||
|
@ -157,6 +157,8 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
|
||||
result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
||||
} else if case .suggestedProfilePhoto = action.action {
|
||||
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 {
|
||||
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default)))
|
||||
}
|
||||
|
@ -0,0 +1,312 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import AccountContext
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import TextFormat
|
||||
import LocalizedPeerData
|
||||
import TelegramStringFormatting
|
||||
import WallpaperBackgroundNode
|
||||
import PhotoResources
|
||||
import WallpaperResources
|
||||
import Markdown
|
||||
|
||||
class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?
|
||||
private let mediaBackgroundNode: NavigationBackgroundNode
|
||||
private let subtitleNode: TextNode
|
||||
private let imageNode: TransformImageNode
|
||||
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
private let buttonTitleNode: TextNode
|
||||
|
||||
private var absoluteRect: (CGRect, CGSize)?
|
||||
|
||||
private let fetchDisposable = MetaDisposable()
|
||||
|
||||
required init() {
|
||||
self.mediaBackgroundNode = NavigationBackgroundNode(color: .clear)
|
||||
self.mediaBackgroundNode.clipsToBounds = true
|
||||
self.mediaBackgroundNode.cornerRadius = 24.0
|
||||
|
||||
self.subtitleNode = TextNode()
|
||||
self.subtitleNode.isUserInteractionEnabled = false
|
||||
self.subtitleNode.displaysAsynchronously = false
|
||||
|
||||
self.imageNode = TransformImageNode()
|
||||
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
self.buttonNode.clipsToBounds = true
|
||||
self.buttonNode.cornerRadius = 17.0
|
||||
|
||||
self.buttonTitleNode = TextNode()
|
||||
self.buttonTitleNode.isUserInteractionEnabled = false
|
||||
self.buttonTitleNode.displaysAsynchronously = false
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.mediaBackgroundNode)
|
||||
self.addSubnode(self.subtitleNode)
|
||||
self.addSubnode(self.imageNode)
|
||||
|
||||
self.addSubnode(self.buttonNode)
|
||||
self.addSubnode(self.buttonTitleNode)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.buttonNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.buttonNode.alpha = 0.4
|
||||
strongSelf.buttonTitleNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.buttonTitleNode.alpha = 0.4
|
||||
} else {
|
||||
strongSelf.buttonNode.alpha = 1.0
|
||||
strongSelf.buttonNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
strongSelf.buttonTitleNode.alpha = 1.0
|
||||
strongSelf.buttonTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.fetchDisposable.dispose()
|
||||
}
|
||||
|
||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||
if self.item?.message.id == messageId {
|
||||
return (self.imageNode, self.imageNode.bounds, { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
let resultView = strongSelf.imageNode.view.snapshotContentTree(unhide: true)
|
||||
return (resultView, nil)
|
||||
})
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func updateHiddenMedia(_ media: [Media]?) -> Bool {
|
||||
var mediaHidden = false
|
||||
var currentMedia: Media?
|
||||
if let item = item {
|
||||
mediaLoop: for media in item.message.media {
|
||||
if let media = media as? TelegramMediaAction {
|
||||
switch media.action {
|
||||
case let .suggestedProfilePhoto(image):
|
||||
currentMedia = image
|
||||
break mediaLoop
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let currentMedia = currentMedia, let media = media {
|
||||
for item in media {
|
||||
if item.isSemanticallyEqual(to: currentMedia) {
|
||||
mediaHidden = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.imageNode.isHidden = mediaHidden
|
||||
return mediaHidden
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
guard let item = self.item else {
|
||||
return
|
||||
}
|
||||
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
||||
}
|
||||
|
||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||
let makeImageLayout = self.imageNode.asyncLayout()
|
||||
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
|
||||
let makeButtonTitleLayout = TextNode.asyncLayout(self.buttonTitleNode)
|
||||
|
||||
let currentItem = self.item
|
||||
|
||||
return { item, layoutConstants, _, _, _, _ in
|
||||
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center)
|
||||
|
||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||
let width: CGFloat = 220.0
|
||||
let imageSize = CGSize(width: 100.0, height: 100.0)
|
||||
|
||||
let primaryTextColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText
|
||||
|
||||
var wallpaper: TelegramWallpaper?
|
||||
if let media = item.message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .setChatWallpaper(wallpaperValue) = media.action {
|
||||
wallpaper = wallpaperValue
|
||||
}
|
||||
|
||||
var mediaUpdated = true
|
||||
if let wallpaper = wallpaper, let media = currentItem?.message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .setChatWallpaper(currentWallpaper) = media.action {
|
||||
mediaUpdated = wallpaper != currentWallpaper
|
||||
}
|
||||
|
||||
var media: WallpaperPreviewMedia?
|
||||
if let wallpaper {
|
||||
media = WallpaperPreviewMedia(wallpaper: wallpaper)
|
||||
}
|
||||
|
||||
let fromYou = item.message.author?.id == item.context.account.peerId
|
||||
|
||||
let peerName = item.message.peers[item.message.id.peerId].flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
||||
let text: String
|
||||
if fromYou {
|
||||
text = item.presentationData.strings.Notification_YouChangedWallpaper
|
||||
} else {
|
||||
text = item.presentationData.strings.Notification_ChangedWallpaper(peerName).string
|
||||
}
|
||||
|
||||
let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: primaryTextColor)
|
||||
let bold = MarkdownAttributeSet(font: Font.semibold(13.0), textColor: primaryTextColor)
|
||||
|
||||
let subtitle = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in
|
||||
return nil
|
||||
}), textAlignment: .center)
|
||||
|
||||
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Notification_Wallpaper_View, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let backgroundSize = CGSize(width: width, height: subtitleLayout.size.height + 145.0 + (fromYou ? 0.0 : 37.0))
|
||||
|
||||
return (backgroundSize.width, { boundingWidth in
|
||||
return (backgroundSize, { [weak self] animation, synchronousLoads, _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
|
||||
strongSelf.buttonNode.isHidden = fromYou
|
||||
strongSelf.buttonTitleNode.isHidden = fromYou
|
||||
|
||||
let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: 13.0), size: imageSize)
|
||||
if let media {
|
||||
if mediaUpdated {
|
||||
// strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(context: item.context, userLocation: .peer(item.message.id.peerId), photoReference: .message(message: MessageReference(item.message), media: photo), displayAtSize: nil, storeToDownloadsPeerId: nil).start())
|
||||
}
|
||||
|
||||
let boundingSize = imageSize
|
||||
var imageSize = boundingSize
|
||||
let updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
||||
switch media.content {
|
||||
case let .file(file, _, _, _, _, _):
|
||||
var representations: [ImageRepresentationWithReference] = file.previewRepresentations.map({ ImageRepresentationWithReference(representation: $0, reference: AnyMediaReference.message(message: MessageReference(item.message), media: file).resourceReference($0.resource)) })
|
||||
if file.mimeType == "image/svg+xml" || file.mimeType == "application/x-tgwallpattern" {
|
||||
representations.append(ImageRepresentationWithReference(representation: .init(dimensions: PixelDimensions(width: 1440, height: 2960), resource: file.resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false), reference: AnyMediaReference.message(message: MessageReference(item.message), media: file).resourceReference(file.resource)))
|
||||
}
|
||||
if ["image/png", "image/svg+xml", "application/x-tgwallpattern"].contains(file.mimeType) {
|
||||
updateImageSignal = patternWallpaperImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, representations: representations, mode: .screen)
|
||||
|> mapToSignal { value -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
|
||||
if let value {
|
||||
return .single(value)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let dimensions = file.dimensions?.cgSize {
|
||||
imageSize = dimensions.aspectFilled(boundingSize)
|
||||
}
|
||||
updateImageSignal = wallpaperImage(account: item.context.account, accountManager: item.context.sharedContext.accountManager, fileReference: FileMediaReference.message(message: MessageReference(item.message), media: file), representations: representations, alwaysShowThumbnailFirst: true, thumbnail: true, autoFetchFullSize: true)
|
||||
}
|
||||
case let .color(color):
|
||||
updateImageSignal = solidColorImage(color)
|
||||
case let .gradient(colors, rotation):
|
||||
updateImageSignal = gradientImage(colors.map(UIColor.init(rgb:)), rotation: rotation ?? 0)
|
||||
case .themeSettings:
|
||||
updateImageSignal = .complete()
|
||||
}
|
||||
|
||||
strongSelf.imageNode.setSignal(updateImageSignal, attemptSynchronously: synchronousLoads)
|
||||
|
||||
let arguments = TransformImageArguments(corners: ImageCorners(radius: boundingSize.width / 2.0), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets())
|
||||
let apply = makeImageLayout(arguments)
|
||||
apply()
|
||||
|
||||
strongSelf.imageNode.frame = imageFrame
|
||||
}
|
||||
|
||||
let mediaBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize)
|
||||
strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame
|
||||
|
||||
strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: item.controllerInteraction.enableFullTranslucency && dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)
|
||||
strongSelf.mediaBackgroundNode.update(size: mediaBackgroundFrame.size, transition: .immediate)
|
||||
strongSelf.buttonNode.backgroundColor = item.presentationData.theme.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12)
|
||||
|
||||
let _ = subtitleApply()
|
||||
let _ = buttonTitleApply()
|
||||
|
||||
let subtitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 127.0), size: subtitleLayout.size)
|
||||
strongSelf.subtitleNode.frame = subtitleFrame
|
||||
|
||||
let buttonTitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonTitleLayout.size.width) / 2.0), y: subtitleFrame.maxY + 18.0), size: buttonTitleLayout.size)
|
||||
strongSelf.buttonTitleNode.frame = buttonTitleFrame
|
||||
|
||||
let buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0)
|
||||
strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: subtitleFrame.maxY + 10.0), size: buttonSize)
|
||||
|
||||
if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true {
|
||||
if strongSelf.mediaBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||
strongSelf.mediaBackgroundNode.isHidden = true
|
||||
backgroundContent.clipsToBounds = true
|
||||
backgroundContent.allowsGroupOpacity = true
|
||||
backgroundContent.cornerRadius = 24.0
|
||||
|
||||
strongSelf.mediaBackgroundContent = backgroundContent
|
||||
strongSelf.insertSubnode(backgroundContent, at: 0)
|
||||
}
|
||||
|
||||
strongSelf.mediaBackgroundContent?.frame = mediaBackgroundFrame
|
||||
} else {
|
||||
strongSelf.mediaBackgroundNode.isHidden = false
|
||||
strongSelf.mediaBackgroundContent?.removeFromSupernode()
|
||||
strongSelf.mediaBackgroundContent = nil
|
||||
}
|
||||
|
||||
if let (rect, size) = strongSelf.absoluteRect {
|
||||
strongSelf.updateAbsoluteRect(rect, within: size)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||
self.absoluteRect = (rect, containerSize)
|
||||
|
||||
if let mediaBackgroundContent = self.mediaBackgroundContent {
|
||||
var backgroundFrame = mediaBackgroundContent.frame
|
||||
backgroundFrame.origin.x += rect.minX
|
||||
backgroundFrame.origin.y += rect.minY
|
||||
mediaBackgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||
if self.mediaBackgroundNode.frame.contains(point) {
|
||||
return .openMessage
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
}
|
||||
}
|
@ -1406,7 +1406,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
}))
|
||||
|
||||
items[.peerSettings]!.append(PeerInfoScreenActionItem(id: ItemIntro, text: "Edit Intro", icon: UIImage(bundleImageName: "Peer Info/BotIntro"), action: {
|
||||
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: {
|
||||
interaction.openPeerMention("botfather", .withBotStartPayload(ChatControllerInitialBotStart(payload: "\(user.addressName ?? "")-commands", behavior: .interactive)))
|
||||
@ -4132,7 +4132,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
}
|
||||
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):
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer), attachBotStart: attachBotStart))
|
||||
case let .withBotApp(botAppStart):
|
||||
|
@ -45,3 +45,18 @@ final class WallpaperPreviewMedia: Media {
|
||||
return self.isEqual(to: other)
|
||||
}
|
||||
}
|
||||
|
||||
extension WallpaperPreviewMedia {
|
||||
convenience init?(wallpaper: TelegramWallpaper) {
|
||||
switch wallpaper {
|
||||
case let .color(color):
|
||||
self.init(content: .color(UIColor(rgb: color)))
|
||||
case let .gradient(gradient):
|
||||
self.init(content: .gradient(gradient.colors, gradient.settings.rotation))
|
||||
case let .file(file):
|
||||
self.init(content: .file(file: file.file, colors: file.settings.colors, rotation: file.settings.rotation, intensity: file.settings.intensity, false, false))
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user