Wallpaper improvements

This commit is contained in:
Ilya Laktyushin 2023-04-03 21:01:16 +04:00
parent f158b8fa79
commit 3bf5ad9f8a
12 changed files with 295 additions and 90 deletions

View File

@ -9123,6 +9123,9 @@ Sorry for the inconvenience.";
"Notification.YouChangedWallpaper" = "You set a new background for this chat";
"Notification.Wallpaper.View" = "View Background";
"Notification.ChangedToSameWallpaper" = "%1$@ set the same background for this chat";
"Notification.YouChangedToSameWallpaper" = "You set the same background for this chat";
"Channel.AdminLog.JoinedViaFolderInviteLink" = "%1$@ joined via invite link %2$@ (community)";
"Conversation.OpenChatFolder" = "VIEW CHAT LIST";

View File

@ -308,7 +308,7 @@ func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: WallpaperGall
completion()
}
let _ = uploadWallpaper(account: context.account, resource: resource, settings: WallpaperSettings(blur: false, motion: mode.contains(.motion), colors: [], intensity: nil)).start(next: { status in
let _ = uploadWallpaper(account: context.account, resource: resource, settings: WallpaperSettings(blur: false, motion: mode.contains(.motion), colors: [], intensity: nil), forChat: true).start(next: { status in
if case let .complete(wallpaper) = status {
if case let .file(file) = wallpaper {
context.account.postbox.mediaBox.copyResourceData(from: resource.id, to: file.file.resource.id, synchronous: true)

View File

@ -95,18 +95,14 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
private let blurredNode: BlurredImageNode
let cropNode: WallpaperCropNode
private let cancelButtonBackgroundNode: NavigationBackgroundNode
private var cancelButtonNode: HighlightableButtonNode
private let shareButtonBackgroundNode: NavigationBackgroundNode
private var shareButtonNode: HighlightableButtonNode
private var cancelButtonNode: WallpaperNavigationButtonNode
private var shareButtonNode: WallpaperNavigationButtonNode
private var blurButtonNode: WallpaperOptionButtonNode
private var motionButtonNode: WallpaperOptionButtonNode
private var patternButtonNode: WallpaperOptionButtonNode
private var colorsButtonNode: WallpaperOptionButtonNode
private var playButtonNode: HighlightableButtonNode
private let playButtonBackgroundNode: NavigationBackgroundNode
private var playButtonNode: WallpaperNavigationButtonNode
private let messagesContainerNode: ASDisplayNode
private var messageNodes: [ListViewItemNode]?
@ -163,20 +159,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
self.colorsButtonNode = WallpaperOptionButtonNode(title: self.presentationData.strings.WallpaperPreview_WallpaperColors, value: .colors(false, [.clear]))
self.cancelButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(white: 0.0, alpha: 0.3))
self.cancelButtonNode = HighlightableButtonNode()
self.cancelButtonNode.insertSubnode(self.cancelButtonBackgroundNode, at: 0)
self.cancelButtonNode.setAttributedTitle(NSAttributedString(string: self.presentationData.strings.Common_Cancel, font: Font.semibold(15.0), textColor: .white), for: .normal)
self.cancelButtonNode.titleNode.textShadowColor = UIColor(rgb: 0x000000, alpha: 0.1)
self.shareButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(white: 0.0, alpha: 0.3))
self.shareButtonNode = HighlightableButtonNode()
self.shareButtonNode.insertSubnode(self.shareButtonBackgroundNode, at: 0)
self.shareButtonNode.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Share"), color: .white), for: .normal)
self.playButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(white: 0.0, alpha: 0.3))
self.playButtonNode = HighlightableButtonNode()
self.playButtonNode.insertSubnode(self.playButtonBackgroundNode, at: 0)
self.cancelButtonNode = WallpaperNavigationButtonNode(content: .text(self.presentationData.strings.Common_Cancel))
self.shareButtonNode = WallpaperNavigationButtonNode(content: .icon(image: UIImage(bundleImageName: "Chat/Links/Share"), size: CGSize(width: 28.0, height: 28.0)))
self.playButtonPlayImage = generateImage(CGSize(width: 48.0, height: 48.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
@ -205,7 +189,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
self.playButtonRotateImage = generateTintedImage(image: UIImage(bundleImageName: "Settings/ThemeColorRotateIcon"), color: .white)
self.playButtonNode.setImage(self.playButtonPlayImage, for: [])
self.playButtonNode = WallpaperNavigationButtonNode(content: .icon(image: self.playButtonPlayImage, size: CGSize(width: 48.0, height: 48.0)))
super.init()
@ -245,7 +229,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
self.colorsButtonNode.addTarget(self, action: #selector(self.toggleColors), forControlEvents: .touchUpInside)
self.playButtonNode.addTarget(self, action: #selector(self.togglePlay), forControlEvents: .touchUpInside)
self.cancelButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
self.shareButtonNode.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside)
self.shareButtonNode.addTarget(self, action: #selector(self.actionPressed), forControlEvents: .touchUpInside)
}
deinit {
@ -331,9 +315,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
self.patternButtonNode.isSelected = file.isPattern
if file.isPattern && file.settings.colors.count >= 3 {
self.playButtonNode.setImage(self.playButtonPlayImage, for: [])
self.playButtonNode.setIcon(self.playButtonPlayImage)
} else {
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
self.playButtonNode.setIcon(self.playButtonRotateImage)
}
} else if case let .gradient(gradient) = wallpaper {
self.nativeNode.isHidden = false
@ -341,9 +325,9 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
self.patternButtonNode.isSelected = false
if gradient.colors.count >= 3 {
self.playButtonNode.setImage(self.playButtonPlayImage, for: [])
self.playButtonNode.setIcon(self.playButtonPlayImage)
} else {
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
self.playButtonNode.setIcon(self.playButtonRotateImage)
}
} else if case .color = wallpaper {
self.nativeNode.isHidden = false
@ -352,19 +336,20 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
} else {
self.nativeNode.isHidden = true
self.patternButtonNode.isSelected = false
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
self.playButtonNode.setIcon(self.playButtonRotateImage)
}
case .asset:
self.nativeNode._internalUpdateIsSettingUpWallpaper()
self.nativeNode.isHidden = true
self.patternButtonNode.isSelected = false
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
self.playButtonNode.setIcon(self.playButtonRotateImage)
default:
self.nativeNode.isHidden = true
self.patternButtonNode.isSelected = false
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
self.playButtonNode.setIcon(self.playButtonRotateImage)
}
var canShare = false
switch entry {
case let .wallpaper(wallpaper, message):
self.initialWallpaper = wallpaper
@ -389,6 +374,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
actionSignal = .single(defaultAction)
colorSignal = chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: self.context.account.postbox.mediaBox)
isBlurrable = false
canShare = true
case .gradient:
displaySize = CGSize(width: 1.0, height: 1.0)
contentSize = displaySize
@ -399,6 +385,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
actionSignal = .single(defaultAction)
colorSignal = chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: self.context.account.postbox.mediaBox)
isBlurrable = false
canShare = true
case let .file(file):
let dimensions = file.file.dimensions ?? PixelDimensions(width: 2000, height: 4000)
contentSize = dimensions.cgSize
@ -467,6 +454,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
actionSignal = .single(nil)
} else {
actionSignal = .single(defaultAction)
canShare = true
}
colorSignal = .single(UIColor(rgb: 0x000000, alpha: 0.3))
case let .image(representations, _):
@ -590,6 +578,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
}
self.contentSize = contentSize
self.shareButtonNode.isHidden = !canShare
if self.cropNode.supernode == nil {
self.imageNode.contentMode = .scaleAspectFill
self.wrapperNode.addSubnode(self.imageNode)
@ -656,16 +646,6 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
strongSelf.blurButtonNode.buttonColor = color
strongSelf.motionButtonNode.buttonColor = color
strongSelf.colorsButtonNode.buttonColor = color
if color == UIColor(rgb: 0x000000, alpha: 0.3) {
strongSelf.playButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
strongSelf.cancelButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
strongSelf.shareButtonBackgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
} else {
strongSelf.playButtonBackgroundNode.updateColor(color: color, transition: .immediate)
strongSelf.cancelButtonBackgroundNode.updateColor(color: color, transition: .immediate)
strongSelf.shareButtonBackgroundNode.updateColor(color: color, transition: .immediate)
}
}))
} else if self.arguments.patternEnabled != previousArguments.patternEnabled {
self.patternButtonNode.isSelected = self.arguments.patternEnabled
@ -959,9 +939,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let playFrame = CGRect(origin: CGPoint(x: centerButtonFrame.midX - playButtonSize.width / 2.0, y: centerButtonFrame.midY - playButtonSize.height / 2.0), size: playButtonSize)
var playAlpha: CGFloat = 0.0
var cancelSize = self.cancelButtonNode.measure(layout.size)
cancelSize.width += 16.0
cancelSize.height = 28.0
let cancelSize = self.cancelButtonNode.measure(layout.size)
let cancelFrame = CGRect(origin: CGPoint(x: 16.0 + offset.x, y: 16.0), size: cancelSize)
let shareFrame = CGRect(origin: CGPoint(x: layout.size.width - 16.0 - 28.0 + offset.x, y: 16.0), size: CGSize(width: 28.0, height: 28.0))
@ -1061,18 +1039,11 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
transition.updateAlpha(node: self.colorsButtonNode, alpha: colorsAlpha * alpha)
transition.updateFrame(node: self.playButtonNode, frame: playFrame)
transition.updateFrame(node: self.playButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: playFrame.size))
self.playButtonBackgroundNode.update(size: playFrame.size, cornerRadius: playFrame.size.height / 2.0, transition: transition)
transition.updateAlpha(node: self.playButtonNode, alpha: playAlpha * alpha)
transition.updateSublayerTransformScale(node: self.playButtonNode, scale: max(0.1, playAlpha))
transition.updateFrame(node: self.cancelButtonNode, frame: cancelFrame)
transition.updateFrame(node: self.cancelButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: cancelFrame.size))
self.cancelButtonBackgroundNode.update(size: cancelFrame.size, cornerRadius: cancelFrame.size.height / 2.0, transition: transition)
transition.updateFrame(node: self.shareButtonNode, frame: shareFrame)
transition.updateFrame(node: self.shareButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: shareFrame.size))
self.shareButtonBackgroundNode.update(size: shareFrame.size, cornerRadius: shareFrame.size.height / 2.0, transition: transition)
}
private func updateMessagesLayout(layout: ContainerViewLayout, offset: CGPoint, transition: ContainedViewLayoutTransition) {

View File

@ -34,8 +34,10 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
private let doneButton = HighlightTrackingButtonNode()
private let doneButtonBackgroundNode: NavigationBackgroundNode
private let doneButtonBackgroundView: UIVisualEffectView
private let doneButtonTitleNode: ImmediateTextNode
private let doneButtonVibrancyView: UIVisualEffectView
private let doneButtonVibrancyTitleNode: ImmediateTextNode
private let doneButtonSolidBackgroundNode: ASDisplayNode
private let doneButtonSolidTitleNode: ImmediateTextNode
@ -49,26 +51,25 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
self.cancelButtonType = cancelButtonType
self.doneButtonType = doneButtonType
self.doneButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55))
self.doneButtonBackgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0xf2f2f2, alpha: 0.75))
self.doneButtonBackgroundNode.cornerRadius = 14.0
let blurEffect: UIBlurEffect
if #available(iOS 13.0, *) {
blurEffect = UIBlurEffect(style: .systemUltraThinMaterialLight)
blurEffect = UIBlurEffect(style: .extraLight)
} else {
blurEffect = UIBlurEffect(style: .light)
}
self.doneButtonBackgroundView = UIVisualEffectView(effect: blurEffect)
self.doneButtonBackgroundView.clipsToBounds = true
self.doneButtonBackgroundView.layer.cornerRadius = 14.0
self.doneButtonBackgroundView.isUserInteractionEnabled = false
self.doneButtonVibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
self.doneButtonTitleNode = ImmediateTextNode()
self.doneButtonTitleNode.displaysAsynchronously = false
self.doneButtonTitleNode.textShadowColor = UIColor(rgb: 0x000000, alpha: 0.1)
self.doneButtonTitleNode.isUserInteractionEnabled = false
self.doneButtonVibrancyTitleNode = ImmediateTextNode()
self.doneButtonVibrancyTitleNode.displaysAsynchronously = false
self.doneButtonVibrancyTitleNode.isUserInteractionEnabled = false
self.doneButtonSolidBackgroundNode = ASDisplayNode()
self.doneButtonSolidBackgroundNode.alpha = 0.0
self.doneButtonSolidBackgroundNode.clipsToBounds = true
@ -86,7 +87,9 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
super.init()
self.addSubnode(self.doneButtonBackgroundNode)
self.addSubnode(self.doneButtonTitleNode)
self.doneButtonVibrancyView.contentView.addSubnode(self.doneButtonVibrancyTitleNode)
self.doneButtonBackgroundNode.view.addSubview(self.doneButtonVibrancyView)
self.doneButtonBackgroundNode.addSubnode(self.doneButtonTitleNode)
self.addSubnode(self.doneButtonSolidBackgroundNode)
self.addSubnode(self.doneButtonSolidTitleNode)
@ -106,8 +109,8 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
} else {
strongSelf.doneButtonBackgroundNode.layer.removeAnimation(forKey: "opacity")
strongSelf.doneButtonBackgroundNode.alpha = 0.55
strongSelf.doneButtonTitleNode.layer.removeAnimation(forKey: "opacity")
strongSelf.doneButtonTitleNode.alpha = 0.55
strongSelf.doneButtonVibrancyTitleNode.layer.removeAnimation(forKey: "opacity")
strongSelf.doneButtonVibrancyTitleNode.alpha = 0.55
}
} else {
if strongSelf.isSolid {
@ -118,8 +121,8 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
} else {
strongSelf.doneButtonBackgroundNode.alpha = 1.0
strongSelf.doneButtonBackgroundNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
strongSelf.doneButtonTitleNode.alpha = 1.0
strongSelf.doneButtonTitleNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
strongSelf.doneButtonVibrancyTitleNode.alpha = 1.0
strongSelf.doneButtonVibrancyTitleNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
}
}
}
@ -143,6 +146,7 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
transition.updateAlpha(node: self.doneButtonBackgroundNode, alpha: isSolid ? 0.0 : 1.0)
transition.updateAlpha(node: self.doneButtonSolidBackgroundNode, alpha: isSolid ? 1.0 : 0.0)
transition.updateAlpha(node: self.doneButtonTitleNode, alpha: isSolid ? 0.0 : 1.0)
transition.updateAlpha(node: self.doneButtonVibrancyTitleNode, alpha: isSolid ? 0.0 : 1.0)
transition.updateAlpha(node: self.doneButtonSolidTitleNode, alpha: isSolid ? 1.0 : 0.0)
}
@ -163,7 +167,8 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
doneTitle = ""
self.doneButton.isUserInteractionEnabled = false
}
self.doneButtonTitleNode.attributedText = NSAttributedString(string: doneTitle, font: Font.semibold(17.0), textColor: .white)
self.doneButtonTitleNode.attributedText = NSAttributedString(string: doneTitle, font: Font.semibold(17.0), textColor: UIColor(rgb: 0x000000, alpha: 0.25))
self.doneButtonVibrancyTitleNode.attributedText = NSAttributedString(string: doneTitle, font: Font.semibold(17.0), textColor: .white)
self.doneButtonSolidBackgroundNode.backgroundColor = theme.list.itemCheckColors.fillColor
self.doneButtonSolidTitleNode.attributedText = NSAttributedString(string: doneTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor)
@ -177,16 +182,17 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode {
self.doneButton.frame = doneFrame
self.doneButtonBackgroundNode.frame = doneFrame
self.doneButtonBackgroundNode.update(size: doneFrame.size, cornerRadius: 14.0, transition: transition)
self.doneButtonBackgroundView.frame = doneFrame
self.doneButtonVibrancyView.frame = self.doneButtonBackgroundNode.bounds
self.doneButtonSolidBackgroundNode.frame = doneFrame
let doneTitleSize = self.doneButtonTitleNode.updateLayout(doneFrame.size)
self.doneButtonTitleNode.frame = CGRect(origin: CGPoint(x: doneFrame.minX + floorToScreenPixels((doneFrame.width - doneTitleSize.width) / 2.0), y: doneFrame.minY + floorToScreenPixels((doneFrame.height - doneTitleSize.height) / 2.0)), size: doneTitleSize)
self.doneButtonTitleNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((doneFrame.width - doneTitleSize.width) / 2.0), y: floorToScreenPixels((doneFrame.height - doneTitleSize.height) / 2.0)), size: doneTitleSize)
let _ = self.doneButtonVibrancyTitleNode.updateLayout(doneFrame.size)
self.doneButtonVibrancyTitleNode.frame = self.doneButtonTitleNode.frame
let _ = self.doneButtonSolidTitleNode.updateLayout(doneFrame.size)
self.doneButtonSolidTitleNode.frame = self.doneButtonTitleNode.frame
self.doneButtonSolidTitleNode.frame = self.doneButtonTitleNode.frame.offsetBy(dx: doneFrame.minX, dy: doneFrame.minY)
}
@objc func cancelPressed() {

View File

@ -34,11 +34,156 @@ private func generateColorsImage(diameter: CGFloat, colors: [UIColor]) -> UIImag
})
}
final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
enum Content {
case icon(image: UIImage?, size: CGSize)
case text(String)
}
private let content: Content
private let backgroundNode: NavigationBackgroundNode
private let vibrancyView: UIVisualEffectView
private let iconNode: ASImageNode
private let darkIconNode: ASImageNode
private let textNode: ImmediateTextNode
private let darkTextNode: ImmediateTextNode
func setIcon(_ image: UIImage?) {
self.iconNode.image = generateTintedImage(image: image, color: .white)
self.darkIconNode.image = generateTintedImage(image: image, color: UIColor(rgb: 0x000000, alpha: 0.25))
}
init(content: Content) {
self.content = content
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0xf2f2f2, alpha: 0.75))
self.backgroundNode.cornerRadius = 14.0
let blurEffect: UIBlurEffect
if #available(iOS 13.0, *) {
blurEffect = UIBlurEffect(style: .extraLight)
} else {
blurEffect = UIBlurEffect(style: .light)
}
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
self.iconNode = ASImageNode()
self.iconNode.displaysAsynchronously = false
self.iconNode.contentMode = .center
self.darkIconNode = ASImageNode()
self.darkIconNode.displaysAsynchronously = false
self.darkIconNode.contentMode = .center
var title: String
switch content {
case let .text(text):
title = text
self.backgroundNode.cornerRadius = 14.0
case let .icon(icon, size):
title = ""
self.backgroundNode.cornerRadius = size.height / 2.0
self.iconNode.image = generateTintedImage(image: icon, color: .white)
self.darkIconNode.image = generateTintedImage(image: icon, color: UIColor(rgb: 0x000000, alpha: 0.25))
}
self.textNode = ImmediateTextNode()
self.textNode.attributedText = NSAttributedString(string: title, font: Font.semibold(15.0), textColor: .white)
self.darkTextNode = ImmediateTextNode()
self.darkTextNode.attributedText = NSAttributedString(string: title, font: Font.semibold(15.0), textColor: UIColor(rgb: 0x000000, alpha: 0.25))
super.init()
self.addSubnode(self.backgroundNode)
self.vibrancyView.contentView.addSubnode(self.iconNode)
self.vibrancyView.contentView.addSubnode(self.textNode)
self.backgroundNode.view.addSubview(self.vibrancyView)
self.backgroundNode.addSubnode(self.darkIconNode)
self.backgroundNode.addSubnode(self.darkTextNode)
self.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
if highlighted {
strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity")
strongSelf.backgroundNode.alpha = 0.4
strongSelf.iconNode.layer.removeAnimation(forKey: "opacity")
strongSelf.iconNode.alpha = 0.4
strongSelf.textNode.layer.removeAnimation(forKey: "opacity")
strongSelf.textNode.alpha = 0.4
} else {
strongSelf.backgroundNode.alpha = 1.0
strongSelf.backgroundNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
strongSelf.iconNode.alpha = 1.0
strongSelf.iconNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
strongSelf.textNode.alpha = 1.0
strongSelf.textNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
}
}
}
}
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
didSet {
if self.buttonColor == UIColor(rgb: 0x000000, alpha: 0.3) {
self.backgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.75), transition: .immediate)
} else {
self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
}
}
}
private var textSize: CGSize?
override func measure(_ constrainedSize: CGSize) -> CGSize {
switch self.content {
case .text:
let size = self.textNode.updateLayout(constrainedSize)
let _ = self.darkTextNode.updateLayout(constrainedSize)
self.textSize = size
return CGSize(width: ceil(size.width) + 16.0, height: 28.0)
case let .icon(_, size):
return size
}
}
override func layout() {
super.layout()
let size = self.bounds.size
self.backgroundNode.frame = self.bounds
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: 14.0, transition: .immediate)
self.vibrancyView.frame = self.bounds
self.iconNode.frame = self.bounds
self.darkIconNode.frame = self.bounds
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.darkTextNode.frame = self.textNode.frame
}
}
}
final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
private let backgroundNode: NavigationBackgroundNode
private let vibrancyView: UIVisualEffectView
private let checkNode: CheckNode
private let darkCheckNode: CheckNode
private let colorNode: ASImageNode
private let textNode: ImmediateTextNode
private let darkTextNode: ImmediateTextNode
private var textSize: CGSize?
@ -60,12 +205,14 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
self._value = .colors(newValue, colors)
}
self.checkNode.setSelected(newValue, animated: false)
self.darkCheckNode.setSelected(newValue, animated: false)
}
}
var title: String {
didSet {
self.textNode.attributedText = NSAttributedString(string: title, font: Font.medium(13), textColor: .white)
self.darkTextNode.attributedText = NSAttributedString(string: title, font: Font.medium(13), textColor: UIColor(rgb: 0x000000, alpha: 0.25))
}
}
@ -76,36 +223,60 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0xffffff, alpha: 0.4))
self.backgroundNode.cornerRadius = 14.0
self.checkNode = CheckNode(theme: CheckNodeTheme(backgroundColor: .white, strokeColor: .clear, borderColor: .white, overlayBorder: false, hasInset: false, hasShadow: true, borderWidth: 1.5))
let blurEffect: UIBlurEffect
if #available(iOS 13.0, *) {
blurEffect = UIBlurEffect(style: .extraLight)
} else {
blurEffect = UIBlurEffect(style: .light)
}
self.vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blurEffect))
let darkColor = UIColor(rgb: 0x000000, alpha: 0.25)
self.checkNode = CheckNode(theme: CheckNodeTheme(backgroundColor: .white, strokeColor: .clear, borderColor: .white, overlayBorder: false, hasInset: false, hasShadow: false, borderWidth: 1.5))
self.checkNode.isUserInteractionEnabled = false
self.darkCheckNode = CheckNode(theme: CheckNodeTheme(backgroundColor: darkColor, strokeColor: .clear, borderColor: darkColor, overlayBorder: false, hasInset: false, hasShadow: false, borderWidth: 1.5))
self.darkCheckNode.isUserInteractionEnabled = false
self.colorNode = ASImageNode()
self.textNode = ImmediateTextNode()
self.textNode.displaysAsynchronously = false
self.textNode.attributedText = NSAttributedString(string: title, font: Font.medium(13), textColor: .white)
self.textNode.textShadowColor = UIColor(rgb: 0x000000, alpha: 0.1)
self.darkTextNode = ImmediateTextNode()
self.darkTextNode.displaysAsynchronously = false
self.darkTextNode.attributedText = NSAttributedString(string: title, font: Font.medium(13), textColor: UIColor(rgb: 0x000000, alpha: 0.25))
super.init()
switch value {
case let .check(selected):
self.checkNode.isHidden = false
self.darkCheckNode.isHidden = false
self.colorNode.isHidden = true
self.checkNode.selected = selected
self.darkCheckNode.selected = selected
case let .color(_, color):
self.checkNode.isHidden = true
self.darkCheckNode.isHidden = true
self.colorNode.isHidden = false
self.colorNode.image = generateFilledCircleImage(diameter: 18.0, color: color)
case let .colors(_, colors):
self.checkNode.isHidden = true
self.darkCheckNode.isHidden = true
self.colorNode.isHidden = false
self.colorNode.image = generateColorsImage(diameter: 18.0, colors: colors)
}
self.addSubnode(self.backgroundNode)
self.addSubnode(self.checkNode)
self.vibrancyView.contentView.addSubnode(self.checkNode)
self.vibrancyView.contentView.addSubnode(self.textNode)
self.backgroundNode.view.addSubview(self.vibrancyView)
self.addSubnode(self.darkCheckNode)
self.addSubnode(self.darkTextNode)
self.addSubnode(self.colorNode)
self.addSubnode(self.textNode)
self.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
@ -141,7 +312,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
didSet {
if self.buttonColor == UIColor(rgb: 0x000000, alpha: 0.3) {
self.backgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.55), transition: .immediate)
self.backgroundNode.updateColor(color: UIColor(rgb: 0xf2f2f2, alpha: 0.75), transition: .immediate)
} else {
self.backgroundNode.updateColor(color: self.buttonColor, transition: .immediate)
}
@ -214,6 +385,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
self._value = .colors(selected, colors)
}
self.checkNode.setSelected(selected, animated: animated)
self.darkCheckNode.setSelected(selected, animated: animated)
}
func setEnabled(_ enabled: Bool) {
@ -227,6 +399,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
override func measure(_ constrainedSize: CGSize) -> CGSize {
let size = self.textNode.updateLayout(constrainedSize)
let _ = self.darkTextNode.updateLayout(constrainedSize)
self.textSize = size
return CGSize(width: ceil(size.width) + 48.0, height: 30.0)
}
@ -236,6 +409,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
self.backgroundNode.frame = self.bounds
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: 15.0, transition: .immediate)
self.vibrancyView.frame = self.bounds
guard let _ = self.textSize else {
return
@ -244,12 +418,14 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
let padding: CGFloat = 6.0
let spacing: CGFloat = 9.0
let checkSize = CGSize(width: 18.0, height: 18.0)
self.checkNode.frame = CGRect(origin: CGPoint(x: padding, y: padding), size: checkSize)
self.colorNode.frame = CGRect(origin: CGPoint(x: padding, y: padding), size: checkSize)
let checkFrame = CGRect(origin: CGPoint(x: padding, y: padding), size: checkSize)
self.checkNode.frame = checkFrame
self.darkCheckNode.frame = checkFrame
self.colorNode.frame = checkFrame
if let textSize = self.textSize {
self.textNode.frame = CGRect(x: max(padding + checkSize.width + spacing, padding + checkSize.width + floor((self.bounds.width - padding - checkSize.width - textSize.width) / 2.0) - 2.0), y: 6.0 + UIScreenPixel, width: textSize.width, height: textSize.height)
self.textNode.frame = CGRect(x: max(padding + checkSize.width + spacing, padding + checkSize.width + floor((self.bounds.width - padding - checkSize.width - textSize.width) / 2.0) - 2.0), y: floorToScreenPixels((self.bounds.height - textSize.height) / 2.0), width: textSize.width, height: textSize.height)
self.darkTextNode.frame = self.textNode.frame
}
}
}

