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
8e6ed4c4d0
commit
1e2ed2d2f4
@ -9149,7 +9149,7 @@ Sorry for the inconvenience.";
|
|||||||
"WallpaperPreview.ChatBottomText" = "Enjoy the view.";
|
"WallpaperPreview.ChatBottomText" = "Enjoy the view.";
|
||||||
|
|
||||||
"Conversation.Theme.SetPhotoWallpaper" = "Choose Background from Photos";
|
"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.OtherOptions" = "Other Options...";
|
||||||
|
|
||||||
"Conversation.Theme.ChooseWallpaperTitle" = "Choose Background";
|
"Conversation.Theme.ChooseWallpaperTitle" = "Choose Background";
|
||||||
@ -9161,3 +9161,8 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"WebApp.LaunchMoreInfo" = "More about this bot";
|
"WebApp.LaunchMoreInfo" = "More about this bot";
|
||||||
"WebApp.LaunchConfirmation" = "To launch this web app, you will connect to its website.";
|
"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 self.selectionState?.dayRange == nil {
|
||||||
if let selectionToolbarNode = self.selectionToolbarNode {
|
if let selectionToolbarNode = self.selectionToolbarNode {
|
||||||
let toolbarFrame = selectionToolbarNode.view.convert(selectionToolbarNode.bounds, to: self.view)
|
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)
|
return .dismiss(consume: false)
|
||||||
}), in: .current)
|
}), 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())
|
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 {
|
guard let strongSelf = self, let parentController = strongSelf.parent as? TabBarController else {
|
||||||
return .dismiss(consume: false)
|
return .dismiss(consume: false)
|
||||||
}
|
}
|
||||||
|
@ -829,7 +829,7 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
|||||||
text = strongSelf.presentationData.strings.Location_ProximityTip(EnginePeer(peer).compactDisplayTitle).string
|
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)
|
return .dismiss(consume: false)
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
@ -2010,18 +2010,18 @@ public func wallpaperMediaPickerController(
|
|||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||||
peer: EnginePeer,
|
peer: EnginePeer,
|
||||||
canDelete: Bool,
|
completion: @escaping (PHAsset) -> Void = { _ in },
|
||||||
completion: @escaping (PHAsset) -> Void = { _ in }
|
openColors: @escaping () -> Void
|
||||||
) -> ViewController {
|
) -> ViewController {
|
||||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
controller.requestController = { [weak controller] _, present in
|
controller.requestController = { [weak controller] _, present in
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
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 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: {
|
||||||
let _ = context.engine.themes.setChatWallpaper(peerId: peer.id, wallpaper: nil).start()
|
|
||||||
controller?.dismiss(animated: true)
|
controller?.dismiss(animated: true)
|
||||||
} : nil)
|
openColors()
|
||||||
|
})
|
||||||
mediaPickerController.customSelection = completion
|
mediaPickerController.customSelection = completion
|
||||||
present(mediaPickerController, mediaPickerController.mediaPickerContext)
|
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(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody))
|
||||||
entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts))
|
entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts))
|
||||||
switch kind {
|
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody))
|
||||||
case .presence, .voiceCalls, .forwards, .phoneNumber, .voiceMessages, .profilePhoto:
|
|
||||||
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody))
|
|
||||||
case .groupInvitations:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
let phoneLink = "https://t.me/+\(phoneNumber)"
|
let phoneLink = "https://t.me/+\(phoneNumber)"
|
||||||
if let settingInfoText = settingInfoText {
|
if let settingInfoText = settingInfoText {
|
||||||
entries.append(.settingInfo(presentationData.theme, settingInfoText, phoneLink))
|
entries.append(.settingInfo(presentationData.theme, settingInfoText, phoneLink))
|
||||||
|
@ -196,7 +196,7 @@ func uploadCustomWallpaper(context: AccountContext, wallpaper: WallpaperGalleryE
|
|||||||
}).start()
|
}).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>
|
let imageSignal: Signal<UIImage, NoError>
|
||||||
switch wallpaper {
|
switch wallpaper {
|
||||||
case let .wallpaper(wallpaper, _):
|
case let .wallpaper(wallpaper, _):
|
||||||
@ -279,24 +279,6 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
|||||||
croppedImage = blurredImage(croppedImage, radius: 30.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))
|
let thumbnailDimensions = finalCropRect.size.fitted(CGSize(width: 320.0, height: 320.0))
|
||||||
let thumbnailImage = generateScaledImage(image: croppedImage, size: thumbnailDimensions, scale: 1.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.sharedContext.accountManager.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
|
||||||
context.account.postbox.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 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
|
let _ = context.account.postbox.transaction({ transaction in
|
||||||
@ -326,7 +313,7 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
|||||||
completion()
|
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 .complete(wallpaper) = status {
|
||||||
if case let .file(file) = wallpaper {
|
if case let .file(file) = wallpaper {
|
||||||
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: file.file.resource.id, synchronous: true)
|
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: file.file.resource.id, synchronous: true)
|
||||||
|
@ -11,8 +11,8 @@ import TelegramUIPreferences
|
|||||||
import AccountContext
|
import AccountContext
|
||||||
import AttachmentUI
|
import AttachmentUI
|
||||||
|
|
||||||
private func availableGradients(theme: PresentationTheme) -> [[UInt32]] {
|
private func availableGradients(dark: Bool) -> [[UInt32]] {
|
||||||
if theme.overallDarkAppearance {
|
if dark {
|
||||||
return [
|
return [
|
||||||
[0x1e3557, 0x151a36, 0x1c4352, 0x2a4541] as [UInt32],
|
[0x1e3557, 0x151a36, 0x1c4352, 0x2a4541] as [UInt32],
|
||||||
[0x1d223f, 0x1d1832, 0x1b2943, 0x141631] as [UInt32],
|
[0x1d223f, 0x1d1832, 0x1b2943, 0x141631] as [UInt32],
|
||||||
@ -39,8 +39,8 @@ private func availableGradients(theme: PresentationTheme) -> [[UInt32]] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func availableColors(theme: PresentationTheme) -> [UInt32] {
|
private func availableColors(dark: Bool) -> [UInt32] {
|
||||||
if theme.overallDarkAppearance {
|
if dark {
|
||||||
return [
|
return [
|
||||||
0x1D2D3C,
|
0x1D2D3C,
|
||||||
0x111B26,
|
0x111B26,
|
||||||
@ -150,6 +150,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
|||||||
|
|
||||||
var pushController: (ViewController) -> Void = { _ in }
|
var pushController: (ViewController) -> Void = { _ in }
|
||||||
var dismissControllers: (() -> Void)?
|
var dismissControllers: (() -> Void)?
|
||||||
|
var openGallery: (() -> Void)?
|
||||||
|
|
||||||
public init(context: AccountContext, mode: Mode = .default, canDelete: Bool = false) {
|
public init(context: AccountContext, mode: Mode = .default, canDelete: Bool = false) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -192,9 +193,7 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
|||||||
self?.push(controller)
|
self?.push(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
if canDelete {
|
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)))
|
||||||
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)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
@ -270,7 +269,11 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override func loadDisplayNode() {
|
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)
|
self?.pushController(controller)
|
||||||
}, pop: { [weak self] in
|
}, pop: { [weak self] in
|
||||||
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
@ -327,12 +330,8 @@ public final class ThemeColorsGridController: ViewController, AttachmentContaina
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc fileprivate func mainButtonPressed() {
|
@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.dismiss(animated: true)
|
||||||
|
self.openGallery?()
|
||||||
}
|
}
|
||||||
|
|
||||||
public var requestAttachmentMenuExpansion: () -> Void = {}
|
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: {
|
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
controller.requestController = { _, present in
|
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
|
colorPickerController.pushController = { controller in
|
||||||
push(controller)
|
push(controller)
|
||||||
}
|
}
|
||||||
colorPickerController.dismissControllers = { [weak controller] in
|
colorPickerController.dismissControllers = { [weak controller] in
|
||||||
controller?.dismiss(animated: true)
|
controller?.dismiss(animated: true)
|
||||||
}
|
}
|
||||||
|
colorPickerController.openGallery = openGallery
|
||||||
present(colorPickerController, colorPickerController.mediaPickerContext)
|
present(colorPickerController, colorPickerController.mediaPickerContext)
|
||||||
}
|
}
|
||||||
return controller
|
return controller
|
||||||
|
@ -19,6 +19,8 @@ import WallpaperResources
|
|||||||
import AppBundle
|
import AppBundle
|
||||||
import WallpaperBackgroundNode
|
import WallpaperBackgroundNode
|
||||||
import TextFormat
|
import TextFormat
|
||||||
|
import TooltipUI
|
||||||
|
import TelegramNotices
|
||||||
|
|
||||||
struct WallpaperGalleryItemArguments {
|
struct WallpaperGalleryItemArguments {
|
||||||
let colorPreview: Bool
|
let colorPreview: Bool
|
||||||
@ -83,7 +85,7 @@ private func reference(for resource: MediaResource, media: Media, message: Messa
|
|||||||
|
|
||||||
final class WallpaperGalleryItemNode: GalleryItemNode {
|
final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
|
|
||||||
var entry: WallpaperGalleryEntry?
|
var entry: WallpaperGalleryEntry?
|
||||||
var source: WallpaperListSource?
|
var source: WallpaperListSource?
|
||||||
@ -102,6 +104,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
|
|
||||||
private let cancelButtonNode: WallpaperNavigationButtonNode
|
private let cancelButtonNode: WallpaperNavigationButtonNode
|
||||||
private let shareButtonNode: WallpaperNavigationButtonNode
|
private let shareButtonNode: WallpaperNavigationButtonNode
|
||||||
|
private let dayNightButtonNode: WallpaperNavigationButtonNode
|
||||||
|
|
||||||
private let blurButtonNode: WallpaperOptionButtonNode
|
private let blurButtonNode: WallpaperOptionButtonNode
|
||||||
private let motionButtonNode: WallpaperOptionButtonNode
|
private let motionButtonNode: WallpaperOptionButtonNode
|
||||||
@ -139,10 +142,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
|
|
||||||
private var isReadyDisposable: Disposable?
|
private var isReadyDisposable: Disposable?
|
||||||
|
|
||||||
|
private var isDarkAppearance: Bool = false
|
||||||
|
private var didChangeAppearance: Bool = false
|
||||||
|
private var darkAppearanceIntensity: CGFloat = 0.8
|
||||||
|
|
||||||
init(context: AccountContext) {
|
init(context: AccountContext) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
|
self.isDarkAppearance = self.presentationData.theme.overallDarkAppearance
|
||||||
|
|
||||||
self.wrapperNode = ASDisplayNode()
|
self.wrapperNode = ASDisplayNode()
|
||||||
self.imageNode = TransformImageNode()
|
self.imageNode = TransformImageNode()
|
||||||
self.imageNode.contentAnimations = .subsequentUpdates
|
self.imageNode.contentAnimations = .subsequentUpdates
|
||||||
@ -154,6 +163,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
|
|
||||||
self.blurredNode = BlurredImageNode()
|
self.blurredNode = BlurredImageNode()
|
||||||
self.brightnessNode = ASDisplayNode()
|
self.brightnessNode = ASDisplayNode()
|
||||||
|
self.brightnessNode.alpha = 0.0
|
||||||
|
|
||||||
self.messagesContainerNode = ASDisplayNode()
|
self.messagesContainerNode = ASDisplayNode()
|
||||||
self.messagesContainerNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
|
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))
|
self.serviceBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x333333, alpha: 0.33))
|
||||||
|
|
||||||
var sliderValueChangedImpl: ((CGFloat) -> Void)?
|
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)
|
sliderValueChangedImpl?(value)
|
||||||
})
|
})
|
||||||
|
|
||||||
self.colorsButtonNode = WallpaperOptionButtonNode(title: self.presentationData.strings.WallpaperPreview_WallpaperColors, value: .colors(false, [.clear]))
|
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.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.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
|
self.playButtonPlayImage = generateImage(CGSize(width: 48.0, height: 48.0), rotatedContext: { size, context in
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
@ -242,6 +254,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
self.addSubnode(self.sliderNode)
|
self.addSubnode(self.sliderNode)
|
||||||
self.addSubnode(self.cancelButtonNode)
|
self.addSubnode(self.cancelButtonNode)
|
||||||
self.addSubnode(self.shareButtonNode)
|
self.addSubnode(self.shareButtonNode)
|
||||||
|
self.addSubnode(self.dayNightButtonNode)
|
||||||
|
|
||||||
self.imageNode.addSubnode(self.brightnessNode)
|
self.imageNode.addSubnode(self.brightnessNode)
|
||||||
|
|
||||||
@ -252,22 +265,11 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
self.playButtonNode.addTarget(self, action: #selector(self.togglePlay), forControlEvents: .touchUpInside)
|
self.playButtonNode.addTarget(self, action: #selector(self.togglePlay), forControlEvents: .touchUpInside)
|
||||||
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
|
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
|
||||||
self.shareButtonNode.addTarget(self, action: #selector(self.actionPressed), 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
|
sliderValueChangedImpl = { [weak self] value in
|
||||||
if let self {
|
if let self {
|
||||||
let value = (value - 0.5) * 2.0
|
self.updateIntensity(transition: .immediate)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,7 +299,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
}
|
}
|
||||||
switch entry {
|
switch entry {
|
||||||
case .asset, .contextResult:
|
case .asset, .contextResult:
|
||||||
return (self.sliderNode.value - 0.5) * 2.0
|
return self.sliderNode.value
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -311,6 +313,53 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
self.action?()
|
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() {
|
@objc private func cancelPressed() {
|
||||||
self.dismiss()
|
self.dismiss()
|
||||||
}
|
}
|
||||||
@ -329,6 +378,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var showPreviewTooltip = false
|
||||||
|
|
||||||
if self.entry != entry || self.arguments.colorPreview != previousArguments.colorPreview {
|
if self.entry != entry || self.arguments.colorPreview != previousArguments.colorPreview {
|
||||||
let previousEntry = self.entry
|
let previousEntry = self.entry
|
||||||
self.entry = entry
|
self.entry = entry
|
||||||
@ -357,8 +408,6 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
|
|
||||||
var isBlurrable = true
|
var isBlurrable = true
|
||||||
|
|
||||||
self.nativeNode.updateBubbleTheme(bubbleTheme: presentationData.theme, bubbleCorners: presentationData.chatBubbleCorners)
|
|
||||||
|
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .wallpaper(wallpaper, _):
|
case let .wallpaper(wallpaper, _):
|
||||||
self.nativeNode.update(wallpaper: wallpaper)
|
self.nativeNode.update(wallpaper: wallpaper)
|
||||||
@ -393,6 +442,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
}
|
}
|
||||||
case .asset:
|
case .asset:
|
||||||
self.nativeNode._internalUpdateIsSettingUpWallpaper()
|
self.nativeNode._internalUpdateIsSettingUpWallpaper()
|
||||||
|
//self.nativeNode.update(wallpaper: self.presentationData.chatWallpaper)
|
||||||
self.nativeNode.isHidden = true
|
self.nativeNode.isHidden = true
|
||||||
self.patternButtonNode.isSelected = false
|
self.patternButtonNode.isSelected = false
|
||||||
self.playButtonNode.setIcon(self.playButtonRotateImage)
|
self.playButtonNode.setIcon(self.playButtonRotateImage)
|
||||||
@ -402,7 +452,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
self.playButtonNode.setIcon(self.playButtonRotateImage)
|
self.playButtonNode.setIcon(self.playButtonRotateImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isEditable = false
|
self.nativeNode.updateBubbleTheme(bubbleTheme: presentationData.theme, bubbleCorners: presentationData.chatBubbleCorners)
|
||||||
|
|
||||||
var canShare = false
|
var canShare = false
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .wallpaper(wallpaper, message):
|
case let .wallpaper(wallpaper, message):
|
||||||
@ -566,7 +617,6 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
}
|
}
|
||||||
self.cropNode.removeFromSupernode()
|
self.cropNode.removeFromSupernode()
|
||||||
case let .asset(asset):
|
case let .asset(asset):
|
||||||
isEditable = true
|
|
||||||
let dimensions = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
|
let dimensions = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
|
||||||
contentSize = dimensions
|
contentSize = dimensions
|
||||||
displaySize = dimensions.dividedByScreenScale().integralFloor
|
displaySize = dimensions.dividedByScreenScale().integralFloor
|
||||||
@ -576,8 +626,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
subtitleSignal = .single(nil)
|
subtitleSignal = .single(nil)
|
||||||
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
|
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
|
||||||
self.wrapperNode.addSubnode(self.cropNode)
|
self.wrapperNode.addSubnode(self.cropNode)
|
||||||
|
showPreviewTooltip = true
|
||||||
case let .contextResult(result):
|
case let .contextResult(result):
|
||||||
isEditable = true
|
|
||||||
var imageDimensions: CGSize?
|
var imageDimensions: CGSize?
|
||||||
var imageResource: TelegramMediaResource?
|
var imageResource: TelegramMediaResource?
|
||||||
var thumbnailDimensions: CGSize?
|
var thumbnailDimensions: CGSize?
|
||||||
@ -631,11 +681,12 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
|
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
|
||||||
subtitleSignal = .single(nil)
|
subtitleSignal = .single(nil)
|
||||||
self.wrapperNode.addSubnode(self.cropNode)
|
self.wrapperNode.addSubnode(self.cropNode)
|
||||||
|
showPreviewTooltip = true
|
||||||
}
|
}
|
||||||
self.contentSize = contentSize
|
self.contentSize = contentSize
|
||||||
|
|
||||||
self.cancelButtonNode.dark = !isEditable
|
//self.cancelButtonNode.dark = !isEditable
|
||||||
self.shareButtonNode.dark = !isEditable
|
//self.shareButtonNode.dark = !isEditable
|
||||||
self.shareButtonNode.isHidden = !canShare
|
self.shareButtonNode.isHidden = !canShare
|
||||||
|
|
||||||
if self.cropNode.supernode == nil {
|
if self.cropNode.supernode == nil {
|
||||||
@ -713,6 +764,18 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
self.updateButtonsLayout(layout: layout, offset: CGPoint(), transition: .immediate)
|
self.updateButtonsLayout(layout: layout, offset: CGPoint(), transition: .immediate)
|
||||||
self.updateMessagesLayout(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) {
|
override func screenFrameUpdated(_ frame: CGRect) {
|
||||||
@ -966,7 +1029,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
if let source = self.source {
|
if let source = self.source {
|
||||||
switch source {
|
switch source {
|
||||||
case .asset, .contextResult:
|
case .asset, .contextResult:
|
||||||
additionalYOffset -= 44.0
|
if self.isDarkAppearance {
|
||||||
|
additionalYOffset -= 44.0
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -996,8 +1061,17 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
var playAlpha: CGFloat = 0.0
|
var playAlpha: CGFloat = 0.0
|
||||||
|
|
||||||
let sliderSize = CGSize(width: 268.0, height: 30.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 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 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 cancelSize = self.cancelButtonNode.measure(layout.size)
|
||||||
let cancelFrame = CGRect(origin: CGPoint(x: 16.0 + offset.x, y: 16.0), size: cancelSize)
|
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
|
blurFrame = leftButtonFrame
|
||||||
motionAlpha = 1.0
|
motionAlpha = 1.0
|
||||||
motionFrame = rightButtonFrame
|
motionFrame = rightButtonFrame
|
||||||
sliderIsHidden = false
|
dayNightHidden = false
|
||||||
case .contextResult:
|
case .contextResult:
|
||||||
blurAlpha = 1.0
|
blurAlpha = 1.0
|
||||||
blurFrame = leftButtonFrame
|
blurFrame = leftButtonFrame
|
||||||
motionAlpha = 1.0
|
motionAlpha = 1.0
|
||||||
motionFrame = rightButtonFrame
|
motionFrame = rightButtonFrame
|
||||||
sliderIsHidden = false
|
dayNightHidden = false
|
||||||
case let .wallpaper(wallpaper, _):
|
case let .wallpaper(wallpaper, _):
|
||||||
switch wallpaper {
|
switch wallpaper {
|
||||||
case .builtin:
|
case .builtin:
|
||||||
@ -1104,12 +1178,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
transition.updateAlpha(node: self.playButtonNode, alpha: playAlpha * alpha)
|
transition.updateAlpha(node: self.playButtonNode, alpha: playAlpha * alpha)
|
||||||
transition.updateSublayerTransformScale(node: self.playButtonNode, scale: max(0.1, playAlpha))
|
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.updateLayout(size: sliderFrame.size)
|
||||||
self.sliderNode.isHidden = sliderIsHidden
|
|
||||||
|
|
||||||
transition.updateFrame(node: self.cancelButtonNode, frame: cancelFrame)
|
transition.updateFrame(node: self.cancelButtonNode, frame: cancelFrame)
|
||||||
transition.updateFrame(node: self.shareButtonNode, frame: shareFrame)
|
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) {
|
private func updateMessagesLayout(layout: ContainerViewLayout, offset: CGPoint, transition: ContainedViewLayoutTransition) {
|
||||||
@ -1182,7 +1260,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
case .asset, .contextResult:
|
case .asset, .contextResult:
|
||||||
topMessageText = presentationData.strings.WallpaperPreview_CropTopText
|
topMessageText = presentationData.strings.WallpaperPreview_CropTopText
|
||||||
bottomMessageText = presentationData.strings.WallpaperPreview_CropBottomText
|
bottomMessageText = presentationData.strings.WallpaperPreview_CropBottomText
|
||||||
bottomInset += 44.0
|
if self.isDarkAppearance {
|
||||||
|
bottomInset += 44.0
|
||||||
|
}
|
||||||
case .customColor:
|
case .customColor:
|
||||||
topMessageText = presentationData.strings.WallpaperPreview_CustomColorTopText
|
topMessageText = presentationData.strings.WallpaperPreview_CustomColorTopText
|
||||||
bottomMessageText = presentationData.strings.WallpaperPreview_CustomColorBottomText
|
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)
|
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))
|
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.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
|
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
|
self.brightnessNode.frame = self.imageNode.bounds
|
||||||
|
|
||||||
@ -1322,4 +1412,41 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
func animateWallpaperAppeared() {
|
func animateWallpaperAppeared() {
|
||||||
self.nativeNode.animateEvent(transition: .animated(duration: 2.0, curve: .spring), extendAnimation: true)
|
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 SwiftSignalKit
|
||||||
import Postbox
|
import Postbox
|
||||||
import CheckNode
|
import CheckNode
|
||||||
|
import AnimationUI
|
||||||
|
|
||||||
enum WallpaperOptionButtonValue {
|
enum WallpaperOptionButtonValue {
|
||||||
case check(Bool)
|
case check(Bool)
|
||||||
@ -93,6 +94,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
|||||||
enum Content {
|
enum Content {
|
||||||
case icon(image: UIImage?, size: CGSize)
|
case icon(image: UIImage?, size: CGSize)
|
||||||
case text(String)
|
case text(String)
|
||||||
|
case dayNight(isNight: Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
var enableSaturation: Bool = false
|
var enableSaturation: Bool = false
|
||||||
@ -115,6 +117,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
|||||||
private var backgroundNode: ASDisplayNode
|
private var backgroundNode: ASDisplayNode
|
||||||
private let iconNode: ASImageNode
|
private let iconNode: ASImageNode
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
|
private var animationNode: AnimationNode?
|
||||||
|
|
||||||
func setIcon(_ image: UIImage?) {
|
func setIcon(_ image: UIImage?) {
|
||||||
self.iconNode.image = generateTintedImage(image: image, color: .white)
|
self.iconNode.image = generateTintedImage(image: image, color: .white)
|
||||||
@ -141,6 +144,12 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
|||||||
case let .icon(icon, _):
|
case let .icon(icon, _):
|
||||||
title = ""
|
title = ""
|
||||||
self.iconNode.image = generateTintedImage(image: icon, color: .white)
|
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()
|
self.textNode = ImmediateTextNode()
|
||||||
@ -152,19 +161,53 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
|||||||
self.addSubnode(self.iconNode)
|
self.addSubnode(self.iconNode)
|
||||||
self.addSubnode(self.textNode)
|
self.addSubnode(self.textNode)
|
||||||
|
|
||||||
|
if let animationNode = self.animationNode {
|
||||||
|
self.addSubnode(animationNode)
|
||||||
|
}
|
||||||
|
|
||||||
self.highligthedChanged = { [weak self] highlighted in
|
self.highligthedChanged = { [weak self] highlighted in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if highlighted {
|
if highlighted {
|
||||||
strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity")
|
strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity")
|
||||||
strongSelf.backgroundNode.alpha = 0.4
|
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 {
|
} else {
|
||||||
strongSelf.backgroundNode.alpha = 1.0
|
strongSelf.backgroundNode.alpha = 1.0
|
||||||
strongSelf.backgroundNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
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) {
|
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||||
didSet {
|
didSet {
|
||||||
}
|
}
|
||||||
@ -179,6 +222,8 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
|||||||
return CGSize(width: ceil(size.width) + 16.0, height: 28.0)
|
return CGSize(width: ceil(size.width) + 16.0, height: 28.0)
|
||||||
case let .icon(_, size):
|
case let .icon(_, size):
|
||||||
return 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 {
|
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)
|
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)
|
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
|
self.validLayout = size
|
||||||
|
|
||||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: .zero, size: 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 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))
|
let foregroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: value * size.width, height: size.height))
|
||||||
transition.updateFrameAdditive(node: self.foregroundNode, frame: foregroundFrame)
|
transition.updateFrame(node: self.foregroundNode, frame: foregroundFrame)
|
||||||
transition.updateFrameAdditive(node: self.foregroundLightNode, 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) {
|
@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))
|
self.value = max(self.minValue, min(self.maxValue, self.value + delta))
|
||||||
gestureRecognizer.setTranslation(CGPoint(), in: gestureRecognizer.view)
|
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)
|
self.hapticFeedback.impact(.soft)
|
||||||
} else if self.value == 1.0 && previousValue != 1.0 {
|
} else if self.value == 1.0 && previousValue != 1.0 {
|
||||||
self.hapticFeedback.impact(.soft)
|
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 {
|
if abs(previousValue - self.value) >= 0.001 {
|
||||||
self.valueChanged(self.value, false)
|
self.valueChanged(self.value, false)
|
||||||
|
@ -526,7 +526,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
|||||||
let _ = (ApplicationSpecificNotice.incrementAudioRateOptionsTip(accountManager: self.context.sharedContext.accountManager)
|
let _ = (ApplicationSpecificNotice.incrementAudioRateOptionsTip(accountManager: self.context.sharedContext.accountManager)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] value in
|
|> deliverOnMainQueue).start(next: { [weak self] value in
|
||||||
if let strongSelf = self, let controller = strongSelf.getController?(), value == 2 {
|
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)
|
return .dismiss(consume: false)
|
||||||
})
|
})
|
||||||
controller.present(tooltipController, in: .window(.root))
|
controller.present(tooltipController, in: .window(.root))
|
||||||
|
@ -760,8 +760,8 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
|||||||
}) else {
|
}) else {
|
||||||
return
|
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)
|
return .dismiss(consume: false)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -2310,7 +2310,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
|||||||
} else {
|
} else {
|
||||||
text = presentationData.strings.VoiceChat_RecordingInProgress
|
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)
|
return .dismiss(consume: true)
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
@ -3507,7 +3507,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
|||||||
if !callState.subscribedToScheduled {
|
if !callState.subscribedToScheduled {
|
||||||
let location = self.actionButton.view.convert(self.actionButton.bounds, to: self.view).center
|
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))
|
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)
|
return .dismiss(consume: false)
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
@ -6411,7 +6411,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
|
|||||||
point.origin.y += 32.0
|
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)
|
return .dismiss(consume: false)
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,8 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
|||||||
case audioRateOptionsTip = 36
|
case audioRateOptionsTip = 36
|
||||||
case translationSuggestion = 37
|
case translationSuggestion = 37
|
||||||
case sendWhenOnlineTip = 38
|
case sendWhenOnlineTip = 38
|
||||||
|
case chatWallpaperLightPreviewTip = 39
|
||||||
|
case chatWallpaperDarkPreviewTip = 40
|
||||||
|
|
||||||
var key: ValueBoxKey {
|
var key: ValueBoxKey {
|
||||||
let v = ValueBoxKey(length: 4)
|
let v = ValueBoxKey(length: 4)
|
||||||
@ -332,6 +334,14 @@ private struct ApplicationSpecificNoticeKeys {
|
|||||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatSpecificThemeDarkPreviewTip.key)
|
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 {
|
static func chatForwardOptionsTip() -> NoticeEntryKey {
|
||||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatForwardOptionsTip.key)
|
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> {
|
public static func getChatForwardOptionsTip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||||
return accountManager.transaction { transaction -> Int32 in
|
return accountManager.transaction { transaction -> Int32 in
|
||||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatForwardOptionsTip())?.get(ApplicationSpecificCounterNotice.self) {
|
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatForwardOptionsTip())?.get(ApplicationSpecificCounterNotice.self) {
|
||||||
|
@ -130,7 +130,7 @@ final class ChatBotStartInputPanelNode: ChatInputPanelNode {
|
|||||||
tooltipController.location = .point(location, .bottom)
|
tooltipController.location = .point(location, .bottom)
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
return .ignore
|
||||||
})
|
})
|
||||||
controller.alwaysVisible = true
|
controller.alwaysVisible = true
|
||||||
|
@ -676,14 +676,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if strongSelf.presentVoiceMessageDiscardAlert(action: { [weak self] in
|
let displayVoiceMessageDiscardAlert: () -> Bool = {
|
||||||
if let strongSelf = self {
|
if strongSelf.presentVoiceMessageDiscardAlert(action: { [weak self] in
|
||||||
Queue.mainQueue().after(0.1, {
|
if let strongSelf = self {
|
||||||
let _ = strongSelf.controllerInteraction?.openMessage(message, mode)
|
Queue.mainQueue().after(0.1, {
|
||||||
})
|
let _ = strongSelf.controllerInteraction?.openMessage(message, mode)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, performAction: false) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}, performAction: false) {
|
return true
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.commitPurposefulAction()
|
strongSelf.commitPurposefulAction()
|
||||||
@ -696,6 +699,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if media is TelegramMediaMap {
|
if media is TelegramMediaMap {
|
||||||
|
if !displayVoiceMessageDiscardAlert() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
isLocation = true
|
isLocation = true
|
||||||
}
|
}
|
||||||
if let file = media as? TelegramMediaFile, file.isInstantVideo {
|
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 {
|
if let invoice = media as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia {
|
||||||
switch extendedMedia {
|
switch extendedMedia {
|
||||||
case .preview:
|
case .preview:
|
||||||
strongSelf.controllerInteraction?.openCheckoutOrReceipt(message.id)
|
if displayVoiceMessageDiscardAlert() {
|
||||||
return true
|
strongSelf.controllerInteraction?.openCheckoutOrReceipt(message.id)
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
case .full:
|
case .full:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if let action = media as? TelegramMediaAction {
|
} else if let action = media as? TelegramMediaAction {
|
||||||
|
if !displayVoiceMessageDiscardAlert() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
switch action.action {
|
switch action.action {
|
||||||
case .pinnedMessageUpdated:
|
case .pinnedMessageUpdated:
|
||||||
for attribute in message.attributes {
|
for attribute in message.attributes {
|
||||||
@ -5839,6 +5852,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
|
let (themeEmoticonPreview, darkAppearancePreview) = themeEmoticonAndDarkAppearance
|
||||||
|
|
||||||
|
var chatWallpaper = chatWallpaper
|
||||||
|
|
||||||
let previousTheme = strongSelf.presentationData.theme
|
let previousTheme = strongSelf.presentationData.theme
|
||||||
let previousStrings = strongSelf.presentationData.strings
|
let previousStrings = strongSelf.presentationData.strings
|
||||||
let previousChatWallpaper = strongSelf.presentationData.chatWallpaper
|
let previousChatWallpaper = strongSelf.presentationData.chatWallpaper
|
||||||
@ -5846,7 +5861,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var themeEmoticon = themeEmoticon
|
var themeEmoticon = themeEmoticon
|
||||||
if let themeEmoticonPreview = themeEmoticonPreview {
|
if let themeEmoticonPreview = themeEmoticonPreview {
|
||||||
if !themeEmoticonPreview.isEmpty {
|
if !themeEmoticonPreview.isEmpty {
|
||||||
themeEmoticon = themeEmoticonPreview
|
if themeEmoticon != themeEmoticonPreview {
|
||||||
|
chatWallpaper = nil
|
||||||
|
themeEmoticon = themeEmoticonPreview
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
themeEmoticon = nil
|
themeEmoticon = nil
|
||||||
}
|
}
|
||||||
@ -5857,7 +5875,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
var presentationData = presentationData
|
var presentationData = presentationData
|
||||||
var useDarkAppearance = presentationData.theme.overallDarkAppearance
|
var useDarkAppearance = presentationData.theme.overallDarkAppearance
|
||||||
|
|
||||||
if let themeEmoticon = themeEmoticon, let theme = chatThemes.first(where: { $0.emoticon?.strippedEmoji == themeEmoticon.strippedEmoji }) {
|
if let themeEmoticon = themeEmoticon, let theme = chatThemes.first(where: { $0.emoticon?.strippedEmoji == themeEmoticon.strippedEmoji }) {
|
||||||
if let darkAppearancePreview = darkAppearancePreview {
|
if let darkAppearancePreview = darkAppearancePreview {
|
||||||
useDarkAppearance = darkAppearancePreview
|
useDarkAppearance = darkAppearancePreview
|
||||||
@ -5896,7 +5914,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
lightWallpaper = theme.chat.defaultWallpaper
|
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 {
|
} else {
|
||||||
lightTheme = presentationData.theme
|
lightTheme = presentationData.theme
|
||||||
lightWallpaper = presentationData.chatWallpaper
|
lightWallpaper = presentationData.chatWallpaper
|
||||||
@ -5905,7 +5928,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
let effectiveColors = themeSettings.themeSpecificAccentColors[automaticTheme.index]
|
let effectiveColors = themeSettings.themeSpecificAccentColors[automaticTheme.index]
|
||||||
let themeSpecificWallpaper = (themeSettings.themeSpecificChatWallpapers[coloredThemeIndex(reference: automaticTheme, accentColor: effectiveColors)] ?? themeSettings.themeSpecificChatWallpapers[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 {
|
if let themeSpecificWallpaper = themeSpecificWallpaper {
|
||||||
darkWallpaper = themeSpecificWallpaper
|
darkWallpaper = themeSpecificWallpaper
|
||||||
@ -5944,7 +5974,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
presentationData = presentationData.withUpdated(chatWallpaper: chatWallpaper)
|
presentationData = presentationData.withUpdated(chatWallpaper: chatWallpaper)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let isFirstTime = !strongSelf.didSetPresentationData
|
let isFirstTime = !strongSelf.didSetPresentationData
|
||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
strongSelf.didSetPresentationData = true
|
strongSelf.didSetPresentationData = true
|
||||||
@ -14314,7 +14343,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
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
|
return .ignore
|
||||||
}, openActiveTextItem: { [weak self] item, action in
|
}, openActiveTextItem: { [weak self] item, action in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -14407,7 +14436,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
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
|
return .ignore
|
||||||
}, openActiveTextItem: { [weak self] item, action in
|
}, openActiveTextItem: { [weak self] item, action in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -14521,7 +14550,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
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
|
return .ignore
|
||||||
}, openActiveTextItem: { [weak self] item, action in
|
}, openActiveTextItem: { [weak self] item, action in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -18508,12 +18537,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
let selectedEmoticon: String? = themeEmoticon
|
let selectedEmoticon: String? = themeEmoticon
|
||||||
|
|
||||||
|
var canResetWallpaper = false
|
||||||
|
if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData {
|
||||||
|
canResetWallpaper = cachedUserData.wallpaper != nil
|
||||||
|
}
|
||||||
|
|
||||||
let controller = ChatThemeScreen(
|
let controller = ChatThemeScreen(
|
||||||
context: context,
|
context: context,
|
||||||
updatedPresentationData: strongSelf.updatedPresentationData,
|
updatedPresentationData: strongSelf.updatedPresentationData,
|
||||||
animatedEmojiStickers: animatedEmojiStickers,
|
animatedEmojiStickers: animatedEmojiStickers,
|
||||||
initiallySelectedEmoticon: selectedEmoticon,
|
initiallySelectedEmoticon: selectedEmoticon,
|
||||||
peerName: strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer.flatMap(EnginePeer.init)?.compactDisplayTitle ?? "",
|
peerName: strongSelf.presentationInterfaceState.renderedPeer?.chatMainPeer.flatMap(EnginePeer.init)?.compactDisplayTitle ?? "",
|
||||||
|
canResetWallpaper: canResetWallpaper,
|
||||||
previewTheme: { [weak self] emoticon, dark in
|
previewTheme: { [weak self] emoticon, dark in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.presentCrossfadeSnapshot()
|
strongSelf.presentCrossfadeSnapshot()
|
||||||
@ -18540,54 +18575,47 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var canDelete = false
|
var openWallpaperPickerImpl: (() -> Void)?
|
||||||
if let cachedUserData = strongSelf.peerView?.cachedData as? CachedUserData {
|
let openWallpaperPicker = {
|
||||||
canDelete = cachedUserData.wallpaper != nil
|
let controller = wallpaperMediaPickerController(
|
||||||
}
|
context: strongSelf.context,
|
||||||
let controller = wallpaperMediaPickerController(
|
updatedPresentationData: strongSelf.updatedPresentationData,
|
||||||
context: strongSelf.context,
|
peer: EnginePeer(peer),
|
||||||
updatedPresentationData: strongSelf.updatedPresentationData,
|
completion: { asset in
|
||||||
peer: EnginePeer(peer),
|
guard let strongSelf = self else {
|
||||||
canDelete: canDelete,
|
return
|
||||||
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()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
controller.navigationPresentation = .flatModal
|
|
||||||
strongSelf.push(controller)
|
|
||||||
},
|
|
||||||
changeColor: {
|
|
||||||
guard let strongSelf = self else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if let themeController = strongSelf.themeScreen {
|
openWallpaperPickerImpl = openWallpaperPicker
|
||||||
strongSelf.themeScreen = nil
|
openWallpaperPicker()
|
||||||
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)
|
|
||||||
},
|
},
|
||||||
completion: { [weak self] emoticon in
|
completion: { [weak self] emoticon in
|
||||||
guard let strongSelf = self, let peerId else {
|
guard let strongSelf = self, let peerId else {
|
||||||
|
@ -1483,7 +1483,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
|||||||
tooltipController.location = .point(location, .bottom)
|
tooltipController.location = .point(location, .bottom)
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
return .ignore
|
||||||
})
|
})
|
||||||
controller.alwaysVisible = true
|
controller.alwaysVisible = true
|
||||||
|
@ -554,9 +554,9 @@ final class ChatThemeScreen: ViewController {
|
|||||||
private let animatedEmojiStickers: [String: [StickerPackItem]]
|
private let animatedEmojiStickers: [String: [StickerPackItem]]
|
||||||
private let initiallySelectedEmoticon: String?
|
private let initiallySelectedEmoticon: String?
|
||||||
private let peerName: String
|
private let peerName: String
|
||||||
|
let canResetWallpaper: Bool
|
||||||
private let previewTheme: (String?, Bool?) -> Void
|
private let previewTheme: (String?, Bool?) -> Void
|
||||||
fileprivate let changeWallpaper: () -> Void
|
fileprivate let changeWallpaper: () -> Void
|
||||||
fileprivate let changeColor: () -> Void
|
|
||||||
private let completion: (String?) -> Void
|
private let completion: (String?) -> Void
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
@ -578,9 +578,9 @@ final class ChatThemeScreen: ViewController {
|
|||||||
animatedEmojiStickers: [String: [StickerPackItem]],
|
animatedEmojiStickers: [String: [StickerPackItem]],
|
||||||
initiallySelectedEmoticon: String?,
|
initiallySelectedEmoticon: String?,
|
||||||
peerName: String,
|
peerName: String,
|
||||||
|
canResetWallpaper: Bool,
|
||||||
previewTheme: @escaping (String?, Bool?) -> Void,
|
previewTheme: @escaping (String?, Bool?) -> Void,
|
||||||
changeWallpaper: @escaping () -> Void,
|
changeWallpaper: @escaping () -> Void,
|
||||||
changeColor: @escaping () -> Void,
|
|
||||||
completion: @escaping (String?) -> Void
|
completion: @escaping (String?) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -588,9 +588,9 @@ final class ChatThemeScreen: ViewController {
|
|||||||
self.animatedEmojiStickers = animatedEmojiStickers
|
self.animatedEmojiStickers = animatedEmojiStickers
|
||||||
self.initiallySelectedEmoticon = initiallySelectedEmoticon
|
self.initiallySelectedEmoticon = initiallySelectedEmoticon
|
||||||
self.peerName = peerName
|
self.peerName = peerName
|
||||||
|
self.canResetWallpaper = canResetWallpaper
|
||||||
self.previewTheme = previewTheme
|
self.previewTheme = previewTheme
|
||||||
self.changeWallpaper = changeWallpaper
|
self.changeWallpaper = changeWallpaper
|
||||||
self.changeColor = changeColor
|
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
@ -1013,18 +1013,22 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateButtons() {
|
private func updateButtons() {
|
||||||
|
let canResetWallpaper = self.controller?.canResetWallpaper ?? false
|
||||||
|
|
||||||
let doneButtonTitle: String
|
let doneButtonTitle: String
|
||||||
let otherButtonTitle: String
|
let otherButtonTitle: String
|
||||||
var accentButtonTheme = true
|
var accentButtonTheme = true
|
||||||
|
var destructiveOtherButton = false
|
||||||
if self.selectedEmoticon == self.initiallySelectedEmoticon {
|
if self.selectedEmoticon == self.initiallySelectedEmoticon {
|
||||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_SetPhotoWallpaper
|
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
|
accentButtonTheme = false
|
||||||
|
destructiveOtherButton = canResetWallpaper
|
||||||
} else if self.selectedEmoticon == nil && self.initiallySelectedEmoticon != nil {
|
} else if self.selectedEmoticon == nil && self.initiallySelectedEmoticon != nil {
|
||||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_Reset
|
doneButtonTitle = self.presentationData.strings.Conversation_Theme_Reset
|
||||||
otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions
|
otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions
|
||||||
} else {
|
} else {
|
||||||
doneButtonTitle = self.presentationData.strings.Conversation_Theme_Apply
|
doneButtonTitle = self.presentationData.strings.Conversation_Theme_ApplyBackground
|
||||||
otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions
|
otherButtonTitle = self.presentationData.strings.Conversation_Theme_OtherOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1040,7 +1044,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
|||||||
}
|
}
|
||||||
self.doneButton.updateTheme(buttonTheme)
|
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?
|
private var switchThemeIconAnimator: DisplayLinkAnimator?
|
||||||
@ -1102,7 +1106,11 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega
|
|||||||
if self.selectedEmoticon != self.initiallySelectedEmoticon {
|
if self.selectedEmoticon != self.initiallySelectedEmoticon {
|
||||||
self.setEmoticon(self.initiallySelectedEmoticon)
|
self.setEmoticon(self.initiallySelectedEmoticon)
|
||||||
} else {
|
} 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 {
|
if let strongSelf = self, count < 2 && currentTimestamp > timestamp + 24 * 60 * 60 {
|
||||||
strongSelf.displayedPreviewTooltip = true
|
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)
|
return .dismiss(consume: false)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
@ -8467,7 +8467,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let buttonFrame = buttonNode.view.convert(buttonNode.bounds, to: self.view)
|
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)
|
return .dismiss(consume: false)
|
||||||
}), in: .current)
|
}), in: .current)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import TelegramCore
|
|||||||
import TextFormat
|
import TextFormat
|
||||||
import Postbox
|
import Postbox
|
||||||
import UrlEscaping
|
import UrlEscaping
|
||||||
|
import AccountContext
|
||||||
|
|
||||||
public protocol TooltipCustomContentNode: ASDisplayNode {
|
public protocol TooltipCustomContentNode: ASDisplayNode {
|
||||||
func animateIn()
|
func animateIn()
|
||||||
@ -127,12 +128,11 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
private let backgroundContainerNode: ASDisplayNode
|
private let backgroundContainerNode: ASDisplayNode
|
||||||
private let backgroundClipNode: ASDisplayNode
|
private let backgroundClipNode: ASDisplayNode
|
||||||
private let backgroundMaskNode: ASDisplayNode
|
private let backgroundMaskNode: ASDisplayNode
|
||||||
private var effectView: UIView?
|
private var effectNode: NavigationBackgroundNode?
|
||||||
private var gradientNode: ASDisplayNode?
|
private var gradientNode: ASDisplayNode?
|
||||||
private var arrowGradientNode: ASDisplayNode?
|
private var arrowGradientNode: ASDisplayNode?
|
||||||
private let arrowNode: ASImageNode
|
private let arrowNode: ASImageNode
|
||||||
private let arrowContainer: ASDisplayNode
|
private let arrowContainer: ASDisplayNode
|
||||||
private var arrowEffectView: UIView?
|
|
||||||
private let animatedStickerNode: AnimatedStickerNode
|
private let animatedStickerNode: AnimatedStickerNode
|
||||||
private var downArrowsNode: DownArrowsIconNode?
|
private var downArrowsNode: DownArrowsIconNode?
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
@ -143,7 +143,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
|
|
||||||
private var validLayout: ContainerViewLayout?
|
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.tooltipStyle = style
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.customContentNode = customContentNode
|
self.customContentNode = customContentNode
|
||||||
@ -210,9 +210,16 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
|
|
||||||
self.arrowContainer = ASDisplayNode()
|
self.arrowContainer = ASDisplayNode()
|
||||||
|
|
||||||
|
let theme = sharedContext.currentPresentationData.with { $0 }.theme
|
||||||
let fontSize: CGFloat
|
let fontSize: CGFloat
|
||||||
if case .top = location {
|
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.backgroundMaskNode.addSubnode(self.backgroundClipNode)
|
||||||
self.backgroundClipNode.clipsToBounds = true
|
self.backgroundClipNode.clipsToBounds = true
|
||||||
if case let .point(_, arrowPosition) = location, case .right = arrowPosition {
|
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)
|
maskLayer.frame = CGRect(origin: CGPoint(), size: arrowSize)
|
||||||
self.arrowContainer.layer.mask = maskLayer
|
self.arrowContainer.layer.mask = maskLayer
|
||||||
} else {
|
} else {
|
||||||
let effect: UIBlurEffect
|
var enableSaturation = true
|
||||||
if case .light = style {
|
let backgroundColor: UIColor
|
||||||
effect = UIBlurEffect(style: .light)
|
if case let .customBlur(color) = style {
|
||||||
|
backgroundColor = color
|
||||||
|
enableSaturation = false
|
||||||
|
} else if case .light = style {
|
||||||
|
backgroundColor = theme.rootController.navigationBar.blurredBackgroundColor
|
||||||
} else {
|
} 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.backgroundMaskNode.addSubnode(self.backgroundClipNode)
|
||||||
self.backgroundClipNode.clipsToBounds = true
|
self.backgroundClipNode.clipsToBounds = true
|
||||||
if case let .point(_, arrowPosition) = location, case .right = arrowPosition {
|
if case let .point(_, arrowPosition) = location, case .right = arrowPosition {
|
||||||
self.backgroundClipNode.cornerRadius = 8.5
|
self.backgroundClipNode.cornerRadius = 8.5
|
||||||
} else {
|
} else {
|
||||||
self.backgroundClipNode.cornerRadius = 14.0
|
self.backgroundClipNode.cornerRadius = 12.5
|
||||||
}
|
}
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
self.backgroundClipNode.layer.cornerCurve = .continuous
|
self.backgroundClipNode.layer.cornerCurve = .continuous
|
||||||
@ -318,8 +333,8 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
if let gradientNode = self.gradientNode {
|
if let gradientNode = self.gradientNode {
|
||||||
self.backgroundContainerNode.addSubnode(gradientNode)
|
self.backgroundContainerNode.addSubnode(gradientNode)
|
||||||
self.containerNode.addSubnode(self.arrowContainer)
|
self.containerNode.addSubnode(self.arrowContainer)
|
||||||
} else if let effectView = self.effectView {
|
} else if let effectNode = self.effectNode {
|
||||||
self.backgroundContainerNode.view.addSubview(effectView)
|
self.backgroundContainerNode.addSubnode(effectNode)
|
||||||
self.backgroundContainerNode.layer.mask = self.backgroundMaskNode.layer
|
self.backgroundContainerNode.layer.mask = self.backgroundMaskNode.layer
|
||||||
}
|
}
|
||||||
self.containerNode.addSubnode(self.textNode)
|
self.containerNode.addSubnode(self.textNode)
|
||||||
@ -430,7 +445,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
|||||||
|
|
||||||
let backgroundHeight: CGFloat
|
let backgroundHeight: CGFloat
|
||||||
switch self.tooltipStyle {
|
switch self.tooltipStyle {
|
||||||
case .default, .gradient:
|
case .default, .gradient, .customBlur:
|
||||||
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0
|
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0
|
||||||
case .light:
|
case .light:
|
||||||
backgroundHeight = max(28.0, max(animationSize.height, textSize.height) + 4.0 * 2.0)
|
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.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))
|
transition.updateFrame(node: self.backgroundClipNode, frame: CGRect(origin: CGPoint(x: 10.0, y: 10.0), size: backgroundFrame.size))
|
||||||
|
|
||||||
if let effectView = self.effectView {
|
if let effectNode = self.effectNode {
|
||||||
transition.updateFrame(view: effectView, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size).insetBy(dx: -10.0, dy: -10.0))
|
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 {
|
if let gradientNode = self.gradientNode {
|
||||||
transition.updateFrame(node: gradientNode, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
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)
|
let arrowBounds = CGRect(origin: CGPoint(), size: arrowSize)
|
||||||
self.arrowNode.frame = arrowBounds
|
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)
|
self.arrowGradientNode?.frame = CGRect(origin: CGPoint(x: -arrowFrame.minX + backgroundFrame.minX, y: 0.0), size: backgroundFrame.size)
|
||||||
case .right:
|
case .right:
|
||||||
arrowFrame = CGRect(origin: CGPoint(x: backgroundFrame.width + arrowSize.height, y: rect.midY), size: CGSize(width: arrowSize.height, height: arrowSize.width))
|
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)
|
let arrowBounds = CGRect(origin: .zero, size: arrowSize)
|
||||||
self.arrowNode.frame = arrowBounds
|
self.arrowNode.frame = arrowBounds
|
||||||
self.arrowEffectView?.frame = arrowBounds
|
|
||||||
self.arrowGradientNode?.frame = arrowBounds
|
self.arrowGradientNode?.frame = arrowBounds
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.arrowNode.isHidden = true
|
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))
|
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 {
|
public enum Style {
|
||||||
case `default`
|
case `default`
|
||||||
case light
|
case light
|
||||||
|
case customBlur(UIColor)
|
||||||
case gradient(UIColor, UIColor)
|
case gradient(UIColor, UIColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private let account: Account
|
private let account: Account
|
||||||
|
private let sharedContext: SharedAccountContext
|
||||||
public let text: String
|
public let text: String
|
||||||
public let textEntities: [MessageTextEntity]
|
public let textEntities: [MessageTextEntity]
|
||||||
private let style: TooltipScreen.Style
|
private let style: TooltipScreen.Style
|
||||||
@ -707,8 +723,9 @@ public final class TooltipScreen: ViewController {
|
|||||||
|
|
||||||
public var alwaysVisible = false
|
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.account = account
|
||||||
|
self.sharedContext = sharedContext
|
||||||
self.text = text
|
self.text = text
|
||||||
self.textEntities = textEntities
|
self.textEntities = textEntities
|
||||||
self.style = style
|
self.style = style
|
||||||
@ -776,7 +793,7 @@ public final class TooltipScreen: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
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 {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -743,6 +743,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
private var gradientBackgroundNode: GradientBackgroundNode?
|
private var gradientBackgroundNode: GradientBackgroundNode?
|
||||||
private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode?
|
private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode?
|
||||||
private let patternImageLayer: EffectImageLayer
|
private let patternImageLayer: EffectImageLayer
|
||||||
|
private let dimLayer: SimpleLayer
|
||||||
private var isGeneratingPatternImage: Bool = false
|
private var isGeneratingPatternImage: Bool = false
|
||||||
|
|
||||||
private let bakedBackgroundView: UIImageView
|
private let bakedBackgroundView: UIImageView
|
||||||
@ -862,6 +863,9 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
self.bakedBackgroundView = UIImageView()
|
self.bakedBackgroundView = UIImageView()
|
||||||
self.bakedBackgroundView.isHidden = true
|
self.bakedBackgroundView.isHidden = true
|
||||||
|
|
||||||
|
self.dimLayer = SimpleLayer()
|
||||||
|
self.dimLayer.backgroundColor = UIColor.black.cgColor
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
if #available(iOS 12.0, *) {
|
if #available(iOS 12.0, *) {
|
||||||
@ -885,6 +889,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
self.contentNode.frame = self.bounds
|
self.contentNode.frame = self.bounds
|
||||||
self.addSubnode(self.contentNode)
|
self.addSubnode(self.contentNode)
|
||||||
self.layer.addSublayer(self.patternImageLayer)
|
self.layer.addSublayer(self.patternImageLayer)
|
||||||
|
|
||||||
|
self.layer.addSublayer(self.dimLayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -892,6 +898,19 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
self.wallpaperDisposable.dispose()
|
self.wallpaperDisposable.dispose()
|
||||||
self.imageDisposable.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) {
|
func update(wallpaper: TelegramWallpaper) {
|
||||||
if self.wallpaper == wallpaper {
|
if self.wallpaper == wallpaper {
|
||||||
@ -915,7 +934,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
gradientColors = file.settings.colors
|
gradientColors = file.settings.colors
|
||||||
gradientAngle = file.settings.rotation ?? 0
|
gradientAngle = file.settings.rotation ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var scheduleLoopingEvent = false
|
var scheduleLoopingEvent = false
|
||||||
if gradientColors.count >= 3 {
|
if gradientColors.count >= 3 {
|
||||||
let mappedColors = gradientColors.map { color -> UIColor in
|
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.animateEvent(transition: .animated(duration: 0.7, curve: .linear), extendAnimation: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.updateDimming()
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internalUpdateIsSettingUpWallpaper() {
|
func _internalUpdateIsSettingUpWallpaper() {
|
||||||
@ -1304,6 +1325,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
transition.updateFrame(node: outgoingBackgroundNode, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(node: outgoingBackgroundNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
outgoingBackgroundNode.update(rect: CGRect(origin: CGPoint(), size: size), within: size, transition: transition)
|
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)
|
self.loadPatternForSizeIfNeeded(size: size, displayMode: displayMode, transition: transition)
|
||||||
|
|
||||||
@ -1378,6 +1401,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.updateBubbles()
|
self.updateBubbles()
|
||||||
|
self.updateDimming()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user