mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Chat wallpaper improvements
This commit is contained in:
parent
e4e810ae29
commit
97e0e96552
@ -9158,3 +9158,6 @@ Sorry for the inconvenience.";
|
||||
"Conversation.Theme.SetCustomColor" = "Set Custom";
|
||||
|
||||
"Appearance.ShowNextMediaOnTap" = "Show Next Media on Tap";
|
||||
|
||||
"WebApp.LaunchMoreInfo" = "More about this bot";
|
||||
"WebApp.LaunchConfirmation" = "To launch this web app, you will connect to its website.";
|
||||
|
@ -756,6 +756,7 @@ public protocol SharedAccountContext: AnyObject {
|
||||
var currentInAppNotificationSettings: Atomic<InAppNotificationSettings> { get }
|
||||
var currentMediaInputSettings: Atomic<MediaInputSettings> { get }
|
||||
var currentStickerSettings: Atomic<StickerSettings> { get }
|
||||
var currentMediaDisplaySettings: Atomic<MediaDisplaySettings> { get }
|
||||
|
||||
var energyUsageSettings: EnergyUsageSettings { get }
|
||||
|
||||
|
@ -138,6 +138,7 @@ public final class NavigationBackgroundNode: ASDisplayNode {
|
||||
private var _color: UIColor
|
||||
|
||||
private var enableBlur: Bool
|
||||
private var enableSaturation: Bool
|
||||
|
||||
public var effectView: UIVisualEffectView?
|
||||
private let backgroundNode: ASDisplayNode
|
||||
@ -152,9 +153,10 @@ public final class NavigationBackgroundNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
public init(color: UIColor, enableBlur: Bool = true) {
|
||||
public init(color: UIColor, enableBlur: Bool = true, enableSaturation: Bool = true) {
|
||||
self._color = .clear
|
||||
self.enableBlur = enableBlur
|
||||
self.enableSaturation = enableSaturation
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
|
||||
@ -195,10 +197,12 @@ public final class NavigationBackgroundNode: ASDisplayNode {
|
||||
if let sublayer = effectView.layer.sublayers?[0], let filters = sublayer.filters {
|
||||
sublayer.backgroundColor = nil
|
||||
sublayer.isOpaque = false
|
||||
let allowedKeys: [String] = [
|
||||
"colorSaturate",
|
||||
var allowedKeys: [String] = [
|
||||
"gaussianBlur"
|
||||
]
|
||||
if self.enableSaturation {
|
||||
allowedKeys.append("colorSaturate")
|
||||
}
|
||||
sublayer.filters = filters.filter { filter in
|
||||
guard let filter = filter as? NSObject else {
|
||||
return true
|
||||
|
@ -1211,7 +1211,9 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
||||
})
|
||||
}
|
||||
})
|
||||
self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction)
|
||||
|
||||
let disableTapNavigation = !(self.context.sharedContext.currentMediaDisplaySettings.with { $0 }.showNextMediaOnTap)
|
||||
self.displayNode = GalleryControllerNode(controllerInteraction: controllerInteraction, disableTapNavigation: disableTapNavigation)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.statusBar = self.statusBar
|
||||
|
@ -39,6 +39,7 @@ public func blurredImage(_ image: UIImage, radius: CGFloat, iterations: Int = 3)
|
||||
let source = CFDataGetBytePtr(providerData)
|
||||
memcpy(inBuffer.data, source, bytes)
|
||||
|
||||
|
||||
for _ in 0 ..< iterations {
|
||||
vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, tempData, 0, 0, boxSize, boxSize, nil, vImage_Flags(kvImageEdgeExtend))
|
||||
|
||||
|
@ -25,9 +25,9 @@ func presentCustomWallpaperPicker(context: AccountContext, present: @escaping (V
|
||||
controller.selectionBlock = { [weak legacyController] asset, _ in
|
||||
if let asset = asset {
|
||||
let controller = WallpaperGalleryController(context: context, source: .asset(asset.backingAsset))
|
||||
controller.apply = { [weak legacyController, weak controller] wallpaper, mode, cropRect in
|
||||
controller.apply = { [weak legacyController, weak controller] wallpaper, mode, cropRect, brightness in
|
||||
if let legacyController = legacyController, let controller = controller {
|
||||
uploadCustomWallpaper(context: context, wallpaper: wallpaper, mode: mode, cropRect: cropRect, completion: { [weak legacyController, weak controller] in
|
||||
uploadCustomWallpaper(context: context, wallpaper: wallpaper, mode: mode, cropRect: cropRect, brightness: brightness, completion: { [weak legacyController, weak controller] in
|
||||
if let legacyController = legacyController, let controller = controller {
|
||||
legacyController.dismiss()
|
||||
controller.dismiss(forceAway: true)
|
||||
@ -47,7 +47,7 @@ func presentCustomWallpaperPicker(context: AccountContext, present: @escaping (V
|
||||
})
|
||||
}
|
||||
|
||||
func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, completion: @escaping () -> Void) {
|
||||
func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, brightness: CGFloat?, completion: @escaping () -> Void) {
|
||||
let imageSignal: Signal<UIImage, NoError>
|
||||
switch wallpaper {
|
||||
case let .wallpaper(wallpaper, _):
|
||||
@ -196,7 +196,7 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE
|
||||
}).start()
|
||||
}
|
||||
|
||||
public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, brightnessMultiplier: CGFloat?, peerId: PeerId, completion: @escaping () -> Void) {
|
||||
public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, brightness: CGFloat?, peerId: PeerId, completion: @escaping () -> Void) {
|
||||
let imageSignal: Signal<UIImage, NoError>
|
||||
switch wallpaper {
|
||||
case let .wallpaper(wallpaper, _):
|
||||
@ -276,7 +276,25 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
||||
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: 20.0)!
|
||||
croppedImage = blurredImage(croppedImage, radius: 30.0)!
|
||||
}
|
||||
|
||||
if let brightness, abs(brightness) > 0.01 {
|
||||
if let updatedImage = generateImage(croppedImage.size, contextGenerator: { size, context in
|
||||
let bounds = CGRect(origin: .zero, size: size)
|
||||
if let cgImage = croppedImage.cgImage {
|
||||
context.draw(cgImage, in: bounds)
|
||||
}
|
||||
if brightness > 0.0 {
|
||||
context.setFillColor(UIColor(rgb: 0xffffff, alpha: brightness).cgColor)
|
||||
context.setBlendMode(.overlay)
|
||||
} else {
|
||||
context.setFillColor(UIColor(rgb: 0x000000, alpha: brightness * -1.0).cgColor)
|
||||
}
|
||||
context.fill(bounds)
|
||||
}) {
|
||||
croppedImage = updatedImage
|
||||
}
|
||||
}
|
||||
|
||||
let thumbnailDimensions = finalCropRect.size.fitted(CGSize(width: 320.0, height: 320.0))
|
||||
|
@ -152,7 +152,7 @@ final class ThemeColorsGridControllerNode: ASDisplayNode {
|
||||
let wallpapers = entries.map { $0.wallpaper }
|
||||
let controller = WallpaperGalleryController(context: context, source: .list(wallpapers: wallpapers, central: wallpaper, type: .colors), mode: strongSelf.controller?.mode.galleryMode ?? .default)
|
||||
controller.navigationPresentation = .modal
|
||||
controller.apply = { [weak self] wallpaper, _, _ in
|
||||
controller.apply = { [weak self] wallpaper, _, _, _ in
|
||||
if let strongSelf = self, let mode = strongSelf.controller?.mode, case let .peer(peer) = mode, case let .wallpaper(wallpaperValue, _) = wallpaper {
|
||||
let _ = (strongSelf.context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: wallpaperValue)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
|
@ -120,9 +120,9 @@ public final class ThemeGridController: ViewController {
|
||||
self.displayNode = ThemeGridControllerNode(context: self.context, presentationData: self.presentationData, presentPreviewController: { [weak self] source in
|
||||
if let strongSelf = self {
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: source)
|
||||
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in
|
||||
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect, brightness in
|
||||
if let strongSelf = self {
|
||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak self, weak controller] in
|
||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, brightness: brightness, completion: { [weak self, weak controller] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.deactivateSearch(animated: false)
|
||||
strongSelf.controllerNode.scrollToTop(animated: false)
|
||||
@ -148,9 +148,9 @@ public final class ThemeGridController: ViewController {
|
||||
return
|
||||
}
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset))
|
||||
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect in
|
||||
controller.apply = { [weak self, weak controller] wallpaper, options, cropRect, brightness in
|
||||
if let strongSelf = self, let controller = controller {
|
||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, completion: { [weak controller] in
|
||||
uploadCustomWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, brightness: brightness, completion: { [weak controller] in
|
||||
if let controller = controller {
|
||||
controller.dismiss(forceAway: true)
|
||||
}
|
||||
|
@ -58,13 +58,13 @@ private final class ThemeSettingsControllerArguments {
|
||||
let openBubbleSettings: () -> Void
|
||||
let openPowerSavingSettings: () -> Void
|
||||
let openStickersAndEmoji: () -> Void
|
||||
let disableAnimations: (Bool) -> Void
|
||||
let toggleShowNextMediaOnTap: (Bool) -> Void
|
||||
let selectAppIcon: (PresentationAppIcon) -> Void
|
||||
let editTheme: (PresentationCloudTheme) -> Void
|
||||
let themeContextAction: (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void
|
||||
let colorContextAction: (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void
|
||||
|
||||
init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, openThemeSettings: @escaping () -> Void, openWallpaperSettings: @escaping () -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor?) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, Bool) -> Void, toggleNightTheme: @escaping (Bool) -> Void, openAutoNightTheme: @escaping () -> Void, openTextSize: @escaping () -> Void, openBubbleSettings: @escaping () -> Void, openPowerSavingSettings: @escaping () -> Void, openStickersAndEmoji: @escaping () -> Void, disableAnimations: @escaping (Bool) -> Void, selectAppIcon: @escaping (PresentationAppIcon) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, themeContextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void, colorContextAction: @escaping (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void) {
|
||||
init(context: AccountContext, selectTheme: @escaping (PresentationThemeReference) -> Void, openThemeSettings: @escaping () -> Void, openWallpaperSettings: @escaping () -> Void, selectAccentColor: @escaping (PresentationThemeAccentColor?) -> Void, openAccentColorPicker: @escaping (PresentationThemeReference, Bool) -> Void, toggleNightTheme: @escaping (Bool) -> Void, openAutoNightTheme: @escaping () -> Void, openTextSize: @escaping () -> Void, openBubbleSettings: @escaping () -> Void, openPowerSavingSettings: @escaping () -> Void, openStickersAndEmoji: @escaping () -> Void, toggleShowNextMediaOnTap: @escaping (Bool) -> Void, selectAppIcon: @escaping (PresentationAppIcon) -> Void, editTheme: @escaping (PresentationCloudTheme) -> Void, themeContextAction: @escaping (Bool, PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void, colorContextAction: @escaping (Bool, PresentationThemeReference, ThemeSettingsColorOption?, ASDisplayNode, ContextGesture?) -> Void) {
|
||||
self.context = context
|
||||
self.selectTheme = selectTheme
|
||||
self.openThemeSettings = openThemeSettings
|
||||
@ -77,7 +77,7 @@ private final class ThemeSettingsControllerArguments {
|
||||
self.openBubbleSettings = openBubbleSettings
|
||||
self.openPowerSavingSettings = openPowerSavingSettings
|
||||
self.openStickersAndEmoji = openStickersAndEmoji
|
||||
self.disableAnimations = disableAnimations
|
||||
self.toggleShowNextMediaOnTap = toggleShowNextMediaOnTap
|
||||
self.selectAppIcon = selectAppIcon
|
||||
self.editTheme = editTheme
|
||||
self.themeContextAction = themeContextAction
|
||||
@ -128,7 +128,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
case powerSaving
|
||||
case stickersAndEmoji
|
||||
case otherHeader(PresentationTheme, String)
|
||||
case animations(PresentationTheme, String, Bool)
|
||||
case showNextMediaOnTap(PresentationTheme, String, Bool)
|
||||
case animationsInfo(PresentationTheme, String)
|
||||
|
||||
var section: ItemListSectionId {
|
||||
@ -143,7 +143,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
return ThemeSettingsControllerSection.icon.rawValue
|
||||
case .powerSaving, .stickersAndEmoji:
|
||||
return ThemeSettingsControllerSection.message.rawValue
|
||||
case .otherHeader, .animations, .animationsInfo:
|
||||
case .otherHeader, .showNextMediaOnTap, .animationsInfo:
|
||||
return ThemeSettingsControllerSection.other.rawValue
|
||||
}
|
||||
}
|
||||
@ -178,7 +178,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
return 12
|
||||
case .otherHeader:
|
||||
return 13
|
||||
case .animations:
|
||||
case .showNextMediaOnTap:
|
||||
return 14
|
||||
case .animationsInfo:
|
||||
return 15
|
||||
@ -271,8 +271,8 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .animations(lhsTheme, lhsTitle, lhsValue):
|
||||
if case let .animations(rhsTheme, rhsTitle, rhsValue) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsValue == rhsValue {
|
||||
case let .showNextMediaOnTap(lhsTheme, lhsTitle, lhsValue):
|
||||
if case let .showNextMediaOnTap(rhsTheme, rhsTitle, rhsValue) = rhs, lhsTheme === rhsTheme, lhsTitle == rhsTitle, lhsValue == rhsValue {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -343,9 +343,9 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
case let .otherHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .animations(_, title, value):
|
||||
case let .showNextMediaOnTap(_, title, value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.disableAnimations(value)
|
||||
arguments.toggleShowNextMediaOnTap(value)
|
||||
}, tag: ThemeSettingsEntryTag.animations)
|
||||
case let .animationsInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
@ -353,7 +353,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
private func themeSettingsControllerEntries(presentationData: PresentationData, presentationThemeSettings: PresentationThemeSettings, themeReference: PresentationThemeReference, availableThemes: [PresentationThemeReference], availableAppIcons: [PresentationAppIcon], currentAppIconName: String?, isPremium: Bool, chatThemes: [PresentationThemeReference], animatedEmojiStickers: [String: [StickerPackItem]]) -> [ThemeSettingsControllerEntry] {
|
||||
private func themeSettingsControllerEntries(presentationData: PresentationData, presentationThemeSettings: PresentationThemeSettings, mediaSettings: MediaDisplaySettings, themeReference: PresentationThemeReference, availableThemes: [PresentationThemeReference], availableAppIcons: [PresentationAppIcon], currentAppIconName: String?, isPremium: Bool, chatThemes: [PresentationThemeReference], animatedEmojiStickers: [String: [StickerPackItem]]) -> [ThemeSettingsControllerEntry] {
|
||||
var entries: [ThemeSettingsControllerEntry] = []
|
||||
|
||||
let strings = presentationData.strings
|
||||
@ -404,8 +404,7 @@ private func themeSettingsControllerEntries(presentationData: PresentationData,
|
||||
}
|
||||
|
||||
entries.append(.otherHeader(presentationData.theme, strings.Appearance_Other.uppercased()))
|
||||
entries.append(.animations(presentationData.theme, strings.Appearance_ReduceMotion, presentationData.reduceMotion))
|
||||
entries.append(.animationsInfo(presentationData.theme, strings.Appearance_ReduceMotionInfo))
|
||||
entries.append(.showNextMediaOnTap(presentationData.theme, strings.Appearance_ShowNextMediaOnTap, mediaSettings.showNextMediaOnTap))
|
||||
|
||||
return entries
|
||||
}
|
||||
@ -522,9 +521,9 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
pushControllerImpl?(installedStickerPacksController(context: context, mode: .general, archivedPacks: archivedStickerPacks, updatedPacks: { _ in
|
||||
}))
|
||||
})
|
||||
}, disableAnimations: { reduceMotion in
|
||||
let _ = updatePresentationThemeSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||
return current.withUpdatedReduceMotion(reduceMotion)
|
||||
}, toggleShowNextMediaOnTap: { value in
|
||||
let _ = updateMediaDisplaySettingsInteractively(accountManager: context.sharedContext.accountManager, { current in
|
||||
return current.withUpdatedShowNextMediaOnTap(value)
|
||||
}).start()
|
||||
}, selectAppIcon: { icon in
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
||||
@ -1000,10 +999,11 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
})
|
||||
})
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings, SharedDataKeys.chatThemes]), cloudThemes.get(), availableAppIcons, currentAppIconName.get(), removedThemeIndexesPromise.get(), animatedEmojiStickers, context.account.postbox.peerView(id: context.account.peerId))
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.presentationThemeSettings, SharedDataKeys.chatThemes, ApplicationSpecificSharedDataKeys.mediaDisplaySettings]), cloudThemes.get(), availableAppIcons, currentAppIconName.get(), removedThemeIndexesPromise.get(), animatedEmojiStickers, context.account.postbox.peerView(id: context.account.peerId))
|
||||
|> map { presentationData, sharedData, cloudThemes, availableAppIcons, currentAppIconName, removedThemeIndexes, animatedEmojiStickers, peerView -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings]?.get(PresentationThemeSettings.self) ?? PresentationThemeSettings.defaultSettings
|
||||
|
||||
let mediaSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.mediaDisplaySettings]?.get(MediaDisplaySettings.self) ?? MediaDisplaySettings.defaultSettings
|
||||
|
||||
let isPremium = peerView.peers[peerView.peerId]?.isPremium ?? false
|
||||
|
||||
let themeReference: PresentationThemeReference
|
||||
@ -1041,7 +1041,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The
|
||||
chatThemes.insert(.builtin(.dayClassic), at: 0)
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Appearance_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: themeSettingsControllerEntries(presentationData: presentationData, presentationThemeSettings: settings, themeReference: themeReference, availableThemes: availableThemes, availableAppIcons: availableAppIcons, currentAppIconName: currentAppIconName, isPremium: isPremium, chatThemes: chatThemes, animatedEmojiStickers: animatedEmojiStickers), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: themeSettingsControllerEntries(presentationData: presentationData, presentationThemeSettings: settings, mediaSettings: mediaSettings, themeReference: themeReference, availableThemes: availableThemes, availableAppIcons: availableAppIcons, currentAppIconName: currentAppIconName, isPremium: isPremium, chatThemes: chatThemes, animatedEmojiStickers: animatedEmojiStickers), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ public class WallpaperGalleryController: ViewController {
|
||||
private let context: AccountContext
|
||||
private let source: WallpaperListSource
|
||||
private let mode: Mode
|
||||
public var apply: ((WallpaperGalleryEntry, WallpaperPresentationOptions, CGRect?) -> Void)?
|
||||
public var apply: ((WallpaperGalleryEntry, WallpaperPresentationOptions, CGRect?, CGFloat?) -> Void)?
|
||||
|
||||
private let _ready = Promise<Bool>()
|
||||
override public var ready: Promise<Bool> {
|
||||
@ -453,7 +453,7 @@ public class WallpaperGalleryController: ViewController {
|
||||
let entry = strongSelf.entries[centralItemNode.index]
|
||||
|
||||
if case .peer = strongSelf.mode {
|
||||
strongSelf.apply?(entry, options, centralItemNode.cropRect)
|
||||
strongSelf.apply?(entry, options, centralItemNode.cropRect, centralItemNode.brightness)
|
||||
return
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ public class WallpaperGalleryController: ViewController {
|
||||
break
|
||||
}
|
||||
|
||||
strongSelf.apply?(entry, options, centralItemNode.cropRect)
|
||||
strongSelf.apply?(entry, options, centralItemNode.cropRect, centralItemNode.brightness)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,23 +95,27 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let wrapperNode: ASDisplayNode
|
||||
let imageNode: TransformImageNode
|
||||
let nativeNode: WallpaperBackgroundNode
|
||||
let brightnessNode: ASDisplayNode
|
||||
private let statusNode: RadialStatusNode
|
||||
private let blurredNode: BlurredImageNode
|
||||
let cropNode: WallpaperCropNode
|
||||
|
||||
private var cancelButtonNode: WallpaperNavigationButtonNode
|
||||
private var shareButtonNode: WallpaperNavigationButtonNode
|
||||
private let cancelButtonNode: WallpaperNavigationButtonNode
|
||||
private let shareButtonNode: WallpaperNavigationButtonNode
|
||||
|
||||
private var blurButtonNode: WallpaperOptionButtonNode
|
||||
private var motionButtonNode: WallpaperOptionButtonNode
|
||||
private var patternButtonNode: WallpaperOptionButtonNode
|
||||
private var colorsButtonNode: WallpaperOptionButtonNode
|
||||
private var playButtonNode: WallpaperNavigationButtonNode
|
||||
private let blurButtonNode: WallpaperOptionButtonNode
|
||||
private let motionButtonNode: WallpaperOptionButtonNode
|
||||
private let patternButtonNode: WallpaperOptionButtonNode
|
||||
private let colorsButtonNode: WallpaperOptionButtonNode
|
||||
private let playButtonNode: WallpaperNavigationButtonNode
|
||||
private let sliderNode: WallpaperSliderNode
|
||||
|
||||
private let messagesContainerNode: ASDisplayNode
|
||||
private var messageNodes: [ListViewItemNode]?
|
||||
private var validMessages: [String]?
|
||||
|
||||
private let serviceBackgroundNode: NavigationBackgroundNode
|
||||
|
||||
fileprivate let _ready = Promise<Void>()
|
||||
private let fetchDisposable = MetaDisposable()
|
||||
private let statusDisposable = MetaDisposable()
|
||||
@ -149,6 +153,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.statusNode.isUserInteractionEnabled = false
|
||||
|
||||
self.blurredNode = BlurredImageNode()
|
||||
self.brightnessNode = ASDisplayNode()
|
||||
|
||||
self.messagesContainerNode = ASDisplayNode()
|
||||
self.messagesContainerNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
|
||||
@ -160,11 +165,18 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.motionButtonNode.setEnabled(false)
|
||||
self.patternButtonNode = WallpaperOptionButtonNode(title: self.presentationData.strings.WallpaperPreview_Pattern, value: .check(false))
|
||||
self.patternButtonNode.setEnabled(false)
|
||||
|
||||
self.serviceBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x000000, alpha: 0.35))
|
||||
|
||||
var sliderValueChangedImpl: ((CGFloat) -> Void)?
|
||||
self.sliderNode = WallpaperSliderNode(minValue: 0.0, maxValue: 1.0, value: 0.5, valueChanged: { value, _ in
|
||||
sliderValueChangedImpl?(value)
|
||||
})
|
||||
|
||||
self.colorsButtonNode = WallpaperOptionButtonNode(title: self.presentationData.strings.WallpaperPreview_WallpaperColors, value: .colors(false, [.clear]))
|
||||
|
||||
self.cancelButtonNode = WallpaperNavigationButtonNode(content: .text(self.presentationData.strings.Common_Cancel))
|
||||
self.shareButtonNode = WallpaperNavigationButtonNode(content: .icon(image: UIImage(bundleImageName: "Chat/Links/Share"), size: CGSize(width: 28.0, height: 28.0)))
|
||||
self.cancelButtonNode = WallpaperNavigationButtonNode(content: .text(self.presentationData.strings.Common_Cancel), dark: false)
|
||||
self.shareButtonNode = WallpaperNavigationButtonNode(content: .icon(image: UIImage(bundleImageName: "Chat/Links/Share"), size: CGSize(width: 28.0, height: 28.0)), dark: false)
|
||||
|
||||
self.playButtonPlayImage = generateImage(CGSize(width: 48.0, height: 48.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
@ -193,7 +205,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
self.playButtonRotateImage = generateTintedImage(image: UIImage(bundleImageName: "Settings/ThemeColorRotateIcon"), color: .white)
|
||||
|
||||
self.playButtonNode = WallpaperNavigationButtonNode(content: .icon(image: self.playButtonPlayImage, size: CGSize(width: 48.0, height: 48.0)))
|
||||
self.playButtonNode = WallpaperNavigationButtonNode(content: .icon(image: self.playButtonPlayImage, size: CGSize(width: 48.0, height: 48.0)), dark: true)
|
||||
|
||||
super.init()
|
||||
|
||||
@ -217,6 +229,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
self.addSubnode(self.wrapperNode)
|
||||
//self.addSubnode(self.statusNode)
|
||||
self.addSubnode(self.serviceBackgroundNode)
|
||||
self.addSubnode(self.messagesContainerNode)
|
||||
|
||||
self.addSubnode(self.blurButtonNode)
|
||||
@ -224,9 +237,12 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.addSubnode(self.patternButtonNode)
|
||||
self.addSubnode(self.colorsButtonNode)
|
||||
self.addSubnode(self.playButtonNode)
|
||||
self.addSubnode(self.sliderNode)
|
||||
self.addSubnode(self.cancelButtonNode)
|
||||
self.addSubnode(self.shareButtonNode)
|
||||
|
||||
self.imageNode.addSubnode(self.brightnessNode)
|
||||
|
||||
self.blurButtonNode.addTarget(self, action: #selector(self.toggleBlur), forControlEvents: .touchUpInside)
|
||||
self.motionButtonNode.addTarget(self, action: #selector(self.toggleMotion), forControlEvents: .touchUpInside)
|
||||
self.patternButtonNode.addTarget(self, action: #selector(self.togglePattern), forControlEvents: .touchUpInside)
|
||||
@ -234,6 +250,24 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.playButtonNode.addTarget(self, action: #selector(self.togglePlay), forControlEvents: .touchUpInside)
|
||||
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
|
||||
self.shareButtonNode.addTarget(self, action: #selector(self.actionPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
sliderValueChangedImpl = { [weak self] value in
|
||||
if let self {
|
||||
let value = (value - 0.5) * 2.0
|
||||
if value < 0.0 {
|
||||
self.brightnessNode.backgroundColor = UIColor(rgb: 0x000000)
|
||||
self.brightnessNode.layer.compositingFilter = nil
|
||||
self.brightnessNode.alpha = value * -1.0
|
||||
} else if value > 0.0 {
|
||||
self.brightnessNode.backgroundColor = UIColor(rgb: 0xffffff)
|
||||
self.brightnessNode.layer.compositingFilter = "overlayBlendMode"
|
||||
self.brightnessNode.alpha = value
|
||||
} else {
|
||||
self.brightnessNode.layer.compositingFilter = nil
|
||||
self.brightnessNode.alpha = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -255,6 +289,18 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
var brightness: CGFloat? {
|
||||
guard let entry = self.entry else {
|
||||
return nil
|
||||
}
|
||||
switch entry {
|
||||
case .asset, .contextResult:
|
||||
return (self.sliderNode.value - 0.5) * 2.0
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
override func ready() -> Signal<Void, NoError> {
|
||||
return self._ready.get()
|
||||
}
|
||||
@ -721,7 +767,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
|
||||
func setBlurEnabled(_ enabled: Bool, animated: Bool) {
|
||||
let blurRadius: CGFloat = 45.0
|
||||
let blurRadius: CGFloat = 30.0
|
||||
|
||||
var animated = animated
|
||||
if animated, let (layout, _) = self.validLayout {
|
||||
@ -732,13 +778,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
if enabled {
|
||||
if self.blurredNode.supernode == nil {
|
||||
if self.cropNode.supernode != nil {
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
self.imageNode.addSubnode(self.blurredNode)
|
||||
} else {
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
self.imageNode.addSubnode(self.blurredNode)
|
||||
}
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
self.imageNode.insertSubnode(self.blurredNode, at: 0)
|
||||
}
|
||||
|
||||
if animated {
|
||||
@ -914,12 +955,15 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let buttonSize = CGSize(width: maxButtonWidth, height: 30.0)
|
||||
let alpha = 1.0 - min(1.0, max(0.0, abs(offset.y) / 50.0))
|
||||
|
||||
let additionalYOffset: CGFloat = 0.0
|
||||
/*if self.patternButtonNode.isSelected {
|
||||
additionalYOffset = -235.0
|
||||
} else if self.colorsButtonNode.isSelected {
|
||||
additionalYOffset = -235.0
|
||||
}*/
|
||||
var additionalYOffset: CGFloat = 0.0
|
||||
if let source = self.source {
|
||||
switch source {
|
||||
case .asset, .contextResult:
|
||||
additionalYOffset -= 44.0
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let buttonSpacing: CGFloat = 18.0
|
||||
|
||||
@ -937,13 +981,17 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
var motionFrame = centerButtonFrame
|
||||
var motionAlpha: CGFloat = 0.0
|
||||
|
||||
|
||||
var colorsFrame = CGRect(origin: CGPoint(x: rightButtonFrame.maxX - colorsButtonSize.width, y: rightButtonFrame.minY), size: colorsButtonSize)
|
||||
var colorsAlpha: CGFloat = 0.0
|
||||
|
||||
let playFrame = CGRect(origin: CGPoint(x: centerButtonFrame.midX - playButtonSize.width / 2.0, y: centerButtonFrame.midY - playButtonSize.height / 2.0), size: playButtonSize)
|
||||
var playAlpha: CGFloat = 0.0
|
||||
|
||||
let sliderSize = CGSize(width: 268.0, height: 30.0)
|
||||
let sliderFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - sliderSize.width) / 2.0) + offset.x, y: layout.size.height - toolbarHeight - layout.intrinsicInsets.bottom - 52.0 + offset.y), size: sliderSize)
|
||||
var sliderIsHidden = true
|
||||
|
||||
let cancelSize = self.cancelButtonNode.measure(layout.size)
|
||||
let cancelFrame = CGRect(origin: CGPoint(x: 16.0 + offset.x, y: 16.0), size: cancelSize)
|
||||
|
||||
@ -958,11 +1006,13 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
blurFrame = leftButtonFrame
|
||||
motionAlpha = 1.0
|
||||
motionFrame = rightButtonFrame
|
||||
sliderIsHidden = false
|
||||
case .contextResult:
|
||||
blurAlpha = 1.0
|
||||
blurFrame = leftButtonFrame
|
||||
motionAlpha = 1.0
|
||||
motionFrame = rightButtonFrame
|
||||
sliderIsHidden = false
|
||||
case let .wallpaper(wallpaper, _):
|
||||
switch wallpaper {
|
||||
case .builtin:
|
||||
@ -1047,17 +1097,17 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
transition.updateAlpha(node: self.playButtonNode, alpha: playAlpha * alpha)
|
||||
transition.updateSublayerTransformScale(node: self.playButtonNode, scale: max(0.1, playAlpha))
|
||||
|
||||
transition.updateFrame(node: self.sliderNode, frame: sliderFrame)
|
||||
self.sliderNode.updateLayout(size: sliderFrame.size)
|
||||
self.sliderNode.isHidden = sliderIsHidden
|
||||
|
||||
transition.updateFrame(node: self.cancelButtonNode, frame: cancelFrame)
|
||||
transition.updateFrame(node: self.shareButtonNode, frame: shareFrame)
|
||||
}
|
||||
|
||||
private func updateMessagesLayout(layout: ContainerViewLayout, offset: CGPoint, transition: ContainedViewLayoutTransition) {
|
||||
let bottomInset: CGFloat = 132.0
|
||||
var bottomInset: CGFloat = 132.0
|
||||
|
||||
if self.patternButtonNode.isSelected || self.colorsButtonNode.isSelected {
|
||||
//bottomInset = 350.0
|
||||
}
|
||||
|
||||
var items: [ListViewItem] = []
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1))
|
||||
let otherPeerId = self.context.account.peerId
|
||||
@ -1125,6 +1175,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
case .asset, .contextResult:
|
||||
topMessageText = presentationData.strings.WallpaperPreview_CropTopText
|
||||
bottomMessageText = presentationData.strings.WallpaperPreview_CropBottomText
|
||||
bottomInset += 44.0
|
||||
case .customColor:
|
||||
topMessageText = presentationData.strings.WallpaperPreview_CustomColorTopText
|
||||
bottomMessageText = presentationData.strings.WallpaperPreview_CustomColorBottomText
|
||||
@ -1188,6 +1239,14 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.messageNodes = messageNodes
|
||||
}
|
||||
|
||||
if let _ = serviceMessageText, let messageNodes = self.messageNodes, let node = messageNodes.last {
|
||||
if let backgroundNode = node.subnodes?.first?.subnodes?.first?.subnodes?.first?.subnodes?.first {
|
||||
let serviceBackgroundFrame = backgroundNode.view.convert(backgroundNode.bounds, to: self.view).offsetBy(dx: 0.0, dy: -1.0).insetBy(dx: 0.0, dy: -1.0)
|
||||
transition.updateFrame(node: self.serviceBackgroundNode, frame: serviceBackgroundFrame)
|
||||
self.serviceBackgroundNode.update(size: serviceBackgroundFrame.size, cornerRadius: serviceBackgroundFrame.height / 2.0, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
let alpha = 1.0 - min(1.0, max(0.0, abs(offset.y) / 50.0))
|
||||
|
||||
if let messageNodes = self.messageNodes {
|
||||
@ -1237,6 +1296,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
}
|
||||
self.brightnessNode.frame = self.imageNode.bounds
|
||||
|
||||
let additionalYOffset: CGFloat = 0.0
|
||||
|
||||
|
@ -17,39 +17,6 @@ enum WallpaperGalleryToolbarDoneButtonType {
|
||||
case none
|
||||
}
|
||||
|
||||
final class WallpaperLightButtonBackgroundNode: ASDisplayNode {
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let overlayNode: ASDisplayNode
|
||||
private let lightNode: ASDisplayNode
|
||||
|
||||
override init() {
|
||||
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x000000, alpha: 0.01), enableBlur: true)
|
||||
self.overlayNode = ASDisplayNode()
|
||||
self.overlayNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.55)
|
||||
self.overlayNode.layer.compositingFilter = "overlayBlendMode"
|
||||
|
||||
self.lightNode = ASDisplayNode()
|
||||
self.lightNode.backgroundColor = UIColor(rgb: 0xf2f2f2, alpha: 0.3)
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.overlayNode)
|
||||
//self.addSubnode(self.lightNode)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize) {
|
||||
let frame = CGRect(origin: .zero, size: size)
|
||||
self.backgroundNode.frame = frame
|
||||
self.overlayNode.frame = frame
|
||||
self.lightNode.frame = frame
|
||||
|
||||
self.backgroundNode.update(size: size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperGalleryToolbarNode: ASDisplayNode {
|
||||
private var theme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
|
@ -34,6 +34,61 @@ private func generateColorsImage(diameter: CGFloat, colors: [UIColor]) -> UIImag
|
||||
})
|
||||
}
|
||||
|
||||
final class WallpaperLightButtonBackgroundNode: ASDisplayNode {
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let overlayNode: ASDisplayNode
|
||||
private let lightNode: ASDisplayNode
|
||||
|
||||
override init() {
|
||||
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x333333, alpha: 0.3), enableBlur: true, enableSaturation: false)
|
||||
self.overlayNode = ASDisplayNode()
|
||||
self.overlayNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.75)
|
||||
self.overlayNode.layer.compositingFilter = "overlayBlendMode"
|
||||
|
||||
self.lightNode = ASDisplayNode()
|
||||
self.lightNode.backgroundColor = UIColor(rgb: 0xf2f2f2, alpha: 0.2)
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.overlayNode)
|
||||
self.addSubnode(self.lightNode)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize) {
|
||||
let frame = CGRect(origin: .zero, size: size)
|
||||
self.backgroundNode.frame = frame
|
||||
self.overlayNode.frame = frame
|
||||
self.lightNode.frame = frame
|
||||
|
||||
self.backgroundNode.update(size: size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperOptionBackgroundNode: ASDisplayNode {
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
|
||||
override init() {
|
||||
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x333333, alpha: 0.3), enableBlur: true, enableSaturation: false)
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
self.isUserInteractionEnabled = false
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize) {
|
||||
let frame = CGRect(origin: .zero, size: size)
|
||||
self.backgroundNode.frame = frame
|
||||
|
||||
self.backgroundNode.update(size: size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
enum Content {
|
||||
case icon(image: UIImage?, size: CGSize)
|
||||
@ -42,7 +97,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
|
||||
private let content: Content
|
||||
|
||||
private let backgroundNode: WallpaperLightButtonBackgroundNode
|
||||
private let backgroundNode: ASDisplayNode
|
||||
|
||||
private let iconNode: ASImageNode
|
||||
|
||||
@ -52,10 +107,14 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
self.iconNode.image = generateTintedImage(image: image, color: .white)
|
||||
}
|
||||
|
||||
init(content: Content) {
|
||||
init(content: Content, dark: Bool) {
|
||||
self.content = content
|
||||
|
||||
self.backgroundNode = WallpaperLightButtonBackgroundNode()
|
||||
if dark {
|
||||
self.backgroundNode = WallpaperOptionBackgroundNode()
|
||||
} else {
|
||||
self.backgroundNode = WallpaperLightButtonBackgroundNode()
|
||||
}
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.displaysAsynchronously = false
|
||||
@ -94,11 +153,6 @@ final class WallpaperNavigationButtonNode: 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.75), transition: .immediate)
|
||||
// } else {
|
||||
// self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,7 +173,11 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
|
||||
let size = self.bounds.size
|
||||
self.backgroundNode.frame = self.bounds
|
||||
self.backgroundNode.updateLayout(size: self.backgroundNode.bounds.size)
|
||||
if let backgroundNode = self.backgroundNode as? WallpaperOptionBackgroundNode {
|
||||
backgroundNode.updateLayout(size: self.backgroundNode.bounds.size)
|
||||
} else if let backgroundNode = self.backgroundNode as? WallpaperLightButtonBackgroundNode {
|
||||
backgroundNode.updateLayout(size: self.backgroundNode.bounds.size)
|
||||
}
|
||||
self.backgroundNode.cornerRadius = size.height / 2.0
|
||||
|
||||
self.iconNode.frame = self.bounds
|
||||
@ -132,7 +190,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
|
||||
|
||||
final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let backgroundNode: WallpaperOptionBackgroundNode
|
||||
|
||||
private let checkNode: CheckNode
|
||||
private let colorNode: ASImageNode
|
||||
@ -172,9 +230,8 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
self._value = value
|
||||
self.title = title
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x000000, alpha: 0.01))
|
||||
self.backgroundNode.cornerRadius = 14.0
|
||||
|
||||
self.backgroundNode = WallpaperOptionBackgroundNode()
|
||||
|
||||
self.checkNode = CheckNode(theme: CheckNodeTheme(backgroundColor: .white, strokeColor: .clear, borderColor: .white, overlayBorder: false, hasInset: false, hasShadow: false, borderWidth: 1.5))
|
||||
self.checkNode.isUserInteractionEnabled = false
|
||||
|
||||
@ -186,6 +243,9 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
self.cornerRadius = 14.0
|
||||
|
||||
switch value {
|
||||
case let .check(selected):
|
||||
self.checkNode.isHidden = false
|
||||
@ -202,6 +262,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
|
||||
self.addSubnode(self.checkNode)
|
||||
self.addSubnode(self.textNode)
|
||||
self.addSubnode(self.colorNode)
|
||||
@ -227,11 +288,6 @@ 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.75), transition: .immediate)
|
||||
// } else {
|
||||
// self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,7 +378,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
super.layout()
|
||||
|
||||
self.backgroundNode.frame = self.bounds
|
||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: 15.0, transition: .immediate)
|
||||
self.backgroundNode.updateLayout(size: self.backgroundNode.bounds.size)
|
||||
|
||||
guard let _ = self.textSize else {
|
||||
return
|
||||
@ -340,3 +396,147 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperSliderNode: ASDisplayNode {
|
||||
let minValue: CGFloat
|
||||
let maxValue: CGFloat
|
||||
var value: CGFloat = 1.0 {
|
||||
didSet {
|
||||
if let size = self.validLayout {
|
||||
self.updateLayout(size: size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
|
||||
private let foregroundNode: ASDisplayNode
|
||||
private let foregroundLightNode: ASDisplayNode
|
||||
private let leftIconNode: ASImageNode
|
||||
private let rightIconNode: ASImageNode
|
||||
|
||||
private let valueChanged: (CGFloat, Bool) -> Void
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
private var validLayout: CGSize?
|
||||
|
||||
init(minValue: CGFloat, maxValue: CGFloat, value: CGFloat, valueChanged: @escaping (CGFloat, Bool) -> Void) {
|
||||
self.minValue = minValue
|
||||
self.maxValue = maxValue
|
||||
self.value = value
|
||||
self.valueChanged = valueChanged
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x333333, alpha: 0.3), enableBlur: true, enableSaturation: false)
|
||||
|
||||
self.foregroundNode = ASDisplayNode()
|
||||
self.foregroundNode.clipsToBounds = true
|
||||
self.foregroundNode.cornerRadius = 3.0
|
||||
self.foregroundNode.isAccessibilityElement = false
|
||||
self.foregroundNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.75)
|
||||
self.foregroundNode.layer.compositingFilter = "overlayBlendMode"
|
||||
self.foregroundNode.isUserInteractionEnabled = false
|
||||
|
||||
self.foregroundLightNode = ASDisplayNode()
|
||||
self.foregroundLightNode.clipsToBounds = true
|
||||
self.foregroundLightNode.cornerRadius = 3.0
|
||||
self.foregroundLightNode.backgroundColor = UIColor(rgb: 0xf2f2f2, alpha: 0.2)
|
||||
|
||||
self.leftIconNode = ASImageNode()
|
||||
self.leftIconNode.displaysAsynchronously = false
|
||||
self.leftIconNode.image = UIImage(bundleImageName: "Settings/WallpaperBrightnessMin")
|
||||
self.leftIconNode.contentMode = .center
|
||||
|
||||
self.rightIconNode = ASImageNode()
|
||||
self.rightIconNode.displaysAsynchronously = false
|
||||
self.rightIconNode.image = UIImage(bundleImageName: "Settings/WallpaperBrightnessMax")
|
||||
self.rightIconNode.contentMode = .center
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
self.cornerRadius = 15.0
|
||||
self.isUserInteractionEnabled = true
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
|
||||
self.addSubnode(self.foregroundNode)
|
||||
self.addSubnode(self.foregroundLightNode)
|
||||
|
||||
self.addSubnode(self.leftIconNode)
|
||||
self.addSubnode(self.rightIconNode)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))
|
||||
self.view.addGestureRecognizer(panGestureRecognizer)
|
||||
|
||||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
|
||||
self.view.addGestureRecognizer(tapGestureRecognizer)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition = .immediate) {
|
||||
self.validLayout = size
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: .zero, size: size))
|
||||
self.backgroundNode.update(size: size, transition: transition)
|
||||
|
||||
if let icon = self.leftIconNode.image {
|
||||
transition.updateFrame(node: self.leftIconNode, frame: CGRect(origin: CGPoint(x: 7.0, y: floorToScreenPixels((size.height - icon.size.height) / 2.0)), size: icon.size))
|
||||
}
|
||||
|
||||
if let icon = self.rightIconNode.image {
|
||||
transition.updateFrame(node: self.rightIconNode, frame: CGRect(origin: CGPoint(x: size.width - icon.size.width - 6.0, y: floorToScreenPixels((size.height - icon.size.height) / 2.0)), size: icon.size))
|
||||
}
|
||||
|
||||
let range = self.maxValue - self.minValue
|
||||
let value = (self.value - self.minValue) / range
|
||||
let foregroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: value * size.width, height: size.height))
|
||||
transition.updateFrameAdditive(node: self.foregroundNode, frame: foregroundFrame)
|
||||
transition.updateFrameAdditive(node: self.foregroundLightNode, frame: foregroundFrame)
|
||||
}
|
||||
|
||||
@objc private func panGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||||
let range = self.maxValue - self.minValue
|
||||
switch gestureRecognizer.state {
|
||||
case .began:
|
||||
break
|
||||
case .changed:
|
||||
let previousValue = self.value
|
||||
|
||||
let translation: CGFloat = gestureRecognizer.translation(in: gestureRecognizer.view).x
|
||||
let delta = translation / self.bounds.width * range
|
||||
self.value = max(self.minValue, min(self.maxValue, self.value + delta))
|
||||
gestureRecognizer.setTranslation(CGPoint(), in: gestureRecognizer.view)
|
||||
|
||||
if self.value == 2.0 && previousValue != 2.0 {
|
||||
self.hapticFeedback.impact(.soft)
|
||||
} else if self.value == 1.0 && previousValue != 1.0 {
|
||||
self.hapticFeedback.impact(.soft)
|
||||
} else if self.value == 2.5 && previousValue != 2.5 {
|
||||
self.hapticFeedback.impact(.soft)
|
||||
} else if self.value == 0.05 && previousValue != 0.05 {
|
||||
self.hapticFeedback.impact(.soft)
|
||||
}
|
||||
if abs(previousValue - self.value) >= 0.001 {
|
||||
self.valueChanged(self.value, false)
|
||||
}
|
||||
case .ended:
|
||||
let translation: CGFloat = gestureRecognizer.translation(in: gestureRecognizer.view).x
|
||||
let delta = translation / self.bounds.width * range
|
||||
self.value = max(self.minValue, min(self.maxValue, self.value + delta))
|
||||
self.valueChanged(self.value, true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func tapGesture(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||
let range = self.maxValue - self.minValue
|
||||
let location = gestureRecognizer.location(in: gestureRecognizer.view)
|
||||
self.value = max(self.minValue, min(self.maxValue, self.minValue + location.x / self.bounds.width * range))
|
||||
self.valueChanged(self.value, true)
|
||||
}
|
||||
}
|
||||
|
@ -218,16 +218,18 @@ public final class InitialPresentationDataAndSettings {
|
||||
public let callListSettings: CallListSettings
|
||||
public let inAppNotificationSettings: InAppNotificationSettings
|
||||
public let mediaInputSettings: MediaInputSettings
|
||||
public let mediaDisplaySettings: MediaDisplaySettings
|
||||
public let stickerSettings: StickerSettings
|
||||
public let experimentalUISettings: ExperimentalUISettings
|
||||
|
||||
public init(presentationData: PresentationData, automaticMediaDownloadSettings: MediaAutoDownloadSettings, autodownloadSettings: AutodownloadSettings, callListSettings: CallListSettings, inAppNotificationSettings: InAppNotificationSettings, mediaInputSettings: MediaInputSettings, stickerSettings: StickerSettings, experimentalUISettings: ExperimentalUISettings) {
|
||||
public init(presentationData: PresentationData, automaticMediaDownloadSettings: MediaAutoDownloadSettings, autodownloadSettings: AutodownloadSettings, callListSettings: CallListSettings, inAppNotificationSettings: InAppNotificationSettings, mediaInputSettings: MediaInputSettings, mediaDisplaySettings: MediaDisplaySettings, stickerSettings: StickerSettings, experimentalUISettings: ExperimentalUISettings) {
|
||||
self.presentationData = presentationData
|
||||
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
||||
self.autodownloadSettings = autodownloadSettings
|
||||
self.callListSettings = callListSettings
|
||||
self.inAppNotificationSettings = inAppNotificationSettings
|
||||
self.mediaInputSettings = mediaInputSettings
|
||||
self.mediaDisplaySettings = mediaDisplaySettings
|
||||
self.stickerSettings = stickerSettings
|
||||
self.experimentalUISettings = experimentalUISettings
|
||||
}
|
||||
@ -242,6 +244,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
var callListSettings: PreferencesEntry?
|
||||
var inAppNotificationSettings: PreferencesEntry?
|
||||
var mediaInputSettings: PreferencesEntry?
|
||||
var mediaDisplaySettings: PreferencesEntry?
|
||||
var experimentalUISettings: PreferencesEntry?
|
||||
var contactSynchronizationSettings: PreferencesEntry?
|
||||
var stickerSettings: PreferencesEntry?
|
||||
@ -254,6 +257,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
callListSettings: PreferencesEntry?,
|
||||
inAppNotificationSettings: PreferencesEntry?,
|
||||
mediaInputSettings: PreferencesEntry?,
|
||||
mediaDisplaySettings: PreferencesEntry?,
|
||||
experimentalUISettings: PreferencesEntry?,
|
||||
contactSynchronizationSettings: PreferencesEntry?,
|
||||
stickerSettings: PreferencesEntry?
|
||||
@ -265,6 +269,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
self.callListSettings = callListSettings
|
||||
self.inAppNotificationSettings = inAppNotificationSettings
|
||||
self.mediaInputSettings = mediaInputSettings
|
||||
self.mediaDisplaySettings = mediaDisplaySettings
|
||||
self.experimentalUISettings = experimentalUISettings
|
||||
self.contactSynchronizationSettings = contactSynchronizationSettings
|
||||
self.stickerSettings = stickerSettings
|
||||
@ -279,6 +284,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
let callListSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.callListSettings)
|
||||
let inAppNotificationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.inAppNotificationSettings)
|
||||
let mediaInputSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.mediaInputSettings)
|
||||
let mediaDisplaySettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.mediaDisplaySettings)
|
||||
let experimentalUISettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings)
|
||||
let contactSynchronizationSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.contactSynchronizationSettings)
|
||||
let stickerSettings = transaction.getSharedData(ApplicationSpecificSharedDataKeys.stickerSettings)
|
||||
@ -291,6 +297,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
callListSettings: callListSettings,
|
||||
inAppNotificationSettings: inAppNotificationSettings,
|
||||
mediaInputSettings: mediaInputSettings,
|
||||
mediaDisplaySettings: mediaDisplaySettings,
|
||||
experimentalUISettings: experimentalUISettings,
|
||||
contactSynchronizationSettings: contactSynchronizationSettings,
|
||||
stickerSettings: stickerSettings
|
||||
@ -347,6 +354,13 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
mediaInputSettings = MediaInputSettings.defaultSettings
|
||||
}
|
||||
|
||||
let mediaDisplaySettings: MediaDisplaySettings
|
||||
if let value = internalData.mediaDisplaySettings?.get(MediaDisplaySettings.self) {
|
||||
mediaDisplaySettings = value
|
||||
} else {
|
||||
mediaDisplaySettings = MediaDisplaySettings.defaultSettings
|
||||
}
|
||||
|
||||
let stickerSettings: StickerSettings
|
||||
if let value = internalData.stickerSettings?.get(StickerSettings.self) {
|
||||
stickerSettings = value
|
||||
@ -402,7 +416,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager<Te
|
||||
|
||||
let chatBubbleCorners = PresentationChatBubbleCorners(mainRadius: CGFloat(themeSettings.chatBubbleSettings.mainRadius), auxiliaryRadius: CGFloat(themeSettings.chatBubbleSettings.auxiliaryRadius), mergeBubbleCorners: themeSettings.chatBubbleSettings.mergeBubbleCorners)
|
||||
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, reduceMotion: themeSettings.reduceMotion, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, stickerSettings: stickerSettings, experimentalUISettings: experimentalUISettings)
|
||||
return InitialPresentationDataAndSettings(presentationData: PresentationData(strings: stringsValue, theme: theme, autoNightModeTriggered: autoNightModeTriggered, chatWallpaper: effectiveChatWallpaper, chatFontSize: chatFontSize, chatBubbleCorners: chatBubbleCorners, listsFontSize: listsFontSize, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, nameSortOrder: nameSortOrder, reduceMotion: themeSettings.reduceMotion, largeEmoji: themeSettings.largeEmoji), automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, callListSettings: callListSettings, inAppNotificationSettings: inAppNotificationSettings, mediaInputSettings: mediaInputSettings, mediaDisplaySettings: mediaDisplaySettings, stickerSettings: stickerSettings, experimentalUISettings: experimentalUISettings)
|
||||
}
|
||||
}
|
||||
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMax.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMax.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "brightness_max.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
135
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMax.imageset/brightness_max.pdf
vendored
Normal file
135
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMax.imageset/brightness_max.pdf
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
9.140625 16.273438 m
|
||||
9.140625 16.648438 8.828125 16.960938 8.453125 16.960938 c
|
||||
8.085938 16.960938 7.773438 16.648438 7.773438 16.273438 c
|
||||
7.773438 14.632812 l
|
||||
7.773438 14.265625 8.085938 13.953125 8.453125 13.953125 c
|
||||
8.828125 13.953125 9.140625 14.265625 9.140625 14.632812 c
|
||||
9.140625 16.273438 l
|
||||
h
|
||||
12.312500 13.296875 m
|
||||
12.054688 13.031250 12.054688 12.601562 12.312500 12.335938 c
|
||||
12.578125 12.078125 13.015625 12.070312 13.281250 12.335938 c
|
||||
14.445312 13.500000 l
|
||||
14.710938 13.765625 14.710938 14.210938 14.445312 14.468750 c
|
||||
14.187500 14.734375 13.750000 14.734375 13.492188 14.468750 c
|
||||
12.312500 13.296875 l
|
||||
h
|
||||
3.625000 12.335938 m
|
||||
3.890625 12.078125 4.328125 12.078125 4.585938 12.335938 c
|
||||
4.851562 12.585938 4.851562 13.039062 4.593750 13.296875 c
|
||||
3.429688 14.468750 l
|
||||
3.179688 14.726562 2.734375 14.734375 2.468750 14.468750 c
|
||||
2.210938 14.210938 2.210938 13.765625 2.460938 13.507812 c
|
||||
3.625000 12.335938 l
|
||||
h
|
||||
8.453125 12.468750 m
|
||||
6.273438 12.468750 4.468750 10.664062 4.468750 8.476562 c
|
||||
4.468750 6.296875 6.273438 4.492188 8.453125 4.492188 c
|
||||
10.625000 4.492188 12.429688 6.296875 12.429688 8.476562 c
|
||||
12.429688 10.664062 10.625000 12.468750 8.453125 12.468750 c
|
||||
h
|
||||
16.226562 7.796875 m
|
||||
16.601562 7.796875 16.914062 8.109375 16.914062 8.476562 c
|
||||
16.914062 8.843750 16.601562 9.156250 16.226562 9.156250 c
|
||||
14.593750 9.156250 l
|
||||
14.226562 9.156250 13.914062 8.843750 13.914062 8.476562 c
|
||||
13.914062 8.109375 14.226562 7.796875 14.593750 7.796875 c
|
||||
16.226562 7.796875 l
|
||||
h
|
||||
0.679688 9.156250 m
|
||||
0.312500 9.156250 0.000000 8.843750 0.000000 8.476562 c
|
||||
0.000000 8.109375 0.312500 7.796875 0.679688 7.796875 c
|
||||
2.312500 7.796875 l
|
||||
2.687500 7.796875 3.000000 8.109375 3.000000 8.476562 c
|
||||
3.000000 8.843750 2.687500 9.156250 2.312500 9.156250 c
|
||||
0.679688 9.156250 l
|
||||
h
|
||||
13.273438 4.609375 m
|
||||
13.015625 4.875000 12.578125 4.875000 12.312500 4.609375 c
|
||||
12.054688 4.351562 12.054688 3.914062 12.312500 3.648438 c
|
||||
13.492188 2.476562 l
|
||||
13.750000 2.218750 14.187500 2.226562 14.445312 2.484375 c
|
||||
14.710938 2.750000 14.710938 3.187500 14.445312 3.445312 c
|
||||
13.273438 4.609375 l
|
||||
h
|
||||
2.460938 3.453125 m
|
||||
2.203125 3.195312 2.203125 2.757812 2.453125 2.492188 c
|
||||
2.710938 2.234375 3.156250 2.226562 3.421875 2.484375 c
|
||||
4.585938 3.648438 l
|
||||
4.851562 3.906250 4.851562 4.343750 4.593750 4.609375 c
|
||||
4.335938 4.867188 3.890625 4.867188 3.625000 4.609375 c
|
||||
2.460938 3.453125 l
|
||||
h
|
||||
9.140625 2.320312 m
|
||||
9.140625 2.695312 8.828125 3.007812 8.453125 3.007812 c
|
||||
8.085938 3.007812 7.773438 2.695312 7.773438 2.320312 c
|
||||
7.773438 0.679688 l
|
||||
7.773438 0.312500 8.085938 0.000000 8.453125 0.000000 c
|
||||
8.828125 0.000000 9.140625 0.312500 9.140625 0.679688 c
|
||||
9.140625 2.320312 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
2760
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 16.914062 16.960938 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Pages 5 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000002850 00000 n
|
||||
0000002873 00000 n
|
||||
0000003046 00000 n
|
||||
0000003120 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
3179
|
||||
%%EOF
|
12
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMin.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMin.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "brightness_min.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
198
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMin.imageset/brightness_min.pdf
vendored
Normal file
198
submodules/TelegramUI/Images.xcassets/Settings/WallpaperBrightnessMin.imageset/brightness_min.pdf
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /Length 2 0 R >>
|
||||
stream
|
||||
1.154297 0 0.087402 -0.137207 1.066895 1.066895 d1
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
51
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
[ 1.154297 ]
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Length 5 0 R >>
|
||||
stream
|
||||
/CIDInit /ProcSet findresource begin
|
||||
12 dict begin
|
||||
begincmap
|
||||
/CIDSystemInfo
|
||||
<< /Registry (FigmaPDF)
|
||||
/Ordering (FigmaPDF)
|
||||
/Supplement 0
|
||||
>> def
|
||||
/CMapName /A-B-C def
|
||||
/CMapType 2 def
|
||||
1 begincodespacerange
|
||||
<00> <FF>
|
||||
endcodespacerange
|
||||
1 beginbfchar
|
||||
<00> <DBC0DDAC>
|
||||
endbfchar
|
||||
endcmap
|
||||
CMapName currentdict /CMap defineresource pop
|
||||
end
|
||||
end
|
||||
endstream
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
336
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Subtype /Type3
|
||||
/CharProcs << /C0 1 0 R >>
|
||||
/Encoding << /Type /Encoding
|
||||
/Differences [ 0 /C0 ]
|
||||
>>
|
||||
/Widths 3 0 R
|
||||
/FontBBox [ 0.000000 0.000000 0.000000 0.000000 ]
|
||||
/FontMatrix [ 1.000000 0.000000 0.000000 1.000000 0.000000 0.000000 ]
|
||||
/Type /Font
|
||||
/ToUnicode 4 0 R
|
||||
/FirstChar 0
|
||||
/LastChar 0
|
||||
/Resources << >>
|
||||
>>
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
<< /Font << /F1 6 0 R >> >>
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Length 9 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 -1.653809 1.365723 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
0.342773 0.692383 m
|
||||
h
|
||||
9.000000 11.612793 m
|
||||
9.468750 11.612793 9.856934 12.000977 9.856934 12.469727 c
|
||||
9.856934 12.938477 9.468750 13.326660 9.000000 13.326660 c
|
||||
8.531250 13.326660 8.143066 12.938477 8.143066 12.469727 c
|
||||
8.143066 12.000977 8.531250 11.612793 9.000000 11.612793 c
|
||||
h
|
||||
4.407715 9.715820 m
|
||||
4.883789 9.715820 5.264648 10.104004 5.264648 10.572754 c
|
||||
5.264648 11.041504 4.883789 11.429688 4.407715 11.429688 c
|
||||
3.938965 11.429688 3.550781 11.041504 3.550781 10.572754 c
|
||||
3.550781 10.104004 3.938965 9.715820 4.407715 9.715820 c
|
||||
h
|
||||
13.592285 9.715820 m
|
||||
14.061035 9.715820 14.449219 10.104004 14.449219 10.572754 c
|
||||
14.449219 11.041504 14.061035 11.429688 13.592285 11.429688 c
|
||||
13.123535 11.429688 12.735352 11.041504 12.735352 10.572754 c
|
||||
12.735352 10.104004 13.123535 9.715820 13.592285 9.715820 c
|
||||
h
|
||||
9.000000 2.252441 m
|
||||
11.036133 2.252441 12.735352 3.944336 12.735352 5.980469 c
|
||||
12.735352 8.023926 11.036133 9.715820 9.000000 9.715820 c
|
||||
6.963867 9.715820 5.271973 8.023926 5.271973 5.980469 c
|
||||
5.271973 3.944336 6.963867 2.252441 9.000000 2.252441 c
|
||||
h
|
||||
2.510742 5.123535 m
|
||||
2.979492 5.123535 3.367676 5.511719 3.367676 5.980469 c
|
||||
3.367676 6.456543 2.979492 6.837402 2.510742 6.837402 c
|
||||
2.041992 6.837402 1.653809 6.456543 1.653809 5.980469 c
|
||||
1.653809 5.511719 2.041992 5.123535 2.510742 5.123535 c
|
||||
h
|
||||
15.489258 5.123535 m
|
||||
15.958008 5.123535 16.346191 5.511719 16.346191 5.980469 c
|
||||
16.346191 6.456543 15.958008 6.837402 15.489258 6.837402 c
|
||||
15.020508 6.837402 14.632324 6.456543 14.632324 5.980469 c
|
||||
14.632324 5.511719 15.020508 5.123535 15.489258 5.123535 c
|
||||
h
|
||||
13.592285 0.531250 m
|
||||
14.061035 0.531250 14.449219 0.919434 14.449219 1.388184 c
|
||||
14.449219 1.864258 14.061035 2.245117 13.592285 2.245117 c
|
||||
13.123535 2.245117 12.735352 1.864258 12.735352 1.388184 c
|
||||
12.735352 0.919434 13.123535 0.531250 13.592285 0.531250 c
|
||||
h
|
||||
4.407715 0.531250 m
|
||||
4.883789 0.531250 5.264648 0.919434 5.264648 1.388184 c
|
||||
5.264648 1.864258 4.883789 2.245117 4.407715 2.245117 c
|
||||
3.938965 2.245117 3.550781 1.864258 3.550781 1.388184 c
|
||||
3.550781 0.919434 3.938965 0.531250 4.407715 0.531250 c
|
||||
h
|
||||
9.000000 -1.365723 m
|
||||
9.468750 -1.365723 9.856934 -0.977539 9.856934 -0.508789 c
|
||||
9.856934 -0.032715 9.468750 0.348145 9.000000 0.348145 c
|
||||
8.531250 0.348145 8.143066 -0.032715 8.143066 -0.508789 c
|
||||
8.143066 -0.977539 8.531250 -1.365723 9.000000 -1.365723 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 -1.653809 1.365723 cm
|
||||
BT
|
||||
15.000000 0.000000 0.000000 15.000000 0.342773 0.692383 Tm
|
||||
/F1 1.000000 Tf
|
||||
[ (\000) ] TJ
|
||||
ET
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
2605
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 14.692383 14.692383 ]
|
||||
/Resources 7 0 R
|
||||
/Contents 8 0 R
|
||||
/Parent 11 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
11 0 obj
|
||||
<< /Kids [ 10 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
12 0 obj
|
||||
<< /Pages 11 0 R
|
||||
/Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 13
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000117 00000 n
|
||||
0000000138 00000 n
|
||||
0000000169 00000 n
|
||||
0000000561 00000 n
|
||||
0000000583 00000 n
|
||||
0000000995 00000 n
|
||||
0000001041 00000 n
|
||||
0000003702 00000 n
|
||||
0000003725 00000 n
|
||||
0000003900 00000 n
|
||||
0000003976 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 12 0 R
|
||||
/Size 13
|
||||
>>
|
||||
startxref
|
||||
4037
|
||||
%%EOF
|
@ -845,7 +845,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
let wallpaperPreviewController = WallpaperGalleryController(context: strongSelf.context, source: .wallpaper(wallpaper, nil, [], nil, nil, nil), mode: .peer(EnginePeer(peer), true))
|
||||
wallpaperPreviewController.apply = { wallpaper, options, _ in
|
||||
wallpaperPreviewController.apply = { wallpaper, options, _, _ in
|
||||
let _ = (strongSelf.context.engine.themes.setExistingChatWallpaper(messageId: message.id, wallpaper: nil)
|
||||
|> deliverOnMainQueue).start(completed: { [weak wallpaperPreviewController] in
|
||||
wallpaperPreviewController?.dismiss()
|
||||
@ -4264,12 +4264,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if value {
|
||||
openWebView()
|
||||
} else {
|
||||
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertTitle, text: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertText(botName).string, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
|
||||
if let strongSelf = self {
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id).start()
|
||||
openWebView()
|
||||
}
|
||||
})], parseMarkdown: true), in: .window(.root), with: nil)
|
||||
let controller = webAppLaunchConfirmationController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: EnginePeer(peer), commit: {
|
||||
let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id).start()
|
||||
openWebView()
|
||||
}, showMore: nil)
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
}
|
||||
})
|
||||
}, activateAdAction: { [weak self] messageId in
|
||||
@ -17173,7 +17172,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}))
|
||||
}
|
||||
|
||||
private func openResolved(result: ResolvedUrl, sourceMessageId: MessageId?, forceExternal: Bool = false) {
|
||||
private func openResolved(result: ResolvedUrl, sourceMessageId: MessageId?, forceExternal: Bool = false, concealed: Bool = false) {
|
||||
guard let peerId = self.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
@ -17230,7 +17229,28 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), attachBotStart: attachBotStart))
|
||||
}
|
||||
case let .withBotApp(botAppStart):
|
||||
strongSelf.presentBotApp(botApp: botAppStart.botApp, payload: botAppStart.payload)
|
||||
let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId.id))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
if let strongSelf = self, let peer {
|
||||
let openBotApp = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentBotApp(botApp: botAppStart.botApp, payload: botAppStart.payload)
|
||||
}
|
||||
}
|
||||
if concealed {
|
||||
let controller = webAppLaunchConfirmationController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: peer, commit: {
|
||||
openBotApp()
|
||||
}, showMore: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.openResolved(result: .peer(peer._asPeer(), .info), sourceMessageId: nil)
|
||||
}
|
||||
})
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
} else {
|
||||
openBotApp()
|
||||
}
|
||||
}
|
||||
})
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -17256,7 +17276,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
openUserGeneratedUrl(context: self.context, peerId: self.peerView?.peerId, url: url, concealed: concealed, skipUrlAuth: skipUrlAuth, skipConcealedAlert: skipConcealedAlert, present: { [weak self] c in
|
||||
self?.present(c, in: .window(.root))
|
||||
}, openResolved: { [weak self] resolved in
|
||||
self?.openResolved(result: resolved, sourceMessageId: message?.id, forceExternal: forceExternal)
|
||||
self?.openResolved(result: resolved, sourceMessageId: message?.id, forceExternal: forceExternal, concealed: concealed)
|
||||
})
|
||||
}, performAction: true)
|
||||
}
|
||||
@ -18535,9 +18555,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false))
|
||||
controller.navigationPresentation = .modal
|
||||
controller.apply = { [weak self] wallpaper, options, cropRect in
|
||||
controller.apply = { [weak self] wallpaper, options, cropRect, brightness in
|
||||
if let strongSelf = self {
|
||||
uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, brightnessMultiplier: nil, peerId: peerId, completion: {
|
||||
uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, brightness: brightness, peerId: peerId, completion: {
|
||||
dismissControllers()
|
||||
})
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ private func fetchCachedBlurredWallpaperRepresentation(resource: MediaResource,
|
||||
let path = NSTemporaryDirectory() + "\(Int64.random(in: Int64.min ... Int64.max))"
|
||||
let url = URL(fileURLWithPath: path)
|
||||
|
||||
if let colorImage = blurredImage(image, radius: 20.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
|
||||
if let colorImage = blurredImage(image, radius: 30.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
|
||||
CGImageDestinationSetProperties(colorDestination, [:] as CFDictionary)
|
||||
|
||||
let colorQuality: Float = 0.5
|
||||
@ -447,7 +447,7 @@ private func fetchCachedBlurredWallpaperRepresentation(account: Account, resourc
|
||||
let path = NSTemporaryDirectory() + "\(Int64.random(in: Int64.min ... Int64.max))"
|
||||
let url = URL(fileURLWithPath: path)
|
||||
|
||||
if let colorImage = blurredImage(image, radius: 20.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
|
||||
if let colorImage = blurredImage(image, radius: 30.0), let colorDestination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeJPEG, 1, nil) {
|
||||
CGImageDestinationSetProperties(colorDestination, [:] as CFDictionary)
|
||||
|
||||
let colorQuality: Float = 0.5
|
||||
|
@ -162,6 +162,9 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
public let currentMediaInputSettings: Atomic<MediaInputSettings>
|
||||
private var mediaInputSettingsDisposable: Disposable?
|
||||
|
||||
public let currentMediaDisplaySettings: Atomic<MediaDisplaySettings>
|
||||
private var mediaDisplaySettingsDisposable: Disposable?
|
||||
|
||||
public let currentStickerSettings: Atomic<StickerSettings>
|
||||
private var stickerSettingsDisposable: Disposable?
|
||||
|
||||
@ -241,6 +244,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
self.currentAutomaticMediaDownloadSettings = initialPresentationDataAndSettings.automaticMediaDownloadSettings
|
||||
self.currentAutodownloadSettings = Atomic(value: initialPresentationDataAndSettings.autodownloadSettings)
|
||||
self.currentMediaInputSettings = Atomic(value: initialPresentationDataAndSettings.mediaInputSettings)
|
||||
self.currentMediaDisplaySettings = Atomic(value: initialPresentationDataAndSettings.mediaDisplaySettings)
|
||||
self.currentStickerSettings = Atomic(value: initialPresentationDataAndSettings.stickerSettings)
|
||||
self.currentInAppNotificationSettings = Atomic(value: initialPresentationDataAndSettings.inAppNotificationSettings)
|
||||
|
||||
@ -359,6 +363,15 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
}
|
||||
})
|
||||
|
||||
self.mediaDisplaySettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.mediaDisplaySettings])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] sharedData in
|
||||
if let strongSelf = self {
|
||||
if let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.mediaDisplaySettings]?.get(MediaDisplaySettings.self) {
|
||||
let _ = strongSelf.currentMediaDisplaySettings.swap(settings)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
self.stickerSettingsDisposable = (self.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] sharedData in
|
||||
if let strongSelf = self {
|
||||
@ -895,6 +908,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
self.currentAutodownloadSettingsDisposable.dispose()
|
||||
self.inAppNotificationSettingsDisposable?.dispose()
|
||||
self.mediaInputSettingsDisposable?.dispose()
|
||||
self.mediaDisplaySettingsDisposable?.dispose()
|
||||
self.callDisposable?.dispose()
|
||||
self.groupCallDisposable?.dispose()
|
||||
self.callStateDisposable?.dispose()
|
||||
|
@ -0,0 +1,50 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
|
||||
public struct MediaDisplaySettings: Codable, Equatable {
|
||||
public let showNextMediaOnTap: Bool
|
||||
|
||||
public static var defaultSettings: MediaDisplaySettings {
|
||||
return MediaDisplaySettings(showNextMediaOnTap: true)
|
||||
}
|
||||
|
||||
public init(showNextMediaOnTap: Bool) {
|
||||
self.showNextMediaOnTap = showNextMediaOnTap
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
self.showNextMediaOnTap = (try container.decode(Int32.self, forKey: "showNextMediaOnTap")) != 0
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
||||
|
||||
try container.encode((self.showNextMediaOnTap ? 1 : 0) as Int32, forKey: "showNextMediaOnTap")
|
||||
}
|
||||
|
||||
public static func ==(lhs: MediaDisplaySettings, rhs: MediaDisplaySettings) -> Bool {
|
||||
return lhs.showNextMediaOnTap == rhs.showNextMediaOnTap
|
||||
}
|
||||
|
||||
public func withUpdatedShowNextMediaOnTap(_ showNextMediaOnTap: Bool) -> MediaDisplaySettings {
|
||||
return MediaDisplaySettings(showNextMediaOnTap: showNextMediaOnTap)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateMediaDisplaySettingsInteractively(accountManager: AccountManager<TelegramAccountManagerTypes>, _ f: @escaping (MediaDisplaySettings) -> MediaDisplaySettings) -> Signal<Void, NoError> {
|
||||
return accountManager.transaction { transaction -> Void in
|
||||
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.mediaDisplaySettings, { entry in
|
||||
let currentSettings: MediaDisplaySettings
|
||||
if let entry = entry?.get(MediaDisplaySettings.self) {
|
||||
currentSettings = entry
|
||||
} else {
|
||||
currentSettings = MediaDisplaySettings.defaultSettings
|
||||
}
|
||||
return PreferencesEntry(f(currentSettings))
|
||||
})
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@ private enum ApplicationSpecificSharedDataKeyValues: Int32 {
|
||||
case intentsSettings = 17
|
||||
case translationSettings = 18
|
||||
case drawingSettings = 19
|
||||
case mediaDisplaySettings = 20
|
||||
}
|
||||
|
||||
public struct ApplicationSpecificSharedDataKeys {
|
||||
@ -62,6 +63,7 @@ public struct ApplicationSpecificSharedDataKeys {
|
||||
public static let intentsSettings = applicationSpecificPreferencesKey(ApplicationSpecificSharedDataKeyValues.intentsSettings.rawValue)
|
||||
public static let translationSettings = applicationSpecificPreferencesKey(ApplicationSpecificSharedDataKeyValues.translationSettings.rawValue)
|
||||
public static let drawingSettings = applicationSpecificPreferencesKey(ApplicationSpecificSharedDataKeyValues.drawingSettings.rawValue)
|
||||
public static let mediaDisplaySettings = applicationSpecificPreferencesKey(ApplicationSpecificSharedDataKeyValues.mediaDisplaySettings.rawValue)
|
||||
}
|
||||
|
||||
private enum ApplicationSpecificItemCacheCollectionIdValues: Int8 {
|
||||
|
287
submodules/WebUI/Sources/WebAppOpenConfirmationController.swift
Normal file
287
submodules/WebUI/Sources/WebAppOpenConfirmationController.swift
Normal file
@ -0,0 +1,287 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import AccountContext
|
||||
import AppBundle
|
||||
import AvatarNode
|
||||
|
||||
private final class WebAppLaunchConfirmationAlertContentNode: AlertContentNode {
|
||||
private let strings: PresentationStrings
|
||||
private let title: String
|
||||
private let text: String
|
||||
private let showMore: Bool
|
||||
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let textNode: ASTextNode
|
||||
private let avatarNode: AvatarNode
|
||||
|
||||
private let moreButton: HighlightableButtonNode
|
||||
private let arrowNode: ASImageNode
|
||||
|
||||
private let actionNodesSeparator: ASDisplayNode
|
||||
private let actionNodes: [TextAlertContentActionNode]
|
||||
private let actionVerticalSeparators: [ASDisplayNode]
|
||||
|
||||
private var validLayout: CGSize?
|
||||
|
||||
private let morePressed: () -> Void
|
||||
|
||||
override var dismissOnOutsideTap: Bool {
|
||||
return self.isUserInteractionEnabled
|
||||
}
|
||||
|
||||
init(context: AccountContext, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, peer: EnginePeer, title: String, text: String, showMore: Bool, actions: [TextAlertAction], morePressed: @escaping () -> Void) {
|
||||
self.strings = strings
|
||||
self.title = title
|
||||
self.text = text
|
||||
self.showMore = showMore
|
||||
self.morePressed = morePressed
|
||||
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.textAlignment = .center
|
||||
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.displaysAsynchronously = false
|
||||
self.textNode.maximumNumberOfLines = 0
|
||||
|
||||
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 26.0))
|
||||
|
||||
self.moreButton = HighlightableButtonNode()
|
||||
|
||||
self.arrowNode = ASImageNode()
|
||||
self.arrowNode.displaysAsynchronously = false
|
||||
self.arrowNode.displayWithoutProcessing = true
|
||||
self.arrowNode.isHidden = !showMore
|
||||
self.arrowNode.contentMode = .scaleAspectFit
|
||||
|
||||
self.actionNodesSeparator = ASDisplayNode()
|
||||
self.actionNodesSeparator.isLayerBacked = true
|
||||
|
||||
self.actionNodes = actions.map { action -> TextAlertContentActionNode in
|
||||
return TextAlertContentActionNode(theme: theme, action: action)
|
||||
}
|
||||
|
||||
var actionVerticalSeparators: [ASDisplayNode] = []
|
||||
if actions.count > 1 {
|
||||
for _ in 0 ..< actions.count - 1 {
|
||||
let separatorNode = ASDisplayNode()
|
||||
separatorNode.isLayerBacked = true
|
||||
actionVerticalSeparators.append(separatorNode)
|
||||
}
|
||||
}
|
||||
self.actionVerticalSeparators = actionVerticalSeparators
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.textNode)
|
||||
self.addSubnode(self.avatarNode)
|
||||
self.addSubnode(self.moreButton)
|
||||
self.moreButton.addSubnode(self.arrowNode)
|
||||
|
||||
self.addSubnode(self.actionNodesSeparator)
|
||||
|
||||
for actionNode in self.actionNodes {
|
||||
self.addSubnode(actionNode)
|
||||
}
|
||||
|
||||
for separatorNode in self.actionVerticalSeparators {
|
||||
self.addSubnode(separatorNode)
|
||||
}
|
||||
|
||||
self.updateTheme(theme)
|
||||
|
||||
self.avatarNode.setPeer(context: context, theme: ptheme, peer: peer)
|
||||
|
||||
self.moreButton.addTarget(self, action: #selector(self.moreButtonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
@objc private func moreButtonPressed() {
|
||||
self.morePressed()
|
||||
}
|
||||
|
||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
self.moreButton.setAttributedTitle(NSAttributedString(string: self.strings.WebApp_LaunchMoreInfo, font: Font.regular(13.0), textColor: theme.accentColor), for: .normal)
|
||||
self.arrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Peer Info/AlertArrow"), color: theme.accentColor)
|
||||
|
||||
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
||||
for actionNode in self.actionNodes {
|
||||
actionNode.updateTheme(theme)
|
||||
}
|
||||
for separatorNode in self.actionVerticalSeparators {
|
||||
separatorNode.backgroundColor = theme.separatorColor
|
||||
}
|
||||
|
||||
if let size = self.validLayout {
|
||||
_ = self.updateLayout(size: size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
var size = size
|
||||
size.width = min(size.width, 270.0)
|
||||
|
||||
self.validLayout = size
|
||||
|
||||
var origin: CGPoint = CGPoint(x: 0.0, y: 20.0)
|
||||
|
||||
let avatarSize = CGSize(width: 60.0, height: 60.0)
|
||||
self.avatarNode.updateSize(size: avatarSize)
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - avatarSize.width) / 2.0), y: origin.y), size: avatarSize)
|
||||
transition.updateFrame(node: self.avatarNode, frame: avatarFrame)
|
||||
|
||||
origin.y += avatarSize.height + 17.0
|
||||
|
||||
if let arrowImage = self.arrowNode.image {
|
||||
let arrowFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - arrowImage.size.width) / 2.0), y: origin.y + floorToScreenPixels((avatarSize.height - arrowImage.size.height) / 2.0)), size: arrowImage.size)
|
||||
transition.updateFrame(node: self.arrowNode, frame: arrowFrame)
|
||||
}
|
||||
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - 32.0, height: size.height))
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: origin.y), size: titleSize))
|
||||
origin.y += titleSize.height + 6.0
|
||||
|
||||
if self.showMore {
|
||||
let moreButtonSize = self.moreButton.measure(CGSize(width: size.width - 32.0, height: size.height))
|
||||
transition.updateFrame(node: self.moreButton, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - moreButtonSize.width) / 2.0) - 5.0, y: origin.y), size: moreButtonSize))
|
||||
transition.updateFrame(node: self.arrowNode, frame: CGRect(origin: CGPoint(x: moreButtonSize.width + 3.0, y: 4.0), size: CGSize(width: 9.0, height: 9.0)))
|
||||
origin.y += moreButtonSize.height + 22.0
|
||||
}
|
||||
|
||||
let textSize = self.textNode.measure(CGSize(width: size.width - 32.0, height: size.height))
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: origin.y), size: textSize))
|
||||
|
||||
let actionButtonHeight: CGFloat = 44.0
|
||||
var minActionsWidth: CGFloat = 0.0
|
||||
let maxActionWidth: CGFloat = floor(size.width / CGFloat(self.actionNodes.count))
|
||||
let actionTitleInsets: CGFloat = 8.0
|
||||
|
||||
var effectiveActionLayout = TextAlertContentActionLayout.horizontal
|
||||
for actionNode in self.actionNodes {
|
||||
let actionTitleSize = actionNode.titleNode.updateLayout(CGSize(width: maxActionWidth, height: actionButtonHeight))
|
||||
if case .horizontal = effectiveActionLayout, actionTitleSize.height > actionButtonHeight * 0.6667 {
|
||||
effectiveActionLayout = .vertical
|
||||
}
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
minActionsWidth += actionTitleSize.width + actionTitleInsets
|
||||
case .vertical:
|
||||
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
|
||||
}
|
||||
}
|
||||
|
||||
let insets = UIEdgeInsets(top: 18.0, left: 18.0, bottom: 18.0, right: 18.0)
|
||||
|
||||
let contentWidth = max(size.width, minActionsWidth)
|
||||
|
||||
var actionsHeight: CGFloat = 0.0
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
actionsHeight = actionButtonHeight
|
||||
case .vertical:
|
||||
actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count)
|
||||
}
|
||||
|
||||
var resultSize = CGSize(width: contentWidth, height: avatarSize.height + titleSize.height + textSize.height + actionsHeight + 25.0 + insets.top + insets.bottom)
|
||||
if self.showMore {
|
||||
resultSize.height += 37.0
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||
|
||||
var actionOffset: CGFloat = 0.0
|
||||
let actionWidth: CGFloat = floor(resultSize.width / CGFloat(self.actionNodes.count))
|
||||
var separatorIndex = -1
|
||||
var nodeIndex = 0
|
||||
for actionNode in self.actionNodes {
|
||||
if separatorIndex >= 0 {
|
||||
let separatorNode = self.actionVerticalSeparators[separatorIndex]
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
|
||||
case .vertical:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||
}
|
||||
}
|
||||
separatorIndex += 1
|
||||
|
||||
let currentActionWidth: CGFloat
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
if nodeIndex == self.actionNodes.count - 1 {
|
||||
currentActionWidth = resultSize.width - actionOffset
|
||||
} else {
|
||||
currentActionWidth = actionWidth
|
||||
}
|
||||
case .vertical:
|
||||
currentActionWidth = resultSize.width
|
||||
}
|
||||
|
||||
let actionNodeFrame: CGRect
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
actionNodeFrame = CGRect(origin: CGPoint(x: actionOffset, y: resultSize.height - actionsHeight), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
|
||||
actionOffset += currentActionWidth
|
||||
case .vertical:
|
||||
actionNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
|
||||
actionOffset += actionButtonHeight
|
||||
}
|
||||
|
||||
transition.updateFrame(node: actionNode, frame: actionNodeFrame)
|
||||
|
||||
nodeIndex += 1
|
||||
}
|
||||
|
||||
return resultSize
|
||||
}
|
||||
}
|
||||
|
||||
public func webAppLaunchConfirmationController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peer: EnginePeer, commit: @escaping () -> Void, showMore: (() -> Void)?) -> AlertController {
|
||||
let theme = defaultDarkColorPresentationTheme
|
||||
let presentationData: PresentationData
|
||||
if let updatedPresentationData {
|
||||
presentationData = updatedPresentationData.initial
|
||||
} else {
|
||||
presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
}
|
||||
let strings = presentationData.strings
|
||||
|
||||
var dismissImpl: ((Bool) -> Void)?
|
||||
var contentNode: WebAppLaunchConfirmationAlertContentNode?
|
||||
let actions: [TextAlertAction] = [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
dismissImpl?(true)
|
||||
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
||||
dismissImpl?(true)
|
||||
commit()
|
||||
})]
|
||||
|
||||
let title = peer.compactDisplayTitle
|
||||
let text = presentationData.strings.WebApp_LaunchConfirmation
|
||||
|
||||
contentNode = WebAppLaunchConfirmationAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, peer: peer, title: title, text: text, showMore: showMore != nil, actions: actions, morePressed: {
|
||||
dismissImpl?(true)
|
||||
showMore?()
|
||||
})
|
||||
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode!)
|
||||
dismissImpl = { [weak controller] animated in
|
||||
if animated {
|
||||
controller?.dismissAnimated()
|
||||
} else {
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
return controller
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user