View File

@ -419,12 +419,16 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
func didAppear(initialWallpaper: TelegramWallpaper? = nil, intensity: Int32? = nil) {
let wallpaper: TelegramWallpaper?
switch initialWallpaper {
case var .file(file):
file.settings = self.wallpapers[0].settings ?? WallpaperSettings()
wallpaper = .file(file)
default:
wallpaper = self.wallpapers.first
if self.wallpapers.isEmpty {
wallpaper = nil
} else {
switch initialWallpaper {
case var .file(file):
file.settings = self.wallpapers[0].settings ?? WallpaperSettings()
wallpaper = .file(file)
default:
wallpaper = self.wallpapers.first
}
}
if let wallpaper = wallpaper {

View File

@ -102,6 +102,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case attachMenuBotAllowed
case requestedPeer(buttonId: Int32, peerId: PeerId)
case setChatWallpaper(wallpaper: TelegramWallpaper)
case setSameChatWallpaper
public init(decoder: PostboxDecoder) {
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
@ -188,6 +189,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
self = .unknown
}
case 34:
self = .setSameChatWallpaper
default:
self = .unknown
}
@ -352,6 +355,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case let .setChatWallpaper(wallpaper):
encoder.encodeInt32(33, forKey: "_rawValue")
encoder.encode(TelegramWallpaperNativeCodable(wallpaper), forKey: "wallpaper")
case .setSameChatWallpaper:
encoder.encodeInt32(34, forKey: "_rawValue")
}
}

