mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 21:45:19 +00:00
Chat wallpaper improvements
This commit is contained in:
parent
8e6ed4c4d0
commit
1e2ed2d2f4
@ -9149,7 +9149,7 @@ Sorry for the inconvenience.";
|
||||
"WallpaperPreview.ChatBottomText" = "Enjoy the view.";
|
||||
|
||||
"Conversation.Theme.SetPhotoWallpaper" = "Choose Background from Photos";
|
||||
"Conversation.Theme.SetColorWallpaper" = "Choose Color as a Background";
|
||||
"Conversation.Theme.SetColorWallpaper" = "Set a Color as a Background";
|
||||
"Conversation.Theme.OtherOptions" = "Other Options...";
|
||||
|
||||
"Conversation.Theme.ChooseWallpaperTitle" = "Choose Background";
|
||||
@ -9161,3 +9161,8 @@ Sorry for the inconvenience.";
|
||||
|
||||
"WebApp.LaunchMoreInfo" = "More about this bot";
|
||||
"WebApp.LaunchConfirmation" = "To launch this web app, you will connect to its website.";
|
||||
|
||||
"WallpaperPreview.PreviewInNightMode" = "Preview this background in night mode.";
|
||||
"WallpaperPreview.PreviewInDayMode" = "Preview this background in day mode.";
|
||||
|
||||
"Conversation.Theme.ApplyBackground" = "Set as Background";
|
||||
|
@ -1370,7 +1370,7 @@ public final class CalendarMessageScreen: ViewController {
|
||||
if self.selectionState?.dayRange == nil {
|
||||
if let selectionToolbarNode = self.selectionToolbarNode {
|
||||
let toolbarFrame = selectionToolbarNode.view.convert(selectionToolbarNode.bounds, to: self.view)
|
||||
self.controller?.present(TooltipScreen(account: self.context.account, text: self.presentationData.strings.MessageCalendar_EmptySelectionTooltip, style: .default, icon: .none, location: .point(toolbarFrame.insetBy(dx: 0.0, dy: 10.0), .bottom), shouldDismissOnTouch: { point in
|
||||
self.controller?.present(TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: self.presentationData.strings.MessageCalendar_EmptySelectionTooltip, style: .default, icon: .none, location: .point(toolbarFrame.insetBy(dx: 0.0, dy: 10.0), .bottom), shouldDismissOnTouch: { point in
|
||||
return .dismiss(consume: false)
|
||||
}), in: .current)
|
||||
}
|
||||
|
@ -2079,7 +2079,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|
||||
let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.minY - 8.0), size: CGSize())
|
||||
|
||||
parentController.present(TooltipScreen(account: strongSelf.context.account, text: text, icon: .chatListPress, location: .point(location, .bottom), shouldDismissOnTouch: { point in
|
||||
parentController.present(TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: text, icon: .chatListPress, location: .point(location, .bottom), shouldDismissOnTouch: { point in
|
||||
guard let strongSelf = self, let parentController = strongSelf.parent as? TabBarController else {
|
||||
return .dismiss(consume: false)
|
||||
}
|
||||
|
@ -829,7 +829,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
text = strongSelf.presentationData.strings.Location_ProximityTip(EnginePeer(peer).compactDisplayTitle).string
|
||||
}
|
||||
|
||||
strongSelf.interaction.present(TooltipScreen(account: strongSelf.context.account, text: text, icon: nil, location: .point(location.offsetBy(dx: -9.0, dy: 0.0), .right), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
strongSelf.interaction.present(TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: text, icon: nil, location: .point(location.offsetBy(dx: -9.0, dy: 0.0), .right), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
}))
|
||||
})
|
||||
|
@ -2010,18 +2010,18 @@ public func wallpaperMediaPickerController(
|
||||
context: AccountContext,
|
||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||
peer: EnginePeer,
|
||||
canDelete: Bool,
|
||||
completion: @escaping (PHAsset) -> Void = { _ in }
|
||||
completion: @escaping (PHAsset) -> Void = { _ in },
|
||||
openColors: @escaping () -> Void
|
||||
) -> ViewController {
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
controller.requestController = { [weak controller] _, present in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let mediaPickerController = MediaPickerScreen(context: context, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: canDelete ? AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_ResetWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.destructiveActionTextColor, isVisible: true, progress: .none, isEnabled: true) : nil, mainButtonAction: canDelete ? {
|
||||
let _ = context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: nil).start()
|
||||
let mediaPickerController = MediaPickerScreen(context: context, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_SetColorWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true), mainButtonAction: {
|
||||
controller?.dismiss(animated: true)
|
||||
} : nil)
|
||||
openColors()
|
||||
})
|
||||
mediaPickerController.customSelection = completion
|
||||
present(mediaPickerController, mediaPickerController.mediaPickerContext)
|
||||
}
|
||||
|
@ -669,12 +669,8 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
|
||||
|
||||
entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody))
|
||||
entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts))
|
||||
switch kind {
|
||||
case .presence, .voiceCalls, .forwards, .phoneNumber, .voiceMessages, .profilePhoto:
|
||||
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody))
|
||||
case .groupInvitations:
|
||||
break
|
||||
}
|
||||
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody))
|
||||
|
||||
let phoneLink = "https://t.me/+\(phoneNumber)"
|
||||
if let settingInfoText = settingInfoText {
|
||||
entries.append(.settingInfo(presentationData.theme, settingInfoText, phoneLink))
|
||||
|
@ -196,7 +196,7 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE
|
||||
}).start()
|
||||
}
|
||||
|
||||
public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGalleryEntry, mode: WallpaperPresentationOptions, cropRect: CGRect?, brightness: 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, _):
|
||||
@ -279,24 +279,6 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
||||
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))
|
||||
let thumbnailImage = generateScaledImage(image: croppedImage, size: thumbnailDimensions, scale: 1.0)
|
||||
|
||||
@ -309,7 +291,12 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
||||
context.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||
|
||||
let settings = WallpaperSettings(blur: mode.contains(.blur), motion: mode.contains(.motion), colors: [], intensity: nil)
|
||||
var intensity: Int32?
|
||||
if let brightness {
|
||||
intensity = Int32(brightness * 100.0)
|
||||
}
|
||||
|
||||
let settings = WallpaperSettings(blur: mode.contains(.blur), motion: mode.contains(.motion), colors: [], intensity: intensity)
|
||||
let temporaryWallpaper: TelegramWallpaper = .image([TelegramMediaImageRepresentation(dimensions: PixelDimensions(thumbnailDimensions), resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false), TelegramMediaImageRepresentation(dimensions: PixelDimensions(croppedImage.size), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)], settings)
|
||||
|
||||
let _ = context.account.postbox.transaction({ transaction in
|
||||
@ -326,7 +313,7 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
||||
completion()
|
||||
}
|
||||
|
||||
let _ = uploadWallpaper(account: context.account, resource: resource, settings: WallpaperSettings(blur: false, motion: mode.contains(.motion), colors: [], intensity: nil), forChat: true).start(next: { status in
|
||||
let _ = uploadWallpaper(account: context.account, resource: resource, settings: WallpaperSettings(blur: false, motion: mode.contains(.motion), colors: [], intensity: intensity), forChat: true).start(next: { status in
|
||||
if case let .complete(wallpaper) = status {
|
||||
if case let .file(file) = wallpaper {
|
||||
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: file.file.resource.id, synchronous: true)
|
||||
|
@ -11,8 +11,8 @@ import TelegramUIPreferences
|
||||
import AccountContext
|
||||
import AttachmentUI
|
||||
|
||||
private func availableGradients(theme: PresentationTheme) -> [[UInt32]] {
|
||||
if theme.overallDarkAppearance {
|
||||
private func availableGradients(dark: Bool) -> [[UInt32]] {
|
||||
if dark {
|
||||
return [
|
||||
[0x1e3557, 0x151a36, 0x1c4352, 0x2a4541] as [UInt32],
|
||||
[0x1d223f, 0x1d1832, 0x1b2943, 0x141631] as [UInt32],
|
||||
@ -39,8 +39,8 @@ private func availableGradients(theme: PresentationTheme) -> [[UInt32]] {
|
||||
}
|
||||
}
|
||||
|
||||
private func availableColors(theme: PresentationTheme) -> [UInt32] {
|
||||
if theme.overallDarkAppearance {
|
||||
private func availableColors(dark: Bool) -> [UInt32] {
|
||||
if dark {
|
||||
return [
|
||||
0x1D2D3C,
|
||||
0x111B26,
|
||||
@ -150,6 +150,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
||||
|
||||
var pushController: (ViewController) -> Void = { _ in }
|
||||
var dismissControllers: (() -> Void)?
|
||||
var openGallery: (() -> Void)?
|
||||
|
||||
public init(context: AccountContext, mode: Mode = .default, canDelete: Bool = false) {
|
||||
self.context = context
|
||||
@ -192,9 +193,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
||||
self?.push(controller)
|
||||
}
|
||||
|
||||
if canDelete {
|
||||
self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_ResetWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.destructiveActionTextColor, isVisible: true, progress: .none, isEnabled: true)))
|
||||
}
|
||||
self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper, font: .regular, background: .color(.clear), textColor: self.presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true)))
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
@ -270,7 +269,11 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
||||
}
|
||||
|
||||
public override func loadDisplayNode() {
|
||||
self.displayNode = ThemeColorsGridControllerNode(context: self.context, presentationData: self.presentationData, controller: self, gradients: availableGradients(theme: self.presentationData.theme), colors: availableColors(theme: self.presentationData.theme), push: { [weak self] controller in
|
||||
var dark = false
|
||||
if case .default = self.mode {
|
||||
dark = self.presentationData.theme.overallDarkAppearance
|
||||
}
|
||||
self.displayNode = ThemeColorsGridControllerNode(context: self.context, presentationData: self.presentationData, controller: self, gradients: availableGradients(dark: dark), colors: availableColors(dark: dark), push: { [weak self] controller in
|
||||
self?.pushController(controller)
|
||||
}, pop: { [weak self] in
|
||||
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
@ -327,12 +330,8 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
||||
}
|
||||
|
||||
@objc fileprivate func mainButtonPressed() {
|
||||
guard case let .peer(peer) = self.mode else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = self.context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: nil).start()
|
||||
self.dismiss(animated: true)
|
||||
self.openGallery?()
|
||||
}
|
||||
|
||||
public var requestAttachmentMenuExpansion: () -> Void = {}
|
||||
@ -385,18 +384,25 @@ private final class ThemeColorsGridContext: AttachmentMediaPickerContext {
|
||||
}
|
||||
|
||||
|
||||
public func standaloneColorPickerController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peer: EnginePeer, canDelete: Bool, push: @escaping (ViewController) -> Void) -> ViewController {
|
||||
public func standaloneColorPickerController(
|
||||
context: AccountContext,
|
||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||
peer: EnginePeer,
|
||||
push: @escaping (ViewController) -> Void,
|
||||
openGallery: @escaping () -> Void
|
||||
) -> ViewController {
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
controller.requestController = { _, present in
|
||||
let colorPickerController = ThemeColorsGridController(context: context, mode: .peer(peer), canDelete: canDelete)
|
||||
let colorPickerController = ThemeColorsGridController(context: context, mode: .peer(peer))
|
||||
colorPickerController.pushController = { controller in
|
||||
push(controller)
|
||||
}
|
||||
colorPickerController.dismissControllers = { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
}
|
||||
colorPickerController.openGallery = openGallery
|
||||
present(colorPickerController, colorPickerController.mediaPickerContext)
|
||||
}
|
||||
return controller
|
||||
|
@ -19,6 +19,8 @@ import WallpaperResources
|
||||
import AppBundle
|
||||
import WallpaperBackgroundNode
|
||||
import TextFormat
|
||||
import TooltipUI
|
||||
import TelegramNotices
|
||||
|
||||
struct WallpaperGalleryItemArguments {
|
||||
let colorPreview: Bool
|
||||
@ -83,7 +85,7 @@ private func reference(for resource: MediaResource, media: Media, message: Messa
|
||||
|
||||
final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
private let context: AccountContext
|
||||
private let presentationData: PresentationData
|
||||
private var presentationData: PresentationData
|
||||
|
||||
var entry: WallpaperGalleryEntry?
|
||||
var source: WallpaperListSource?
|
||||
@ -102,6 +104,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
private let cancelButtonNode: WallpaperNavigationButtonNode
|
||||
private let shareButtonNode: WallpaperNavigationButtonNode
|
||||
private let dayNightButtonNode: WallpaperNavigationButtonNode
|
||||
|
||||
private let blurButtonNode: WallpaperOptionButtonNode
|
||||
private let motionButtonNode: WallpaperOptionButtonNode
|
||||
@ -139,10 +142,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
private var isReadyDisposable: Disposable?
|
||||
|
||||
private var isDarkAppearance: Bool = false
|
||||
private var didChangeAppearance: Bool = false
|
||||
private var darkAppearanceIntensity: CGFloat = 0.8
|
||||
|
||||
init(context: AccountContext) {
|
||||
self.context = context
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.isDarkAppearance = self.presentationData.theme.overallDarkAppearance
|
||||
|
||||
self.wrapperNode = ASDisplayNode()
|
||||
self.imageNode = TransformImageNode()
|
||||
self.imageNode.contentAnimations = .subsequentUpdates
|
||||
@ -154,6 +163,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
self.blurredNode = BlurredImageNode()
|
||||
self.brightnessNode = ASDisplayNode()
|
||||
self.brightnessNode.alpha = 0.0
|
||||
|
||||
self.messagesContainerNode = ASDisplayNode()
|
||||
self.messagesContainerNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
|
||||
@ -169,16 +179,18 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.serviceBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x333333, alpha: 0.33))
|
||||
|
||||
var sliderValueChangedImpl: ((CGFloat) -> Void)?
|
||||
self.sliderNode = WallpaperSliderNode(minValue: 0.0, maxValue: 1.0, value: 0.5, valueChanged: { value, _ in
|
||||
self.sliderNode = WallpaperSliderNode(minValue: 0.0, maxValue: 1.0, value: 0.7, 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), dark: false)
|
||||
self.cancelButtonNode = WallpaperNavigationButtonNode(content: .text(self.presentationData.strings.Common_Cancel), dark: true)
|
||||
self.cancelButtonNode.enableSaturation = true
|
||||
self.shareButtonNode = WallpaperNavigationButtonNode(content: .icon(image: UIImage(bundleImageName: "Chat/Links/Share"), size: CGSize(width: 28.0, height: 28.0)), dark: false)
|
||||
self.shareButtonNode = WallpaperNavigationButtonNode(content: .icon(image: UIImage(bundleImageName: "Chat/Links/Share"), size: CGSize(width: 28.0, height: 28.0)), dark: true)
|
||||
self.shareButtonNode.enableSaturation = true
|
||||
self.dayNightButtonNode = WallpaperNavigationButtonNode(content: .dayNight(isNight: self.isDarkAppearance), dark: true)
|
||||
self.dayNightButtonNode.enableSaturation = true
|
||||
|
||||
self.playButtonPlayImage = generateImage(CGSize(width: 48.0, height: 48.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
@ -242,6 +254,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.addSubnode(self.sliderNode)
|
||||
self.addSubnode(self.cancelButtonNode)
|
||||
self.addSubnode(self.shareButtonNode)
|
||||
self.addSubnode(self.dayNightButtonNode)
|
||||
|
||||
self.imageNode.addSubnode(self.brightnessNode)
|
||||
|
||||
@ -252,22 +265,11 @@ 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)
|
||||
self.dayNightButtonNode.addTarget(self, action: #selector(self.dayNightPressed), 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
|
||||
}
|
||||
self.updateIntensity(transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -297,7 +299,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
switch entry {
|
||||
case .asset, .contextResult:
|
||||
return (self.sliderNode.value - 0.5) * 2.0
|
||||
return self.sliderNode.value
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -311,6 +313,53 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.action?()
|
||||
}
|
||||
|
||||
|
||||
@objc private func dayNightPressed() {
|
||||
self.isDarkAppearance = !self.isDarkAppearance
|
||||
self.dayNightButtonNode.setIsNight(self.isDarkAppearance)
|
||||
|
||||
if let layout = self.validLayout?.0 {
|
||||
let offset = CGPoint(x: self.validOffset ?? 0.0, y: 0.0)
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.4, curve: .spring)
|
||||
self.updateButtonsLayout(layout: layout, offset: offset, transition: transition)
|
||||
self.updateMessagesLayout(layout: layout, offset: offset, transition: transition)
|
||||
|
||||
if !self.didChangeAppearance {
|
||||
self.didChangeAppearance = true
|
||||
self.animateIntensityChange(delay: 0.15)
|
||||
} else {
|
||||
self.updateIntensity(transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func animateIntensityChange(delay: Double) {
|
||||
let targetValue: CGFloat = self.sliderNode.value
|
||||
self.sliderNode.internalUpdateLayout(size: self.sliderNode.frame.size, value: 1.0)
|
||||
self.sliderNode.ignoreUpdates = true
|
||||
Queue.mainQueue().after(delay, {
|
||||
self.brightnessNode.backgroundColor = UIColor(rgb: 0x000000)
|
||||
self.brightnessNode.layer.compositingFilter = nil
|
||||
|
||||
self.sliderNode.ignoreUpdates = false
|
||||
let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .easeInOut)
|
||||
self.sliderNode.animateValue(from: 1.0, to: targetValue, transition: transition)
|
||||
self.updateIntensity(transition: transition)
|
||||
})
|
||||
}
|
||||
|
||||
private func updateIntensity(transition: ContainedViewLayoutTransition) {
|
||||
let value = self.isDarkAppearance ? self.sliderNode.value : 1.0
|
||||
if value < 1.0 {
|
||||
self.brightnessNode.backgroundColor = UIColor(rgb: 0x000000)
|
||||
self.brightnessNode.layer.compositingFilter = nil
|
||||
transition.updateAlpha(node: self.brightnessNode, alpha: 1.0 - value)
|
||||
} else {
|
||||
self.brightnessNode.layer.compositingFilter = nil
|
||||
transition.updateAlpha(node: self.brightnessNode, alpha: 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func cancelPressed() {
|
||||
self.dismiss()
|
||||
}
|
||||
@ -329,6 +378,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
var showPreviewTooltip = false
|
||||
|
||||
if self.entry != entry || self.arguments.colorPreview != previousArguments.colorPreview {
|
||||
let previousEntry = self.entry
|
||||
self.entry = entry
|
||||
@ -357,8 +408,6 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
var isBlurrable = true
|
||||
|
||||
self.nativeNode.updateBubbleTheme(bubbleTheme: presentationData.theme, bubbleCorners: presentationData.chatBubbleCorners)
|
||||
|
||||
switch entry {
|
||||
case let .wallpaper(wallpaper, _):
|
||||
self.nativeNode.update(wallpaper: wallpaper)
|
||||
@ -393,6 +442,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
case .asset:
|
||||
self.nativeNode._internalUpdateIsSettingUpWallpaper()
|
||||
//self.nativeNode.update(wallpaper: self.presentationData.chatWallpaper)
|
||||
self.nativeNode.isHidden = true
|
||||
self.patternButtonNode.isSelected = false
|
||||
self.playButtonNode.setIcon(self.playButtonRotateImage)
|
||||
@ -402,7 +452,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.playButtonNode.setIcon(self.playButtonRotateImage)
|
||||
}
|
||||
|
||||
var isEditable = false
|
||||
self.nativeNode.updateBubbleTheme(bubbleTheme: presentationData.theme, bubbleCorners: presentationData.chatBubbleCorners)
|
||||
|
||||
var canShare = false
|
||||
switch entry {
|
||||
case let .wallpaper(wallpaper, message):
|
||||
@ -566,7 +617,6 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
self.cropNode.removeFromSupernode()
|
||||
case let .asset(asset):
|
||||
isEditable = true
|
||||
let dimensions = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
|
||||
contentSize = dimensions
|
||||
displaySize = dimensions.dividedByScreenScale().integralFloor
|
||||
@ -576,8 +626,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
subtitleSignal = .single(nil)
|
||||
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
|
||||
self.wrapperNode.addSubnode(self.cropNode)
|
||||
showPreviewTooltip = true
|
||||
case let .contextResult(result):
|
||||
isEditable = true
|
||||
var imageDimensions: CGSize?
|
||||
var imageResource: TelegramMediaResource?
|
||||
var thumbnailDimensions: CGSize?
|
||||
@ -631,11 +681,12 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
|
||||
subtitleSignal = .single(nil)
|
||||
self.wrapperNode.addSubnode(self.cropNode)
|
||||
showPreviewTooltip = true
|
||||
}
|
||||
self.contentSize = contentSize
|
||||
|
||||
self.cancelButtonNode.dark = !isEditable
|
||||
self.shareButtonNode.dark = !isEditable
|
||||
//self.cancelButtonNode.dark = !isEditable
|
||||
//self.shareButtonNode.dark = !isEditable
|
||||
self.shareButtonNode.isHidden = !canShare
|
||||
|
||||
if self.cropNode.supernode == nil {
|
||||
@ -713,6 +764,18 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.updateButtonsLayout(layout: layout, offset: CGPoint(), transition: .immediate)
|
||||
self.updateMessagesLayout(layout: layout, offset: CGPoint(), transition: .immediate)
|
||||
}
|
||||
|
||||
if showPreviewTooltip {
|
||||
Queue.mainQueue().after(0.35) {
|
||||
self.maybePresentPreviewTooltip()
|
||||
}
|
||||
if self.isDarkAppearance && !self.didChangeAppearance {
|
||||
Queue.mainQueue().justDispatch {
|
||||
self.didChangeAppearance = true
|
||||
self.animateIntensityChange(delay: 0.35)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func screenFrameUpdated(_ frame: CGRect) {
|
||||
@ -966,7 +1029,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
if let source = self.source {
|
||||
switch source {
|
||||
case .asset, .contextResult:
|
||||
additionalYOffset -= 44.0
|
||||
if self.isDarkAppearance {
|
||||
additionalYOffset -= 44.0
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -996,8 +1061,17 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
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
|
||||
var 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 sliderAlpha: CGFloat = 0.0
|
||||
var sliderScale: CGFloat = 0.2
|
||||
if !additionalYOffset.isZero {
|
||||
sliderAlpha = 1.0
|
||||
sliderScale = 1.0
|
||||
} else {
|
||||
sliderFrame = sliderFrame.offsetBy(dx: 0.0, dy: 22.0)
|
||||
}
|
||||
|
||||
var dayNightHidden = true
|
||||
|
||||
let cancelSize = self.cancelButtonNode.measure(layout.size)
|
||||
let cancelFrame = CGRect(origin: CGPoint(x: 16.0 + offset.x, y: 16.0), size: cancelSize)
|
||||
@ -1013,13 +1087,13 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
blurFrame = leftButtonFrame
|
||||
motionAlpha = 1.0
|
||||
motionFrame = rightButtonFrame
|
||||
sliderIsHidden = false
|
||||
dayNightHidden = false
|
||||
case .contextResult:
|
||||
blurAlpha = 1.0
|
||||
blurFrame = leftButtonFrame
|
||||
motionAlpha = 1.0
|
||||
motionFrame = rightButtonFrame
|
||||
sliderIsHidden = false
|
||||
dayNightHidden = false
|
||||
case let .wallpaper(wallpaper, _):
|
||||
switch wallpaper {
|
||||
case .builtin:
|
||||
@ -1104,12 +1178,16 @@ 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)
|
||||
transition.updateFrameAsPositionAndBounds(node: self.sliderNode, frame: sliderFrame)
|
||||
transition.updateAlpha(node: self.sliderNode, alpha: sliderAlpha * alpha)
|
||||
transition.updateTransformScale(node: self.sliderNode, scale: sliderScale)
|
||||
self.sliderNode.updateLayout(size: sliderFrame.size)
|
||||
self.sliderNode.isHidden = sliderIsHidden
|
||||
|
||||
transition.updateFrame(node: self.cancelButtonNode, frame: cancelFrame)
|
||||
transition.updateFrame(node: self.shareButtonNode, frame: shareFrame)
|
||||
transition.updateFrame(node: self.dayNightButtonNode, frame: shareFrame)
|
||||
|
||||
self.dayNightButtonNode.isHidden = dayNightHidden
|
||||
}
|
||||
|
||||
private func updateMessagesLayout(layout: ContainerViewLayout, offset: CGPoint, transition: ContainedViewLayoutTransition) {
|
||||
@ -1182,7 +1260,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
case .asset, .contextResult:
|
||||
topMessageText = presentationData.strings.WallpaperPreview_CropTopText
|
||||
bottomMessageText = presentationData.strings.WallpaperPreview_CropBottomText
|
||||
bottomInset += 44.0
|
||||
if self.isDarkAppearance {
|
||||
bottomInset += 44.0
|
||||
}
|
||||
case .customColor:
|
||||
topMessageText = presentationData.strings.WallpaperPreview_CustomColorTopText
|
||||
bottomMessageText = presentationData.strings.WallpaperPreview_CustomColorBottomText
|
||||
@ -1197,7 +1277,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
let theme = self.presentationData.theme.withUpdated(preview: true)
|
||||
let theme = self.presentationData.theme.withUpdated(preview: false)
|
||||
|
||||
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false))
|
||||
@ -1302,6 +1382,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
self.cropNode.zoom(to: CGRect(x: (contentSize.width - fittedSize.width) / 2.0, y: (contentSize.height - fittedSize.height) / 2.0, width: fittedSize.width, height: fittedSize.height))
|
||||
}
|
||||
self.blurredNode.frame = self.imageNode.bounds
|
||||
|
||||
let displayMode: WallpaperDisplayMode
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
displayMode = .aspectFit
|
||||
} else {
|
||||
displayMode = .aspectFill
|
||||
}
|
||||
|
||||
self.nativeNode.frame = self.wrapperNode.bounds
|
||||
self.nativeNode.updateLayout(size: self.nativeNode.bounds.size, displayMode: displayMode, transition: .immediate)
|
||||
}
|
||||
self.brightnessNode.frame = self.imageNode.bounds
|
||||
|
||||
@ -1322,4 +1412,41 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
func animateWallpaperAppeared() {
|
||||
self.nativeNode.animateEvent(transition: .animated(duration: 2.0, curve: .spring), extendAnimation: true)
|
||||
}
|
||||
|
||||
private var displayedPreviewTooltip = false
|
||||
private func maybePresentPreviewTooltip() {
|
||||
guard !self.displayedPreviewTooltip else {
|
||||
return
|
||||
}
|
||||
|
||||
let frame = self.dayNightButtonNode.view.convert(self.dayNightButtonNode.bounds, to: self.view)
|
||||
let currentTimestamp = Int32(Date().timeIntervalSince1970)
|
||||
|
||||
let isDark = self.isDarkAppearance
|
||||
|
||||
let signal: Signal<(Int32, Int32), NoError>
|
||||
if isDark {
|
||||
signal = ApplicationSpecificNotice.getChatWallpaperLightPreviewTip(accountManager: self.context.sharedContext.accountManager)
|
||||
} else {
|
||||
signal = ApplicationSpecificNotice.getChatWallpaperDarkPreviewTip(accountManager: self.context.sharedContext.accountManager)
|
||||
}
|
||||
|
||||
let _ = (signal
|
||||
|> deliverOnMainQueue).start(next: { [weak self] count, timestamp in
|
||||
if let strongSelf = self, (count < 2 && currentTimestamp > timestamp + 24 * 60 * 60) || "".isEmpty {
|
||||
strongSelf.displayedPreviewTooltip = true
|
||||
|
||||
let controller = TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: isDark ? strongSelf.presentationData.strings.WallpaperPreview_PreviewInDayMode : strongSelf.presentationData.strings.WallpaperPreview_PreviewInNightMode, style: .customBlur(UIColor(rgb: 0x333333, alpha: 0.33)), icon: nil, location: .point(frame.offsetBy(dx: 1.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
})
|
||||
strongSelf.galleryController()?.present(controller, in: .current)
|
||||
|
||||
if isDark {
|
||||
let _ = ApplicationSpecificNotice.incrementChatWallpaperLightPreviewTip(accountManager: strongSelf.context.sharedContext.accountManager, timestamp: currentTimestamp).start()
|
||||
} else {
|
||||
let _ = ApplicationSpecificNotice.incrementChatWallpaperDarkPreviewTip(accountManager: strongSelf.context.sharedContext.accountManager, timestamp: currentTimestamp).start()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import CheckNode
|
||||
import AnimationUI
|
||||
|
||||
enum WallpaperOptionButtonValue {
|
||||
case check(Bool)
|
||||
@ -93,6 +94,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
enum Content {
|
||||
case icon(image: UIImage?, size: CGSize)
|
||||
case text(String)
|
||||
case dayNight(isNight: Bool)
|
||||
}
|
||||
|
||||
var enableSaturation: Bool = false
|
||||
@ -115,6 +117,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
private var backgroundNode: ASDisplayNode
|
||||
private let iconNode: ASImageNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private var animationNode: AnimationNode?
|
||||
|
||||
func setIcon(_ image: UIImage?) {
|
||||
self.iconNode.image = generateTintedImage(image: image, color: .white)
|
||||
@ -141,6 +144,12 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
case let .icon(icon, _):
|
||||
title = ""
|
||||
self.iconNode.image = generateTintedImage(image: icon, color: .white)
|
||||
case let .dayNight(isNight):
|
||||
title = ""
|
||||
let animationNode = AnimationNode(animation: isNight ? "anim_sun_reverse" : "anim_sun", colors: [:], scale: 1.0)
|
||||
animationNode.speed = 1.5
|
||||
animationNode.isUserInteractionEnabled = false
|
||||
self.animationNode = animationNode
|
||||
}
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
@ -152,19 +161,53 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
if let animationNode = self.animationNode {
|
||||
self.addSubnode(animationNode)
|
||||
}
|
||||
|
||||
self.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.backgroundNode.alpha = 0.4
|
||||
|
||||
strongSelf.iconNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.iconNode.alpha = 0.4
|
||||
|
||||
strongSelf.textNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.textNode.alpha = 0.4
|
||||
|
||||
// if let animationNode = strongSelf.animationNode {
|
||||
// animationNode.layer.removeAnimation(forKey: "opacity")
|
||||
// animationNode.alpha = 0.4
|
||||
// }
|
||||
} else {
|
||||
strongSelf.backgroundNode.alpha = 1.0
|
||||
strongSelf.backgroundNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
|
||||
strongSelf.iconNode.alpha = 1.0
|
||||
strongSelf.iconNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
|
||||
strongSelf.textNode.alpha = 1.0
|
||||
strongSelf.textNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
|
||||
// if let animationNode = strongSelf.animationNode {
|
||||
// animationNode.alpha = 1.0
|
||||
// animationNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setIsNight(_ isNight: Bool) {
|
||||
self.animationNode?.setAnimation(name: !isNight ? "anim_sun_reverse" : "anim_sun", colors: [:])
|
||||
self.animationNode?.speed = 1.5
|
||||
Queue.mainQueue().after(0.01) {
|
||||
self.animationNode?.playOnce()
|
||||
}
|
||||
}
|
||||
|
||||
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||
didSet {
|
||||
}
|
||||
@ -179,6 +222,8 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
return CGSize(width: ceil(size.width) + 16.0, height: 28.0)
|
||||
case let .icon(_, size):
|
||||
return size
|
||||
case .dayNight:
|
||||
return CGSize(width: 28.0, height: 28.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,6 +244,11 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
if let textSize = self.textSize {
|
||||
self.textNode.frame = CGRect(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0), width: textSize.width, height: textSize.height)
|
||||
}
|
||||
|
||||
if let animationNode = self.animationNode {
|
||||
animationNode.bounds = CGRect(origin: .zero, size: CGSize(width: 24.0, height: 24.0))
|
||||
animationNode.position = CGPoint(x: 14.0, y: 14.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,7 +541,16 @@ final class WallpaperSliderNode: ASDisplayNode {
|
||||
self.view.addGestureRecognizer(tapGestureRecognizer)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition = .immediate) {
|
||||
var ignoreUpdates = false
|
||||
func animateValue(from: CGFloat, to: CGFloat, transition: ContainedViewLayoutTransition = .immediate) {
|
||||
guard let size = self.validLayout else {
|
||||
return
|
||||
}
|
||||
self.internalUpdateLayout(size: size, value: from)
|
||||
self.internalUpdateLayout(size: size, value: to, transition: transition)
|
||||
}
|
||||
|
||||
func internalUpdateLayout(size: CGSize, value: CGFloat, transition: ContainedViewLayoutTransition = .immediate) {
|
||||
self.validLayout = size
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: .zero, size: size))
|
||||
@ -506,10 +565,17 @@ final class WallpaperSliderNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
let range = self.maxValue - self.minValue
|
||||
let value = (self.value - self.minValue) / range
|
||||
let value = (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)
|
||||
transition.updateFrame(node: self.foregroundNode, frame: foregroundFrame)
|
||||
transition.updateFrame(node: self.foregroundLightNode, frame: foregroundFrame)
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition = .immediate) {
|
||||
guard !self.ignoreUpdates else {
|
||||
return
|
||||
}
|
||||
self.internalUpdateLayout(size: size, value: self.value, transition: transition)
|
||||
}
|
||||
|
||||
@objc private func panGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||||
@ -525,14 +591,10 @@ final class WallpaperSliderNode: ASDisplayNode {
|
||||
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 {
|
||||
if self.value == 0.0 && previousValue != 0.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)
|
||||
|
@ -526,7 +526,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
||||
let _ = (ApplicationSpecificNotice.incrementAudioRateOptionsTip(accountManager: self.context.sharedContext.accountManager)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||
if let strongSelf = self, let controller = strongSelf.getController?(), value == 2 {
|
||||
let tooltipController = TooltipScreen(account: strongSelf.context.account, text: strongSelf.strings.Conversation_AudioRateOptionsTooltip, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 0.0, dy: 4.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in
|
||||
let tooltipController = TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: strongSelf.strings.Conversation_AudioRateOptionsTooltip, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 0.0, dy: 4.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
})
|
||||
controller.present(tooltipController, in: .window(.root))
|
||||
|
@ -760,8 +760,8 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
}) else {
|
||||
return
|
||||
}
|
||||
|
||||
self.present?(TooltipScreen(account: self.account, text: self.presentationData.strings.Call_CameraOrScreenTooltip, style: .light, icon: nil, location: .point(location.offsetBy(dx: 0.0, dy: -14.0), .bottom), displayDuration: .custom(5.0), shouldDismissOnTouch: { _ in
|
||||
|
||||
self.present?(TooltipScreen(account: self.account, sharedContext: self.sharedContext, text: self.presentationData.strings.Call_CameraOrScreenTooltip, style: .light, icon: nil, location: .point(location.offsetBy(dx: 0.0, dy: -14.0), .bottom), displayDuration: .custom(5.0), shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
}))
|
||||
}
|
||||
|
@ -2310,7 +2310,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
||||
} else {
|
||||
text = presentationData.strings.VoiceChat_RecordingInProgress
|
||||
}
|
||||
strongSelf.controller?.present(TooltipScreen(account: strongSelf.context.account, text: text, icon: nil, location: .point(location.offsetBy(dx: 1.0, dy: 0.0), .top), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
strongSelf.controller?.present(TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: text, icon: nil, location: .point(location.offsetBy(dx: 1.0, dy: 0.0), .top), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: true)
|
||||
}), in: .window(.root))
|
||||
}
|
||||
@ -3507,7 +3507,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
||||
if !callState.subscribedToScheduled {
|
||||
let location = self.actionButton.view.convert(self.actionButton.bounds, to: self.view).center
|
||||
let point = CGRect(origin: CGPoint(x: location.x - 5.0, y: location.y - 5.0 - 68.0), size: CGSize(width: 10.0, height: 10.0))
|
||||
self.controller?.present(TooltipScreen(account: self.context.account, text: self.presentationData.strings.VoiceChat_ReminderNotify, style: .gradient(UIColor(rgb: 0x262c5a), UIColor(rgb: 0x5d2835)), icon: nil, location: .point(point, .bottom), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
self.controller?.present(TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: self.presentationData.strings.VoiceChat_ReminderNotify, style: .gradient(UIColor(rgb: 0x262c5a), UIColor(rgb: 0x5d2835)), icon: nil, location: .point(point, .bottom), displayDuration: .custom(3.0), shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
}), in: .window(.root))
|
||||
}
|
||||
@ -6411,7 +6411,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
||||
point.origin.y += 32.0
|
||||
}
|
||||
}
|
||||
self.controller?.present(TooltipScreen(account: self.context.account, text: self.presentationData.strings.VoiceChat_UnmuteSuggestion, style: .gradient(UIColor(rgb: 0x1d446c), UIColor(rgb: 0x193e63)), icon: nil, location: .point(point, position), displayDuration: .custom(8.0), shouldDismissOnTouch: { _ in
|
||||
self.controller?.present(TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: self.presentationData.strings.VoiceChat_UnmuteSuggestion, style: .gradient(UIColor(rgb: 0x1d446c), UIColor(rgb: 0x193e63)), icon: nil, location: .point(point, position), displayDuration: .custom(8.0), shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
}), in: .window(.root))
|
||||
}
|
||||
|
@ -170,6 +170,8 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
||||
case audioRateOptionsTip = 36
|
||||
case translationSuggestion = 37
|
||||
case sendWhenOnlineTip = 38
|
||||
case chatWallpaperLightPreviewTip = 39
|
||||
case chatWallpaperDarkPreviewTip = 40
|
||||
|
||||
var key: ValueBoxKey {
|
||||
let v = ValueBoxKey(length: 4)
|
||||
@ -332,6 +334,14 @@ private struct ApplicationSpecificNoticeKeys {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatSpecificThemeDarkPreviewTip.key)
|
||||
}
|
||||
|
||||
static func chatWallpaperLightPreviewTip() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatWallpaperLightPreviewTip.key)
|
||||
}
|
||||
|
||||
static func chatWallpaperDarkPreviewTip() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatWallpaperDarkPreviewTip.key)
|
||||
}
|
||||
|
||||
static func chatForwardOptionsTip() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatForwardOptionsTip.key)
|
||||
}
|
||||
@ -1109,6 +1119,60 @@ public struct ApplicationSpecificNotice {
|
||||
}
|
||||
}
|
||||
|
||||
public static func getChatWallpaperLightPreviewTip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<(Int32, Int32), NoError> {
|
||||
return accountManager.transaction { transaction -> (Int32, Int32) in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatWallpaperLightPreviewTip())?.get(ApplicationSpecificTimestampAndCounterNotice.self) {
|
||||
return (value.counter, value.timestamp)
|
||||
} else {
|
||||
return (0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func incrementChatWallpaperLightPreviewTip(accountManager: AccountManager<TelegramAccountManagerTypes>, count: Int = 1, timestamp: Int32) -> Signal<Int, NoError> {
|
||||
return accountManager.transaction { transaction -> Int in
|
||||
var currentValue: Int32 = 0
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatWallpaperLightPreviewTip())?.get(ApplicationSpecificTimestampAndCounterNotice.self) {
|
||||
currentValue = value.counter
|
||||
}
|
||||
let previousValue = currentValue
|
||||
currentValue += Int32(count)
|
||||
|
||||
if let entry = CodableEntry(ApplicationSpecificTimestampAndCounterNotice(counter: currentValue, timestamp: timestamp)) {
|
||||
transaction.setNotice(ApplicationSpecificNoticeKeys.chatWallpaperLightPreviewTip(), entry)
|
||||
}
|
||||
|
||||
return Int(previousValue)
|
||||
}
|
||||
}
|
||||
|
||||
public static func getChatWallpaperDarkPreviewTip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<(Int32, Int32), NoError> {
|
||||
return accountManager.transaction { transaction -> (Int32, Int32) in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatWallpaperDarkPreviewTip())?.get(ApplicationSpecificTimestampAndCounterNotice.self) {
|
||||
return (value.counter, value.timestamp)
|
||||
} else {
|
||||
return (0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func incrementChatWallpaperDarkPreviewTip(accountManager: AccountManager<TelegramAccountManagerTypes>, count: Int = 1, timestamp: Int32) -> Signal<Int, NoError> {
|
||||
return accountManager.transaction { transaction -> Int in
|
||||
var currentValue: Int32 = 0
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatWallpaperDarkPreviewTip())?.get(ApplicationSpecificTimestampAndCounterNotice.self) {
|
||||
currentValue = value.counter
|
||||
}
|
||||
let previousValue = currentValue
|
||||
currentValue += Int32(count)
|
||||
|
||||
if let entry = CodableEntry(ApplicationSpecificTimestampAndCounterNotice(counter: currentValue, timestamp: timestamp)) {
|
||||
transaction.setNotice(ApplicationSpecificNoticeKeys.chatWallpaperDarkPreviewTip(), entry)
|
||||
}
|
||||
|
||||
return Int(previousValue)
|
||||
}
|
||||
}
|
||||
|
||||
public static func getChatForwardOptionsTip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||
return accountManager.transaction { transaction -> Int32 in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatForwardOptionsTip())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
|
@ -130,7 +130,7 @@ final class ChatBotStartInputPanelNode: ChatInputPanelNode {
|
||||
tooltipController.location = .point(location, .bottom)
|
||||
}
|
||||
} else {
|
||||
let controller = TooltipScreen(account: context.account, text: self.strings.Bot_TapToUse, icon: .downArrows, location: .point(location, .bottom), displayDuration: .infinite, shouldDismissOnTouch: { _ in
|
||||
let controller = TooltipScreen(account: context.account, sharedContext: context.sharedContext, text: self.strings.Bot_TapToUse, icon: .downArrows, location: .point(location, .bottom), displayDuration: .infinite, shouldDismissOnTouch: { _ in
|
||||
return .ignore
|
||||
})
|
||||
controller.alwaysVisible = true
|
||||
|
@ -676,14 +676,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return false
|
||||
}
|
||||
|
||||
if strongSelf.presentVoiceMessageDiscardAlert(action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
Queue.mainQueue().after(0.1, {
|
||||
let _ = strongSelf.controllerInteraction?.openMessage(message, mode)
|
||||
})
|
||||
let displayVoiceMessageDiscardAlert: () -> Bool = {
|
||||
if strongSelf.presentVoiceMessageDiscardAlert(action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
Queue.mainQueue().after(0.1, {
|
||||
let _ = strongSelf.controllerInteraction?.openMessage(message, mode)
|
||||
})
|
||||
}
|
||||
}, performAction: false) {
|
||||
return false
|
||||
}
|
||||
}, performAction: false) {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
strongSelf.commitPurposefulAction()
|
||||
@ -696,6 +699,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
for media in message.media {
|
||||
if media is TelegramMediaMap {
|
||||
if !displayVoiceMessageDiscardAlert() {
|
||||
return false
|
||||
}
|
||||
isLocation = true
|
||||
}
|
||||
if let file = media as? TelegramMediaFile, file.isInstantVideo {
|
||||
@ -707,12 +713,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let invoice = media as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia {
|
||||
switch extendedMedia {
|
||||
case .preview:
|
||||
strongSelf.controllerInteraction?.openCheckoutOrReceipt(message.id)
|
||||
return true
|
||||
if displayVoiceMessageDiscardAlert() {
|
||||
strongSelf.controllerInteraction?.openCheckoutOrReceipt(message.id)
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .full:
|
||||
break
|
||||
}
|
||||
} else if let action = media as? TelegramMediaAction {
|
||||
if !displayVoiceMessageDiscardAlert() {
|
||||
return false
|
||||
}
|
||||
switch action.action {
|
||||
case .pinnedMessageUpdated:
|
||||
for attribute in message.attributes {
|
||||
@ -5839,6 +5852,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let strongSelf = self {
|
||||
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
|
||||
|
||||
var chatWallpaper = chatWallpaper
|
||||
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
let previousStrings = strongSelf.presentationData.strings
|
||||
let previousChatWallpaper = strongSelf.presentationData.chatWallpaper
|
||||
@ -5846,7 +5861,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
var themeEmoticon = themeEmoticon
|
||||
if let themeEmoticonPreview = themeEmoticonPreview {
|
||||
if !themeEmoticonPreview.isEmpty {
|
||||
themeEmoticon = themeEmoticonPreview
|
||||
if themeEmoticon != themeEmoticonPreview {
|
||||
chatWallpaper = nil
|
||||
themeEmoticon = themeEmoticonPreview
|
||||
}
|
||||
} else {
|
||||
themeEmoticon = nil
|
||||
}
|
||||
@ -5857,7 +5875,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
var presentationData = presentationData
|
||||
var useDarkAppearance = presentationData.theme.overallDarkAppearance
|
||||
|
||||
|
||||
if let themeEmoticon = themeEmoticon, let theme = chatThemes.first(where: { $0.emoticon?.strippedEmoji == themeEmoticon.strippedEmoji }) {
|
||||
if let darkAppearancePreview = darkAppearancePreview {
|
||||
useDarkAppearance = darkAppearancePreview
|
||||
@ -5896,7 +5914,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
lightWallpaper = theme.chat.defaultWallpaper
|
||||
}
|
||||
|
||||
lightTheme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: themeSettings.theme, accentColor: currentColors?.color, bubbleColors: currentColors?.customBubbleColors ?? [], wallpaper: currentColors?.wallpaper, baseColor: currentColors?.baseColor, serviceBackgroundColor: defaultServiceBackgroundColor) ?? defaultPresentationTheme
|
||||
var preferredBaseTheme: TelegramBaseTheme?
|
||||
if let baseTheme = themeSettings.themePreferredBaseTheme[themeSettings.theme.index], [.classic, .day].contains(baseTheme) {
|
||||
preferredBaseTheme = baseTheme
|
||||
}
|
||||
|
||||
lightTheme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: themeSettings.theme, baseTheme: preferredBaseTheme, accentColor: currentColors?.color, bubbleColors: currentColors?.customBubbleColors ?? [], wallpaper: currentColors?.wallpaper, baseColor: currentColors?.baseColor, serviceBackgroundColor: defaultServiceBackgroundColor) ?? defaultPresentationTheme
|
||||
} else {
|
||||
lightTheme = presentationData.theme
|
||||
lightWallpaper = presentationData.chatWallpaper
|
||||
@ -5905,7 +5928,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let effectiveColors = themeSettings.themeSpecificAccentColors[automaticTheme.index]
|
||||
let themeSpecificWallpaper = (themeSettings.themeSpecificChatWallpapers[coloredThemeIndex(reference: automaticTheme, accentColor: effectiveColors)] ?? themeSettings.themeSpecificChatWallpapers[automaticTheme.index])
|
||||
|
||||
darkTheme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: automaticTheme, accentColor: effectiveColors?.color, bubbleColors: effectiveColors?.customBubbleColors ?? [], wallpaper: effectiveColors?.wallpaper, baseColor: effectiveColors?.baseColor, serviceBackgroundColor: defaultServiceBackgroundColor) ?? defaultPresentationTheme
|
||||
var preferredBaseTheme: TelegramBaseTheme?
|
||||
if let baseTheme = themeSettings.themePreferredBaseTheme[automaticTheme.index], [.night, .tinted].contains(baseTheme) {
|
||||
preferredBaseTheme = baseTheme
|
||||
} else {
|
||||
preferredBaseTheme = .night
|
||||
}
|
||||
|
||||
darkTheme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: automaticTheme, baseTheme: preferredBaseTheme, accentColor: effectiveColors?.color, bubbleColors: effectiveColors?.customBubbleColors ?? [], wallpaper: effectiveColors?.wallpaper, baseColor: effectiveColors?.baseColor, serviceBackgroundColor: defaultServiceBackgroundColor) ?? defaultPresentationTheme
|
||||
|
||||
if let themeSpecificWallpaper = themeSpecificWallpaper {
|
||||
darkWallpaper = themeSpecificWallpaper
|
||||
@ -5944,7 +5974,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
presentationData = presentationData.withUpdated(chatWallpaper: chatWallpaper)
|
||||
}
|
||||
|
||||
|
||||
let isFirstTime = !strongSelf.didSetPresentationData
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.didSetPresentationData = true
|
||||
@ -14314,7 +14343,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, text: solution.text, textEntities: solution.entities, icon: .info, location: .top, shouldDismissOnTouch: { point in
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: solution.text, textEntities: solution.entities, icon: .info, location: .top, shouldDismissOnTouch: { point in
|
||||
return .ignore
|
||||
}, openActiveTextItem: { [weak self] item, action in
|
||||
guard let strongSelf = self else {
|
||||
@ -14407,7 +14436,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in
|
||||
return .ignore
|
||||
}, openActiveTextItem: { [weak self] item, action in
|
||||
guard let strongSelf = self else {
|
||||
@ -14521,7 +14550,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in
|
||||
let tooltipScreen = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: psaText, textEntities: psaEntities, icon: .info, location: .top, displayDuration: .custom(10.0), shouldDismissOnTouch: { point in
|
||||
return .ignore
|
||||
}, openActiveTextItem: { [weak self] item, action in
|
||||
guard let strongSelf = self else {
|
||||
@ -18508,12 +18537,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
let selectedEmoticon: String? = themeEmoticon
|
||||
|
||||
var canResetWallpaper = false
|
||||
if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData {
|
||||
canResetWallpaper = cachedUserData.wallpaper != nil
|
||||
}
|
||||
|
||||
let controller = ChatThemeScreen(
|
||||
context: context,
|
||||
updatedPresentationData: strongSelf.updatedPresentationData,
|
||||
animatedEmojiStickers: animatedEmojiStickers,
|
||||
initiallySelectedEmoticon: selectedEmoticon,
|
||||
peerName: strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer.flatMap(EnginePeer.init)?.compactDisplayTitle ?? "",
|
||||
canResetWallpaper: canResetWallpaper,
|
||||
previewTheme: { [weak self] emoticon, dark in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentCrossfadeSnapshot()
|
||||
@ -18540,54 +18575,47 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
|
||||
var canDelete = false
|
||||
if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData {
|
||||
canDelete = cachedUserData.wallpaper != nil
|
||||
}
|
||||
let controller = wallpaperMediaPickerController(
|
||||
context: strongSelf.context,
|
||||
updatedPresentationData: strongSelf.updatedPresentationData,
|
||||
peer: EnginePeer(peer),
|
||||
canDelete: canDelete,
|
||||
completion: { asset in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false))
|
||||
controller.navigationPresentation = .modal
|
||||
controller.apply = { [weak self] wallpaper, options, cropRect, brightness in
|
||||
if let strongSelf = self {
|
||||
uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, brightness: brightness, peerId: peerId, completion: {
|
||||
dismissControllers()
|
||||
})
|
||||
var openWallpaperPickerImpl: (() -> Void)?
|
||||
let openWallpaperPicker = {
|
||||
let controller = wallpaperMediaPickerController(
|
||||
context: strongSelf.context,
|
||||
updatedPresentationData: strongSelf.updatedPresentationData,
|
||||
peer: EnginePeer(peer),
|
||||
completion: { asset in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false))
|
||||
controller.navigationPresentation = .modal
|
||||
controller.apply = { [weak self] wallpaper, options, cropRect, brightness in
|
||||
if let strongSelf = self {
|
||||
uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, cropRect: cropRect, brightness: brightness, peerId: peerId, completion: {
|
||||
dismissControllers()
|
||||
})
|
||||
}
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
},
|
||||
openColors: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let controller = standaloneColorPickerController(context: strongSelf.context, peer: EnginePeer(peer), push: { [weak self] controller in
|
||||
if let strongSelf = self {
|
||||
strongSelf.push(controller)
|
||||
}
|
||||
}, openGallery: {
|
||||
openWallpaperPickerImpl?()
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.push(controller)
|
||||
}
|
||||
strongSelf.push(controller)
|
||||
}
|
||||
)
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.push(controller)
|
||||
},
|
||||
changeColor: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
)
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.push(controller)
|
||||
}
|
||||
if let themeController = strongSelf.themeScreen {
|
||||
strongSelf.themeScreen = nil
|
||||
themeController.dimTapped()
|
||||
}
|
||||
|
||||
var canDelete = false
|
||||
if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData {
|
||||
canDelete = cachedUserData.wallpaper != nil
|
||||
}
|
||||
let controller = standaloneColorPickerController(context: strongSelf.context, peer: EnginePeer(peer), canDelete: canDelete, push: { [weak self] controller in
|
||||
if let strongSelf = self {
|
||||
strongSelf.push(controller)
|
||||
}
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.push(controller)
|
||||
openWallpaperPickerImpl = openWallpaperPicker
|
||||
openWallpaperPicker()
|
||||
},
|
||||
completion: { [weak self] emoticon in
|
||||
guard let strongSelf = self, let peerId else {
|
||||
|
@ -1483,7 +1483,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
tooltipController.location = .point(location, .bottom)
|
||||
}
|
||||
} else {
|
||||
let controller = TooltipScreen(account: context.account, text: interfaceState.strings.Bot_TapToUse, icon: .downArrows, location: .point(location, .bottom), displayDuration: .infinite, shouldDismissOnTouch: { _ in
|
||||
let controller = TooltipScreen(account: context.account, sharedContext: context.sharedContext, text: interfaceState.strings.Bot_TapToUse, icon: .downArrows, location: .point(location, .bottom), displayDuration: .infinite, shouldDismissOnTouch: { _ in
|
||||
return .ignore
|
||||
})
|
||||
controller.alwaysVisible = true
|
||||
|
@ -554,9 +554,9 @@ final class ChatThemeScreen: ViewController {
|
||||
private let animatedEmojiStickers: [String: [StickerPackItem]]
|
||||
private let initiallySelectedEmoticon: String?
|
||||
private let peerName: String
|
||||
let canResetWallpaper: Bool
|
||||
private let previewTheme: (String?, Bool?) -> Void
|
||||
fileprivate let changeWallpaper: () -> Void
|
||||
fileprivate let changeColor: () -> Void
|
||||
private let completion: (String?) -> Void
|
||||
|
||||
private var presentationData: PresentationData
|
||||
@ -578,9 +578,9 @@ final class ChatThemeScreen: ViewController {
|
||||
animatedEmojiStickers: [String: [StickerPackItem]],
|
||||
initiallySelectedEmoticon: String?,
|
||||
peerName: String,
|
||||
canResetWallpaper: Bool,
|
||||
previewTheme: @escaping (String?, Bool?) -> Void,
|
||||
changeWallpaper: @escaping () -> Void,
|
||||
changeColor: @escaping () -> Void,
|
||||
completion: @escaping (String?) -> Void
|
||||
) {
|
||||
self.context = context
|
||||
@ -588,9 +588,9 @@ final class ChatThemeScreen: ViewController {
|
||||
self.animatedEmojiStickers = animatedEmojiStickers
|
||||
self.initiallySelectedEmoticon = initiallySelectedEmoticon
|
||||
self.peerName = peerName
|
||||
self.canResetWallpaper = canResetWallpaper
|
||||
self.previewTheme = previewTheme
|
||||
self.changeWallpaper = changeWallpaper
|
||||
self.changeColor = changeColor
|
||||
self.completion = completion
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
@ -1013,18 +1013,22 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
||||
}
|
||||
|
||||
private func updateButtons() {
|
||||
let canResetWallpaper = self.controller?.canResetWallpaper ?? false
|
||||
|
||||
let doneButtonTitle: String
|
||||
let otherButtonTitle: String
|
||||
var accentButtonTheme = true
|
||||
var destructiveOtherButton = false
|
||||
if self.selectedEmoticon == self.initiallySelectedEmoticon {
|
||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper
|
||||
otherButtonTitle = self.presentationData.strings.Conversation_Theme_SetColorWallpaper
|
||||
otherButtonTitle = canResetWallpaper ? self.presentationData.strings.Conversation_Theme_ResetWallpaper : self.presentationData.strings.Common_Cancel
|
||||
accentButtonTheme = false
|
||||
destructiveOtherButton = canResetWallpaper
|
||||
} else if self.selectedEmoticon == nil && self.initiallySelectedEmoticon != nil {
|
||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_Reset
|
||||
otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions
|
||||
} else {
|
||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_Apply
|
||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_ApplyBackground
|
||||
otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions
|
||||
}
|
||||
|
||||
@ -1040,7 +1044,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
||||
}
|
||||
self.doneButton.updateTheme(buttonTheme)
|
||||
|
||||
self.otherButton.setTitle(otherButtonTitle, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||
self.otherButton.setTitle(otherButtonTitle, with: Font.regular(17.0), with: destructiveOtherButton ? self.presentationData.theme.actionSheet.destructiveActionTextColor : self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||
}
|
||||
|
||||
private var switchThemeIconAnimator: DisplayLinkAnimator?
|
||||
@ -1102,7 +1106,11 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
||||
if self.selectedEmoticon != self.initiallySelectedEmoticon {
|
||||
self.setEmoticon(self.initiallySelectedEmoticon)
|
||||
} else {
|
||||
self.controller?.changeColor()
|
||||
if self.controller?.canResetWallpaper == true {
|
||||
|
||||
} else {
|
||||
self.cancelButtonPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1229,7 +1237,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
||||
if let strongSelf = self, count < 2 && currentTimestamp > timestamp + 24 * 60 * 60 {
|
||||
strongSelf.displayedPreviewTooltip = true
|
||||
|
||||
strongSelf.present?(TooltipScreen(account: strongSelf.context.account, text: isDark ? strongSelf.presentationData.strings.Conversation_Theme_PreviewLight(strongSelf.peerName).string : strongSelf.presentationData.strings.Conversation_Theme_PreviewDark(strongSelf.peerName).string, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 3.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in
|
||||
strongSelf.present?(TooltipScreen(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, text: isDark ? strongSelf.presentationData.strings.Conversation_Theme_PreviewLight(strongSelf.peerName).string : strongSelf.presentationData.strings.Conversation_Theme_PreviewDark(strongSelf.peerName).string, style: .default, icon: nil, location: .point(frame.offsetBy(dx: 3.0, dy: 6.0), .bottom), displayDuration: .custom(3.0), inset: 3.0, shouldDismissOnTouch: { _ in
|
||||
return .dismiss(consume: false)
|
||||
}))
|
||||
|
||||
|
@ -8467,7 +8467,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
return
|
||||
}
|
||||
let buttonFrame = buttonNode.view.convert(buttonNode.bounds, to: self.view)
|
||||
controller.present(TooltipScreen(account: self.context.account, text: self.presentationData.strings.SharedMedia_CalendarTooltip, style: .default, icon: .none, location: .point(buttonFrame.insetBy(dx: 0.0, dy: 5.0), .top), shouldDismissOnTouch: { point in
|
||||
controller.present(TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: self.presentationData.strings.SharedMedia_CalendarTooltip, style: .default, icon: .none, location: .point(buttonFrame.insetBy(dx: 0.0, dy: 5.0), .top), shouldDismissOnTouch: { point in
|
||||
return .dismiss(consume: false)
|
||||
}), in: .current)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import TelegramCore
|
||||
import TextFormat
|
||||
import Postbox
|
||||
import UrlEscaping
|
||||
import AccountContext
|
||||
|
||||
public protocol TooltipCustomContentNode: ASDisplayNode {
|
||||
func animateIn()
|
||||
@ -127,12 +128,11 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
private let backgroundContainerNode: ASDisplayNode
|
||||
private let backgroundClipNode: ASDisplayNode
|
||||
private let backgroundMaskNode: ASDisplayNode
|
||||
private var effectView: UIView?
|
||||
private var effectNode: NavigationBackgroundNode?
|
||||
private var gradientNode: ASDisplayNode?
|
||||
private var arrowGradientNode: ASDisplayNode?
|
||||
private let arrowNode: ASImageNode
|
||||
private let arrowContainer: ASDisplayNode
|
||||
private var arrowEffectView: UIView?
|
||||
private let animatedStickerNode: AnimatedStickerNode
|
||||
private var downArrowsNode: DownArrowsIconNode?
|
||||
private let textNode: ImmediateTextNode
|
||||
@ -143,7 +143,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
init(account: Account, text: String, textEntities: [MessageTextEntity], style: TooltipScreen.Style, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: TooltipScreen.DisplayDuration, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?) {
|
||||
init(account: Account, sharedContext: SharedAccountContext, text: String, textEntities: [MessageTextEntity], style: TooltipScreen.Style, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: TooltipScreen.DisplayDuration, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, requestDismiss: @escaping () -> Void, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)?) {
|
||||
self.tooltipStyle = style
|
||||
self.icon = icon
|
||||
self.customContentNode = customContentNode
|
||||
@ -210,9 +210,16 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
|
||||
self.arrowContainer = ASDisplayNode()
|
||||
|
||||
let theme = sharedContext.currentPresentationData.with { $0 }.theme
|
||||
let fontSize: CGFloat
|
||||
if case .top = location {
|
||||
self.effectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
|
||||
let backgroundColor: UIColor
|
||||
if theme.overallDarkAppearance {
|
||||
backgroundColor = theme.rootController.navigationBar.blurredBackgroundColor
|
||||
} else {
|
||||
backgroundColor = UIColor(rgb: 0x000000, alpha: 0.6)
|
||||
}
|
||||
self.effectNode = NavigationBackgroundNode(color: backgroundColor)
|
||||
self.backgroundMaskNode.addSubnode(self.backgroundClipNode)
|
||||
self.backgroundClipNode.clipsToBounds = true
|
||||
if case let .point(_, arrowPosition) = location, case .right = arrowPosition {
|
||||
@ -258,20 +265,28 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
maskLayer.frame = CGRect(origin: CGPoint(), size: arrowSize)
|
||||
self.arrowContainer.layer.mask = maskLayer
|
||||
} else {
|
||||
let effect: UIBlurEffect
|
||||
if case .light = style {
|
||||
effect = UIBlurEffect(style: .light)
|
||||
var enableSaturation = true
|
||||
let backgroundColor: UIColor
|
||||
if case let .customBlur(color) = style {
|
||||
backgroundColor = color
|
||||
enableSaturation = false
|
||||
} else if case .light = style {
|
||||
backgroundColor = theme.rootController.navigationBar.blurredBackgroundColor
|
||||
} else {
|
||||
effect = UIBlurEffect(style: .dark)
|
||||
if theme.overallDarkAppearance {
|
||||
backgroundColor = theme.rootController.navigationBar.blurredBackgroundColor
|
||||
} else {
|
||||
backgroundColor = UIColor(rgb: 0x000000, alpha: 0.6)
|
||||
}
|
||||
}
|
||||
self.effectView = UIVisualEffectView(effect: effect)
|
||||
self.effectNode = NavigationBackgroundNode(color: backgroundColor, enableBlur: true, enableSaturation: enableSaturation)
|
||||
|
||||
self.backgroundMaskNode.addSubnode(self.backgroundClipNode)
|
||||
self.backgroundClipNode.clipsToBounds = true
|
||||
if case let .point(_, arrowPosition) = location, case .right = arrowPosition {
|
||||
self.backgroundClipNode.cornerRadius = 8.5
|
||||
} else {
|
||||
self.backgroundClipNode.cornerRadius = 14.0
|
||||
self.backgroundClipNode.cornerRadius = 12.5
|
||||
}
|
||||
if #available(iOS 13.0, *) {
|
||||
self.backgroundClipNode.layer.cornerCurve = .continuous
|
||||
@ -318,8 +333,8 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
if let gradientNode = self.gradientNode {
|
||||
self.backgroundContainerNode.addSubnode(gradientNode)
|
||||
self.containerNode.addSubnode(self.arrowContainer)
|
||||
} else if let effectView = self.effectView {
|
||||
self.backgroundContainerNode.view.addSubview(effectView)
|
||||
} else if let effectNode = self.effectNode {
|
||||
self.backgroundContainerNode.addSubnode(effectNode)
|
||||
self.backgroundContainerNode.layer.mask = self.backgroundMaskNode.layer
|
||||
}
|
||||
self.containerNode.addSubnode(self.textNode)
|
||||
@ -430,7 +445,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
|
||||
let backgroundHeight: CGFloat
|
||||
switch self.tooltipStyle {
|
||||
case .default, .gradient:
|
||||
case .default, .gradient, .customBlur:
|
||||
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0
|
||||
case .light:
|
||||
backgroundHeight = max(28.0, max(animationSize.height, textSize.height) + 4.0 * 2.0)
|
||||
@ -472,8 +487,10 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
transition.updateFrame(node: self.backgroundMaskNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0))
|
||||
transition.updateFrame(node: self.backgroundClipNode, frame: CGRect(origin: CGPoint(x: 10.0, y: 10.0), size: backgroundFrame.size))
|
||||
|
||||
if let effectView = self.effectView {
|
||||
transition.updateFrame(view: effectView, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0))
|
||||
if let effectNode = self.effectNode {
|
||||
let effectFrame = CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0)
|
||||
transition.updateFrame(node: effectNode, frame: effectFrame)
|
||||
effectNode.update(size: effectFrame.size, transition: transition)
|
||||
}
|
||||
if let gradientNode = self.gradientNode {
|
||||
transition.updateFrame(node: gradientNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||
@ -501,7 +518,6 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
|
||||
let arrowBounds = CGRect(origin: CGPoint(), size: arrowSize)
|
||||
self.arrowNode.frame = arrowBounds
|
||||
self.arrowEffectView?.frame = arrowBounds
|
||||
self.arrowGradientNode?.frame = CGRect(origin: CGPoint(x: -arrowFrame.minX + backgroundFrame.minX, y: 0.0), size: backgroundFrame.size)
|
||||
case .right:
|
||||
arrowFrame = CGRect(origin: CGPoint(x: backgroundFrame.width + arrowSize.height, y: rect.midY), size: CGSize(width: arrowSize.height, height: arrowSize.width))
|
||||
@ -512,12 +528,10 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
|
||||
let arrowBounds = CGRect(origin: .zero, size: arrowSize)
|
||||
self.arrowNode.frame = arrowBounds
|
||||
self.arrowEffectView?.frame = arrowBounds
|
||||
self.arrowGradientNode?.frame = arrowBounds
|
||||
}
|
||||
} else {
|
||||
self.arrowNode.isHidden = true
|
||||
self.arrowEffectView?.isHidden = true
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: contentInset + animationSize.width + animationSpacing, y: floor((backgroundHeight - textSize.height) / 2.0)), size: textSize))
|
||||
@ -672,10 +686,12 @@ public final class TooltipScreen: ViewController {
|
||||
public enum Style {
|
||||
case `default`
|
||||
case light
|
||||
case customBlur(UIColor)
|
||||
case gradient(UIColor, UIColor)
|
||||
}
|
||||
|
||||
private let account: Account
|
||||
private let sharedContext: SharedAccountContext
|
||||
public let text: String
|
||||
public let textEntities: [MessageTextEntity]
|
||||
private let style: TooltipScreen.Style
|
||||
@ -707,8 +723,9 @@ public final class TooltipScreen: ViewController {
|
||||
|
||||
public var alwaysVisible = false
|
||||
|
||||
public init(account: Account, text: String, textEntities: [MessageTextEntity] = [], style: TooltipScreen.Style = .default, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)? = nil) {
|
||||
public init(account: Account, sharedContext: SharedAccountContext, text: String, textEntities: [MessageTextEntity] = [], style: TooltipScreen.Style = .default, icon: TooltipScreen.Icon?, customContentNode: TooltipCustomContentNode? = nil, location: TooltipScreen.Location, displayDuration: DisplayDuration = .default, inset: CGFloat = 13.0, shouldDismissOnTouch: @escaping (CGPoint) -> TooltipScreen.DismissOnTouch, openActiveTextItem: ((TooltipActiveTextItem, TooltipActiveTextAction) -> Void)? = nil) {
|
||||
self.account = account
|
||||
self.sharedContext = sharedContext
|
||||
self.text = text
|
||||
self.textEntities = textEntities
|
||||
self.style = style
|
||||
@ -776,7 +793,7 @@ public final class TooltipScreen: ViewController {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = TooltipScreenNode(account: self.account, text: self.text, textEntities: self.textEntities, style: self.style, icon: self.icon, customContentNode: self.customContentNode, location: self.location, displayDuration: self.displayDuration, inset: self.inset, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||
self.displayNode = TooltipScreenNode(account: self.account, sharedContext: self.sharedContext, text: self.text, textEntities: self.textEntities, style: self.style, icon: self.icon, customContentNode: self.customContentNode, location: self.location, displayDuration: self.displayDuration, inset: self.inset, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
@ -743,6 +743,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
private var gradientBackgroundNode: GradientBackgroundNode?
|
||||
private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode?
|
||||
private let patternImageLayer: EffectImageLayer
|
||||
private let dimLayer: SimpleLayer
|
||||
private var isGeneratingPatternImage: Bool = false
|
||||
|
||||
private let bakedBackgroundView: UIImageView
|
||||
@ -862,6 +863,9 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
self.bakedBackgroundView = UIImageView()
|
||||
self.bakedBackgroundView.isHidden = true
|
||||
|
||||
self.dimLayer = SimpleLayer()
|
||||
self.dimLayer.backgroundColor = UIColor.black.cgColor
|
||||
|
||||
super.init()
|
||||
|
||||
if #available(iOS 12.0, *) {
|
||||
@ -885,6 +889,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
self.contentNode.frame = self.bounds
|
||||
self.addSubnode(self.contentNode)
|
||||
self.layer.addSublayer(self.patternImageLayer)
|
||||
|
||||
self.layer.addSublayer(self.dimLayer)
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -892,6 +898,19 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
self.wallpaperDisposable.dispose()
|
||||
self.imageDisposable.dispose()
|
||||
}
|
||||
|
||||
private func updateDimming() {
|
||||
guard let wallpaper = self.wallpaper, let theme = self.bubbleTheme else {
|
||||
return
|
||||
}
|
||||
var dimAlpha: Float = 0.0
|
||||
if case let .file(file) = wallpaper, !file.isPattern {
|
||||
if let intensity = file.settings.intensity, intensity < 100, theme.overallDarkAppearance == true {
|
||||
dimAlpha = 1.0 - max(0.0, min(1.0, Float(intensity) / 100.0))
|
||||
}
|
||||
}
|
||||
self.dimLayer.opacity = dimAlpha
|
||||
}
|
||||
|
||||
func update(wallpaper: TelegramWallpaper) {
|
||||
if self.wallpaper == wallpaper {
|
||||
@ -915,7 +934,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
gradientColors = file.settings.colors
|
||||
gradientAngle = file.settings.rotation ?? 0
|
||||
}
|
||||
|
||||
|
||||
var scheduleLoopingEvent = false
|
||||
if gradientColors.count >= 3 {
|
||||
let mappedColors = gradientColors.map { color -> UIColor in
|
||||
@ -1032,6 +1051,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
self.animateEvent(transition: .animated(duration: 0.7, curve: .linear), extendAnimation: false)
|
||||
}
|
||||
}
|
||||
|
||||
self.updateDimming()
|
||||
}
|
||||
|
||||
func _internalUpdateIsSettingUpWallpaper() {
|
||||
@ -1304,6 +1325,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
transition.updateFrame(node: outgoingBackgroundNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
outgoingBackgroundNode.update(rect: CGRect(origin: CGPoint(), size: size), within: size, transition: transition)
|
||||
}
|
||||
|
||||
transition.updateFrame(layer: self.dimLayer, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
self.loadPatternForSizeIfNeeded(size: size, displayMode: displayMode, transition: transition)
|
||||
|
||||
@ -1378,6 +1401,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
||||
}
|
||||
|
||||
self.updateBubbles()
|
||||
self.updateDimming()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user