From ce97e49ed7a8babb95a9877708d8ddb5a0c840ee Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Aug 2021 00:46:30 +0400 Subject: [PATCH 01/10] Various theme editing imrpovements --- .../Telegram-iOS/en.lproj/Localizable.strings | 38 +++ .../Themes/ThemeAccentColorController.swift | 12 +- .../ThemeAccentColorControllerNode.swift | 233 ++++++++++++------ .../Themes/WallpaperColorPanelNode.swift | 37 +-- .../Themes/WallpaperGalleryController.swift | 2 +- .../Themes/WallpaperOptionButtonNode.swift | 7 + .../TelegramCore/Sources/ApiUtils/Theme.swift | 8 +- .../SyncCore/SyncCore_TelegramTheme.swift | 9 +- .../DefaultDarkPresentationTheme.swift | 6 +- .../DefaultDarkTintedPresentationTheme.swift | 4 +- .../Sources/DefaultDayPresentationTheme.swift | 4 +- .../Sources/MakePresentationTheme.swift | 20 +- .../Sources/PresentationTheme.swift | 8 +- .../Sources/PresentationThemeCodable.swift | 2 + .../Sources/WallpaperBackgroundNode.swift | 2 +- 15 files changed, 251 insertions(+), 141 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index fa105398a0..abff60c6e0 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -6608,3 +6608,41 @@ Sorry for the inconvenience."; "Conversation.ForwardOptions.Messages_0" = "%@ messages"; "Conversation.ForwardOptions.You" = "You (senders' names hidden)"; + +"Activity.ChoosingSticker" = "choosing sticker"; +"WallpaperPreview.Animate" = "Animate"; +"WallpaperPreview.AnimateDescription" = "Colors will move when you send messages"; + + +"Appstore.Cloud" = "**Cloud-based**\nUnlimited storage for chats,\nmedia and documents."; +"Appstore.Cloud.Profile" = "**Jennifer**\n23 y.o. designer from San Francisco."; +"Appstore.Creative" = "**Creative**\nColor themes, stickers, GIFs,\nvideo messages and more."; +"Appstore.Creative.Chat" = "**You**\nSend a dice emoji to roll a die!\n**You**\nAdvance to Illinois Ave. If you pass Go, collect coffee\n**Gabriella**\nPassed!\n**You**\nOkay\nWait for me there."; +"Appstore.Creative.Chat.Name" = "**Gabriella**"; +"Appstore.Fast" = "**Fast**\nSimple, reliable and synced\nacross all your devices."; +"Appstore.Fast.Chat1" = "**Alicia Torreaux**\nBob says hi."; +"Appstore.Fast.Chat2" = "**Roberto**\nSay hello to Alice."; +"Appstore.Fast.Chat3" = "**Digital Nomads**\nJennie\nWe just reached 2,500 members! WOO!"; +"Appstore.Fast.Chat4" = "**Veronica**\nTable for four, 2 PM. Be there."; +"Appstore.Fast.Chat5" = "**Animal Videos**\nVote now! Moar cat videos in this channel?"; +"Appstore.Fast.Chat6" = "**Little Sister**\nDon't tell mom yet, but I got the job! I'm going to ROME!"; +"Appstore.Fast.Chat7" = "**James**\nCheck these out"; +"Appstore.Fast.Chat8" = "**Study Group**\nEmma\nSticker"; +"Appstore.Fast.Chat9" = "**Digital Nomads**"; +"Appstore.Free.Chat" = "**Jessica**\nPaper airplane is lyfted by...\nWings\nPropeller\n**You**\nIs this from Monday’s test?\n**Harry**\nOnlinePartyPlan.ppd\nLet's get back to planning!\n**You**\n550 MB keynote file??\n**Helene**\nHe added fireworks videos"; +"Appstore.Free.Chat.Name" = "**Study Group**"; +"Appstore.Open" = "**Open**\nNo ads, no fees. Open source\ncode free for everyone."; +"Appstore.Powerful" = "**Powerful**\nNo limits on the size of\ngroups and broadcasts."; +"Appstore.Powerful.Chat" = "**James**\nGood morning!\n\nDwayne joined the group\n\n**You**\nDo you have any idea what time it is?\n**Roxanne**\nIs it still morning?\nSure!\nNot sure\n**Emma**\nVoice"; +"Appstore.Private" = "**Private**\nYour data is never disclosed.\nOnly you are in control."; +"Appstore.Private.Chat" = "**You**\nNo limits on the size of your cats."; +"Appstore.Private.Chat.Name" = "**Beatrice**"; +"Appstore.Public" = "**Public**\nPublic channels, open groups,\nbots for integrations."; +"Appstore.Public.Chat1" = "**Financial Times**\nTruth is like the sun. You can shut it out for a time, but it ain’t goin’ away."; +"Appstore.Public.Chat2" = "**Bloomberg**\nWe'll be sending you a few big stories daily, which you can expect to start..."; +"Appstore.Public.Chat3" = "**Health and Safety**\nIf you're looking for official news about the Novel Coronavirus and COVID-19"; +"Appstore.Public.IV" = "We now have enough data to measure the relative effectiveness of major climate solutions. This simulator lets you see which ones would work best.\n\nBloomberg\n\nThe Best Way to Slow Global Warming? You Decide in This Climate Simulator\nIt was on Earth Day 2016 when more than 170 nations signed the Paris Agreement calling for limiting global warming \"to well below 2°C\"."; +"Appstore.Secure" = "**Secure**\nAll chats are protected\nwith strong encryption."; +"Appstore.Secure.Chat" = "**Little Sister**\nAny gift ideas for mom?\n**You**A dog!\n**You**I'm serious. Let's get her a puppy. \n**You**\nI saw this!\n**Little Sister**\nI needed proof this was your idea!"; +"Appstore.Secure.Chat.Name" = "**Little Sister**"; + diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 627794a1a0..1c6ad0ad5e 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -14,8 +14,8 @@ import MediaResources private let randomBackgroundColors: [Int32] = [0x007aff, 0x00c2ed, 0x29b327, 0xeb6ca4, 0xf08200, 0x9472ee, 0xd33213, 0xedb400, 0x6d839e] extension TelegramThemeSettings { - convenience init(baseTheme: TelegramBaseTheme, accentColor: UIColor, messageColors: [UInt32], wallpaper: TelegramWallpaper?) { - self.init(baseTheme: baseTheme, accentColor: accentColor.argb, messageColors: messageColors, wallpaper: wallpaper) + convenience init(baseTheme: TelegramBaseTheme, accentColor: UIColor, messageColors: [UInt32], animateMessageColors: Bool, wallpaper: TelegramWallpaper?) { + self.init(baseTheme: baseTheme, accentColor: accentColor.argb, messageColors: messageColors, animateMessageColors: animateMessageColors, wallpaper: wallpaper) } } @@ -203,11 +203,11 @@ final class ThemeAccentColorController: ViewController { if let themeReference = generalThemeReference { updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: state.accentColor.color, backgroundColors: state.backgroundColors.map { $0.rgb }, bubbleColors: state.messagesColors.map { $0.rgb }, wallpaper: coloredWallpaper ?? state.initialWallpaper, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme } else { - updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: state.accentColor.color, backgroundColors: state.backgroundColors.map { $0.rgb }, bubbleColors: state.messagesColors.map { $0.rgb }, wallpaper: state.initialWallpaper ?? coloredWallpaper) + updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: state.accentColor.color, backgroundColors: state.backgroundColors.map { $0.rgb }, bubbleColors: state.messagesColors.map { $0.rgb }, animateBubbleColors: state.animateMessageColors, wallpaper: state.initialWallpaper ?? coloredWallpaper) } if hasSettings, let baseTheme = baseTheme { - settings = TelegramThemeSettings(baseTheme: baseTheme, accentColor: state.accentColor.color, messageColors: state.messagesColors.map { $0.rgb }, wallpaper: coloredWallpaper) + settings = TelegramThemeSettings(baseTheme: baseTheme, accentColor: state.accentColor.color, messageColors: state.messagesColors.map { $0.rgb }, animateMessageColors: state.animateMessageColors, wallpaper: coloredWallpaper) } completion(updatedTheme, settings) @@ -226,7 +226,7 @@ final class ThemeAccentColorController: ViewController { let wallpaper = coloredWallpaper ?? state.initialWallpaper - let settings = TelegramThemeSettings(baseTheme: baseTheme, accentColor: state.accentColor.rgb, messageColors: state.messagesColors.map { $0.rgb }, wallpaper: wallpaper) + let settings = TelegramThemeSettings(baseTheme: baseTheme, accentColor: state.accentColor.rgb, messageColors: state.messagesColors.map { $0.rgb }, animateMessageColors: state.animateMessageColors, wallpaper: wallpaper) let baseThemeReference = PresentationThemeReference.builtin(PresentationBuiltinThemeReference(baseTheme: baseTheme)) let apply: Signal @@ -552,7 +552,7 @@ final class ThemeAccentColorController: ViewController { messageColors = [] } - let initialState = ThemeColorState(section: strongSelf.section, accentColor: HSBColor(color: accentColor), initialWallpaper: initialWallpaper, backgroundColors: backgroundColors.map { HSBColor(rgb: $0) }, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, defaultMessagesColor: defaultMessagesColor.flatMap { HSBColor(color: $0) }, messagesColors: messageColors.map { HSBColor(rgb: $0) }, rotation: rotation) + let initialState = ThemeColorState(section: strongSelf.section, accentColor: HSBColor(color: accentColor), initialWallpaper: initialWallpaper, backgroundColors: backgroundColors.map { HSBColor(rgb: $0) }, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, animateMessageColors: false, defaultMessagesColor: defaultMessagesColor.flatMap { HSBColor(color: $0) }, messagesColors: messageColors.map { HSBColor(rgb: $0) }, selectedColor: 0, rotation: rotation) strongSelf.controllerNode.updateState({ _ in return initialState diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 192d23aca3..9f10567e80 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -48,9 +48,12 @@ struct ThemeColorState { var patternWallpaper: TelegramWallpaper? var patternIntensity: Int32 + var animateMessageColors: Bool var defaultMessagesColor: HSBColor? var messagesColors: [HSBColor] + var selectedColor: Int + var rotation: Int32 init() { @@ -64,12 +67,14 @@ struct ThemeColorState { self.previousPatternWallpaper = nil self.patternWallpaper = nil self.patternIntensity = 50 + self.animateMessageColors = false self.defaultMessagesColor = nil self.messagesColors = [] + self.selectedColor = 0 self.rotation = 0 } - init(section: ThemeColorSection, accentColor: HSBColor, initialWallpaper: TelegramWallpaper?, backgroundColors: [HSBColor], patternWallpaper: TelegramWallpaper?, patternIntensity: Int32, defaultMessagesColor: HSBColor?, messagesColors: [HSBColor], rotation: Int32 = 0) { + init(section: ThemeColorSection, accentColor: HSBColor, initialWallpaper: TelegramWallpaper?, backgroundColors: [HSBColor], patternWallpaper: TelegramWallpaper?, patternIntensity: Int32, animateMessageColors: Bool, defaultMessagesColor: HSBColor?, messagesColors: [HSBColor], selectedColor: Int = 0, rotation: Int32 = 0) { self.section = section self.colorPanelCollapsed = false self.displayPatternPanel = false @@ -80,8 +85,10 @@ struct ThemeColorState { self.previousPatternWallpaper = nil self.patternWallpaper = patternWallpaper self.patternIntensity = patternIntensity + self.animateMessageColors = animateMessageColors self.defaultMessagesColor = defaultMessagesColor self.messagesColors = messagesColors + self.selectedColor = selectedColor self.rotation = rotation } @@ -98,17 +105,21 @@ struct ThemeColorState { if self.patternIntensity != otherState.patternIntensity { return false } - if self.rotation != otherState.rotation { + if self.animateMessageColors != otherState.animateMessageColors { return false } if self.backgroundColors != otherState.backgroundColors { return false } - if self.messagesColors != otherState.messagesColors { return false } - + if self.selectedColor != otherState.selectedColor { + return false + } + if self.rotation != otherState.rotation { + return false + } return true } } @@ -324,7 +335,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate self.colorsButtonNode.addTarget(self, action: #selector(self.toggleColors), forControlEvents: .touchUpInside) self.playButtonNode.addTarget(self, action: #selector(self.playPressed), forControlEvents: .touchUpInside) - self.colorPanelNode.colorsChanged = { [weak self] colors, ended in + self.colorPanelNode.colorsChanged = { [weak self] colors, selectedColor, ended in if let strongSelf = self, let section = strongSelf.state.section { strongSelf.updateState({ current in var updated = current @@ -339,8 +350,9 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate case .messages: updated.messagesColors = colors } + updated.selectedColor = selectedColor return updated - }) + }, animated: true) } } @@ -472,9 +484,9 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate if !updateOnlyWallpaper { if let themeReference = mode.themeReference { - updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: accentColor.color, backgroundColors: backgroundColors.map { $0.rgb }, bubbleColors: messagesColors.map { $0.rgb }, serviceBackgroundColor: serviceBackgroundColor, preview: true) ?? defaultPresentationTheme + updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: accentColor.color, backgroundColors: backgroundColors.map { $0.rgb }, bubbleColors: messagesColors.map { $0.rgb }, animateBubbleColors: state.animateMessageColors, serviceBackgroundColor: serviceBackgroundColor, preview: true) ?? defaultPresentationTheme } else if case let .edit(theme, _, _, _, _, _) = mode { - updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: accentColor.color, backgroundColors: backgroundColors.map { $0.rgb }, bubbleColors: messagesColors.map { $0.rgb }) + updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: accentColor.color, backgroundColors: backgroundColors.map { $0.rgb }, bubbleColors: messagesColors.map { $0.rgb }, animateBubbleColors: state.animateMessageColors) } else { updatedTheme = theme } @@ -516,8 +528,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate strongSelf.wallpaper = wallpaper strongSelf.patternArguments = patternArguments - strongSelf.colorsButtonNode.colors = backgroundColors.map { $0.color } - if !preview { if !backgroundColors.isEmpty { strongSelf.currentBackgroundColors = (backgroundColors, strongSelf.state.rotation, strongSelf.state.patternIntensity) @@ -592,6 +602,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } } + private var crossfadeBubbles = false func updateState(_ f: (ThemeColorState) -> ThemeColorState, animated: Bool = false) { let previousState = self.state self.state = f(self.state) @@ -613,14 +624,24 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } } - if (previousState.patternWallpaper != nil) != (self.state.patternWallpaper != nil) { - self.patternButtonNode.setSelected(self.state.patternWallpaper != nil, animated: animated) + let sectionChanged = previousState.section != self.state.section + + if self.state.section == .background { + if (previousState.patternWallpaper != nil) != (self.state.patternWallpaper != nil) || sectionChanged { + self.patternButtonNode.setSelected(self.state.patternWallpaper != nil, animated: animated) + } + } else if self.state.section == .messages { + if previousState.animateMessageColors != self.state.animateMessageColors || sectionChanged { + self.crossfadeBubbles = true + self.patternButtonNode.setSelected(self.state.animateMessageColors, animated: animated) + } } - let sectionChanged = previousState.section != self.state.section if sectionChanged, let section = self.state.section { self.view.endEditing(true) + self.patternButtonNode.title = section == .messages ? self.presentationData.strings.WallpaperPreview_Animate : self.presentationData.strings.WallpaperPreview_Pattern + var colors: [HSBColor] var defaultColor: HSBColor? switch section { @@ -688,6 +709,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate needsLayout = true } + self.colorsButtonNode.colors = state.section == .messages ? state.messagesColors.map { $0.color } : state.backgroundColors.map { $0.color } + if previousState.colorPanelCollapsed != self.state.colorPanelCollapsed { animationCurve = .spring animationDuration = 0.45 @@ -730,12 +753,29 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate if (previousState.backgroundColors.count >= 2) != (self.state.backgroundColors.count >= 2) { needsLayout = true } + + if previousState.messagesColors.count != self.state.messagesColors.count { + needsLayout = true + } + + if previousState.selectedColor != self.state.selectedColor { + needsLayout = true + } - if previousState.backgroundColors.count != self.state.backgroundColors.count { - if self.state.backgroundColors.count <= 2 { - self.playButtonNode.setImage(self.playButtonRotateImage, for: []) - } else { - self.playButtonNode.setImage(self.playButtonPlayImage, for: []) + if let section = self.state.section { + switch section { + case .background: + if previousState.backgroundColors.count != self.state.backgroundColors.count { + if self.state.backgroundColors.count <= 2 { + self.playButtonNode.setImage(self.playButtonRotateImage, for: []) + } else { + self.playButtonNode.setImage(self.playButtonPlayImage, for: []) + } + } + case .accent: + break + case .messages: + self.playButtonNode.setImage(self.playButtonPlayImage, for: []) } } @@ -755,6 +795,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate updated.section = section updated.displayPatternPanel = false updated.colorPanelCollapsed = false + updated.selectedColor = 0 return updated }, animated: true) } @@ -884,22 +925,11 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } strongSelf.updateState({ state in var state = state - //if state.section == .background { - state.colorPanelCollapsed = true - state.displayPatternPanel = false - //} + state.colorPanelCollapsed = true + state.displayPatternPanel = false return state }, animated: true) - /*if message.flags.contains(.Incoming) { - self?.updateSection(.accent) - self?.requestSectionUpdate?(.accent) - } else { - self?.updateSection(.messages) - self?.requestSectionUpdate?(.messages) - }*/ - }, clickThroughMessage: { [weak self] in - self?.updateSection(.background) - self?.requestSectionUpdate?(.background) + }, clickThroughMessage: { }, backgroundNode: self.backgroundNode) return item } @@ -908,6 +938,18 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate if let messageNodes = self.messageNodes { for i in 0 ..< items.count { let itemNode = messageNodes[i] + + if self.crossfadeBubbles { + if let snapshot = itemNode.view.snapshotView(afterScreenUpdates: false) { + snapshot.frame = itemNode.bounds + itemNode.view.addSubview(snapshot) + + snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, completion: { [weak snapshot] _ in + snapshot?.removeFromSuperview() + }) + } + } + items[i].updateNode(async: { $0() }, node: { return itemNode }, params: params, previousItem: i == 0 ? nil : items[i - 1], nextItem: i == (items.count - 1) ? nil : items[i + 1], animation: .None, completion: { (layout, apply) in @@ -920,6 +962,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate apply(ListViewItemApply(isOnScreen: true)) }) } + self.crossfadeBubbles = false } else { var messageNodes: [ListViewItemNode] = [] for i in 0 ..< items.count { @@ -928,22 +971,30 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate itemNode = node apply().1(ListViewItemApply(isOnScreen: true)) }) - //itemNode!.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0) messageNodes.append(itemNode!) self.messagesContainerNode.addSubnode(itemNode!) } self.messageNodes = messageNodes } + let toolbarHeight = 49.0 + layout.intrinsicInsets.bottom + var relativeOffset: CGFloat = 0.0 + if !self.state.colorPanelCollapsed { + relativeOffset = (CGFloat(self.state.selectedColor) / CGFloat(max(1, self.state.messagesColors.count))) * (self.colorPanelNode.frame.height + toolbarHeight + 144.0) * -1.0 + } + + let containerSize = CGSize(width: layout.size.width, height: layout.size.height - toolbarHeight - 44.0) var bottomOffset: CGFloat = 9.0 + bottomInset if let messageNodes = self.messageNodes { for itemNode in messageNodes { let previousFrame = itemNode.frame transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size)) bottomOffset += itemNode.frame.height - itemNode.updateFrame(itemNode.frame, within: layout.size) + + let relativeFrame = itemNode.frame.offsetBy(dx: 0.0, dy: relativeOffset) + itemNode.updateAbsoluteRect(relativeFrame, within: containerSize) if case let .animated(duration, curve) = transition { - itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -itemNode.frame.minY + previousFrame.minY), animationCurve: curve, duration: duration) + itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -relativeFrame.minY + previousFrame.minY), animationCurve: curve, duration: duration) } } } @@ -954,7 +1005,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem) } else { dateHeaderNode = headerItem.node(synchronousLoad: true) - //dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0) self.messagesContainerNode.addSubnode(dateHeaderNode) self.dateHeaderNode = dateHeaderNode } @@ -1026,9 +1076,9 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate transition.updateBounds(node: self.backgroundWrapperNode, bounds: CGRect(origin: CGPoint(), size: layout.size)) - let displayOptionButtons = self.state.section == .background - var messagesBottomInset: CGFloat = bottomInset + let displayOptionButtons = self.state.section == .background || self.state.section == .messages + var messagesBottomInset: CGFloat = bottomInset if displayOptionButtons { messagesBottomInset += 56.0 } else if chatListPreviewAvailable { @@ -1054,7 +1104,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let maxButtonWidth = max(patternButtonSize.width, colorsButtonSize.width) let buttonSize = CGSize(width: maxButtonWidth, height: 30.0) - let patternAlpha: CGFloat = displayOptionButtons ? 1.0 : 0.0 + var patternAlpha: CGFloat = displayOptionButtons ? 1.0 : 0.0 let colorsAlpha: CGFloat = displayOptionButtons ? 1.0 : 0.0 let patternFrame: CGRect @@ -1067,15 +1117,30 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let playFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - playButtonSize.width) / 2.0), y: layout.size.height - bottomInset - 44.0 - buttonsVerticalOffset + floor((buttonSize.height - playButtonSize.height) / 2.0)), size: playButtonSize) let playAlpha: CGFloat - if self.state.backgroundColors.count >= 2 { - playAlpha = displayOptionButtons ? 1.0 : 0.0 - centerDistance += playButtonSize.width + var centerButtons = false + if self.state.section == .background { + if self.state.backgroundColors.count >= 2 { + playAlpha = displayOptionButtons ? 1.0 : 0.0 + centerDistance += playButtonSize.width + } else { + playAlpha = 0.0 + } + } else if self.state.section == .messages { + if self.state.messagesColors.count >= 3 { + patternAlpha = 1.0 + playAlpha = displayOptionButtons ? 1.0 : 0.0 + centerDistance += playButtonSize.width + } else { + patternAlpha = 0.0 + playAlpha = 0.0 + centerButtons = true + } } else { playAlpha = 0.0 } - - patternFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonSize.width * 2.0 - centerDistance) / 2.0), y: layout.size.height - bottomInset - 44.0 - buttonsVerticalOffset), size: buttonSize) - colorsFrame = CGRect(origin: CGPoint(x: patternFrame.maxX + centerDistance, y: layout.size.height - bottomInset - 44.0 - buttonsVerticalOffset), size: buttonSize) + + patternFrame = CGRect(origin: CGPoint(x: centerButtons ? floor((layout.size.width - buttonSize.width) / 2.0) : floor((layout.size.width - buttonSize.width * 2.0 - centerDistance) / 2.0), y: layout.size.height - bottomInset - 44.0 - buttonsVerticalOffset), size: buttonSize) + colorsFrame = CGRect(origin: CGPoint(x: centerButtons ? floor((layout.size.width - buttonSize.width) / 2.0) : patternFrame.maxX + centerDistance, y: layout.size.height - bottomInset - 44.0 - buttonsVerticalOffset), size: buttonSize) transition.updateFrame(node: self.patternButtonNode, frame: patternFrame) transition.updateAlpha(node: self.patternButtonNode, alpha: patternAlpha) @@ -1089,35 +1154,22 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } @objc private func togglePattern() { - self.view.endEditing(true) - - let wallpaper = self.state.previousPatternWallpaper ?? self.patternPanelNode.wallpapers.first - let backgroundColors = self.currentBackgroundColors - - var appeared = false - self.updateState({ current in - var updated = current - if !updated.displayPatternPanel { - updated.colorPanelCollapsed = false - updated.displayPatternPanel = true - if current.patternWallpaper == nil, let wallpaper = wallpaper { - updated.patternWallpaper = wallpaper - if updated.backgroundColors.isEmpty { - if let backgroundColors = backgroundColors { - updated.backgroundColors = backgroundColors.0 - } else { - updated.backgroundColors = [] - } - } - appeared = true - } - } else { - updated.colorPanelCollapsed = true - if updated.patternWallpaper != nil { - updated.previousPatternWallpaper = updated.patternWallpaper - updated.patternWallpaper = nil - updated.displayPatternPanel = false - } else { + if self.state.section == .messages { + self.updateState({ current in + var updated = current + updated.animateMessageColors = !current.animateMessageColors + return updated + }, animated: true) + } else { + self.view.endEditing(true) + + let wallpaper = self.state.previousPatternWallpaper ?? self.patternPanelNode.wallpapers.first + let backgroundColors = self.currentBackgroundColors + + var appeared = false + self.updateState({ current in + var updated = current + if !updated.displayPatternPanel { updated.colorPanelCollapsed = false updated.displayPatternPanel = true if current.patternWallpaper == nil, let wallpaper = wallpaper { @@ -1131,13 +1183,34 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } appeared = true } + } else { + updated.colorPanelCollapsed = true + if updated.patternWallpaper != nil { + updated.previousPatternWallpaper = updated.patternWallpaper + updated.patternWallpaper = nil + updated.displayPatternPanel = false + } else { + updated.colorPanelCollapsed = false + updated.displayPatternPanel = true + if current.patternWallpaper == nil, let wallpaper = wallpaper { + updated.patternWallpaper = wallpaper + if updated.backgroundColors.isEmpty { + if let backgroundColors = backgroundColors { + updated.backgroundColors = backgroundColors.0 + } else { + updated.backgroundColors = [] + } + } + appeared = true + } + } } + return updated + }, animated: true) + + if appeared { + self.patternPanelNode.didAppear(initialWallpaper: wallpaper, intensity: self.state.patternIntensity) } - return updated - }, animated: true) - - if appeared { - self.patternPanelNode.didAppear(initialWallpaper: wallpaper, intensity: self.state.patternIntensity) } } @@ -1165,7 +1238,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } else { self.updateState({ state in var state = state - state.rotation = (state.rotation + 90) % 360 + state.rotation = (state.rotation + 45) % 360 return state }, animated: true) } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift index 44b4743597..68407bebc6 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperColorPanelNode.swift @@ -390,7 +390,7 @@ final class WallpaperColorPanelNode: ASDisplayNode { private var sampleItemNodes: [ColorSampleItemNode] = [] private let multiColorFieldNode: ColorInputFieldNode - var colorsChanged: (([HSBColor], Bool) -> Void)? + var colorsChanged: (([HSBColor], Int, Bool) -> Void)? var colorSelected: (() -> Void)? var rotate: (() -> Void)? @@ -518,6 +518,7 @@ final class WallpaperColorPanelNode: ASDisplayNode { var updateLayout = updateLayout let previousColors = self.state.colors let previousPreview = self.state.preview + let previousSelection = self.state.selection self.state = f(self.state) let colorWasRemovable = self.multiColorFieldNode.isRemovable @@ -548,8 +549,8 @@ final class WallpaperColorPanelNode: ASDisplayNode { } } - if self.state.colors != previousColors || self.state.preview != previousPreview { - self.colorsChanged?(self.state.colors, !self.state.preview) + if self.state.colors != previousColors || self.state.preview != previousPreview || self.state.selection != previousSelection { + self.colorsChanged?(self.state.colors, self.state.selection ?? 0, !self.state.preview) } } @@ -576,42 +577,12 @@ final class WallpaperColorPanelNode: ASDisplayNode { } let buttonSize = CGSize(width: 26.0, height: 26.0) - //let middleButtonFrame = CGRect(origin: CGPoint(x: self.state.secondColor != nil ? floor((size.width - 26.0) / 2.0) : (self.state.secondColorAvailable ? size.width - rightInsetWithButton + floor((rightInsetWithButton - buttonSize.width) / 2.0) : size.width + buttonOffset), y: floor((topPanelHeight - buttonSize.height) / 2.0)), size: buttonSize) - - //transition.updateFrame(node: self.rotateButton, frame: middleButtonFrame) - //transition.updateFrame(node: self.swapButton, frame: middleButtonFrame) - let canAddColors = self.state.colors.count < self.state.maximumNumberOfColors transition.updateFrame(node: self.addButton, frame: CGRect(origin: CGPoint(x: size.width - rightInset - buttonSize.width, y: floor((topPanelHeight - buttonSize.height) / 2.0)), size: buttonSize)) transition.updateAlpha(node: self.addButton, alpha: canAddColors ? 1.0 : 0.0) transition.updateSublayerTransformScale(node: self.addButton, scale: canAddColors ? 1.0 : 0.1) - /*let rotateButtonAlpha: CGFloat - let swapButtonAlpha: CGFloat - let addButtonAlpha: CGFloat - if let _ = self.state.secondColor { - if self.state.rotateAvailable { - rotateButtonAlpha = 1.0 - swapButtonAlpha = 0.0 - } else { - rotateButtonAlpha = 0.0 - swapButtonAlpha = 1.0 - } - addButtonAlpha = 0.0 - } else { - swapButtonAlpha = 0.0 - rotateButtonAlpha = 0.0 - if self.state.secondColorAvailable { - addButtonAlpha = 1.0 - } else { - addButtonAlpha = 0.0 - } - } - transition.updateAlpha(node: self.rotateButton, alpha: rotateButtonAlpha) - transition.updateAlpha(node: self.swapButton, alpha: swapButtonAlpha) - transition.updateAlpha(node: self.addButton, alpha: addButtonAlpha)*/ - func degreesToRadians(_ degrees: CGFloat) -> CGFloat { var degrees = degrees if degrees >= 270.0 { diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift index d95e1de199..1706880995 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryController.swift @@ -880,7 +880,7 @@ public class WallpaperGalleryController: ViewController { currentColorsPanelNode = colorsPanelNode self.overlayNode?.insertSubnode(colorsPanelNode, belowSubnode: self.toolbarNode!) - colorsPanelNode.colorsChanged = { [weak self] colors, _ in + colorsPanelNode.colorsChanged = { [weak self] colors, _, _ in guard let strongSelf = self else { return } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperOptionButtonNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperOptionButtonNode.swift index b0ebf964cb..51da46b485 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperOptionButtonNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperOptionButtonNode.swift @@ -63,8 +63,15 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode { } } + var title: String { + didSet { + self.textNode.attributedText = NSAttributedString(string: title, font: Font.medium(13), textColor: .white) + } + } + init(title: String, value: WallpaperOptionButtonValue) { self._value = value + self.title = title self.backgroundNode = NavigationBackgroundNode(color: UIColor(rgb: 0x000000, alpha: 0.3)) self.backgroundNode.cornerRadius = 14.0 diff --git a/submodules/TelegramCore/Sources/ApiUtils/Theme.swift b/submodules/TelegramCore/Sources/ApiUtils/Theme.swift index c35376c1d6..9dfef6944f 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/Theme.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/Theme.swift @@ -46,8 +46,8 @@ extension TelegramBaseTheme { extension TelegramThemeSettings { convenience init?(apiThemeSettings: Api.ThemeSettings) { switch apiThemeSettings { - case let .themeSettings(_, baseTheme, accentColor, messageColors, wallpaper): - self.init(baseTheme: TelegramBaseTheme(apiBaseTheme: baseTheme), accentColor: UInt32(bitPattern: accentColor), messageColors: messageColors?.map(UInt32.init(bitPattern:)) ?? [], wallpaper: wallpaper.flatMap(TelegramWallpaper.init(apiWallpaper:))) + case let .themeSettings(flags, baseTheme, accentColor, messageColors, wallpaper): + self.init(baseTheme: TelegramBaseTheme(apiBaseTheme: baseTheme), accentColor: UInt32(bitPattern: accentColor), messageColors: messageColors?.map(UInt32.init(bitPattern:)) ?? [], animateMessageColors: (flags & 1 << 2) != 0, wallpaper: wallpaper.flatMap(TelegramWallpaper.init(apiWallpaper:))) } } @@ -57,6 +57,10 @@ extension TelegramThemeSettings { flags |= 1 << 0 } + if self.animateMessageColors { + flags |= 1 << 2 + } + var inputWallpaper: Api.InputWallPaper? var inputWallpaperSettings: Api.WallPaperSettings? if let wallpaper = self.wallpaper, let inputWallpaperAndSettings = wallpaper.apiInputWallpaperAndSettings { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift index 0404170b21..46034be5d1 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift @@ -24,6 +24,9 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { if lhs.messageColors != rhs.messageColors { return false } + if lhs.animateMessageColors != rhs.animateMessageColors { + return false + } if lhs.wallpaper != rhs.wallpaper { return false } @@ -33,12 +36,14 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { public let baseTheme: TelegramBaseTheme public let accentColor: UInt32 public let messageColors: [UInt32] + public let animateMessageColors: Bool public let wallpaper: TelegramWallpaper? - public init(baseTheme: TelegramBaseTheme, accentColor: UInt32, messageColors: [UInt32], wallpaper: TelegramWallpaper?) { + public init(baseTheme: TelegramBaseTheme, accentColor: UInt32, messageColors: [UInt32], animateMessageColors: Bool, wallpaper: TelegramWallpaper?) { self.baseTheme = baseTheme self.accentColor = accentColor self.messageColors = messageColors + self.animateMessageColors = animateMessageColors self.wallpaper = wallpaper } @@ -55,6 +60,7 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { self.messageColors = [] } } + self.animateMessageColors = decoder.decodeInt32ForKey("animateMessageColors", orElse: 0) != 0 self.wallpaper = decoder.decodeObjectForKey("wallpaper", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper } @@ -62,6 +68,7 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { encoder.encodeInt32(self.baseTheme.rawValue, forKey: "baseTheme") encoder.encodeInt32(Int32(bitPattern: self.accentColor), forKey: "accent") encoder.encodeInt32Array(self.messageColors.map(Int32.init(bitPattern:)), forKey: "messageColors") + encoder.encodeInt32(self.animateMessageColors ? 1 : 0, forKey: "animateMessageColors") if let wallpaper = self.wallpaper { encoder.encodeObject(wallpaper, forKey: "wallpaper") } else { diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 7025ce7819..ada7119ead 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -4,7 +4,7 @@ import TelegramCore import TelegramUIPreferences public let defaultDarkPresentationTheme = makeDefaultDarkPresentationTheme(preview: false) -public let defaultDarkColorPresentationTheme = customizeDefaultDarkPresentationTheme(theme: defaultDarkPresentationTheme, editing: false, title: nil, accentColor: UIColor(rgb: 0x007aff), backgroundColors: [], bubbleColors: [], wallpaper: nil, baseColor: nil) +public let defaultDarkColorPresentationTheme = customizeDefaultDarkPresentationTheme(theme: defaultDarkPresentationTheme, editing: false, title: nil, accentColor: UIColor(rgb: 0x007aff), backgroundColors: [], bubbleColors: [], animateBubbleColors: false, wallpaper: nil, baseColor: nil) private extension PresentationThemeBaseColor { var colorWallpaper: (BuiltinWallpaperData, Int32, [UInt32])? { @@ -37,7 +37,7 @@ private extension PresentationThemeBaseColor { } } -public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { +public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], animateBubbleColors: Bool?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { if (theme.referenceTheme != .night) { return theme } @@ -165,6 +165,7 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit chat = chat.withUpdated( defaultWallpaper: defaultWallpaper, + animateMessageColors: animateBubbleColors, message: chat.message.withUpdated( incoming: chat.message.incoming.withUpdated( linkTextColor: accentColor, @@ -523,6 +524,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati let chat = PresentationThemeChat( defaultWallpaper: .color(0x000000), + animateMessageColors: false, message: message, serviceMessage: serviceMessage, inputPanel: inputPanel, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index 745b6ebf9f..5c6a24eae8 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -38,7 +38,7 @@ private extension PresentationThemeBaseColor { } } -public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { +public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], animateBubbleColors: Bool?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { if (theme.referenceTheme != .nightAccent) { return theme } @@ -303,6 +303,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme chat = chat.withUpdated( defaultWallpaper: defaultWallpaper, + animateMessageColors: animateBubbleColors, message: chat.message.withUpdated( incoming: chat.message.incoming.withUpdated( bubble: chat.message.incoming.bubble.withUpdated( @@ -784,6 +785,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres let chat = PresentationThemeChat( defaultWallpaper: defaultBuiltinWallpaper(data: .default, colors: [0x1b2836, 0x121a22, 0x1b2836, 0x121a22]), + animateMessageColors: false, message: message, serviceMessage: serviceMessage, inputPanel: inputPanel, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index fb99997026..b50bf8fc17 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -35,7 +35,7 @@ public let defaultServiceBackgroundColor = UIColor(rgb: 0x000000, alpha: 0.2) public let defaultPresentationTheme = makeDefaultDayPresentationTheme(serviceBackgroundColor: defaultServiceBackgroundColor, day: false, preview: false) public let defaultDayAccentColor = UIColor(rgb: 0x007ee5) -public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper forcedWallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor?) -> PresentationTheme { +public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], animateBubbleColors: Bool?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor?) -> PresentationTheme { if (theme.referenceTheme != .day && theme.referenceTheme != .dayClassic) { return theme } @@ -236,6 +236,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti chat = chat.withUpdated( defaultWallpaper: defaultWallpaper, + animateMessageColors: animateBubbleColors, message: chat.message.withUpdated( incoming: chat.message.incoming.withUpdated( bubble: chat.message.incoming.bubble.withUpdated( @@ -738,6 +739,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio let chat = PresentationThemeChat( defaultWallpaper: day ? .color(0xffffff) : defaultPatternWallpaper, + animateMessageColors: false, message: day ? messageDay : message, serviceMessage: day ? serviceMessageDay : serviceMessage, inputPanel: inputPanel, diff --git a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift index c4e162eaea..0f5b73c3a0 100644 --- a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift @@ -19,46 +19,46 @@ public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeRefe return theme } -public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool, title: String? = nil, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { +public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool, title: String? = nil, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], animateBubbleColors: Bool?, wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { if accentColor == nil && bubbleColors.isEmpty && backgroundColors.isEmpty && wallpaper == nil { return theme } switch theme.referenceTheme { case .day, .dayClassic: - return customizeDefaultDayTheme(theme: theme, editing: editing, title: title, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper, serviceBackgroundColor: nil) + return customizeDefaultDayTheme(theme: theme, editing: editing, title: title, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, animateBubbleColors: animateBubbleColors ?? false, wallpaper: wallpaper, serviceBackgroundColor: nil) case .night: - return customizeDefaultDarkPresentationTheme(theme: theme, editing: editing, title: title, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper, baseColor: baseColor) + return customizeDefaultDarkPresentationTheme(theme: theme, editing: editing, title: title, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, animateBubbleColors: animateBubbleColors ?? false, wallpaper: wallpaper, baseColor: baseColor) case .nightAccent: - return customizeDefaultDarkTintedPresentationTheme(theme: theme, editing: editing, title: title, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper, baseColor: baseColor) + return customizeDefaultDarkTintedPresentationTheme(theme: theme, editing: editing, title: title, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, animateBubbleColors: animateBubbleColors ?? false, wallpaper: wallpaper, baseColor: baseColor) } } public func makePresentationTheme(settings: TelegramThemeSettings, title: String? = nil, serviceBackgroundColor: UIColor? = nil) -> PresentationTheme? { let defaultTheme = makeDefaultPresentationTheme(reference: PresentationBuiltinThemeReference(baseTheme: settings.baseTheme), extendingThemeReference: nil, serviceBackgroundColor: serviceBackgroundColor, preview: false) - return customizePresentationTheme(defaultTheme, editing: true, title: title, accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors, wallpaper: settings.wallpaper) + return customizePresentationTheme(defaultTheme, editing: true, title: title, accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors, animateBubbleColors: settings.animateMessageColors, wallpaper: settings.wallpaper) } -public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, extendingThemeReference: PresentationThemeReference? = nil, accentColor: UIColor? = nil, backgroundColors: [UInt32] = [], bubbleColors: [UInt32] = [], wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { +public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, extendingThemeReference: PresentationThemeReference? = nil, accentColor: UIColor? = nil, backgroundColors: [UInt32] = [], bubbleColors: [UInt32] = [], animateBubbleColors: Bool? = nil, wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { let theme: PresentationTheme switch themeReference { case let .builtin(reference): let defaultTheme = makeDefaultPresentationTheme(reference: reference, extendingThemeReference: extendingThemeReference, serviceBackgroundColor: serviceBackgroundColor, preview: preview) - theme = customizePresentationTheme(defaultTheme, editing: true, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper, baseColor: baseColor) + theme = customizePresentationTheme(defaultTheme, editing: true, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, animateBubbleColors: animateBubbleColors, wallpaper: wallpaper, baseColor: baseColor) case let .local(info): if let path = mediaBox.completedResourcePath(info.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, themeReference: themeReference, resolvedWallpaper: info.resolvedWallpaper) { - theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) + theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, animateBubbleColors: animateBubbleColors, wallpaper: wallpaper) } else { return nil } case let .cloud(info): if let settings = info.theme.settings { - if let loadedTheme = makePresentationTheme(mediaBox: mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), extendingThemeReference: themeReference, accentColor: accentColor ?? UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: bubbleColors.isEmpty ? settings.messageColors : bubbleColors, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { + if let loadedTheme = makePresentationTheme(mediaBox: mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), extendingThemeReference: themeReference, accentColor: accentColor ?? UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: bubbleColors.isEmpty ? settings.messageColors : bubbleColors, animateBubbleColors: animateBubbleColors ?? settings.animateMessageColors, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { theme = loadedTheme } else { return nil } } else if let file = info.theme.file, let path = mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let loadedTheme = makePresentationTheme(data: data, themeReference: themeReference, resolvedWallpaper: info.resolvedWallpaper) { - theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, wallpaper: wallpaper) + theme = customizePresentationTheme(loadedTheme, editing: false, accentColor: accentColor, backgroundColors: backgroundColors, bubbleColors: bubbleColors, animateBubbleColors: animateBubbleColors, wallpaper: wallpaper) } else { return nil } diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index 5a718a657c..0c3f6c5391 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -1066,6 +1066,7 @@ public final class PresentationThemeChatHistoryNavigation { public final class PresentationThemeChat { public let defaultWallpaper: TelegramWallpaper + public let animateMessageColors: Bool public let message: PresentationThemeChatMessage public let serviceMessage: PresentationThemeServiceMessage public let inputPanel: PresentationThemeChatInputPanel @@ -1073,8 +1074,9 @@ public final class PresentationThemeChat { public let inputButtonPanel: PresentationThemeInputButtonPanel public let historyNavigation: PresentationThemeChatHistoryNavigation - public init(defaultWallpaper: TelegramWallpaper, message: PresentationThemeChatMessage, serviceMessage: PresentationThemeServiceMessage, inputPanel: PresentationThemeChatInputPanel, inputMediaPanel: PresentationThemeInputMediaPanel, inputButtonPanel: PresentationThemeInputButtonPanel, historyNavigation: PresentationThemeChatHistoryNavigation) { + public init(defaultWallpaper: TelegramWallpaper, animateMessageColors: Bool, message: PresentationThemeChatMessage, serviceMessage: PresentationThemeServiceMessage, inputPanel: PresentationThemeChatInputPanel, inputMediaPanel: PresentationThemeInputMediaPanel, inputButtonPanel: PresentationThemeInputButtonPanel, historyNavigation: PresentationThemeChatHistoryNavigation) { self.defaultWallpaper = defaultWallpaper + self.animateMessageColors = animateMessageColors self.message = message self.serviceMessage = serviceMessage self.inputPanel = inputPanel @@ -1083,8 +1085,8 @@ public final class PresentationThemeChat { self.historyNavigation = historyNavigation } - public func withUpdated(defaultWallpaper: TelegramWallpaper? = nil, message: PresentationThemeChatMessage? = nil, serviceMessage: PresentationThemeServiceMessage? = nil, inputPanel: PresentationThemeChatInputPanel? = nil, inputMediaPanel: PresentationThemeInputMediaPanel? = nil, inputButtonPanel: PresentationThemeInputButtonPanel? = nil, historyNavigation: PresentationThemeChatHistoryNavigation? = nil) -> PresentationThemeChat { - return PresentationThemeChat(defaultWallpaper: defaultWallpaper ?? self.defaultWallpaper, message: message ?? self.message, serviceMessage: serviceMessage ?? self.serviceMessage, inputPanel: inputPanel ?? self.inputPanel, inputMediaPanel: inputMediaPanel ?? self.inputMediaPanel, inputButtonPanel: inputButtonPanel ?? self.inputButtonPanel, historyNavigation: historyNavigation ?? self.historyNavigation) + public func withUpdated(defaultWallpaper: TelegramWallpaper? = nil, animateMessageColors: Bool? = nil, message: PresentationThemeChatMessage? = nil, serviceMessage: PresentationThemeServiceMessage? = nil, inputPanel: PresentationThemeChatInputPanel? = nil, inputMediaPanel: PresentationThemeInputMediaPanel? = nil, inputButtonPanel: PresentationThemeInputButtonPanel? = nil, historyNavigation: PresentationThemeChatHistoryNavigation? = nil) -> PresentationThemeChat { + return PresentationThemeChat(defaultWallpaper: defaultWallpaper ?? self.defaultWallpaper, animateMessageColors: animateMessageColors ?? self.animateMessageColors, message: message ?? self.message, serviceMessage: serviceMessage ?? self.serviceMessage, inputPanel: inputPanel ?? self.inputPanel, inputMediaPanel: inputMediaPanel ?? self.inputMediaPanel, inputButtonPanel: inputButtonPanel ?? self.inputButtonPanel, historyNavigation: historyNavigation ?? self.historyNavigation) } } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 2b4e950af7..b9f62a7428 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -1659,6 +1659,7 @@ extension PresentationThemeChat: Codable { enum CodingKeys: String, CodingKey { case defaultWallpaper case message + case animateMessageColors case serviceMessage case inputPanel case inputMediaPanel @@ -1677,6 +1678,7 @@ extension PresentationThemeChat: Codable { } self.init(defaultWallpaper: wallpaper, + animateMessageColors: (try? values.decode(Bool.self, forKey: .animateMessageColors)) ?? false, message: try values.decode(PresentationThemeChatMessage.self, forKey: .message), serviceMessage: try values.decode(PresentationThemeServiceMessage.self, forKey: .serviceMessage), inputPanel: try values.decode(PresentationThemeChatInputPanel.self, forKey: .inputPanel), diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index 678db0363b..61ec3cac11 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -773,7 +773,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { self.bubbleTheme = bubbleTheme self.bubbleCorners = bubbleCorners - if bubbleTheme.chat.message.outgoing.bubble.withoutWallpaper.fill.count >= 3 && self.context.sharedContext.immediateExperimentalUISettings.enableDebugDataDisplay { + if bubbleTheme.chat.message.outgoing.bubble.withoutWallpaper.fill.count >= 3 && bubbleTheme.chat.animateMessageColors { if self.outgoingBubbleGradientBackgroundNode == nil { let outgoingBubbleGradientBackgroundNode = GradientBackgroundNode() if let size = self.validLayout { From 74c2145b219cb9a2a940037880a3e4972b1aaddc Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Aug 2021 00:47:36 +0400 Subject: [PATCH 02/10] Add "Choosing sticker" input activity --- .../Sources/Node/ChatListTypingNode.swift | 8 + ...atChoosingStickerActivityContentNode.swift | 145 ++++++++++++++++++ .../Sources/ChatTitleActivityNode.swift | 3 + .../State/ManagedLocalInputActivities.swift | 2 + .../Sources/State/PeerInputActivity.swift | 3 + .../TelegramUI/Sources/ChatTitleView.swift | 4 + 6 files changed, 165 insertions(+) create mode 100644 submodules/ChatTitleActivityNode/Sources/ChatChoosingStickerActivityContentNode.swift diff --git a/submodules/ChatListUI/Sources/Node/ChatListTypingNode.swift b/submodules/ChatListUI/Sources/Node/ChatListTypingNode.swift index ab7ef7a0f3..3c93404932 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListTypingNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListTypingNode.swift @@ -59,6 +59,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode { text = strings.Activity_PlayingGame case .typingText: text = strings.DialogList_Typing + case .choosingSticker: + text = strings.Activity_ChoosingSticker case .speakingInGroupCall: text = "" } @@ -77,6 +79,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode { state = .playingGame(string, lightColor) case .speakingInGroupCall: state = .typingText(string, lightColor) + case .choosingSticker: + state = .choosingSticker(string, lightColor) } } else { let text: String @@ -99,6 +103,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode { text = strings.DialogList_SinglePlayingGameSuffix(peerTitle).string case .typingText: text = strings.DialogList_SingleTypingSuffix(peerTitle).string + case .choosingSticker: + text = "" case .speakingInGroupCall: text = "" } @@ -120,6 +126,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode { state = .playingGame(string, lightColor) case .speakingInGroupCall: state = .typingText(string, lightColor) + case .choosingSticker: + state = .none } } } else { diff --git a/submodules/ChatTitleActivityNode/Sources/ChatChoosingStickerActivityContentNode.swift b/submodules/ChatTitleActivityNode/Sources/ChatChoosingStickerActivityContentNode.swift new file mode 100644 index 0000000000..ede3b2ab0d --- /dev/null +++ b/submodules/ChatTitleActivityNode/Sources/ChatChoosingStickerActivityContentNode.swift @@ -0,0 +1,145 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import LegacyComponents + +private func interpolate(from: CGFloat, to: CGFloat, value: CGFloat) -> CGFloat { + return (1.0 - value) * from + value * to +} + +private final class ChatChoosingStickerActivityIndicatorNodeParameters: NSObject { + let color: UIColor + let progress: CGFloat + + init(color: UIColor, progress: CGFloat) { + self.color = color + self.progress = progress + } +} + +private class ChatChoosingStickerActivityIndicatorNode: ChatTitleActivityIndicatorNode { + override var duration: CFTimeInterval { + return 2.0 + } + + override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? { + if let color = self.color { + return ChatChoosingStickerActivityIndicatorNodeParameters(color: color, progress: self.progress) + } else { + return nil + } + } + + @objc override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) { + let context = UIGraphicsGetCurrentContext()! + + if !isRasterizing { + context.setBlendMode(.copy) + context.setFillColor(UIColor.clear.cgColor) + context.fill(bounds) + } + + guard let parameters = parameters as? ChatChoosingStickerActivityIndicatorNodeParameters else { + return + } + + context.setFillColor(UIColor.red.cgColor) +// context.fill(bounds) + + let color = parameters.color + context.setFillColor(color.cgColor) + context.setStrokeColor(color.cgColor) + + var heightProgress: CGFloat = parameters.progress * 4.0 + if heightProgress > 3.0 { + heightProgress = 4.0 - heightProgress + } else if heightProgress > 2.0 { + heightProgress = heightProgress - 2.0 + heightProgress *= heightProgress + } else if heightProgress > 1.0 { + heightProgress = 2.0 - heightProgress + } else { + heightProgress *= heightProgress + } + + var pupilProgress: CGFloat = parameters.progress * 4.0 + if pupilProgress > 2.0 { + pupilProgress = 3.0 - pupilProgress + } + pupilProgress = min(1.0, max(0.0, pupilProgress)) + pupilProgress *= pupilProgress + + var positionProgress: CGFloat = parameters.progress * 2.0 + if positionProgress > 1.0 { + positionProgress = 2.0 - positionProgress + } + + let eyeWidth: CGFloat = 6.0 + let eyeHeight: CGFloat = 11.0 - 2.0 * heightProgress + + let eyeOffset: CGFloat = -1.0 + positionProgress * 2.0 + let leftCenter = CGPoint(x: bounds.width / 2.0 - eyeWidth - 1.0 + eyeOffset, y: bounds.height / 2.0) + let rightCenter = CGPoint(x: bounds.width / 2.0 + 1.0 + eyeOffset, y: bounds.height / 2.0) + + let pupilSize: CGFloat = 4.0 + let pupilCenter = CGPoint(x: -1.0 + pupilProgress * 2.0, y: 0.0) + + context.strokeEllipse(in: CGRect(x: leftCenter.x - eyeWidth / 2.0, y: leftCenter.y - eyeHeight / 2.0, width: eyeWidth, height: eyeHeight)) + context.fillEllipse(in: CGRect(x: leftCenter.x - pupilSize / 2.0 + pupilCenter.x * eyeWidth / 4.0, y: leftCenter.y - pupilSize / 2.0, width: pupilSize, height: pupilSize)) + + context.strokeEllipse(in: CGRect(x: rightCenter.x - eyeWidth / 2.0, y: rightCenter.y - eyeHeight / 2.0, width: eyeWidth, height: eyeHeight)) + context.fillEllipse(in: CGRect(x: rightCenter.x - pupilSize / 2.0 + pupilCenter.x * eyeWidth / 4.0, y: rightCenter.y - pupilSize / 2.0, width: pupilSize, height: pupilSize)) + +// context.strokeEllipse(in: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 20.0)) +// context.fillEllipse(in: CGRect(x: , y: , width: 4.0, height: 4.0)) + + } +} + +class ChatChoosingStickerActivityContentNode: ChatTitleActivityContentNode { + private let indicatorNode: ChatChoosingStickerActivityIndicatorNode + private let advanced: Bool + + init(text: NSAttributedString, color: UIColor) { + self.indicatorNode = ChatChoosingStickerActivityIndicatorNode(color: color) + + var text = text + self.advanced = text.string == "choosing sticker" + if self.advanced { + let mutable = text.mutableCopy() as? NSMutableAttributedString + mutable?.replaceCharacters(in: NSMakeRange(2, 2), with: " ") + if let updated = mutable{ + text = updated + } + } + + super.init(text: text) + + self.addSubnode(self.indicatorNode) + } + + override func updateLayout(_ constrainedSize: CGSize, offset: CGFloat, alignment: NSTextAlignment) -> CGSize { + let size = self.textNode.updateLayout(constrainedSize) + let indicatorSize = CGSize(width: 24.0, height: 16.0) + let originX: CGFloat + let indicatorOriginX: CGFloat + if case .center = alignment { + if self.advanced { + originX = floorToScreenPixels((-size.width) / 2.0) + } else { + originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0) + } + } else { + originX = indicatorSize.width + } + self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size) + if self.advanced { + indicatorOriginX = self.textNode.frame.minX + 14.0 + UIScreenPixel + } else { + indicatorOriginX = self.textNode.frame.minX - indicatorSize.width + } + self.indicatorNode.frame = CGRect(origin: CGPoint(x: indicatorOriginX, y: 0.0), size: indicatorSize) + return CGSize(width: size.width + indicatorSize.width, height: size.height) + } +} diff --git a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift index d07bd226a4..a2a1abf891 100644 --- a/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift +++ b/submodules/ChatTitleActivityNode/Sources/ChatTitleActivityNode.swift @@ -23,6 +23,7 @@ public enum ChatTitleActivityNodeState: Equatable { case recordingVoice(NSAttributedString, UIColor) case recordingVideo(NSAttributedString, UIColor) case playingGame(NSAttributedString, UIColor) + case choosingSticker(NSAttributedString, UIColor) func contentNode() -> ChatTitleActivityContentNode? { switch self { @@ -40,6 +41,8 @@ public enum ChatTitleActivityNodeState: Equatable { return ChatRecordingVideoActivityContentNode(text: text, color: color) case let .playingGame(text, color): return ChatPlayingActivityContentNode(text: text, color: color) + case let .choosingSticker(text, color): + return ChatChoosingStickerActivityContentNode(text: text, color: color) } } diff --git a/submodules/TelegramCore/Sources/State/ManagedLocalInputActivities.swift b/submodules/TelegramCore/Sources/State/ManagedLocalInputActivities.swift index 2965982be2..849115cec6 100644 --- a/submodules/TelegramCore/Sources/State/ManagedLocalInputActivities.swift +++ b/submodules/TelegramCore/Sources/State/ManagedLocalInputActivities.swift @@ -129,6 +129,8 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa return .sendMessageUploadRoundAction(progress: progress) case .speakingInGroupCall: return .speakingInGroupCallAction + case .choosingSticker: + return .sendMessageGamePlayAction } } else { return .sendMessageCancelAction diff --git a/submodules/TelegramCore/Sources/State/PeerInputActivity.swift b/submodules/TelegramCore/Sources/State/PeerInputActivity.swift index 611ee31e27..b6f0d316c0 100644 --- a/submodules/TelegramCore/Sources/State/PeerInputActivity.swift +++ b/submodules/TelegramCore/Sources/State/PeerInputActivity.swift @@ -11,6 +11,7 @@ public enum PeerInputActivity: Comparable { case recordingInstantVideo case uploadingInstantVideo(progress: Int32) case speakingInGroupCall(timestamp: Int32) + case choosingSticker public var key: Int32 { switch self { @@ -32,6 +33,8 @@ public enum PeerInputActivity: Comparable { return 7 case .playingGame: return 8 + case .choosingSticker: + return 9 } } diff --git a/submodules/TelegramUI/Sources/ChatTitleView.swift b/submodules/TelegramUI/Sources/ChatTitleView.swift index d46fc70974..312e858394 100644 --- a/submodules/TelegramUI/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Sources/ChatTitleView.swift @@ -341,6 +341,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView { stringValue = strings.Activity_RecordingVideoMessage case .uploadingInstantVideo: stringValue = strings.Activity_UploadingVideoMessage + case .choosingSticker: + stringValue = strings.Activity_ChoosingSticker case .speakingInGroupCall: stringValue = "" } @@ -372,6 +374,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView { state = .playingGame(string, color) case .speakingInGroupCall: state = .typingText(string, color) + case .choosingSticker: + state = .choosingSticker(string, color) } } else { if let titleContent = self.titleContent { From b4dbb9698b914d518e5e4b1195313e93953799f0 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Aug 2021 22:36:06 +0400 Subject: [PATCH 03/10] Various Fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 9 ++++++++- .../Sources/ChannelVisibilityController.swift | 16 ++++++++++++---- .../Themes/ThemeAccentColorControllerNode.swift | 2 +- .../Themes/WallpaperColorPickerNode.swift | 6 +++++- .../Sources/UsernameSetupController.swift | 6 +++++- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index abff60c6e0..b6b30bc99d 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -6613,6 +6613,14 @@ Sorry for the inconvenience."; "WallpaperPreview.Animate" = "Animate"; "WallpaperPreview.AnimateDescription" = "Colors will move when you send messages"; +"Username.InvalidStartsWithUnderscore" = "Sorry, a username can't start with an underscore."; +"Username.InvalidEndsWithUnderscore" = "Sorry, a username can't end with an underscore."; + +"Channel.Username.InvalidStartsWithUnderscore" = "Channel names can't start with an underscore."; +"Channel.Username.InvalidEndsWithUnderscore" = "Channel names can't end with an underscore."; + +"Group.Username.InvalidStartsWithUnderscore" = "Group names can't start with an underscore."; +"Group.Username.InvalidEndsWithUnderscore" = "Group names can't end with an underscore."; "Appstore.Cloud" = "**Cloud-based**\nUnlimited storage for chats,\nmedia and documents."; "Appstore.Cloud.Profile" = "**Jennifer**\n23 y.o. designer from San Francisco."; @@ -6645,4 +6653,3 @@ Sorry for the inconvenience."; "Appstore.Secure" = "**Secure**\nAll chats are protected\nwith strong encryption."; "Appstore.Secure.Chat" = "**Little Sister**\nAny gift ideas for mom?\n**You**A dog!\n**You**I'm serious. Let's get her a puppy. \n**You**\nI saw this!\n**Little Sister**\nI needed proof this was your idea!"; "Appstore.Secure.Chat.Name" = "**Little Sister**"; - diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 5b51dff0a7..ad94da6eb9 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -560,9 +560,17 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa text = presentationData.strings.Channel_Username_InvalidStartsWithNumber } case .startsWithUnderscore: - text = presentationData.strings.Channel_Username_InvalidCharacters + if isGroup { + text = presentationData.strings.Group_Username_InvalidStartsWithUnderscore + } else { + text = presentationData.strings.Channel_Username_InvalidStartsWithUnderscore + } case .endsWithUnderscore: - text = presentationData.strings.Channel_Username_InvalidCharacters + if isGroup { + text = presentationData.strings.Group_Username_InvalidEndsWithUnderscore + } else { + text = presentationData.strings.Channel_Username_InvalidEndsWithUnderscore + } case .tooShort: if isGroup { text = presentationData.strings.Group_Username_InvalidTooShort @@ -696,9 +704,9 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa case .startsWithDigit: text = presentationData.strings.Group_Username_InvalidStartsWithNumber case .startsWithUnderscore: - text = presentationData.strings.Channel_Username_InvalidCharacters + text = presentationData.strings.Channel_Username_InvalidStartsWithUnderscore case .endsWithUnderscore: - text = presentationData.strings.Channel_Username_InvalidCharacters + text = presentationData.strings.Channel_Username_InvalidEndsWithUnderscore case .tooShort: text = presentationData.strings.Group_Username_InvalidTooShort case .invalidCharacters: diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 9f10567e80..cdfd7766a4 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -1181,8 +1181,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate updated.backgroundColors = [] } } - appeared = true } + appeared = true } else { updated.colorPanelCollapsed = true if updated.patternWallpaper != nil { diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift index 4f8acaa470..81e8bd28e0 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift @@ -272,6 +272,7 @@ struct HSBColor: Equatable { } let values: (h: CGFloat, s: CGFloat, b: CGFloat) + let backingColor: UIColor var hue: CGFloat { return self.values.h @@ -291,14 +292,17 @@ struct HSBColor: Equatable { init(values: (h: CGFloat, s: CGFloat, b: CGFloat)) { self.values = values + self.backingColor = UIColor(hue: values.h, saturation: values.s, brightness: values.b, alpha: 1.0) } init(hue: CGFloat, saturation: CGFloat, brightness: CGFloat) { self.values = (h: hue, s: saturation, b: brightness) + self.backingColor = UIColor(hue: self.values.h, saturation: self.values.s, brightness: self.values.b, alpha: 1.0) } init(color: UIColor) { self.values = color.hsb + self.backingColor = color } init(rgb: UInt32) { @@ -306,7 +310,7 @@ struct HSBColor: Equatable { } var color: UIColor { - return UIColor(hue: self.values.h, saturation: self.values.s, brightness: self.values.b, alpha: 1.0) + return self.backingColor } } diff --git a/submodules/SettingsUI/Sources/UsernameSetupController.swift b/submodules/SettingsUI/Sources/UsernameSetupController.swift index 11a86a6b54..b3ea2e1a71 100644 --- a/submodules/SettingsUI/Sources/UsernameSetupController.swift +++ b/submodules/SettingsUI/Sources/UsernameSetupController.swift @@ -194,7 +194,11 @@ private func usernameSetupControllerEntries(presentationData: PresentationData, switch error { case .startsWithDigit: statusText = presentationData.strings.Username_InvalidStartsWithNumber - case .startsWithUnderscore, .endsWithUnderscore, .invalidCharacters: + case .startsWithUnderscore: + statusText = presentationData.strings.Username_InvalidStartsWithUnderscore + case .endsWithUnderscore: + statusText = presentationData.strings.Username_InvalidEndsWithUnderscore + case .invalidCharacters: statusText = presentationData.strings.Username_InvalidCharacters case .tooShort: statusText = presentationData.strings.Username_InvalidTooShort From 3fd9c0aa5f8f9bca2b26f81990d00dbe6d6bb745 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Aug 2021 01:17:06 +0400 Subject: [PATCH 04/10] Various theme editing fixes --- .../Sources/SoftwareGradientBackground.swift | 13 ++++++++----- .../Sources/Themes/EditThemeController.swift | 8 +++++++- .../Sources/Themes/ThemeAccentColorController.swift | 4 ++-- .../Themes/ThemeAccentColorControllerNode.swift | 2 +- .../Themes/ThemeSettingsChatPreviewItem.swift | 6 +++--- .../Sources/PresentationThemeCodable.swift | 2 +- .../Sources/WallpaperBackgroundNode.swift | 2 +- 7 files changed, 23 insertions(+), 14 deletions(-) diff --git a/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift b/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift index 21fcde858a..4b4eb1ae2c 100644 --- a/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift +++ b/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift @@ -232,7 +232,7 @@ public final class GradientBackgroundNode: ASDisplayNode { if let current = self._dimmedImage { return current } else if let (size, colors, positions) = self.dimmedImageParams { - self._dimmedImage = generateGradient(size: size, colors: colors, positions: positions, adjustSaturation: 1.7) + self._dimmedImage = generateGradient(size: size, colors: colors, positions: positions, adjustSaturation: self.saturation) return self._dimmedImage } else { return nil @@ -245,8 +245,11 @@ public final class GradientBackgroundNode: ASDisplayNode { private let useSharedAnimationPhase: Bool static var sharedPhase: Int = 0 - public init(colors: [UIColor]? = nil, useSharedAnimationPhase: Bool = false) { + private let saturation: CGFloat + + public init(colors: [UIColor]? = nil, useSharedAnimationPhase: Bool = false, adjustSaturation: Bool = true) { self.useSharedAnimationPhase = useSharedAnimationPhase + self.saturation = adjustSaturation ? 1.7 : 1.0 self.contentView = UIImageView() let defaultColors: [UIColor] = [ UIColor(rgb: 0x7FA381), @@ -345,7 +348,7 @@ public final class GradientBackgroundNode: ASDisplayNode { images.append(generateGradient(size: imageSize, colors: self.colors, positions: morphedPositions)) if needDimmedImages { - dimmedImages.append(generateGradient(size: imageSize, colors: self.colors, positions: morphedPositions, adjustSaturation: 1.7)) + dimmedImages.append(generateGradient(size: imageSize, colors: self.colors, positions: morphedPositions, adjustSaturation: self.saturation)) } } @@ -393,7 +396,7 @@ public final class GradientBackgroundNode: ASDisplayNode { let image = generateGradient(size: imageSize, colors: self.colors, positions: positions) self.contentView.image = image - let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: 1.7) + let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation) self._dimmedImage = dimmedImage self.dimmedImageParams = (imageSize, self.colors, positions) @@ -406,7 +409,7 @@ public final class GradientBackgroundNode: ASDisplayNode { let image = generateGradient(size: imageSize, colors: self.colors, positions: positions) self.contentView.image = image - let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: 1.7) + let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation) self.dimmedImageParams = (imageSize, self.colors, positions) for cloneNode in self.cloneNodes { diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 7d1c27992f..92d95f8309 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -268,6 +268,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll let previewThemePromise = Promise() let settingsPromise = Promise(nil) let hasSettings: Bool + let mayHaveSettings: Bool let presentationData = context.sharedContext.currentPresentationData.with { $0 } switch mode { case let .create(existingTheme, settings): @@ -278,16 +279,19 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll wallpaper = theme.chat.defaultWallpaper settingsPromise.set(.single(settings)) hasSettings = settings != nil + mayHaveSettings = settings != nil } else { theme = presentationData.theme wallpaper = presentationData.chatWallpaper settingsPromise.set(.single(nil)) hasSettings = false + mayHaveSettings = true } initialState = EditThemeControllerState(mode: mode, title: generateThemeName(accentColor: theme.rootController.navigationBar.buttonColor), slug: "", updatedTheme: nil, updating: false) previewThemePromise.set(.single(theme.withUpdated(name: "", defaultWallpaper: wallpaper))) case let .edit(info): hasSettings = info.theme.settings != nil + mayHaveSettings = hasSettings settingsPromise.set(.single(info.theme.settings)) if let file = info.theme.file, let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let theme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) { if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { @@ -323,6 +327,8 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll var generalThemeReference: PresentationThemeReference? if case let .edit(cloudTheme) = mode { generalThemeReference = PresentationThemeReference.cloud(cloudTheme).generalThemeReference + } else if case let .create(existingTheme, _) = mode, existingTheme == nil { + generalThemeReference = PresentationThemeReference.builtin(presentationData.theme.referenceTheme) } let arguments = EditThemeControllerArguments(context: context, updateState: { f in @@ -338,7 +344,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll state.updatedTheme = updatedTheme return state } - if previousSettings != nil { + if previousSettings != nil || mayHaveSettings { settingsPromise.set(.single(settings)) } controllerDismissImpl?() diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 1c6ad0ad5e..f516e14ee9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -186,8 +186,8 @@ final class ThemeAccentColorController: ViewController { if case let .edit(theme, _, generalThemeReference, _, _, completion) = strongSelf.mode { let _ = (prepareWallpaper - |> deliverOnMainQueue).start(completed: { let updatedTheme: PresentationTheme - + |> deliverOnMainQueue).start(completed: { + let updatedTheme: PresentationTheme var settings: TelegramThemeSettings? var hasSettings = false var baseTheme: TelegramBaseTheme? diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index cdfd7766a4..03c9295db2 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -944,7 +944,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate snapshot.frame = itemNode.bounds itemNode.view.addSubview(snapshot) - snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, completion: { [weak snapshot] _ in + snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshot] _ in snapshot?.removeFromSuperview() }) } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index e0c3989f8a..e115dc5dc7 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -141,7 +141,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { currentBackgroundNode = WallpaperBackgroundNode(context: item.context) } currentBackgroundNode?.update(wallpaper: item.wallpaper) - currentBackgroundNode?.updateBubbleTheme(bubbleTheme: item.theme, bubbleCorners: item.chatBubbleCorners) + currentBackgroundNode?.updateBubbleTheme(bubbleTheme: item.componentTheme, bubbleCorners: item.chatBubbleCorners) let insets: UIEdgeInsets let separatorHeight = UIScreenPixel @@ -261,13 +261,13 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { strongSelf.bottomStripeNode.isHidden = hasCorners } - strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.componentTheme, top: hasTopCorners, bottom: hasBottomCorners) : nil let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) if let backgroundNode = strongSelf.backgroundNode { backgroundNode.frame = backgroundFrame.insetBy(dx: 0.0, dy: -100.0) backgroundNode.update(wallpaper: item.wallpaper) - backgroundNode.updateBubbleTheme(bubbleTheme: item.theme, bubbleCorners: item.chatBubbleCorners) + backgroundNode.updateBubbleTheme(bubbleTheme: item.componentTheme, bubbleCorners: item.chatBubbleCorners) backgroundNode.updateLayout(size: backgroundNode.bounds.size, transition: .immediate) } strongSelf.maskNode.frame = backgroundFrame.insetBy(dx: params.leftInset, dy: 0.0) diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index b9f62a7428..b1e9a99a11 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -115,7 +115,7 @@ extension TelegramWallpaper: Codable { colors.append(value.rgb) } else if component.count <= 3, let value = Int32(component) { if intensity == nil { - if value >= 0 && value <= 100 { + if value >= -100 && value <= 100 { intensity = value } else { intensity = 50 diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index 61ec3cac11..38b4842493 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -775,7 +775,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { if bubbleTheme.chat.message.outgoing.bubble.withoutWallpaper.fill.count >= 3 && bubbleTheme.chat.animateMessageColors { if self.outgoingBubbleGradientBackgroundNode == nil { - let outgoingBubbleGradientBackgroundNode = GradientBackgroundNode() + let outgoingBubbleGradientBackgroundNode = GradientBackgroundNode(adjustSaturation: false) if let size = self.validLayout { outgoingBubbleGradientBackgroundNode.frame = CGRect(origin: CGPoint(), size: size) outgoingBubbleGradientBackgroundNode.updateLayout(size: size, transition: .immediate) From db748e3aec6ba5a83ba1a997f23eb75779dfe9f8 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Aug 2021 12:56:44 +0400 Subject: [PATCH 05/10] Various theme editing fixes --- .../Themes/ThemeAccentColorController.swift | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index f516e14ee9..62f2e4888b 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -201,7 +201,7 @@ final class ThemeAccentColorController: ViewController { } if let themeReference = generalThemeReference { - updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: state.accentColor.color, backgroundColors: state.backgroundColors.map { $0.rgb }, bubbleColors: state.messagesColors.map { $0.rgb }, wallpaper: coloredWallpaper ?? state.initialWallpaper, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme + updatedTheme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, accentColor: state.accentColor.color, backgroundColors: state.backgroundColors.map { $0.rgb }, bubbleColors: state.messagesColors.map { $0.rgb }, animateBubbleColors: state.animateMessageColors, wallpaper: coloredWallpaper ?? state.initialWallpaper, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme } else { updatedTheme = customizePresentationTheme(theme, editing: false, accentColor: state.accentColor.color, backgroundColors: state.backgroundColors.map { $0.rgb }, bubbleColors: state.messagesColors.map { $0.rgb }, animateBubbleColors: state.animateMessageColors, wallpaper: state.initialWallpaper ?? coloredWallpaper) } @@ -378,6 +378,7 @@ final class ThemeAccentColorController: ViewController { let messageColors: [UInt32] let defaultMessagesColor: UIColor? = nil var rotation: Int32 = 0 + let animateMessageColors: Bool func extractWallpaperParameters(_ wallpaper: TelegramWallpaper?) { guard let wallpaper = wallpaper else { @@ -428,7 +429,7 @@ final class ThemeAccentColorController: ViewController { } } - if case .colors(_, true) = strongSelf.mode { + if case let .colors(initialThemeReference, true) = strongSelf.mode { let themeSpecificAccentColor = settings.themeSpecificAccentColors[themeReference.index] accentColor = themeSpecificAccentColor?.color ?? defaultDayAccentColor @@ -443,6 +444,14 @@ final class ThemeAccentColorController: ViewController { wallpaper = theme.chat.defaultWallpaper } + if case let .cloud(cloudTheme) = initialThemeReference, let settings = cloudTheme.theme.settings { + animateMessageColors = settings.animateMessageColors + } else if let referenceTheme = referenceTheme { + animateMessageColors = referenceTheme.chat.animateMessageColors + } else { + animateMessageColors = false + } + extractBuiltinWallpaper(wallpaper) if !wallpaper.isColorOrGradient { @@ -486,6 +495,8 @@ final class ThemeAccentColorController: ViewController { } else { messageColors = [] } + + animateMessageColors = themeSettings.animateMessageColors } else if case .builtin = themeReference { let themeSpecificAccentColor = settings.themeSpecificAccentColors[themeReference.index] accentColor = themeSpecificAccentColor?.color ?? defaultDayAccentColor @@ -520,6 +531,8 @@ final class ThemeAccentColorController: ViewController { messageColors = [] } } + + animateMessageColors = false } else { let theme = makePresentationTheme(mediaBox: strongSelf.context.sharedContext.accountManager.mediaBox, themeReference: themeReference)! @@ -533,6 +546,8 @@ final class ThemeAccentColorController: ViewController { } messageColors = theme.chat.message.outgoing.bubble.withWallpaper.fill.map(\.rgb) + + animateMessageColors = theme.chat.animateMessageColors } } } else if case let .edit(theme, wallpaper, _, _, _, _) = strongSelf.mode { @@ -546,13 +561,17 @@ final class ThemeAccentColorController: ViewController { } messageColors = theme.chat.message.outgoing.bubble.withWallpaper.fill.map(\.rgb) + + animateMessageColors = theme.chat.animateMessageColors } else { accentColor = defaultDayAccentColor backgroundColors = [] messageColors = [] + + animateMessageColors = false } - let initialState = ThemeColorState(section: strongSelf.section, accentColor: HSBColor(color: accentColor), initialWallpaper: initialWallpaper, backgroundColors: backgroundColors.map { HSBColor(rgb: $0) }, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, animateMessageColors: false, defaultMessagesColor: defaultMessagesColor.flatMap { HSBColor(color: $0) }, messagesColors: messageColors.map { HSBColor(rgb: $0) }, selectedColor: 0, rotation: rotation) + let initialState = ThemeColorState(section: strongSelf.section, accentColor: HSBColor(color: accentColor), initialWallpaper: initialWallpaper, backgroundColors: backgroundColors.map { HSBColor(rgb: $0) }, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, animateMessageColors: animateMessageColors, defaultMessagesColor: defaultMessagesColor.flatMap { HSBColor(color: $0) }, messagesColors: messageColors.map { HSBColor(rgb: $0) }, selectedColor: 0, rotation: rotation) strongSelf.controllerNode.updateState({ _ in return initialState From 8fd6363e3385678c3968992838c5dcc7c8cb837f Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Aug 2021 14:10:16 +0400 Subject: [PATCH 06/10] Theme decoding fixes --- .../Sources/Themes/EditThemeController.swift | 6 +----- .../Sources/PresentationThemeCodable.swift | 1 + .../Sources/PresentationThemeCoder.swift | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 92d95f8309..b176103e2f 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -268,7 +268,6 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll let previewThemePromise = Promise() let settingsPromise = Promise(nil) let hasSettings: Bool - let mayHaveSettings: Bool let presentationData = context.sharedContext.currentPresentationData.with { $0 } switch mode { case let .create(existingTheme, settings): @@ -279,19 +278,16 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll wallpaper = theme.chat.defaultWallpaper settingsPromise.set(.single(settings)) hasSettings = settings != nil - mayHaveSettings = settings != nil } else { theme = presentationData.theme wallpaper = presentationData.chatWallpaper settingsPromise.set(.single(nil)) hasSettings = false - mayHaveSettings = true } initialState = EditThemeControllerState(mode: mode, title: generateThemeName(accentColor: theme.rootController.navigationBar.buttonColor), slug: "", updatedTheme: nil, updating: false) previewThemePromise.set(.single(theme.withUpdated(name: "", defaultWallpaper: wallpaper))) case let .edit(info): hasSettings = info.theme.settings != nil - mayHaveSettings = hasSettings settingsPromise.set(.single(info.theme.settings)) if let file = info.theme.file, let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let theme = makePresentationTheme(data: data, resolvedWallpaper: info.resolvedWallpaper) { if case let .file(file) = theme.chat.defaultWallpaper, file.id == 0 { @@ -344,7 +340,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll state.updatedTheme = updatedTheme return state } - if previousSettings != nil || mayHaveSettings { + if previousSettings != nil { settingsPromise.set(.single(settings)) } controllerDismissImpl?() diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index b1e9a99a11..7798583021 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -1690,6 +1690,7 @@ extension PresentationThemeChat: Codable { public func encode(to encoder: Encoder) throws { var values = encoder.container(keyedBy: CodingKeys.self) try values.encode(self.defaultWallpaper, forKey: .defaultWallpaper) + try values.encode(self.animateMessageColors, forKey: .animateMessageColors) try values.encode(self.message, forKey: .message) try values.encode(self.serviceMessage, forKey: .serviceMessage) try values.encode(self.inputPanel, forKey: .inputPanel) diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift index 474678ca56..95fb03aa9d 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCoder.swift @@ -465,6 +465,23 @@ class PresentationThemeDecoding: Decoder { } guard let topContainer = self.storage.topContainer as? [Any] else { + if let topContainer = self.storage.topContainer as? [String : Any] { + let sortedKeys = topContainer.keys.sorted(by: { lhs, rhs in + if let lhsValue = Int(lhs), let rhsValue = Int(rhs), lhsValue < rhsValue { + return true + } else { + return false + } + }) + var array: [Any] = [] + for key in sortedKeys { + if let value = topContainer[key] { + array.append(value) + } + } + return PresentationThemeUnkeyedDecodingContainer(referencing: self, wrapping: array) + } + throw PresentationThemeDecodingError.typeMismatch } From a3c07fdf9926e7580a94a2fa3c0375411f6beea0 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Aug 2021 16:12:52 +0400 Subject: [PATCH 07/10] Various theme editing fixes --- .../Themes/ThemeAccentColorControllerNode.swift | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 03c9295db2..78e5ea4337 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -758,6 +758,10 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate needsLayout = true } + if previousState.animateMessageColors != self.state.animateMessageColors { + needsLayout = true + } + if previousState.selectedColor != self.state.selectedColor { needsLayout = true } @@ -979,7 +983,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let toolbarHeight = 49.0 + layout.intrinsicInsets.bottom var relativeOffset: CGFloat = 0.0 - if !self.state.colorPanelCollapsed { + if !self.state.colorPanelCollapsed && self.state.section == .messages { relativeOffset = (CGFloat(self.state.selectedColor) / CGFloat(max(1, self.state.messagesColors.count))) * (self.colorPanelNode.frame.height + toolbarHeight + 144.0) * -1.0 } @@ -1128,8 +1132,10 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } else if self.state.section == .messages { if self.state.messagesColors.count >= 3 { patternAlpha = 1.0 - playAlpha = displayOptionButtons ? 1.0 : 0.0 - centerDistance += playButtonSize.width + playAlpha = displayOptionButtons && self.state.animateMessageColors ? 1.0 : 0.0 + if self.state.animateMessageColors { + centerDistance += playButtonSize.width + } } else { patternAlpha = 0.0 playAlpha = 0.0 @@ -1233,7 +1239,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } @objc private func playPressed() { - if self.state.backgroundColors.count >= 3 { + if self.state.backgroundColors.count >= 3 || self.state.messagesColors.count >= 3 { self.backgroundNode.animateEvent(transition: .animated(duration: 0.5, curve: .spring)) } else { self.updateState({ state in From 59d9772f903d5fccc67b8b8f39ec1f70cc292c9f Mon Sep 17 00:00:00 2001 From: overtake Date: Thu, 19 Aug 2021 15:52:36 +0300 Subject: [PATCH 08/10] syntax fixes --- .../Postbox/Sources/AccountManager.swift | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/submodules/Postbox/Sources/AccountManager.swift b/submodules/Postbox/Sources/AccountManager.swift index eed6a75d83..b2a26e9d54 100644 --- a/submodules/Postbox/Sources/AccountManager.swift +++ b/submodules/Postbox/Sources/AccountManager.swift @@ -245,7 +245,7 @@ final class AccountManagerImpl { if !self.currentRecordOperations.isEmpty || !self.currentMetadataOperations.isEmpty { for (view, pipe) in self.recordsViews.copyItems() { if view.replay(operations: self.currentRecordOperations, metadataOperations: self.currentMetadataOperations) { - pipe.putNext(AccountRecordsView(view)) + pipe.putNext(AccountRecordsView(view)) } } } @@ -253,7 +253,7 @@ final class AccountManagerImpl { if !self.currentUpdatedSharedDataKeys.isEmpty { for (view, pipe) in self.sharedDataViews.copyItems() { if view.replay(accountManagerImpl: self, updatedKeys: self.currentUpdatedSharedDataKeys) { - pipe.putNext(AccountSharedDataView(view)) + pipe.putNext(AccountSharedDataView(view)) } } } @@ -287,7 +287,7 @@ final class AccountManagerImpl { } fileprivate func accountRecords() -> Signal, NoError> { - return self.transaction(ignoreDisabled: false, { transaction -> Signal in + return self.transaction(ignoreDisabled: false, { transaction -> Signal, NoError> in return self.accountRecordsInternal(transaction: transaction) }) |> switchToLatest @@ -323,9 +323,9 @@ final class AccountManagerImpl { let index = self.recordsViews.add((mutableView, pipe)) let queue = self.queue - return (.single(AccountRecordsView(mutableView)) + return (.single(AccountRecordsView(mutableView)) |> then(pipe.signal())) - |> `catch` { _ -> Signal in + |> `catch` { _ -> Signal, NoError> in } |> afterDisposed { [weak self] in queue.async { @@ -337,14 +337,14 @@ final class AccountManagerImpl { } private func sharedDataInternal(transaction: AccountManagerModifier, keys: Set) -> Signal, NoError> { - let mutableView = MutableAccountSharedDataView(accountManagerImpl: self, keys: keys) + let mutableView = MutableAccountSharedDataView(accountManagerImpl: self, keys: keys) let pipe = ValuePipe>() let index = self.sharedDataViews.add((mutableView, pipe)) let queue = self.queue - return (.single(AccountSharedDataView(mutableView)) + return (.single(AccountSharedDataView(mutableView)) |> then(pipe.signal())) - |> `catch` { _ -> Signal in + |> `catch` { _ -> Signal, NoError> in } |> afterDisposed { [weak self] in queue.async { @@ -363,7 +363,7 @@ final class AccountManagerImpl { let queue = self.queue return (.single(NoticeEntryView(mutableView)) |> then(pipe.signal())) - |> `catch` { _ -> Signal in + |> `catch` { _ -> Signal, NoError> in } |> afterDisposed { [weak self] in queue.async { From 29c6321d397432e9398b87721abadd153582a80d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Aug 2021 17:58:07 +0400 Subject: [PATCH 09/10] Fix theme wallpaper coding --- .../Sources/PresentationThemeCodable.swift | 69 ++++++++----------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 7798583021..6af0656c74 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -87,52 +87,41 @@ extension TelegramWallpaper: Codable { blur = true } - if components.count >= 2 && components.count <= 5 && [6, 8].contains(components[0].count) && !optionKeys.contains(components[0]) && [6, 8].contains(components[1].count) && !optionKeys.contains(components[1]), let topColor = UIColor(hexString: components[0]), let bottomColor = UIColor(hexString: components[1]) { - var rotation: Int32? - if components.count > 2, components[2].count <= 3, let value = Int32(components[2]) { - if value >= 0 && value < 360 { - rotation = value - } + var slug: String? + var colors: [UIColor] = [] + var intensity: Int32? + var rotation: Int32? + for i in 0 ..< components.count { + let component = components[i] + if optionKeys.contains(component) { + continue } - self = .gradient(TelegramWallpaper.Gradient(id: nil, colors: [topColor.argb, bottomColor.argb], settings: WallpaperSettings(blur: blur, motion: motion, rotation: rotation))) - } else { - var slug: String? - var colors: [UInt32] = [] - var intensity: Int32? - var rotation: Int32? - - if !components.isEmpty { - slug = components[0] - } - if components.count > 1 { - for i in 1 ..< components.count { - let component = components[i] - if optionKeys.contains(component) { - continue + if i == 0 && component.count > 8 { + slug = component + } else if [6, 8].contains(component.count), let color = UIColor(hexString: component) { + colors.append(color) + } else if component.count <= 4, let value = Int32(component) { + if intensity == nil { + if value >= -100 && value <= 100 { + intensity = value + } else { + intensity = 50 } - if [6, 8].contains(component.count), let value = UIColor(hexString: component) { - colors.append(value.rgb) - } else if component.count <= 3, let value = Int32(component) { - if intensity == nil { - if value >= -100 && value <= 100 { - intensity = value - } else { - intensity = 50 - } - } else if rotation == nil { - if value >= 0 && value < 360 { - rotation = value - } - } + } else if rotation == nil { + if value >= 0 && value < 360 { + rotation = value } } } - if let slug = slug { - self = .file(TelegramWallpaper.File(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: !colors.isEmpty, isDark: false, slug: slug, file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: WallpaperDataResource(slug: slug), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(blur: blur, motion: motion, colors: colors, intensity: intensity, rotation: rotation))) - } else { - throw PresentationThemeDecodingError.generic - } + } + + if let slug = slug { + self = .file(TelegramWallpaper.File(id: 0, accessHash: 0, isCreator: false, isDefault: false, isPattern: !colors.isEmpty, isDark: false, slug: slug, file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: WallpaperDataResource(slug: slug), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "", size: nil, attributes: []), settings: WallpaperSettings(blur: blur, motion: motion, colors: colors.map { $0.argb }, intensity: intensity, rotation: rotation))) + } else if colors.count > 1 { + self = .gradient(TelegramWallpaper.Gradient(id: nil, colors: colors.map { $0.argb }, settings: WallpaperSettings(blur: blur, motion: motion, rotation: rotation))) + } else { + throw PresentationThemeDecodingError.generic } } } From 12879ea450cf456c6de783739e2a73304a096e20 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 19 Aug 2021 18:25:57 +0400 Subject: [PATCH 10/10] Theme editing fixes --- .../SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift b/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift index 81e8bd28e0..50e51a2aef 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperColorPickerNode.swift @@ -287,7 +287,7 @@ struct HSBColor: Equatable { } var rgb: UInt32 { - return self.color.rgb + return self.color.argb } init(values: (h: CGFloat, s: CGFloat, b: CGFloat)) {