View File

@ -152,3 +152,28 @@ func _internal_setChatWallpaper(account: Account, peerId: PeerId, wallpaper: Tel
} |> switchToLatest
}
}
public enum SetExistingChatWallpaperError {
case generic
}
func _internal_setExistingChatWallpaper(account: Account, messageId: MessageId) -> Signal<Void, SetExistingChatWallpaperError> {
return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(messageId.peerId)
}
|> castError(SetExistingChatWallpaperError.self)
|> mapToSignal { peer -> Signal<Void, SetExistingChatWallpaperError> in
guard let peer = peer, let inputPeer = apiInputPeer(peer) else {
return .complete()
}
let flags: Int32 = 1 << 1
return account.network.request(Api.functions.messages.setChatWallPaper(flags: flags, peer: inputPeer, wallpaper: nil, settings: nil, id: messageId.id))
|> `catch` { _ -> Signal<Api.Updates, SetExistingChatWallpaperError> in
return .fail(.generic)
}
|> mapToSignal { updates -> Signal<Void, SetExistingChatWallpaperError> in
account.stateManager.addUpdates(updates)
return .complete()
}
}
}

View File

@ -20,5 +20,9 @@ public extension TelegramEngine {
public func setChatWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?) -> Signal<Void, NoError> {
return _internal_setChatWallpaper(account: self.account, peerId: peerId, wallpaper: wallpaper)
}
public func setExistingChatWallpaper(messageId: MessageId) -> Signal<Void, SetExistingChatWallpaperError> {
return _internal_setExistingChatWallpaper(account: self.account, messageId: messageId)
}
}
}

