mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-05 05:51:42 +00:00
Merge commit 'c7fe52fd728ed7fd11b5ac2c401fff3b3d6de597'
This commit is contained in:
commit
904151cb85
@ -6608,3 +6608,48 @@ 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";
|
||||
|
||||
"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.";
|
||||
"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**";
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -245,7 +245,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
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<Types>(view))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -253,7 +253,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
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<Types>(view))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -287,7 +287,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
}
|
||||
|
||||
fileprivate func accountRecords() -> Signal<AccountRecordsView<Types>, NoError> {
|
||||
return self.transaction(ignoreDisabled: false, { transaction -> Signal<AccountRecordsView, NoError> in
|
||||
return self.transaction(ignoreDisabled: false, { transaction -> Signal<AccountRecordsView<Types>, NoError> in
|
||||
return self.accountRecordsInternal(transaction: transaction)
|
||||
})
|
||||
|> switchToLatest
|
||||
@ -323,9 +323,9 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
let index = self.recordsViews.add((mutableView, pipe))
|
||||
|
||||
let queue = self.queue
|
||||
return (.single(AccountRecordsView(mutableView))
|
||||
return (.single(AccountRecordsView<Types>(mutableView))
|
||||
|> then(pipe.signal()))
|
||||
|> `catch` { _ -> Signal<AccountRecordsView, NoError> in
|
||||
|> `catch` { _ -> Signal<AccountRecordsView<Types>, NoError> in
|
||||
}
|
||||
|> afterDisposed { [weak self] in
|
||||
queue.async {
|
||||
@ -337,14 +337,14 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
}
|
||||
|
||||
private func sharedDataInternal(transaction: AccountManagerModifier<Types>, keys: Set<ValueBoxKey>) -> Signal<AccountSharedDataView<Types>, NoError> {
|
||||
let mutableView = MutableAccountSharedDataView(accountManagerImpl: self, keys: keys)
|
||||
let mutableView = MutableAccountSharedDataView<Types>(accountManagerImpl: self, keys: keys)
|
||||
let pipe = ValuePipe<AccountSharedDataView<Types>>()
|
||||
let index = self.sharedDataViews.add((mutableView, pipe))
|
||||
|
||||
let queue = self.queue
|
||||
return (.single(AccountSharedDataView(mutableView))
|
||||
return (.single(AccountSharedDataView<Types>(mutableView))
|
||||
|> then(pipe.signal()))
|
||||
|> `catch` { _ -> Signal<AccountSharedDataView, NoError> in
|
||||
|> `catch` { _ -> Signal<AccountSharedDataView<Types>, NoError> in
|
||||
}
|
||||
|> afterDisposed { [weak self] in
|
||||
queue.async {
|
||||
@ -363,7 +363,7 @@ final class AccountManagerImpl<Types: AccountManagerTypes> {
|
||||
let queue = self.queue
|
||||
return (.single(NoticeEntryView(mutableView))
|
||||
|> then(pipe.signal()))
|
||||
|> `catch` { _ -> Signal<NoticeEntryView, NoError> in
|
||||
|> `catch` { _ -> Signal<NoticeEntryView<Types>, NoError> in
|
||||
}
|
||||
|> afterDisposed { [weak self] in
|
||||
queue.async {
|
||||
|
||||
@ -323,6 +323,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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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?
|
||||
@ -201,13 +201,13 @@ 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 }, 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<Void, CreateThemeError>
|
||||
@ -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, 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: animateMessageColors, defaultMessagesColor: defaultMessagesColor.flatMap { HSBColor(color: $0) }, messagesColors: messageColors.map { HSBColor(rgb: $0) }, selectedColor: 0, rotation: rotation)
|
||||
|
||||
strongSelf.controllerNode.updateState({ _ in
|
||||
return initialState
|
||||
|
||||
@ -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) {
|
||||
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
|
||||
@ -731,6 +754,21 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
needsLayout = true
|
||||
}
|
||||
|
||||
if previousState.messagesColors.count != self.state.messagesColors.count {
|
||||
needsLayout = true
|
||||
}
|
||||
|
||||
if previousState.animateMessageColors != self.state.animateMessageColors {
|
||||
needsLayout = true
|
||||
}
|
||||
|
||||
if previousState.selectedColor != self.state.selectedColor {
|
||||
needsLayout = true
|
||||
}
|
||||
|
||||
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: [])
|
||||
@ -738,6 +776,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
self.playButtonNode.setImage(self.playButtonPlayImage, for: [])
|
||||
}
|
||||
}
|
||||
case .accent:
|
||||
break
|
||||
case .messages:
|
||||
self.playButtonNode.setImage(self.playButtonPlayImage, for: [])
|
||||
}
|
||||
}
|
||||
|
||||
self.colorsButtonNode.isSelected = !self.state.colorPanelCollapsed
|
||||
|
||||
@ -755,6 +799,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
updated.section = section
|
||||
updated.displayPatternPanel = false
|
||||
updated.colorPanelCollapsed = false
|
||||
updated.selectedColor = 0
|
||||
return updated
|
||||
}, animated: true)
|
||||
}
|
||||
@ -884,22 +929,11 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
}
|
||||
strongSelf.updateState({ state in
|
||||
var state = state
|
||||
//if state.section == .background {
|
||||
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 +942,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, removeOnCompletion: false, 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 +966,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 +975,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 && 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
|
||||
}
|
||||
|
||||
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 +1009,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 +1080,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 +1108,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 +1121,32 @@ 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
|
||||
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 && self.state.animateMessageColors ? 1.0 : 0.0
|
||||
if self.state.animateMessageColors {
|
||||
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,6 +1160,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
}
|
||||
|
||||
@objc private func togglePattern() {
|
||||
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
|
||||
@ -1109,8 +1187,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
updated.backgroundColors = []
|
||||
}
|
||||
}
|
||||
appeared = true
|
||||
}
|
||||
appeared = true
|
||||
} else {
|
||||
updated.colorPanelCollapsed = true
|
||||
if updated.patternWallpaper != nil {
|
||||
@ -1140,6 +1218,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
self.patternPanelNode.didAppear(initialWallpaper: wallpaper, intensity: self.state.patternIntensity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func toggleColors() {
|
||||
self.updateState({ current in
|
||||
@ -1160,12 +1239,12 @@ 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
|
||||
var state = state
|
||||
state.rotation = (state.rotation + 90) % 360
|
||||
state.rotation = (state.rotation + 45) % 360
|
||||
return state
|
||||
}, animated: true)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
@ -286,19 +287,22 @@ struct HSBColor: Equatable {
|
||||
}
|
||||
|
||||
var rgb: UInt32 {
|
||||
return self.color.rgb
|
||||
return self.color.argb
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -87,35 +87,23 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
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 colors: [UIColor] = []
|
||||
var intensity: Int32?
|
||||
var rotation: Int32?
|
||||
|
||||
if !components.isEmpty {
|
||||
slug = components[0]
|
||||
}
|
||||
if components.count > 1 {
|
||||
for i in 1 ..< components.count {
|
||||
for i in 0 ..< components.count {
|
||||
let component = components[i]
|
||||
if optionKeys.contains(component) {
|
||||
continue
|
||||
}
|
||||
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 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 >= 0 && value <= 100 {
|
||||
if value >= -100 && value <= 100 {
|
||||
intensity = value
|
||||
} else {
|
||||
intensity = 50
|
||||
@ -127,15 +115,16 @@ extension TelegramWallpaper: Codable {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw PresentationThemeDecodingError.generic
|
||||
}
|
||||
@ -1659,6 +1648,7 @@ extension PresentationThemeChat: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case defaultWallpaper
|
||||
case message
|
||||
case animateMessageColors
|
||||
case serviceMessage
|
||||
case inputPanel
|
||||
case inputMediaPanel
|
||||
@ -1677,6 +1667,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),
|
||||
@ -1688,6 +1679,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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -773,9 +773,9 @@ 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()
|
||||
let outgoingBubbleGradientBackgroundNode = GradientBackgroundNode(adjustSaturation: false)
|
||||
if let size = self.validLayout {
|
||||
outgoingBubbleGradientBackgroundNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
outgoingBubbleGradientBackgroundNode.updateLayout(size: size, transition: .immediate)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user