mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
1169 lines
61 KiB
Swift
1169 lines
61 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import QuickLook
|
|
import Postbox
|
|
import SwiftSignalKit
|
|
import AsyncDisplayKit
|
|
import TelegramCore
|
|
import Photos
|
|
import TelegramPresentationData
|
|
import TelegramUIPreferences
|
|
import MediaResources
|
|
import AccountContext
|
|
import ShareController
|
|
import GalleryUI
|
|
import HexColor
|
|
import CounterContollerTitleView
|
|
import UndoUI
|
|
import LegacyComponents
|
|
import LegacyMediaPickerUI
|
|
|
|
public enum WallpaperListType {
|
|
case wallpapers(WallpaperPresentationOptions?)
|
|
case colors
|
|
}
|
|
|
|
public enum WallpaperListSource {
|
|
case list(wallpapers: [TelegramWallpaper], central: TelegramWallpaper, type: WallpaperListType)
|
|
case wallpaper(TelegramWallpaper, WallpaperPresentationOptions?, [UInt32], Int32?, Int32?, Message?)
|
|
case slug(String, TelegramMediaFile?, WallpaperPresentationOptions?, [UInt32], Int32?, Int32?, Message?)
|
|
case asset(PHAsset)
|
|
case contextResult(ChatContextResult)
|
|
case customColor(UInt32?)
|
|
}
|
|
|
|
private func areMessagesEqual(_ lhsMessage: Message?, _ rhsMessage: Message?) -> Bool {
|
|
if lhsMessage == nil && rhsMessage == nil {
|
|
return true
|
|
}
|
|
guard let lhsMessage = lhsMessage, let rhsMessage = rhsMessage else {
|
|
return false
|
|
}
|
|
if lhsMessage.stableVersion != rhsMessage.stableVersion {
|
|
return false
|
|
}
|
|
if lhsMessage.id != rhsMessage.id || lhsMessage.flags != rhsMessage.flags {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
public enum WallpaperGalleryEntry: Equatable {
|
|
case wallpaper(TelegramWallpaper, Message?)
|
|
case asset(PHAsset)
|
|
case contextResult(ChatContextResult)
|
|
|
|
public static func ==(lhs: WallpaperGalleryEntry, rhs: WallpaperGalleryEntry) -> Bool {
|
|
switch lhs {
|
|
case let .wallpaper(lhsWallpaper, lhsMessage):
|
|
if case let .wallpaper(rhsWallpaper, rhsMessage) = rhs, lhsWallpaper == rhsWallpaper, areMessagesEqual(lhsMessage, rhsMessage) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .asset(lhsAsset):
|
|
if case let .asset(rhsAsset) = rhs, lhsAsset.localIdentifier == rhsAsset.localIdentifier {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case let .contextResult(lhsResult):
|
|
if case let .contextResult(rhsResult) = rhs, lhsResult.id == rhsResult.id {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class WallpaperGalleryOverlayNode: ASDisplayNode {
|
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
let result = super.hitTest(point, with: event)
|
|
if result != self.view {
|
|
return result
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
class WallpaperGalleryControllerNode: GalleryControllerNode {
|
|
var nativeStatusBar: StatusBar?
|
|
|
|
override func updateDistanceFromEquilibrium(_ value: CGFloat) {
|
|
guard let itemNode = self.pager.centralItemNode() as? WallpaperGalleryItemNode else {
|
|
return
|
|
}
|
|
|
|
itemNode.updateDismissTransition(value)
|
|
}
|
|
|
|
override func didLoad() {
|
|
super.didLoad()
|
|
|
|
self.scrollView.isScrollEnabled = false
|
|
self.view.interactiveTransitionGestureRecognizerTest = { point in
|
|
if point.x < 44.0 {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
//self.view.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:))))
|
|
}
|
|
|
|
@objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) {
|
|
switch recognizer.state {
|
|
case .began:
|
|
self.setControlsHidden(true, animated: false)
|
|
|
|
self.overlayNode?.alpha = 0.0
|
|
self.nativeStatusBar?.updateAlpha(0.0, transition: .immediate)
|
|
|
|
if let itemNode = self.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
itemNode.updateDismissTransition(self.bounds.size.height)
|
|
}
|
|
case .ended, .cancelled:
|
|
self.setControlsHidden(false, animated: false)
|
|
|
|
self.overlayNode?.alpha = 1.0
|
|
self.nativeStatusBar?.updateAlpha(1.0, transition: .immediate)
|
|
|
|
if let itemNode = self.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
itemNode.updateDismissTransition(0.0)
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
private func updatedFileWallpaper(wallpaper: TelegramWallpaper, colors: [UInt32], intensity: Int32?, rotation: Int32?) -> TelegramWallpaper {
|
|
if case let .file(file) = wallpaper {
|
|
return updatedFileWallpaper(id: file.id, accessHash: file.accessHash, slug: file.slug, file: file.file, colors: colors, intensity: intensity, rotation: rotation)
|
|
} else {
|
|
return wallpaper
|
|
}
|
|
}
|
|
|
|
private func updatedFileWallpaper(id: Int64? = nil, accessHash: Int64? = nil, slug: String, file: TelegramMediaFile, colors: [UInt32], intensity: Int32?, rotation: Int32?) -> TelegramWallpaper {
|
|
var isPattern = ["image/png", "image/svg+xml", "application/x-tgwallpattern"].contains(file.mimeType)
|
|
if let fileName = file.fileName, fileName.hasSuffix(".svgbg") {
|
|
isPattern = true
|
|
}
|
|
var colorValues: [UInt32] = []
|
|
var intensityValue: Int32?
|
|
if !colors.isEmpty {
|
|
colorValues = colors
|
|
intensityValue = intensity ?? 50
|
|
} else {
|
|
colorValues = [0xd6e2ee]
|
|
intensityValue = 50
|
|
}
|
|
|
|
return .file(TelegramWallpaper.File(id: id ?? 0, accessHash: accessHash ?? 0, isCreator: false, isDefault: false, isPattern: isPattern, isDark: false, slug: slug, file: file, settings: WallpaperSettings(colors: colorValues, intensity: intensityValue, rotation: rotation)))
|
|
}
|
|
|
|
class WallpaperGalleryInteraction {
|
|
let editMedia: (PHAsset, UIImage, CGRect, TGMediaEditAdjustments?, UIView, @escaping (UIImage?, TGMediaEditAdjustments?) -> Void, @escaping (UIImage?) -> Void) -> Void
|
|
let beginTransitionToEditor: () -> Void
|
|
let beginTransitionFromEditor: () -> Void
|
|
let finishTransitionFromEditor: () -> Void
|
|
|
|
init(editMedia: @escaping (PHAsset, UIImage, CGRect, TGMediaEditAdjustments?, UIView, @escaping (UIImage?, TGMediaEditAdjustments?) -> Void, @escaping (UIImage?) -> Void) -> Void, beginTransitionToEditor: @escaping () -> Void, beginTransitionFromEditor: @escaping () -> Void, finishTransitionFromEditor: @escaping () -> Void) {
|
|
self.editMedia = editMedia
|
|
self.beginTransitionToEditor = beginTransitionToEditor
|
|
self.beginTransitionFromEditor = beginTransitionFromEditor
|
|
self.finishTransitionFromEditor = finishTransitionFromEditor
|
|
}
|
|
}
|
|
|
|
public class WallpaperGalleryController: ViewController {
|
|
public enum Mode {
|
|
case `default`
|
|
case peer(EnginePeer, Bool)
|
|
}
|
|
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, UIImage?, CGRect?, CGFloat?) -> Void)?
|
|
|
|
private var interaction: WallpaperGalleryInteraction?
|
|
|
|
private let _ready = Promise<Bool>()
|
|
override public var ready: Promise<Bool> {
|
|
return self._ready
|
|
}
|
|
private var didSetReady = false
|
|
private var didBeginSettingReady = false
|
|
|
|
private let disposable = MetaDisposable()
|
|
|
|
private var presentationData: PresentationData
|
|
private var presentationDataDisposable: Disposable?
|
|
|
|
private var initialOptions: WallpaperPresentationOptions?
|
|
|
|
private var initialEntries: [WallpaperGalleryEntry] = []
|
|
private var entries: [WallpaperGalleryEntry] = []
|
|
private var centralEntryIndex: Int?
|
|
private var previousCentralEntryIndex: Int?
|
|
|
|
private let centralItemSubtitle = Promise<String?>()
|
|
private let centralItemStatus = Promise<MediaResourceStatus>()
|
|
private let centralItemAction = Promise<UIBarButtonItem?>()
|
|
private let centralItemAttributesDisposable = DisposableSet();
|
|
|
|
private var validLayout: (ContainerViewLayout, CGFloat)?
|
|
|
|
private var overlayNode: WallpaperGalleryOverlayNode?
|
|
private var toolbarNode: WallpaperGalleryToolbarNode?
|
|
private var patternPanelNode: WallpaperPatternPanelNode?
|
|
private var colorsPanelNode: WallpaperColorPanelNode?
|
|
|
|
private var patternInitialWallpaper: TelegramWallpaper?
|
|
private var patternPanelEnabled = false
|
|
private var colorsPanelEnabled = false
|
|
|
|
private var savedPatternWallpaper: TelegramWallpaper?
|
|
private var savedPatternIntensity: Int32?
|
|
|
|
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)
|
|
|
|
self.navigationPresentation = .modal
|
|
|
|
self.title = self.presentationData.strings.WallpaperPreview_Title
|
|
//self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
|
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
|
|
|
self.interaction = WallpaperGalleryInteraction(editMedia: { [weak self] asset, image, cropRect, adjustments, referenceView, apply, fullSizeApply in
|
|
guard let self else {
|
|
return
|
|
}
|
|
let item = LegacyWallpaperItem(asset: asset, screenImage: image, dimensions: CGSize(width: asset.pixelWidth, height: asset.pixelHeight))
|
|
legacyWallpaperEditor(context: context, item: item, cropRect: cropRect, adjustments: adjustments, referenceView: referenceView, beginTransitionOut: { [weak self] in
|
|
self?.interaction?.beginTransitionFromEditor()
|
|
}, finishTransitionOut: { [weak self] in
|
|
self?.interaction?.finishTransitionFromEditor()
|
|
}, completion: { image, adjustments in
|
|
apply(image, adjustments)
|
|
}, fullSizeCompletion: { image in
|
|
fullSizeApply(image)
|
|
}, present: { [weak self] c, a in
|
|
if let self {
|
|
self.present(c, in: .window(.root))
|
|
}
|
|
})
|
|
}, beginTransitionToEditor: { [weak self] in
|
|
guard let self else {
|
|
return
|
|
}
|
|
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)
|
|
if let toolbarNode = self.toolbarNode {
|
|
transition.updateAlpha(node: toolbarNode, alpha: 0.0)
|
|
}
|
|
}, beginTransitionFromEditor: { [weak self] in
|
|
guard let self else {
|
|
return
|
|
}
|
|
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)
|
|
if let toolbarNode = self.toolbarNode {
|
|
transition.updateAlpha(node: toolbarNode, alpha: 1.0)
|
|
}
|
|
if let centralItemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
centralItemNode.beginTransitionFromEditor()
|
|
}
|
|
}, finishTransitionFromEditor: { [weak self] in
|
|
guard let self else {
|
|
return
|
|
}
|
|
if let centralItemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
centralItemNode.finishTransitionFromEditor()
|
|
}
|
|
})
|
|
|
|
var entries: [WallpaperGalleryEntry] = []
|
|
var centralEntryIndex: Int?
|
|
switch source {
|
|
case let .list(wallpapers, central, type):
|
|
entries = wallpapers.map { .wallpaper($0, nil) }
|
|
centralEntryIndex = wallpapers.firstIndex(of: central)!
|
|
|
|
if case let .wallpapers(wallpaperOptions) = type, let options = wallpaperOptions {
|
|
self.initialOptions = options
|
|
}
|
|
case let .slug(slug, file, options, colors, intensity, rotation, message):
|
|
if let file = file {
|
|
let wallpaper = updatedFileWallpaper(slug: slug, file: file, colors: colors, intensity: intensity, rotation: rotation)
|
|
entries = [.wallpaper(wallpaper, message)]
|
|
centralEntryIndex = 0
|
|
self.initialOptions = options
|
|
}
|
|
case let .wallpaper(wallpaper, options, colors, intensity, rotation, message):
|
|
let wallpaper = updatedFileWallpaper(wallpaper: wallpaper, colors: colors, intensity: intensity, rotation: rotation)
|
|
entries = [.wallpaper(wallpaper, message)]
|
|
centralEntryIndex = 0
|
|
self.initialOptions = options
|
|
case let .asset(asset):
|
|
entries = [.asset(asset)]
|
|
centralEntryIndex = 0
|
|
case let .contextResult(result):
|
|
entries = [.contextResult(result)]
|
|
centralEntryIndex = 0
|
|
case let .customColor(color):
|
|
let initialColor: UInt32 = color ?? 0x000000
|
|
entries = [.wallpaper(.color(initialColor), nil)]
|
|
centralEntryIndex = 0
|
|
}
|
|
|
|
self.entries = entries
|
|
self.initialEntries = entries
|
|
self.centralEntryIndex = centralEntryIndex
|
|
|
|
self.presentationDataDisposable = (context.sharedContext.presentationData
|
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
|
if let strongSelf = self {
|
|
let previousTheme = strongSelf.presentationData.theme
|
|
let previousStrings = strongSelf.presentationData.strings
|
|
|
|
strongSelf.presentationData = presentationData
|
|
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
|
strongSelf.updateThemeAndStrings()
|
|
}
|
|
}
|
|
})
|
|
|
|
self.centralItemAttributesDisposable.add(self.centralItemSubtitle.get().start(next: { [weak self] subtitle in
|
|
if let strongSelf = self {
|
|
if let subtitle = subtitle {
|
|
let titleView = CounterContollerTitleView(theme: strongSelf.presentationData.theme)
|
|
titleView.title = CounterContollerTitle(title: strongSelf.presentationData.strings.WallpaperPreview_Title, counter: subtitle)
|
|
strongSelf.navigationItem.titleView = titleView
|
|
strongSelf.title = nil
|
|
} else {
|
|
strongSelf.navigationItem.titleView = nil
|
|
strongSelf.title = strongSelf.presentationData.strings.WallpaperPreview_Title
|
|
}
|
|
}
|
|
}))
|
|
|
|
self.centralItemAttributesDisposable.add(self.centralItemStatus.get().start(next: { [weak self] status in
|
|
if let strongSelf = self {
|
|
let enabled: Bool
|
|
switch status {
|
|
case .Local:
|
|
enabled = true
|
|
default:
|
|
enabled = false
|
|
}
|
|
strongSelf.toolbarNode?.setDoneEnabled(enabled)
|
|
}
|
|
}))
|
|
|
|
self.centralItemAttributesDisposable.add(self.centralItemAction.get().start(next: { [weak self] barButton in
|
|
if let strongSelf = self {
|
|
strongSelf.navigationItem.rightBarButtonItem = barButton
|
|
}
|
|
}))
|
|
}
|
|
|
|
required public init(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
deinit {
|
|
self.disposable.dispose()
|
|
self.presentationDataDisposable?.dispose()
|
|
self.centralItemAttributesDisposable.dispose()
|
|
}
|
|
|
|
private func updateThemeAndStrings() {
|
|
if self.title != nil {
|
|
self.title = self.presentationData.strings.WallpaperPreview_Title
|
|
}
|
|
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
|
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
|
|
self.toolbarNode?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings)
|
|
self.patternPanelNode?.updateTheme(self.presentationData.theme)
|
|
|
|
self.colorsPanelNode?.updateTheme(self.presentationData.theme)
|
|
}
|
|
|
|
func dismiss(forceAway: Bool) {
|
|
// let completion: () -> Void = { [weak self] in
|
|
// self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
|
// }
|
|
self.presentingViewController?.dismiss(animated: true, completion: nil)
|
|
//self.galleryNode.modalAnimateOut(completion: completion)
|
|
}
|
|
|
|
private func updateTransaction(entries: [WallpaperGalleryEntry], arguments: WallpaperGalleryItemArguments) -> GalleryPagerTransaction {
|
|
var i: Int = 0
|
|
var updateItems: [GalleryPagerUpdateItem] = []
|
|
for entry in entries {
|
|
let item = GalleryPagerUpdateItem(index: i, previousIndex: i, item: WallpaperGalleryItem(context: self.context, index: updateItems.count, entry: entry, arguments: arguments, source: self.source, mode: self.mode, interaction: self.interaction!))
|
|
updateItems.append(item)
|
|
i += 1
|
|
}
|
|
return GalleryPagerTransaction(deleteItems: [], insertItems: [], updateItems: updateItems, focusOnItem: self.galleryNode.pager.centralItemNode()?.index, synchronous: false)
|
|
}
|
|
|
|
private func updateCurrentEntryTransaction(entry: WallpaperGalleryEntry, arguments: WallpaperGalleryItemArguments, index: Int) -> GalleryPagerTransaction {
|
|
var updateItems: [GalleryPagerUpdateItem] = []
|
|
for i in 0 ..< self.entries.count {
|
|
if i == index {
|
|
let item = GalleryPagerUpdateItem(index: index, previousIndex: index, item: WallpaperGalleryItem(context: self.context, index: index, entry: entry, arguments: arguments, source: self.source, mode: self.mode, interaction: self.interaction!))
|
|
updateItems.append(item)
|
|
}
|
|
}
|
|
return GalleryPagerTransaction(deleteItems: [], insertItems: [], updateItems: updateItems, focusOnItem: self.galleryNode.pager.centralItemNode()?.index, synchronous: false)
|
|
}
|
|
|
|
override public func loadDisplayNode() {
|
|
let controllerInteraction = GalleryControllerInteraction(presentController: { [weak self] controller, arguments in
|
|
if let strongSelf = self {
|
|
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
|
}
|
|
}, pushController: { _ in
|
|
}, dismissController: { [weak self] in
|
|
self?.dismiss(forceAway: true)
|
|
}, replaceRootController: { controller, ready in
|
|
}, editMedia: { _ in
|
|
})
|
|
self.displayNode = WallpaperGalleryControllerNode(controllerInteraction: controllerInteraction, pageGap: 0.0, disableTapNavigation: true)
|
|
self.displayNodeDidLoad()
|
|
|
|
(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)
|
|
}
|
|
|
|
var currentCentralItemIndex: Int?
|
|
self.galleryNode.pager.centralItemIndexUpdated = { [weak self] index in
|
|
if let strongSelf = self {
|
|
let updated = currentCentralItemIndex != index
|
|
currentCentralItemIndex = index
|
|
strongSelf.bindCentralItemNode(animated: true, updated: updated)
|
|
}
|
|
}
|
|
|
|
self.galleryNode.backgroundNode.backgroundColor = nil
|
|
self.galleryNode.backgroundNode.isOpaque = false
|
|
self.galleryNode.isBackgroundExtendedOverNavigationBar = true
|
|
|
|
switch self.source {
|
|
case .asset, .contextResult, .customColor:
|
|
self.galleryNode.scrollView.isScrollEnabled = false
|
|
default:
|
|
break
|
|
}
|
|
|
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
|
let overlayNode = WallpaperGalleryOverlayNode()
|
|
self.overlayNode = overlayNode
|
|
self.galleryNode.overlayNode = overlayNode
|
|
self.galleryNode.addSubnode(overlayNode)
|
|
|
|
var doneButtonType: WallpaperGalleryToolbarDoneButtonType = .set
|
|
switch self.source {
|
|
case let .wallpaper(wallpaper, _, _, _, _, _):
|
|
switch wallpaper {
|
|
case let .file(file):
|
|
if file.id == 0 {
|
|
doneButtonType = .none
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
if case .peer = self.mode {
|
|
doneButtonType = .setPeer
|
|
}
|
|
|
|
let toolbarNode = WallpaperGalleryToolbarNode(theme: presentationData.theme, strings: presentationData.strings, doneButtonType: doneButtonType)
|
|
switch self.source {
|
|
case .asset, .contextResult:
|
|
toolbarNode.dark = false
|
|
default:
|
|
toolbarNode.dark = true
|
|
}
|
|
self.toolbarNode = toolbarNode
|
|
overlayNode.addSubnode(toolbarNode)
|
|
|
|
toolbarNode.cancel = { [weak self] in
|
|
self?.dismiss(forceAway: true)
|
|
}
|
|
var dismissed = false
|
|
toolbarNode.done = { [weak self] in
|
|
if let strongSelf = self, !dismissed {
|
|
if let centralItemNode = strongSelf.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
if centralItemNode.cropNode.scrollNode.view.isDecelerating {
|
|
return
|
|
}
|
|
dismissed = true
|
|
let options = centralItemNode.options
|
|
if !strongSelf.entries.isEmpty {
|
|
let entry = strongSelf.entries[centralItemNode.index]
|
|
let apply = strongSelf.apply
|
|
if case .peer = strongSelf.mode {
|
|
if case let .wallpaper(wallpaper, _) = entry, options.contains(.blur) {
|
|
var resource: MediaResource?
|
|
switch wallpaper {
|
|
case let .file(file):
|
|
resource = file.file.resource
|
|
case let .image(representations, _):
|
|
if let largestSize = largestImageRepresentation(representations) {
|
|
resource = largestSize.resource
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
if let resource = resource {
|
|
let representation = CachedBlurredWallpaperRepresentation()
|
|
var data: Data?
|
|
if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
data = maybeData
|
|
} else if let path = strongSelf.context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
data = maybeData
|
|
}
|
|
|
|
if let data = data {
|
|
strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
|
let _ = (strongSelf.context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true)
|
|
|> filter({ $0.complete })
|
|
|> take(1)
|
|
|> deliverOnMainQueue).start(next: { _ in
|
|
apply?(entry, options, nil, nil, centralItemNode.brightness)
|
|
})
|
|
}
|
|
}
|
|
} else {
|
|
apply?(entry, options, centralItemNode.editedFullSizeImage, centralItemNode.editedCropRect, centralItemNode.brightness)
|
|
}
|
|
return
|
|
}
|
|
|
|
switch entry {
|
|
case let .wallpaper(wallpaper, _):
|
|
var resource: MediaResource?
|
|
switch wallpaper {
|
|
case let .file(file):
|
|
resource = file.file.resource
|
|
case let .image(representations, _):
|
|
if let largestSize = largestImageRepresentation(representations) {
|
|
resource = largestSize.resource
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
|
|
let completion: (TelegramWallpaper) -> Void = { wallpaper in
|
|
let baseSettings = wallpaper.settings
|
|
let updatedSettings = WallpaperSettings(blur: options.contains(.blur), motion: options.contains(.motion), colors: baseSettings?.colors ?? [], intensity: baseSettings?.intensity, rotation: baseSettings?.rotation)
|
|
let wallpaper = wallpaper.withUpdatedSettings(updatedSettings)
|
|
|
|
let autoNightModeTriggered = strongSelf.presentationData.autoNightModeTriggered
|
|
let _ = (updatePresentationThemeSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { current in
|
|
var themeSpecificChatWallpapers = current.themeSpecificChatWallpapers
|
|
let wallpaper = wallpaper.isBasicallyEqual(to: strongSelf.presentationData.theme.chat.defaultWallpaper) ? nil : wallpaper
|
|
let themeReference: PresentationThemeReference
|
|
if autoNightModeTriggered {
|
|
themeReference = current.automaticThemeSwitchSetting.theme
|
|
} else {
|
|
themeReference = current.theme
|
|
}
|
|
let accentColor = current.themeSpecificAccentColors[themeReference.index]
|
|
if let accentColor = accentColor, accentColor.baseColor == .custom {
|
|
themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: accentColor)] = wallpaper
|
|
} else {
|
|
themeSpecificChatWallpapers[coloredThemeIndex(reference: themeReference, accentColor: accentColor)] = nil
|
|
themeSpecificChatWallpapers[themeReference.index] = wallpaper
|
|
}
|
|
return current.withUpdatedThemeSpecificChatWallpapers(themeSpecificChatWallpapers)
|
|
}) |> deliverOnMainQueue).start(completed: {
|
|
self?.dismiss(animated: true)
|
|
})
|
|
|
|
switch strongSelf.source {
|
|
case .wallpaper, .slug:
|
|
let _ = saveWallpaper(account: strongSelf.context.account, wallpaper: wallpaper).start()
|
|
default:
|
|
break
|
|
}
|
|
let _ = installWallpaper(account: strongSelf.context.account, wallpaper: wallpaper).start()
|
|
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction in
|
|
WallpapersState.update(transaction: transaction, { state in
|
|
var state = state
|
|
if let index = state.wallpapers.firstIndex(where: {
|
|
$0.isBasicallyEqual(to: wallpaper)
|
|
}) {
|
|
state.wallpapers.remove(at: index)
|
|
}
|
|
state.wallpapers.insert(wallpaper, at: 0)
|
|
return state
|
|
})
|
|
}).start()
|
|
}
|
|
|
|
let applyWallpaper: (TelegramWallpaper) -> Void = { wallpaper in
|
|
if options.contains(.blur) {
|
|
if let resource = resource {
|
|
let representation = CachedBlurredWallpaperRepresentation()
|
|
var data: Data?
|
|
if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
data = maybeData
|
|
} else if let path = strongSelf.context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
data = maybeData
|
|
}
|
|
|
|
if let data = data {
|
|
strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
|
let _ = (strongSelf.context.sharedContext.accountManager.mediaBox.cachedResourceRepresentation(resource, representation: representation, complete: true, fetch: true)
|
|
|> filter({ $0.complete })
|
|
|> take(1)
|
|
|> deliverOnMainQueue).start(next: { _ in
|
|
completion(wallpaper)
|
|
})
|
|
}
|
|
}
|
|
} else if case let .file(file) = wallpaper, let resource = resource {
|
|
if wallpaper.isPattern, !file.settings.colors.isEmpty, let _ = file.settings.intensity {
|
|
var data: Data?
|
|
var thumbnailData: Data?
|
|
if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
data = maybeData
|
|
} else if let path = strongSelf.context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
data = maybeData
|
|
}
|
|
|
|
let thumbnailResource = file.file.previewRepresentations.first?.resource
|
|
|
|
if let resource = thumbnailResource {
|
|
if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
thumbnailData = maybeData
|
|
} else if let path = strongSelf.context.sharedContext.accountManager.mediaBox.completedResourcePath(resource), let maybeData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
thumbnailData = maybeData
|
|
}
|
|
}
|
|
|
|
if let data = data {
|
|
strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
|
if let thumbnailResource = thumbnailResource, let thumbnailData = thumbnailData {
|
|
strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(thumbnailResource.id, data: thumbnailData, synchronous: true)
|
|
}
|
|
completion(wallpaper)
|
|
}
|
|
} else if let path = strongSelf.context.account.postbox.mediaBox.completedResourcePath(file.file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
|
|
strongSelf.context.sharedContext.accountManager.mediaBox.storeResourceData(file.file.resource.id, data: data)
|
|
completion(wallpaper)
|
|
}
|
|
} else {
|
|
completion(wallpaper)
|
|
}
|
|
}
|
|
|
|
if case let .image(currentRepresentations, currentSettings) = wallpaper {
|
|
let _ = (strongSelf.context.wallpaperUploadManager!.stateSignal()
|
|
|> take(1)
|
|
|> deliverOnMainQueue).start(next: { status in
|
|
switch status {
|
|
case let .uploaded(uploadedWallpaper, resultWallpaper):
|
|
if case let .image(uploadedRepresentations, _) = uploadedWallpaper, uploadedRepresentations == currentRepresentations {
|
|
let updatedWallpaper = resultWallpaper.withUpdatedSettings(currentSettings)
|
|
applyWallpaper(updatedWallpaper)
|
|
return
|
|
}
|
|
case let .uploading(uploadedWallpaper, _):
|
|
if case let .image(uploadedRepresentations, uploadedSettings) = uploadedWallpaper, uploadedRepresentations == currentRepresentations, uploadedSettings != currentSettings {
|
|
let updatedWallpaper = uploadedWallpaper.withUpdatedSettings(currentSettings)
|
|
applyWallpaper(updatedWallpaper)
|
|
return
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
applyWallpaper(wallpaper)
|
|
})
|
|
} else {
|
|
var updatedWallpaper = wallpaper
|
|
if var settings = wallpaper.settings {
|
|
settings.motion = options.contains(.motion)
|
|
updatedWallpaper = updatedWallpaper.withUpdatedSettings(settings)
|
|
}
|
|
applyWallpaper(updatedWallpaper)
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
|
|
strongSelf.apply?(entry, options, nil, centralItemNode.cropRect, centralItemNode.brightness)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func currentEntry() -> WallpaperGalleryEntry? {
|
|
if let centralItemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
return centralItemNode.entry
|
|
} else if let centralEntryIndex = self.centralEntryIndex {
|
|
return self.entries[centralEntryIndex]
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
override public func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
|
|
//self.galleryNode.modalAnimateIn()
|
|
self.bindCentralItemNode(animated: false, updated: false)
|
|
|
|
if let centralItemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
centralItemNode.animateWallpaperAppeared()
|
|
}
|
|
}
|
|
|
|
private func bindCentralItemNode(animated: Bool, updated: Bool) {
|
|
if let node = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
self.centralItemSubtitle.set(node.subtitle.get())
|
|
self.centralItemStatus.set(node.status.get())
|
|
self.centralItemAction.set(node.actionButton.get())
|
|
node.action = { [weak self] in
|
|
self?.actionPressed()
|
|
}
|
|
node.requestPatternPanel = { [weak self] enabled, initialWallpaper in
|
|
if let strongSelf = self, let (layout, _) = strongSelf.validLayout {
|
|
strongSelf.colorsPanelEnabled = false
|
|
strongSelf.colorsPanelNode?.view.endEditing(true)
|
|
|
|
if !enabled {
|
|
strongSelf.savedPatternWallpaper = initialWallpaper
|
|
strongSelf.savedPatternIntensity = initialWallpaper.settings?.intensity
|
|
}
|
|
|
|
strongSelf.patternInitialWallpaper = enabled ? initialWallpaper : nil
|
|
switch initialWallpaper {
|
|
case let .color(color):
|
|
strongSelf.patternPanelNode?.backgroundColors = ([HSBColor(rgb: color)], nil, nil)
|
|
case let .gradient(gradient):
|
|
strongSelf.patternPanelNode?.backgroundColors = (gradient.colors.map { HSBColor(rgb: $0) }, gradient.settings.rotation, nil)
|
|
case let .file(file) where file.isPattern:
|
|
strongSelf.patternPanelNode?.backgroundColors = (file.settings.colors.map { HSBColor(rgb: $0) }, file.settings.rotation, file.settings.intensity)
|
|
default:
|
|
break
|
|
}
|
|
strongSelf.patternPanelNode?.serviceBackgroundColor = serviceColor(for: (initialWallpaper, nil))
|
|
strongSelf.patternPanelEnabled = enabled
|
|
if enabled {
|
|
strongSelf.patternPanelNode?.updateWallpapers()
|
|
strongSelf.patternPanelNode?.didAppear(initialWallpaper: strongSelf.savedPatternWallpaper, intensity: strongSelf.savedPatternIntensity)
|
|
} else {
|
|
switch initialWallpaper {
|
|
case .color, .gradient:
|
|
strongSelf.updateEntries(wallpaper: initialWallpaper)
|
|
case let .file(file):
|
|
if !file.settings.colors.isEmpty {
|
|
if file.settings.colors.count >= 2 {
|
|
strongSelf.updateEntries(wallpaper: .gradient(TelegramWallpaper.Gradient(id: nil, colors: file.settings.colors, settings: WallpaperSettings(rotation: file.settings.rotation))))
|
|
} else {
|
|
strongSelf.updateEntries(wallpaper: .color(file.settings.colors[0]))
|
|
}
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .spring))
|
|
}
|
|
}
|
|
|
|
node.toggleColorsPanel = { [weak self] colors in
|
|
if let strongSelf = self, let (layout, _) = strongSelf.validLayout, let colors = colors, let itemNode = strongSelf.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
strongSelf.patternPanelEnabled = false
|
|
strongSelf.colorsPanelEnabled = !strongSelf.colorsPanelEnabled
|
|
if !strongSelf.colorsPanelEnabled {
|
|
strongSelf.colorsPanelNode?.view.endEditing(true)
|
|
}
|
|
|
|
if strongSelf.colorsPanelEnabled {
|
|
strongSelf.colorsPanelNode?.updateState({ _ in
|
|
return WallpaperColorPanelNodeState(
|
|
selection: 0,
|
|
colors: colors.map { HSBColor(color: $0) },
|
|
maximumNumberOfColors: 4,
|
|
rotateAvailable: false,
|
|
rotation: 0,
|
|
preview: false,
|
|
simpleGradientGeneration: false
|
|
)
|
|
}, animated: false)
|
|
}
|
|
|
|
itemNode.updateIsColorsPanelActive(strongSelf.colorsPanelEnabled, animated: true)
|
|
|
|
strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .spring))
|
|
}
|
|
}
|
|
|
|
node.requestRotateGradient = { [weak self] angle in
|
|
guard let strongSelf = self, let _ = strongSelf.validLayout, let entry = strongSelf.currentEntry(), case let .wallpaper(wallpaper, _) = entry else {
|
|
return
|
|
}
|
|
var settings = wallpaper.settings ?? WallpaperSettings()
|
|
settings.rotation = angle
|
|
strongSelf.updateEntries(wallpaper: wallpaper.withUpdatedSettings(settings))
|
|
}
|
|
|
|
if updated {
|
|
if self.colorsPanelEnabled || self.patternPanelEnabled {
|
|
self.colorsPanelEnabled = false
|
|
self.colorsPanelNode?.view.endEditing(true)
|
|
self.patternPanelEnabled = false
|
|
|
|
if let (layout, _) = self.validLayout {
|
|
self.containerLayoutUpdated(layout, transition: .animated(duration: 0.3, curve: .spring))
|
|
}
|
|
}
|
|
}
|
|
if !self.didBeginSettingReady {
|
|
self.didBeginSettingReady = true
|
|
|
|
let ready = self.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak self] _ in
|
|
self?.didSetReady = true
|
|
}
|
|
self._ready.set(ready |> map { true })
|
|
}
|
|
}
|
|
}
|
|
|
|
private func updateEntries(color: UIColor, preview: Bool = false) {
|
|
guard self.validLayout != nil, let centralEntryIndex = self.galleryNode.pager.centralItemNode()?.index else {
|
|
return
|
|
}
|
|
|
|
var entries = self.entries
|
|
var currentEntry = entries[centralEntryIndex]
|
|
switch currentEntry {
|
|
case let .wallpaper(wallpaper, _):
|
|
switch wallpaper {
|
|
case .color:
|
|
currentEntry = .wallpaper(.color(color.argb), nil)
|
|
default:
|
|
break
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
entries[centralEntryIndex] = currentEntry
|
|
self.entries = entries
|
|
|
|
self.galleryNode.pager.transaction(self.updateTransaction(entries: entries, arguments: WallpaperGalleryItemArguments(colorPreview: preview, isColorsList: false, patternEnabled: self.patternPanelEnabled)))
|
|
}
|
|
|
|
private func updateEntries(wallpaper: TelegramWallpaper, preview: Bool = false) {
|
|
guard self.validLayout != nil, let centralEntryIndex = self.galleryNode.pager.centralItemNode()?.index else {
|
|
return
|
|
}
|
|
|
|
var entries = self.entries
|
|
var currentEntry = entries[centralEntryIndex]
|
|
switch currentEntry {
|
|
case .wallpaper:
|
|
currentEntry = .wallpaper(wallpaper, nil)
|
|
default:
|
|
break
|
|
}
|
|
entries[centralEntryIndex] = currentEntry
|
|
self.entries = entries
|
|
|
|
self.galleryNode.pager.transaction(self.updateCurrentEntryTransaction(entry: currentEntry, arguments: WallpaperGalleryItemArguments(colorPreview: preview, isColorsList: false, patternEnabled: self.patternPanelEnabled), index: centralEntryIndex))
|
|
}
|
|
|
|
private func updateEntries(pattern: TelegramWallpaper?, intensity: Int32? = nil, preview: Bool = false) {
|
|
var updatedEntries: [WallpaperGalleryEntry] = []
|
|
for entry in self.entries {
|
|
var entryColors: [UInt32] = []
|
|
if case let .wallpaper(wallpaper, _) = entry {
|
|
if case let .color(color) = wallpaper {
|
|
entryColors = [color]
|
|
} else if case let .file(file) = wallpaper, file.isPattern {
|
|
entryColors = file.settings.colors
|
|
} else if case let .gradient(gradient) = wallpaper {
|
|
entryColors = gradient.colors
|
|
}
|
|
}
|
|
|
|
if !entryColors.isEmpty {
|
|
if let pattern = pattern, case let .file(file) = pattern {
|
|
let newSettings = WallpaperSettings(blur: file.settings.blur, motion: file.settings.motion, colors: entryColors, intensity: intensity)
|
|
let newWallpaper = TelegramWallpaper.file(TelegramWallpaper.File(id: file.id, accessHash: file.accessHash, isCreator: file.isCreator, isDefault: file.isDefault, isPattern: pattern.isPattern, isDark: file.isDark, slug: file.slug, file: file.file, settings: newSettings))
|
|
updatedEntries.append(.wallpaper(newWallpaper, nil))
|
|
} else {
|
|
if entryColors.count == 1 {
|
|
let newWallpaper = TelegramWallpaper.color(entryColors[0])
|
|
updatedEntries.append(.wallpaper(newWallpaper, nil))
|
|
} else {
|
|
let newWallpaper = TelegramWallpaper.gradient(TelegramWallpaper.Gradient(id: nil, colors: entryColors, settings: WallpaperSettings(rotation: nil)))
|
|
updatedEntries.append(.wallpaper(newWallpaper, nil))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self.entries = updatedEntries
|
|
self.galleryNode.pager.transaction(self.updateTransaction(entries: updatedEntries, arguments: WallpaperGalleryItemArguments(colorPreview: preview, isColorsList: true, patternEnabled: self.patternPanelEnabled)))
|
|
}
|
|
|
|
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
|
let hadLayout = self.validLayout != nil
|
|
|
|
super.containerLayoutUpdated(layout, transition: transition)
|
|
|
|
let panelHeight: CGFloat = 235.0
|
|
|
|
var pagerLayout = layout
|
|
if self.patternPanelEnabled || self.colorsPanelEnabled {
|
|
pagerLayout.intrinsicInsets.bottom += panelHeight
|
|
}
|
|
pagerLayout.intrinsicInsets.bottom = max(pagerLayout.intrinsicInsets.bottom, layout.inputHeight ?? 0.0)
|
|
|
|
self.galleryNode.frame = CGRect(origin: CGPoint(), size: layout.size)
|
|
self.galleryNode.containerLayoutUpdated(pagerLayout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition)
|
|
self.overlayNode?.frame = self.galleryNode.bounds
|
|
|
|
let toolbarHeight: CGFloat = 66.0
|
|
transition.updateFrame(node: self.toolbarNode!, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - toolbarHeight - layout.intrinsicInsets.bottom), size: CGSize(width: layout.size.width, height: toolbarHeight + layout.intrinsicInsets.bottom)))
|
|
self.toolbarNode!.updateLayout(size: CGSize(width: layout.size.width, height: toolbarHeight), layout: layout, transition: transition)
|
|
|
|
var bottomInset = toolbarHeight + layout.intrinsicInsets.bottom
|
|
|
|
let currentPatternPanelNode: WallpaperPatternPanelNode
|
|
if let patternPanelNode = self.patternPanelNode {
|
|
currentPatternPanelNode = patternPanelNode
|
|
} else {
|
|
let patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: presentationData.theme, strings: presentationData.strings)
|
|
patternPanelNode.patternChanged = { [weak self] pattern, intensity, preview in
|
|
if let strongSelf = self, strongSelf.validLayout != nil, let patternInitialWallpaper = strongSelf.patternInitialWallpaper {
|
|
var colors: [UInt32] = []
|
|
var rotation: Int32?
|
|
switch patternInitialWallpaper {
|
|
case let .color(color):
|
|
colors = [color]
|
|
case let .file(file):
|
|
colors = file.settings.colors
|
|
rotation = file.settings.rotation
|
|
case let .gradient(gradient):
|
|
colors = gradient.colors
|
|
rotation = gradient.settings.rotation
|
|
default:
|
|
break
|
|
}
|
|
switch patternInitialWallpaper {
|
|
case .color, .file, .gradient:
|
|
if let pattern = pattern, case let .file(file) = pattern {
|
|
let newSettings = WallpaperSettings(blur: file.settings.blur, motion: file.settings.motion, colors: colors, intensity: intensity)
|
|
let newWallpaper = TelegramWallpaper.file(TelegramWallpaper.File(id: file.id, accessHash: file.accessHash, isCreator: file.isCreator, isDefault: file.isDefault, isPattern: pattern.isPattern, isDark: file.isDark, slug: file.slug, file: file.file, settings: newSettings))
|
|
|
|
strongSelf.savedPatternWallpaper = newWallpaper
|
|
strongSelf.savedPatternIntensity = intensity
|
|
|
|
strongSelf.updateEntries(wallpaper: newWallpaper, preview: preview)
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
|
|
strongSelf.patternPanelNode?.backgroundColors = (colors.map { HSBColor(rgb: $0) }, rotation, intensity)
|
|
}
|
|
}
|
|
self.patternPanelNode = patternPanelNode
|
|
currentPatternPanelNode = patternPanelNode
|
|
self.overlayNode?.insertSubnode(patternPanelNode, belowSubnode: self.toolbarNode!)
|
|
}
|
|
|
|
let currentColorsPanelNode: WallpaperColorPanelNode
|
|
if let current = self.colorsPanelNode {
|
|
currentColorsPanelNode = current
|
|
} else {
|
|
let colorsPanelNode = WallpaperColorPanelNode(theme: self.presentationData.theme, strings: self.presentationData.strings)
|
|
self.colorsPanelNode = colorsPanelNode
|
|
currentColorsPanelNode = colorsPanelNode
|
|
self.overlayNode?.insertSubnode(colorsPanelNode, belowSubnode: self.toolbarNode!)
|
|
|
|
colorsPanelNode.colorsChanged = { [weak self] colors, _, _ in
|
|
guard let strongSelf = self else {
|
|
return
|
|
}
|
|
guard let entry = strongSelf.currentEntry(), case let .wallpaper(currentWallpaper, _) = entry else {
|
|
return
|
|
}
|
|
|
|
var wallpaper: TelegramWallpaper = .gradient(TelegramWallpaper.Gradient(id: nil, colors: colors.map { $0.rgb }, settings: WallpaperSettings(blur: false, motion: false, colors: [], intensity: nil, rotation: nil)))
|
|
|
|
if case let .file(file) = currentWallpaper {
|
|
wallpaper = currentWallpaper.withUpdatedSettings(WallpaperSettings(blur: false, motion: false, colors: colors.map { $0.rgb }, intensity: file.settings.intensity, rotation: file.settings.rotation))
|
|
}
|
|
|
|
strongSelf.updateEntries(wallpaper: wallpaper)
|
|
}
|
|
}
|
|
|
|
let originalBottomInset = bottomInset
|
|
var patternPanelFrame = CGRect(x: 0.0, y: layout.size.height, width: layout.size.width, height: panelHeight)
|
|
if self.patternPanelEnabled {
|
|
patternPanelFrame.origin = CGPoint(x: 0.0, y: layout.size.height - max((layout.inputHeight ?? 0.0) - panelHeight + 44.0, bottomInset) - panelHeight)
|
|
bottomInset += panelHeight
|
|
}
|
|
|
|
transition.updateFrame(node: currentPatternPanelNode, frame: patternPanelFrame)
|
|
currentPatternPanelNode.updateLayout(size: patternPanelFrame.size, bottomInset: originalBottomInset, transition: transition)
|
|
|
|
var colorsPanelFrame = CGRect(x: 0.0, y: layout.size.height, width: layout.size.width, height: panelHeight)
|
|
if self.colorsPanelEnabled {
|
|
colorsPanelFrame.origin = CGPoint(x: 0.0, y: layout.size.height - max((layout.inputHeight ?? 0.0) - panelHeight + 44.0, bottomInset) - panelHeight)
|
|
bottomInset += panelHeight
|
|
}
|
|
|
|
transition.updateFrame(node: currentColorsPanelNode, frame: CGRect(origin: colorsPanelFrame.origin, size: CGSize(width: colorsPanelFrame.width, height: colorsPanelFrame.height + originalBottomInset)))
|
|
currentColorsPanelNode.updateLayout(size: colorsPanelFrame.size, bottomInset: originalBottomInset, transition: transition)
|
|
|
|
self.toolbarNode?.setDoneIsSolid(self.patternPanelEnabled || self.colorsPanelEnabled, transition: transition)
|
|
|
|
bottomInset += 66.0
|
|
|
|
self.validLayout = (layout, bottomInset)
|
|
if !hadLayout {
|
|
var colors = false
|
|
if case let .list(_, _, type) = self.source, case .colors = type {
|
|
colors = true
|
|
}
|
|
|
|
self.galleryNode.pager.replaceItems(zip(0 ..< self.entries.count, self.entries).map({ WallpaperGalleryItem(context: self.context, index: $0, entry: $1, arguments: WallpaperGalleryItemArguments(isColorsList: colors), source: self.source, mode: self.mode, interaction: self.interaction!) }), centralItemIndex: self.centralEntryIndex)
|
|
|
|
if let initialOptions = self.initialOptions, let itemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode {
|
|
itemNode.options = initialOptions
|
|
}
|
|
}
|
|
}
|
|
|
|
private func actionPressed() {
|
|
guard let entry = self.currentEntry(), case let .wallpaper(wallpaper, _) = entry, let itemNode = self.galleryNode.pager.centralItemNode() as? WallpaperGalleryItemNode else {
|
|
return
|
|
}
|
|
|
|
var controller: ShareController?
|
|
var options: [String] = []
|
|
if (itemNode.options.contains(.blur)) {
|
|
if (itemNode.options.contains(.motion)) {
|
|
options.append("mode=blur+motion")
|
|
} else {
|
|
options.append("mode=blur")
|
|
}
|
|
} else if (itemNode.options.contains(.motion)) {
|
|
options.append("mode=motion")
|
|
}
|
|
|
|
let context = self.context
|
|
switch wallpaper {
|
|
case .image:
|
|
let _ = (context.wallpaperUploadManager!.stateSignal()
|
|
|> take(1)
|
|
|> filter { status -> Bool in
|
|
return status.wallpaper == wallpaper
|
|
}).start(next: { [weak self] status in
|
|
if case let .uploaded(uploadedWallpaper, resultWallpaper) = status, uploadedWallpaper == wallpaper, case let .file(file) = resultWallpaper {
|
|
var optionsString = ""
|
|
if !options.isEmpty {
|
|
optionsString = "?\(options.joined(separator: "&"))"
|
|
}
|
|
|
|
let shareController = ShareController(context: context, subject: .url("https://t.me/bg/\(file.slug)\(optionsString)"))
|
|
shareController.actionCompleted = { [weak self] in
|
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
|
self?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
|
|
}
|
|
self?.present(shareController, in: .window(.root), blockInteraction: true)
|
|
}
|
|
})
|
|
case let .file(file):
|
|
if file.isPattern {
|
|
if !file.settings.colors.isEmpty {
|
|
if file.settings.colors.count == 2 {
|
|
options.append("bg_color=\(UIColor(rgb: file.settings.colors[0]).hexString)-\(UIColor(rgb: file.settings.colors[1]).hexString)")
|
|
} else if file.settings.colors.count >= 3 {
|
|
var colorsString = ""
|
|
for color in file.settings.colors {
|
|
if !colorsString.isEmpty {
|
|
colorsString.append("~")
|
|
}
|
|
colorsString.append(UIColor(rgb: color).hexString)
|
|
}
|
|
options.append("bg_color=\(colorsString)")
|
|
} else {
|
|
options.append("bg_color=\(UIColor(rgb: file.settings.colors[0]).hexString)")
|
|
}
|
|
}
|
|
if let intensity = file.settings.intensity {
|
|
options.append("intensity=\(intensity)")
|
|
}
|
|
if let rotation = file.settings.rotation {
|
|
options.append("rotation=\(rotation)")
|
|
}
|
|
}
|
|
|
|
var optionsString = ""
|
|
if !options.isEmpty {
|
|
optionsString = "?\(options.joined(separator: "&"))"
|
|
}
|
|
|
|
controller = ShareController(context: context, subject: .url("https://t.me/bg/\(file.slug)\(optionsString)"))
|
|
case let .color(color):
|
|
controller = ShareController(context: context, subject: .url("https://t.me/bg/\(UIColor(rgb: color).hexString)"))
|
|
case let .gradient(gradient):
|
|
var colorsString = ""
|
|
|
|
for color in gradient.colors {
|
|
if !colorsString.isEmpty {
|
|
if gradient.colors.count >= 3 {
|
|
colorsString.append("~")
|
|
} else {
|
|
colorsString.append("-")
|
|
}
|
|
}
|
|
colorsString.append(UIColor(rgb: color).hexString)
|
|
}
|
|
|
|
controller = ShareController(context: context, subject: .url("https://t.me/bg/\(colorsString)"))
|
|
default:
|
|
break
|
|
}
|
|
if let controller = controller {
|
|
controller.actionCompleted = { [weak self] in
|
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
|
self?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
|
|
}
|
|
self.present(controller, in: .window(.root), blockInteraction: true)
|
|
}
|
|
}
|
|
}
|