View File

@ -118,7 +118,7 @@ private func uploadedWallpaper(postbox: Postbox, network: Network, resource: Med
}
}
public func uploadWallpaper(account: Account, resource: MediaResource, mimeType: String = "image/jpeg", settings: WallpaperSettings) -> Signal<UploadWallpaperStatus, UploadWallpaperError> {
public func uploadWallpaper(account: Account, resource: MediaResource, mimeType: String = "image/jpeg", settings: WallpaperSettings, forChat: Bool) -> Signal<UploadWallpaperStatus, UploadWallpaperError> {
return uploadedWallpaper(postbox: account.postbox, network: account.network, resource: resource)
|> mapError { _ -> UploadWallpaperError in }
|> mapToSignal { result -> Signal<(UploadWallpaperStatus, MediaResource?), UploadWallpaperError> in
@ -130,7 +130,11 @@ public func uploadWallpaper(account: Account, resource: MediaResource, mimeType:
case let .progress(progress):
return .single((.progress(progress), result.resource))
case let .inputFile(file):
return account.network.request(Api.functions.account.uploadWallPaper(flags: 0, file: file, mimeType: mimeType, settings: apiWallpaperSettings(settings)))
var flags: Int32 = 0
if forChat {
flags |= 1 << 0
}
return account.network.request(Api.functions.account.uploadWallPaper(flags: flags, file: file, mimeType: mimeType, settings: apiWallpaperSettings(settings)))
|> mapError { _ in return UploadWallpaperError.generic }
|> map { wallpaper -> (UploadWallpaperStatus, MediaResource?) in
return (.complete(TelegramWallpaper(apiWallpaper: wallpaper)), result.resource)

View File

@ -880,6 +880,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
let resultTitleString = strings.Notification_ChangedWallpaper(authorName)
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
}
case .setSameChatWallpaper:
if message.author?.id == accountPeerId {
attributedString = NSAttributedString(string: strings.Notification_YouChangedToSameWallpaper, font: titleFont, textColor: primaryTextColor)
} else {
let resultTitleString = strings.Notification_ChangedToSameWallpaper(authorName)
attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
}
case .unknown:
attributedString = nil
}

View File

@ -90,7 +90,7 @@ final class WallpaperUploadManagerImpl: WallpaperUploadManager {
let sharedContext = self.sharedContext
let account = self.account
let uploadSignal = uploadWallpaper(account: account, resource: currentResource, settings: currentWallpaper.settings ?? WallpaperSettings())
let uploadSignal = uploadWallpaper(account: account, resource: currentResource, settings: currentWallpaper.settings ?? WallpaperSettings(), forChat: false)
|> map { result -> UploadWallpaperStatus in
switch result {
case let .complete(wallpaper):