diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 818c215c06..97b818ce4c 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -6573,3 +6573,12 @@ Sorry for the inconvenience."; "PlaybackSpeed.Title" = "Playback Speed"; "PlaybackSpeed.Normal" = "Normal"; + +"Chat.NextChannelSameLocationSwipeProgress" = "Swipe up to go to the next unread channel"; +"Chat.NextChannelSameLocationSwipeAction" = "Release to go to the next unread channel"; +"Chat.NextChannelFolderSwipeProgress" = "Swipe up to go to the %@ folder"; +"Chat.NextChannelFolderSwipeAction" = "Release to go to the %@ folder"; +"Chat.NextChannelArchivedSwipeProgress" = "Swipe up to go to archived channels"; +"Chat.NextChannelArchivedSwipeAction" = "Release to go to archived channels"; +"Chat.NextChannelUnarchivedSwipeProgress" = "Swipe up to go to unarchived channels"; +"Chat.NextChannelUnarchivedSwipeAction" = "Release to go to unarchived channels"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 6367b713ef..610862991c 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -289,10 +289,10 @@ public final class NavigateToChatControllerParams { public let animated: Bool public let options: NavigationAnimationOptions public let parentGroupId: PeerGroupId? - public let chatListFilter: ChatListFilterData? + public let chatListFilter: Int32? public let completion: (ChatController) -> Void - public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic = Atomic(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: ChatListFilterData? = nil, completion: @escaping (ChatController) -> Void = { _ in }) { + public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic = Atomic(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, completion: @escaping (ChatController) -> Void = { _ in }) { self.navigationController = navigationController self.chatController = chatController self.chatLocationContextHolder = chatLocationContextHolder diff --git a/submodules/AudioBlob/Sources/BlobView.swift b/submodules/AudioBlob/Sources/BlobView.swift index 9bae6d2c5b..c1b287fbe5 100644 --- a/submodules/AudioBlob/Sources/BlobView.swift +++ b/submodules/AudioBlob/Sources/BlobView.swift @@ -46,6 +46,8 @@ public final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDeco private let hierarchyTrackingNode: HierarchyTrackingNode private var isCurrentlyInHierarchy = true + + public var isManuallyInHierarchy: Bool? private var audioLevel: CGFloat = 0 public var presentationAudioLevel: CGFloat = 0 @@ -136,6 +138,9 @@ public final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDeco } public func setColor(_ color: UIColor, animated: Bool) { + if let isManuallyInHierarchy = self.isManuallyInHierarchy, !isManuallyInHierarchy { + return + } smallBlob.setColor(color, animated: animated) mediumBlob.setColor(color.withAlphaComponent(0.3), animated: animated) bigBlob.setColor(color.withAlphaComponent(0.15), animated: animated) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 34f22c5b6b..0971c9c5b7 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -612,7 +612,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController scrollToEndIfExists = true } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), activateInput: activateInput && !peer.isDeleted, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, chatListFilter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.data, completion: { [weak self] controller in + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), activateInput: activateInput && !peer.isDeleted, scrollToEndIfExists: scrollToEndIfExists, animated: !scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, chatListFilter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.id, completion: { [weak self] controller in self?.chatListDisplayNode.containerNode.currentItemNode.clearHighlightAnimated(true) if let promoInfo = promoInfo { switch promoInfo { diff --git a/submodules/ComponentFlow/Source/Base/CombinedComponent.swift b/submodules/ComponentFlow/Source/Base/CombinedComponent.swift index ead71c9b1f..0d64eb3a67 100644 --- a/submodules/ComponentFlow/Source/Base/CombinedComponent.swift +++ b/submodules/ComponentFlow/Source/Base/CombinedComponent.swift @@ -175,6 +175,8 @@ public final class _UpdatedChildComponent { var _removed: Bool = false var _position: CGPoint? var _opacity: CGFloat? + var _cornerRadius: CGFloat? + var _clipsToBounds: Bool? fileprivate var transitionAppear: Transition.Appear? fileprivate var transitionAppearWithGuide: (Transition.AppearWithGuide, _AnyChildComponent.Id)? @@ -241,6 +243,16 @@ public final class _UpdatedChildComponent { return self } + @discardableResult public func cornerRadius(_ cornerRadius: CGFloat) -> _UpdatedChildComponent { + self._cornerRadius = cornerRadius + return self + } + + @discardableResult public func clipsToBounds(_ clipsToBounds: Bool) -> _UpdatedChildComponent { + self._clipsToBounds = clipsToBounds + return self + } + @discardableResult public func gesture(_ gesture: Gesture) -> _UpdatedChildComponent { self.gestures.append(gesture) return self @@ -672,6 +684,8 @@ public extension CombinedComponent { updatedChild.view.frame = updatedChild.size.centered(around: updatedChild._position ?? CGPoint()) updatedChild.view.alpha = updatedChild._opacity ?? 1.0 + updatedChild.view.clipsToBounds = updatedChild._clipsToBounds ?? false + updatedChild.view.layer.cornerRadius = updatedChild._cornerRadius ?? 0.0 updatedChild.view.context(typeErasedComponent: updatedChild.component).erasedState._updated = { [weak viewContext] transition in guard let viewContext = viewContext else { return diff --git a/submodules/Display/Source/GenerateImage.swift b/submodules/Display/Source/GenerateImage.swift index 8d3e7a6ae6..83a49888c7 100644 --- a/submodules/Display/Source/GenerateImage.swift +++ b/submodules/Display/Source/GenerateImage.swift @@ -300,18 +300,23 @@ public func generateGradientTintedImage(image: UIImage?, colors: [UIColor]) -> U context.scaleBy(x: 1.0, y: -1.0) context.translateBy(x: -imageRect.midX, y: -imageRect.midY) context.clip(to: imageRect, mask: image.cgImage!) - - let gradientColors = colors.map { $0.cgColor } as CFArray - let delta: CGFloat = 1.0 / (CGFloat(colors.count) - 1.0) - - var locations: [CGFloat] = [] - for i in 0 ..< colors.count { - locations.append(delta * CGFloat(i)) + + if colors.count >= 2 { + let gradientColors = colors.map { $0.cgColor } as CFArray + + var locations: [CGFloat] = [] + for i in 0 ..< colors.count { + let t = CGFloat(i) / CGFloat(colors.count - 1) + locations.append(t) + } + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: imageRect.height), end: CGPoint(x: 0.0, y: 0.0), options: CGGradientDrawingOptions()) + } else if !colors.isEmpty { + context.setFillColor(colors[0].cgColor) + context.fill(imageRect) } - let colorSpace = CGColorSpaceCreateDeviceRGB() - let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)! - - context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: imageRect.height), end: CGPoint(x: 0.0, y: 0.0), options: CGGradientDrawingOptions()) context.restoreGState() } diff --git a/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift b/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift index 3d99089a0a..429c89d459 100644 --- a/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift +++ b/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift @@ -207,7 +207,7 @@ final class PasscodeEntryControllerNode: ASDisplayNode { let baseColor: UIColor let lightness = color.lightness if lightness < 0.1 || lightness > 0.9 { - baseColor = self.theme.chat.message.outgoing.bubble.withoutWallpaper.fill + baseColor = self.theme.chat.message.outgoing.bubble.withoutWallpaper.fill[0] } else{ baseColor = color } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index 751669efed..828478a78a 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -10,6 +10,7 @@ import TelegramUIPreferences import ItemListUI import PresentationDataUtils import AccountContext +import WallpaperBackgroundNode class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { let context: AccountContext @@ -75,7 +76,7 @@ class ForwardPrivacyChatPreviewItem: ListViewItem, ItemListItem { } class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { - private let backgroundNode: ASImageNode + private var backgroundNode: WallpaperBackgroundNode? private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let maskNode: ASImageNode @@ -91,12 +92,6 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { private var item: ForwardPrivacyChatPreviewItem? init() { - self.backgroundNode = ASImageNode() - self.backgroundNode.isLayerBacked = true - self.backgroundNode.displaysAsynchronously = false - self.backgroundNode.displayWithoutProcessing = true - self.backgroundNode.contentMode = .scaleAspectFill - self.topStripeNode = ASDisplayNode() self.topStripeNode.isLayerBacked = true @@ -130,21 +125,17 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { } func asyncLayout() -> (_ item: ForwardPrivacyChatPreviewItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { - let currentItem = self.item - let currentNode = self.messageNode let makeTextLayout = TextNode.asyncLayout(self.measureTextNode) + + var currentBackgroundNode = self.backgroundNode return { item, params, neighbors in - var updatedBackgroundImage: UIImage? - var backgroundImageContentMode = UIView.ContentMode.scaleAspectFill - if currentItem?.wallpaper != item.wallpaper { - updatedBackgroundImage = chatControllerBackgroundImage(theme: item.theme, wallpaper: item.wallpaper, mediaBox: item.context.sharedContext.accountManager.mediaBox, knockoutMode: item.context.sharedContext.immediateExperimentalUISettings.knockoutWallpaper) - - if case .gradient = item.wallpaper { - backgroundImageContentMode = .scaleToFill - } + if currentBackgroundNode == nil { + currentBackgroundNode = WallpaperBackgroundNode(context: item.context) } + currentBackgroundNode?.update(wallpaper: item.wallpaper) + currentBackgroundNode?.updateBubbleTheme(bubbleTheme: item.theme, bubbleCorners: item.chatBubbleCorners) let insets: UIEdgeInsets let separatorHeight = UIScreenPixel @@ -158,7 +149,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: []) - let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: nil) + let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode) var node: ListViewItemNode? if let current = currentNode { @@ -227,17 +218,15 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { node.updateFrame(CGRect(origin: CGPoint(x: 0.0, y: topOffset), size: node.frame.size), within: layout.contentSize) topOffset += node.frame.size.height } - - if let updatedBackgroundImage = updatedBackgroundImage { - strongSelf.backgroundNode.image = updatedBackgroundImage - strongSelf.backgroundNode.contentMode = backgroundImageContentMode - } + strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor - - if strongSelf.backgroundNode.supernode == nil { - strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) + + if let currentBackgroundNode = currentBackgroundNode, strongSelf.backgroundNode !== currentBackgroundNode { + strongSelf.backgroundNode = currentBackgroundNode + strongSelf.insertSubnode(currentBackgroundNode, at: 0) } + if strongSelf.topStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1) } @@ -273,7 +262,14 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, 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))) - strongSelf.backgroundNode.frame = backgroundFrame.insetBy(dx: 0.0, dy: -100.0) + + 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.updateLayout(size: backgroundNode.bounds.size, transition: .immediate) + } + strongSelf.maskNode.frame = backgroundFrame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index 10bc360375..ce33330196 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -14,12 +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: (top: UIColor, bottom: UIColor?)?, wallpaper: TelegramWallpaper?) { - var messageColorsValues: (UInt32, UInt32)? - if let colors = messageColors { - messageColorsValues = (colors.0.argb, colors.1?.argb ?? colors.0.argb) - } - self.init(baseTheme: baseTheme, accentColor: accentColor.argb, messageColors: messageColorsValues, wallpaper: wallpaper) + convenience init(baseTheme: TelegramBaseTheme, accentColor: UIColor, messageColors: [UInt32], wallpaper: TelegramWallpaper?) { + self.init(baseTheme: baseTheme, accentColor: accentColor.argb, messageColors: messageColors, wallpaper: wallpaper) } } @@ -379,7 +375,7 @@ final class ThemeAccentColorController: ViewController { var backgroundColors: [UInt32] = [] var patternWallpaper: TelegramWallpaper? var patternIntensity: Int32 = 50 - let messageColors: (UIColor, UIColor?)? + let messageColors: [UInt32] let defaultMessagesColor: UIColor? = nil var rotation: Int32 = 0 @@ -459,19 +455,15 @@ final class ThemeAccentColorController: ViewController { extractWallpaperParameters(wallpaper) } - if let bubbleColors = settings.themeSpecificAccentColors[themeReference.index]?.customBubbleColors { - if let bottomColor = bubbleColors.1 { - messageColors = (bubbleColors.0, bottomColor) - } else { - messageColors = (bubbleColors.0, nil) - } + if let bubbleColors = settings.themeSpecificAccentColors[themeReference.index]?.customBubbleColors, !bubbleColors.isEmpty { + messageColors = bubbleColors } else { if let themeReference = strongSelf.mode.themeReference, themeReference == .builtin(.dayClassic), settings.themeSpecificAccentColors[themeReference.index] == nil { - messageColors = (UIColor(rgb: 0xe1ffc7), nil) + messageColors = [UIColor(rgb: 0xe1ffc7).rgb] } else if let referenceTheme = referenceTheme { - messageColors = (referenceTheme.chat.message.outgoing.bubble.withoutWallpaper.fill, referenceTheme.chat.message.outgoing.bubble.withoutWallpaper.gradientFill) + messageColors = referenceTheme.chat.message.outgoing.bubble.withoutWallpaper.fill.map(\.rgb) } else { - messageColors = nil + messageColors = [] } } } else { @@ -489,16 +481,10 @@ final class ThemeAccentColorController: ViewController { initialWallpaper = wallpaper } - if let colors = themeSettings.messageColors { - let topMessageColor = UIColor(argb: colors.top) - let bottomMessageColor = UIColor(argb: colors.bottom) - if topMessageColor.argb == bottomMessageColor.argb { - messageColors = (topMessageColor, nil) - } else { - messageColors = (topMessageColor, bottomMessageColor) - } + if !themeSettings.messageColors.isEmpty { + messageColors = themeSettings.messageColors } else { - messageColors = nil + messageColors = [] } } else if case .builtin = themeReference { let themeSpecificAccentColor = settings.themeSpecificAccentColors[themeReference.index] @@ -525,17 +511,13 @@ final class ThemeAccentColorController: ViewController { extractWallpaperParameters(wallpaper) } - if let bubbleColors = settings.themeSpecificAccentColors[themeReference.index]?.customBubbleColors { - if let bottomColor = bubbleColors.1 { - messageColors = (bubbleColors.0, bottomColor) - } else { - messageColors = (bubbleColors.0, nil) - } + if let bubbleColors = settings.themeSpecificAccentColors[themeReference.index]?.customBubbleColors, !bubbleColors.isEmpty { + messageColors = bubbleColors } else { if let themeReference = strongSelf.mode.themeReference, themeReference == .builtin(.dayClassic), settings.themeSpecificAccentColors[themeReference.index] == nil { - messageColors = (UIColor(rgb: 0xe1ffc7), nil) + messageColors = [UIColor(rgb: 0xe1ffc7).rgb] } else { - messageColors = nil + messageColors = [] } } } else { @@ -550,14 +532,7 @@ final class ThemeAccentColorController: ViewController { initialWallpaper = wallpaper } - let topMessageColor = theme.chat.message.outgoing.bubble.withWallpaper.fill - let bottomMessageColor = theme.chat.message.outgoing.bubble.withWallpaper.gradientFill - - if topMessageColor.argb == bottomMessageColor.argb { - messageColors = (topMessageColor, nil) - } else { - messageColors = (topMessageColor, bottomMessageColor) - } + messageColors = theme.chat.message.outgoing.bubble.withWallpaper.fill.map(\.rgb) } } } else if case let .edit(theme, wallpaper, _, _, _, _) = strongSelf.mode { @@ -570,18 +545,11 @@ final class ThemeAccentColorController: ViewController { initialWallpaper = wallpaper } - let topMessageColor = theme.chat.message.outgoing.bubble.withWallpaper.fill - let bottomMessageColor = theme.chat.message.outgoing.bubble.withWallpaper.gradientFill - - if topMessageColor.argb == bottomMessageColor.argb { - messageColors = (topMessageColor, nil) - } else { - messageColors = (topMessageColor, bottomMessageColor) - } + messageColors = theme.chat.message.outgoing.bubble.withWallpaper.fill.map(\.rgb) } else { accentColor = defaultDayAccentColor backgroundColors = [] - messageColors = nil + messageColors = [] } let initialState = ThemeColorState(section: strongSelf.section, accentColor: accentColor, initialWallpaper: initialWallpaper, backgroundColors: backgroundColors, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, defaultMessagesColor: defaultMessagesColor, messagesColors: messageColors, rotation: rotation) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 2569a513a4..0680d731df 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -49,7 +49,7 @@ struct ThemeColorState { var patternIntensity: Int32 var defaultMessagesColor: UIColor? - var messagesColors: (UIColor, UIColor?)? + var messagesColors: [UInt32] var rotation: Int32 @@ -65,11 +65,11 @@ struct ThemeColorState { self.patternWallpaper = nil self.patternIntensity = 50 self.defaultMessagesColor = nil - self.messagesColors = nil + self.messagesColors = [] self.rotation = 0 } - init(section: ThemeColorSection, accentColor: UIColor, initialWallpaper: TelegramWallpaper?, backgroundColors: [UInt32], patternWallpaper: TelegramWallpaper?, patternIntensity: Int32, defaultMessagesColor: UIColor?, messagesColors: (UIColor, UIColor?)?, rotation: Int32 = 0) { + init(section: ThemeColorSection, accentColor: UIColor, initialWallpaper: TelegramWallpaper?, backgroundColors: [UInt32], patternWallpaper: TelegramWallpaper?, patternIntensity: Int32, defaultMessagesColor: UIColor?, messagesColors: [UInt32], rotation: Int32 = 0) { self.section = section self.colorPanelCollapsed = false self.displayPatternPanel = false @@ -105,20 +105,10 @@ struct ThemeColorState { return false } - if let lhsMessagesColors = self.messagesColors, let rhsMessagesColors = otherState.messagesColors { - if lhsMessagesColors.0 != rhsMessagesColors.0 { - return false - } - if let lhsSecondColor = lhsMessagesColors.1, let rhsSecondColor = rhsMessagesColors.1 { - if lhsSecondColor != rhsSecondColor { - return false - } - } else if (lhsMessagesColors.1 == nil) != (rhsMessagesColors.1 == nil) { - return false - } - } else if (self.messagesColors == nil) != (otherState.messagesColors == nil) { + if self.messagesColors != otherState.messagesColors { return false } + return true } } @@ -347,11 +337,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate case .background: updated.backgroundColors = colors case .messages: - if colors.count >= 1 { - updated.messagesColors = (UIColor(rgb: colors[0]), colors.count >= 2 ? UIColor(rgb: colors[1]) : nil) - } else { - updated.messagesColors = nil - } + updated.messagesColors = colors } return updated }) @@ -662,12 +648,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } else { defaultColor = self.state.accentColor } - if let messagesColors = self.state.messagesColors { - if let second = messagesColors.1 { - colors = [messagesColors.0.rgb, second.rgb] - } else { - colors = [messagesColors.0.rgb] - } + if !self.state.messagesColors.isEmpty { + colors = self.state.messagesColors } else { colors = [] } @@ -684,7 +666,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate case .background: maximumNumberOfColors = 4 case .messages: - maximumNumberOfColors = 2 + maximumNumberOfColors = 4 default: maximumNumberOfColors = 1 } @@ -900,10 +882,10 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } strongSelf.updateState({ state in var state = state - if state.section == .background { + //if state.section == .background { state.colorPanelCollapsed = true state.displayPatternPanel = false - } + //} return state }, animated: true) /*if message.flags.contains(.Incoming) { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeColorPresets.swift b/submodules/SettingsUI/Sources/Themes/ThemeColorPresets.swift index 4fce8c0eb4..2f204a32a5 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeColorPresets.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeColorPresets.swift @@ -10,37 +10,37 @@ private func patternWallpaper(data: BuiltinWallpaperData, colors: [UInt32], inte var dayClassicColorPresets: [PresentationThemeAccentColor] = [ // Pink with Blue - PresentationThemeAccentColor(index: 106, baseColor: .preset, accentColor: 0xfff55783, bubbleColors: (0xffd6f5ff, 0xffc9fdfe), wallpaper: patternWallpaper(data: .default, colors: [0x8dc0eb, 0xb9d1ea, 0xc6b1ef, 0xebd7ef], intensity: 50, rotation: nil)), + PresentationThemeAccentColor(index: 106, baseColor: .preset, accentColor: 0xfff55783, bubbleColors: [0xffd6f5ff, 0xffc9fdfe], wallpaper: patternWallpaper(data: .default, colors: [0x8dc0eb, 0xb9d1ea, 0xc6b1ef, 0xebd7ef], intensity: 50, rotation: nil)), // Pink with Gold - PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0xFFFF5FA9, bubbleColors: (0xFFFFF4D7, nil), wallpaper: patternWallpaper(data: .variant12, colors: [0xeaa36e, 0xf0e486, 0xf29ebf, 0xe8c06e], intensity: 50, rotation: nil)), + PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0xFFFF5FA9, bubbleColors: [0xFFFFF4D7], wallpaper: patternWallpaper(data: .variant12, colors: [0xeaa36e, 0xf0e486, 0xf29ebf, 0xe8c06e], intensity: 50, rotation: nil)), // Green - PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xFF5A9E29, bubbleColors: (0xffFFF8DF, nil), wallpaper: patternWallpaper(data: .variant13, colors: [0x7fc289, 0xe4d573, 0xafd677, 0xf0c07a], intensity: 50, rotation: nil)), + PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xFF5A9E29, bubbleColors: [0xffFFF8DF], wallpaper: patternWallpaper(data: .variant13, colors: [0x7fc289, 0xe4d573, 0xafd677, 0xf0c07a], intensity: 50, rotation: nil)), // Purple - PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0xFF7E5FE5, bubbleColors: (0xFFF5e2FF, nil), wallpaper: patternWallpaper(data: .variant14, colors: [0xe4b2ea, 0x8376c2, 0xeab9d9, 0xb493e6], intensity: 50, rotation: nil)), + PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0xFF7E5FE5, bubbleColors: [0xFFF5e2FF], wallpaper: patternWallpaper(data: .variant14, colors: [0xe4b2ea, 0x8376c2, 0xeab9d9, 0xb493e6], intensity: 50, rotation: nil)), // Light Blue - PresentationThemeAccentColor(index: 107, baseColor: .preset, accentColor: 0xFF2CB9ED, bubbleColors: (0xFFADF7B5, 0xFFFCFF8B), wallpaper: patternWallpaper(data: .variant3, colors: [0x1a2e1a, 0x47623c, 0x222e24, 0x314429], intensity: 50, rotation: nil)), + PresentationThemeAccentColor(index: 107, baseColor: .preset, accentColor: 0xFF2CB9ED, bubbleColors: [0xFFADF7B5, 0xFFFCFF8B], wallpaper: patternWallpaper(data: .variant3, colors: [0x1a2e1a, 0x47623c, 0x222e24, 0x314429], intensity: 50, rotation: nil)), // Mint - PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xFF199972, bubbleColors: (0xFFFFFEC7, nil), wallpaper: patternWallpaper(data: .variant3, colors: [0xdceb92, 0x8fe1d6, 0x67a3f2, 0x85d685], intensity: 50, rotation: nil)), + PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xFF199972, bubbleColors: [0xFFFFFEC7], wallpaper: patternWallpaper(data: .variant3, colors: [0xdceb92, 0x8fe1d6, 0x67a3f2, 0x85d685], intensity: 50, rotation: nil)), // Pink with Green - PresentationThemeAccentColor(index: 105, baseColor: .preset, accentColor: 0xFFDA90D9, bubbleColors: (0xFF94FFF9, 0xFFCCFFC7), wallpaper: patternWallpaper(data: .variant9, colors: [0xffc3b2, 0xe2c0ff, 0xffe7b2], intensity: 50, rotation: nil)) + PresentationThemeAccentColor(index: 105, baseColor: .preset, accentColor: 0xFFDA90D9, bubbleColors: [0xFF94FFF9, 0xFFCCFFC7], wallpaper: patternWallpaper(data: .variant9, colors: [0xffc3b2, 0xe2c0ff, 0xffe7b2], intensity: 50, rotation: nil)) ] var dayColorPresets: [PresentationThemeAccentColor] = [ - PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0x007aff, bubbleColors: (0x007aff, 0xff53f4), wallpaper: nil), - PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0x00b09b, bubbleColors: (0xaee946, 0x00b09b), wallpaper: nil), - PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xd33213, bubbleColors: (0xf9db00, 0xd33213), wallpaper: nil), - PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xea8ced, bubbleColors: (0xea8ced, 0x00c2ed), wallpaper: nil) + PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0x007aff, bubbleColors: [0x007aff, 0xff53f4], wallpaper: nil), + PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0x00b09b, bubbleColors: [0xaee946, 0x00b09b], wallpaper: nil), + PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xd33213, bubbleColors: [0xf9db00, 0xd33213], wallpaper: nil), + PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xea8ced, bubbleColors: [0xea8ced, 0x00c2ed], wallpaper: nil) ] var nightColorPresets: [PresentationThemeAccentColor] = [ - PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0x007aff, bubbleColors: (0x007aff, 0xff53f4), wallpaper: patternWallpaper(data: .variant4, colors: [0xe4b2ea, 0x8376c2, 0xeab9d9, 0xb493e6], intensity: -35, rotation: nil)), - PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0x00b09b, bubbleColors: (0xaee946, 0x00b09b), wallpaper: patternWallpaper(data: .variant9, colors: [0xe4b2ea, 0x8376c2, 0xeab9d9, 0xb493e6], intensity: -35, rotation: nil)), - PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xd33213, bubbleColors: (0xf9db00, 0xd33213), wallpaper: patternWallpaper(data: .variant2, colors: [0xfec496, 0xdd6cb9, 0x962fbf, 0x4f5bd5], intensity: -40, rotation: nil)), - PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xea8ced, bubbleColors: (0xea8ced, 0x00c2ed), wallpaper: patternWallpaper(data: .variant6, colors: [0x8adbf2, 0x888dec, 0xe39fea, 0x679ced], intensity: -30, rotation: nil)) + PresentationThemeAccentColor(index: 101, baseColor: .preset, accentColor: 0x007aff, bubbleColors: [0x007aff, 0xff53f4], wallpaper: patternWallpaper(data: .variant4, colors: [0xe4b2ea, 0x8376c2, 0xeab9d9, 0xb493e6], intensity: -35, rotation: nil)), + PresentationThemeAccentColor(index: 102, baseColor: .preset, accentColor: 0x00b09b, bubbleColors: [0xaee946, 0x00b09b], wallpaper: patternWallpaper(data: .variant9, colors: [0xe4b2ea, 0x8376c2, 0xeab9d9, 0xb493e6], intensity: -35, rotation: nil)), + PresentationThemeAccentColor(index: 103, baseColor: .preset, accentColor: 0xd33213, bubbleColors: [0xf9db00, 0xd33213], wallpaper: patternWallpaper(data: .variant2, colors: [0xfec496, 0xdd6cb9, 0x962fbf, 0x4f5bd5], intensity: -40, rotation: nil)), + PresentationThemeAccentColor(index: 104, baseColor: .preset, accentColor: 0xea8ced, bubbleColors: [0xea8ced, 0x00c2ed], wallpaper: patternWallpaper(data: .variant6, colors: [0x8adbf2, 0x888dec, 0xe39fea, 0x679ced], intensity: -30, rotation: nil)) ] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift index 515d129297..6a6bf55799 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift @@ -110,34 +110,28 @@ enum ThemeSettingsColorOption: Equatable { } } - var plainBubbleColors: (UIColor, UIColor)? { + var plainBubbleColors: [UInt32] { switch self { case let .accentColor(color): return color.plainBubbleColors case let .theme(reference): - if case let .cloud(theme) = reference, let settings = theme.theme.settings, let messageColors = settings.messageColors { - return (UIColor(argb: messageColors.top), UIColor(argb: messageColors.bottom)) + if case let .cloud(theme) = reference, let settings = theme.theme.settings, !settings.messageColors.isEmpty { + return settings.messageColors } else { - return nil + return [] } } } - var customBubbleColors: (UIColor, UIColor?)? { + var customBubbleColors: [UInt32] { switch self { case let .accentColor(color): return color.customBubbleColors case let .theme(reference): - if case let .cloud(theme) = reference, let settings = theme.theme.settings, let messageColors = settings.messageColors { - let topColor = UIColor(argb: messageColors.top) - let bottomColor = UIColor(argb: messageColors.bottom) - if topColor.argb != bottomColor.argb { - return (topColor, bottomColor) - } else { - return (topColor, nil) - } + if case let .cloud(theme) = reference, let settings = theme.theme.settings, !settings.messageColors.isEmpty { + return settings.messageColors } else { - return nil + return [] } } } @@ -381,9 +375,9 @@ private final class ThemeSettingsAccentColorIconItemNode : ListViewItemNode { var topColor: UIColor? var bottomColor: UIColor? - if let colors = item.color?.plainBubbleColors { - topColor = colors.0 - bottomColor = colors.1 + if let colors = item.color?.plainBubbleColors, !colors.isEmpty { + topColor = UIColor(rgb: colors[0]) + bottomColor = UIColor(rgb: colors.last ?? colors[0]) } else if case .builtin(.dayClassic) = item.themeReference { if let accentColor = item.color?.accentColor { let hsb = accentColor.hsb diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index 19eea55b97..e0c3989f8a 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -225,25 +225,6 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { strongSelf.insertSubnode(currentBackgroundNode, at: 0) } - /*if let updatedBackgroundSignal = updatedBackgroundSignal { - strongSelf.disposable.set((updatedBackgroundSignal - |> deliverOnMainQueue).start(next: { [weak self] image in - if let strongSelf = self, let (image, final) = image, let backgroundNode = strongSelf.backgroundNode { - if final && !strongSelf.finalImage { - let tempLayer = CALayer() - tempLayer.frame = backgroundNode.bounds - tempLayer.contentsGravity = backgroundNode.layer.contentsGravity - tempLayer.contents = strongSelf.contents - strongSelf.layer.addSublayer(tempLayer) - tempLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { [weak tempLayer] _ in - tempLayer?.removeFromSuperlayer() - }) - } - backgroundNode.image = image - strongSelf.finalImage = final - } - })) - }*/ strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index 6c082bd9ff..025604f09a 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -647,7 +647,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if let wallpaper = wallpaper { effectiveWallpaper = wallpaper } else { - let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: accentColor?.color, bubbleColors: accentColor?.customBubbleColors, wallpaper: accentColor?.wallpaper) + let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: accentColor?.color, bubbleColors: accentColor?.customBubbleColors ?? [], wallpaper: accentColor?.wallpaper) effectiveWallpaper = theme?.chat.defaultWallpaper ?? .builtin(WallpaperSettings()) } return (accentColor, effectiveWallpaper) @@ -669,7 +669,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The |> mapToSignal { accentColor, wallpaper -> Signal<(PresentationTheme?, TelegramWallpaper?), NoError> in return chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: context.sharedContext.accountManager.mediaBox) |> map { serviceBackgroundColor in - return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: accentColor?.color, bubbleColors: accentColor?.customBubbleColors, serviceBackgroundColor: serviceBackgroundColor), wallpaper) + return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: reference, accentColor: accentColor?.color, bubbleColors: accentColor?.customBubbleColors ?? [], serviceBackgroundColor: serviceBackgroundColor), wallpaper) } } |> deliverOnMainQueue).start(next: { theme, wallpaper in @@ -854,7 +854,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The default: break } - theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors, wallpaper: accentColor?.wallpaper, baseColor: baseColor) + theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors ?? [], wallpaper: accentColor?.wallpaper, baseColor: baseColor) } effectiveWallpaper = theme?.chat.defaultWallpaper ?? .builtin(WallpaperSettings()) } @@ -880,7 +880,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The if let accentColor = accentColor, case let .theme(themeReference) = accentColor { return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: themeReference, serviceBackgroundColor: serviceBackgroundColor), effectiveThemeReference, wallpaper) } else { - return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors, serviceBackgroundColor: serviceBackgroundColor), effectiveThemeReference, wallpaper) + return (makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: generalThemeReference, accentColor: accentColor?.accentColor, bubbleColors: accentColor?.customBubbleColors ?? [], serviceBackgroundColor: serviceBackgroundColor), effectiveThemeReference, wallpaper) } } |> mapToSignal { theme, reference, wallpaper in diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift b/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift index 68eeba736b..d2b25b7365 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatFullscreenParticipantItem.swift @@ -207,6 +207,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode { didSet { if self.isCurrentlyInHierarchy != oldValue { self.highlightNode.isCurrentlyInHierarchy = self.isCurrentlyInHierarchy + self.audioLevelView?.isManuallyInHierarchy = self.isCurrentlyInHierarchy } } } diff --git a/submodules/TelegramCore/Sources/ApiUtils/Theme.swift b/submodules/TelegramCore/Sources/ApiUtils/Theme.swift index 2fb3916c78..24f1b8c586 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/Theme.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/Theme.swift @@ -47,9 +47,9 @@ extension TelegramThemeSettings { convenience init?(apiThemeSettings: Api.ThemeSettings) { switch apiThemeSettings { case let .themeSettings(_, baseTheme, accentColor, messageTopColor, messageBottomColor, wallpaper): - var messageColors: (UInt32, UInt32)? + var messageColors: [UInt32] = [] if let messageTopColor = messageTopColor, let messageBottomColor = messageBottomColor { - messageColors = (UInt32(bitPattern: messageTopColor), UInt32(bitPattern: messageBottomColor)) + messageColors = [UInt32(bitPattern: messageTopColor), UInt32(bitPattern: messageBottomColor)] } self.init(baseTheme: TelegramBaseTheme(apiBaseTheme: baseTheme), accentColor: UInt32(bitPattern: accentColor), messageColors: messageColors, wallpaper: wallpaper.flatMap(TelegramWallpaper.init(apiWallpaper:))) } @@ -57,7 +57,7 @@ extension TelegramThemeSettings { var apiInputThemeSettings: Api.InputThemeSettings { var flags: Int32 = 0 - if let _ = self.messageColors { + if !self.messageColors.isEmpty { flags |= 1 << 0 } @@ -71,11 +71,12 @@ extension TelegramThemeSettings { var messageTopColor: Int32? var messageBottomColor: Int32? - if let color = self.messageColors?.0 { - messageTopColor = Int32(bitPattern: color) + if self.messageColors.count > 0 { + messageTopColor = Int32(bitPattern: self.messageColors[0]) + messageBottomColor = messageTopColor } - if let color = self.messageColors?.1 { - messageBottomColor = Int32(bitPattern: color) + if self.messageColors.count > 1 { + messageBottomColor = Int32(bitPattern: self.messageColors[1]) } return .inputThemeSettings(flags: flags, baseTheme: self.baseTheme.apiBaseTheme, accentColor: Int32(bitPattern: self.accentColor), messageTopColor: messageTopColor, messageBottomColor: messageBottomColor, wallpaper: inputWallpaper, wallpaperSettings: inputWallpaperSettings) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift index 8245179787..0404170b21 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramTheme.swift @@ -21,7 +21,7 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { if lhs.accentColor != rhs.accentColor { return false } - if lhs.messageColors?.0 != rhs.messageColors?.0 || lhs.messageColors?.1 != rhs.messageColors?.1 { + if lhs.messageColors != rhs.messageColors { return false } if lhs.wallpaper != rhs.wallpaper { @@ -32,10 +32,10 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { public let baseTheme: TelegramBaseTheme public let accentColor: UInt32 - public let messageColors: (top: UInt32, bottom: UInt32)? + public let messageColors: [UInt32] public let wallpaper: TelegramWallpaper? - public init(baseTheme: TelegramBaseTheme, accentColor: UInt32, messageColors: (top: UInt32, bottom: UInt32)?, wallpaper: TelegramWallpaper?) { + public init(baseTheme: TelegramBaseTheme, accentColor: UInt32, messageColors: [UInt32], wallpaper: TelegramWallpaper?) { self.baseTheme = baseTheme self.accentColor = accentColor self.messageColors = messageColors @@ -45,10 +45,15 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { public init(decoder: PostboxDecoder) { self.baseTheme = TelegramBaseTheme(rawValue: decoder.decodeInt32ForKey("baseTheme", orElse: 0)) ?? .classic self.accentColor = UInt32(bitPattern: decoder.decodeInt32ForKey("accent", orElse: 0)) - if let topMessageColor = decoder.decodeOptionalInt32ForKey("topMessage"), let bottomMessageColor = decoder.decodeOptionalInt32ForKey("bottomMessage") { - self.messageColors = (UInt32(bitPattern: topMessageColor), UInt32(bitPattern: bottomMessageColor)) + let messageColors = decoder.decodeInt32ArrayForKey("messageColors") + if !messageColors.isEmpty { + self.messageColors = messageColors.map(UInt32.init(bitPattern:)) } else { - self.messageColors = nil + if let topMessageColor = decoder.decodeOptionalInt32ForKey("topMessage"), let bottomMessageColor = decoder.decodeOptionalInt32ForKey("bottomMessage") { + self.messageColors = [UInt32(bitPattern: topMessageColor), UInt32(bitPattern: bottomMessageColor)] + } else { + self.messageColors = [] + } } self.wallpaper = decoder.decodeObjectForKey("wallpaper", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper } @@ -56,13 +61,7 @@ public final class TelegramThemeSettings: PostboxCoding, Equatable { public func encode(_ encoder: PostboxEncoder) { encoder.encodeInt32(self.baseTheme.rawValue, forKey: "baseTheme") encoder.encodeInt32(Int32(bitPattern: self.accentColor), forKey: "accent") - if let (topMessageColor, bottomMessageColor) = self.messageColors { - encoder.encodeInt32(Int32(bitPattern: topMessageColor), forKey: "topMessage") - encoder.encodeInt32(Int32(bitPattern: bottomMessageColor), forKey: "bottomMessage") - } else { - encoder.encodeNil(forKey: "topMessage") - encoder.encodeNil(forKey: "bottomMessage") - } + encoder.encodeInt32Array(self.messageColors.map(Int32.init(bitPattern:)), forKey: "messageColors") if let wallpaper = self.wallpaper { encoder.encodeObject(wallpaper, forKey: "wallpaper") } else { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift index c8b90b2bff..81f323abc2 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift @@ -860,6 +860,11 @@ func _internal_currentChatListFilters(postbox: Postbox) -> Signal<[ChatListFilte } } +func _internal_currentChatListFilters(transaction: Transaction) -> [ChatListFilter] { + let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default + return settings.filters +} + func updateChatListFiltersState(transaction: Transaction, _ f: (ChatListFiltersState) -> ChatListFiltersState) -> ChatListFiltersState { var result: ChatListFiltersState? transaction.updatePreferencesEntry(key: PreferencesKeys.chatListFilters, { entry in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index c66ee732f4..1a1336dc2e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -25,6 +25,13 @@ public final class OpaqueChatInterfaceState { } public extension TelegramEngine { + enum NextUnreadChannelLocation: Equatable { + case same + case archived + case unarchived + case folder(id: Int32, title: String) + } + final class Peers { private let account: Account @@ -495,40 +502,90 @@ public extension TelegramEngine { return _internal_updatePeerDescription(account: self.account, peerId: peerId, description: description) } - public func getNextUnreadChannel(peerId: PeerId, filter: ChatListFilterPredicate?) -> Signal<(peer: EnginePeer, unreadCount: Int)?, NoError> { - return self.account.postbox.transaction { transaction -> (peer: EnginePeer, unreadCount: Int)? in - var results: [(EnginePeer, Int32)] = [] - - var peerIds: [PeerId] = [] - peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: filter)) - peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: filter)) - - for listId in peerIds { - guard let peer = transaction.getPeer(listId) else { - continue - } - guard let channel = peer as? TelegramChannel, case .broadcast = channel.info else { - continue - } - if channel.id == peerId { - continue - } - guard let readState = transaction.getCombinedPeerReadState(channel.id), readState.count != 0 else { - continue - } - guard let topMessageIndex = transaction.getTopPeerMessageIndex(peerId: channel.id) else { - continue + public func getNextUnreadChannel(peerId: PeerId, chatListFilterId: Int32?, getFilterPredicate: @escaping (ChatListFilterData) -> ChatListFilterPredicate) -> Signal<(peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)?, NoError> { + return self.account.postbox.transaction { transaction -> (peer: EnginePeer, unreadCount: Int, location: NextUnreadChannelLocation)? in + func getForFilter(predicate: ChatListFilterPredicate?, isArchived: Bool) -> (peer: EnginePeer, unreadCount: Int)? { + var peerIds: [PeerId] = [] + if predicate != nil { + peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: predicate)) + peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: predicate)) + } else { + if isArchived { + peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: Namespaces.PeerGroup.archive, filterPredicate: nil)) + } else { + peerIds.append(contentsOf: transaction.getUnreadChatListPeerIds(groupId: .root, filterPredicate: nil)) + } } - results.append((EnginePeer(channel), topMessageIndex.timestamp)) + var results: [(EnginePeer, Int32)] = [] + + for listId in peerIds { + guard let peer = transaction.getPeer(listId) else { + continue + } + guard let channel = peer as? TelegramChannel, case .broadcast = channel.info else { + continue + } + if channel.id == peerId { + continue + } + guard let readState = transaction.getCombinedPeerReadState(channel.id), readState.count != 0 else { + continue + } + guard let topMessageIndex = transaction.getTopPeerMessageIndex(peerId: channel.id) else { + continue + } + + results.append((EnginePeer(channel), topMessageIndex.timestamp)) + } + + results.sort(by: { $0.1 > $1.1 }) + + if let peer = results.first?.0 { + let unreadCount: Int32 = transaction.getCombinedPeerReadState(peer.id)?.count ?? 0 + return (peer: peer, unreadCount: Int(unreadCount)) + } else { + return nil + } } - results.sort(by: { $0.1 > $1.1 }) + guard let peerGroupId = transaction.getPeerChatListIndex(peerId)?.0 else { + return nil + } - if let peer = results.first?.0 { - let unreadCount: Int32 = transaction.getCombinedPeerReadState(peer.id)?.count ?? 0 - return (peer: peer, unreadCount: Int(unreadCount)) + if let filterId = chatListFilterId { + let filters = _internal_currentChatListFilters(transaction: transaction) + guard let index = filters.firstIndex(where: { $0.id == filterId }) else { + return nil + } + var sortedFilters: [ChatListFilter] = [] + sortedFilters.append(contentsOf: filters[index...]) + sortedFilters.append(contentsOf: filters[0 ..< index]) + for i in 0 ..< sortedFilters.count { + if let value = getForFilter(predicate: getFilterPredicate(sortedFilters[i].data), isArchived: false) { + return (peer: value.peer, unreadCount: value.unreadCount, location: i == 0 ? .same : .folder(id: sortedFilters[i].id, title: sortedFilters[i].title)) + } + } + return nil } else { + let folderOrder: [(PeerGroupId, NextUnreadChannelLocation)] + if peerGroupId == .root { + folderOrder = [ + (.root, .same), + (Namespaces.PeerGroup.archive, .archived), + ] + } else { + folderOrder = [ + (Namespaces.PeerGroup.archive, .same), + (.root, .unarchived), + ] + } + + for (groupId, location) in folderOrder { + if let value = getForFilter(predicate: nil, isArchived: groupId != .root) { + return (peer: value.peer, unreadCount: value.unreadCount, location: location) + } + } return nil } } diff --git a/submodules/TelegramCore/Sources/Themes.swift b/submodules/TelegramCore/Sources/Themes.swift index 07cceeb731..7da9ac24dc 100644 --- a/submodules/TelegramCore/Sources/Themes.swift +++ b/submodules/TelegramCore/Sources/Themes.swift @@ -348,7 +348,9 @@ public func createTheme(account: Account, title: String, resource: MediaResource return .generic } |> mapToSignal { apiTheme -> Signal in - if let theme = TelegramTheme(apiTheme: apiTheme) { + if var theme = TelegramTheme(apiTheme: apiTheme) { + theme = TelegramTheme(id: theme.id, accessHash: theme.accessHash, slug: theme.slug, title: theme.title, file: theme.file, settings: settings, isCreator: theme.isCreator, isDefault: theme.isDefault, installCount: theme.installCount) + return account.postbox.transaction { transaction -> CreateThemeResult in let entries = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudThemes) var items = entries.map { $0.contents as! TelegramTheme } @@ -427,7 +429,9 @@ public func updateTheme(account: Account, accountManager: AccountManager, theme: return .generic } |> mapToSignal { apiTheme -> Signal in - if let updatedTheme = TelegramTheme(apiTheme: apiTheme) { + if let theme = TelegramTheme(apiTheme: apiTheme) { + let updatedTheme = TelegramTheme(id: theme.id, accessHash: theme.accessHash, slug: theme.slug, title: theme.title, file: theme.file, settings: settings, isCreator: theme.isCreator, isDefault: theme.isDefault, installCount: theme.installCount) + let _ = accountManager.transaction { transaction in transaction.updateSharedData(SharedDataKeys.themeSettings, { current in var updated = current as? ThemeSettings ?? ThemeSettings(currentTheme: nil) diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index f1ced61ca5..7025ce7819 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -4,25 +4,9 @@ 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: nil, wallpaper: nil, baseColor: nil) +public let defaultDarkColorPresentationTheme = customizeDefaultDarkPresentationTheme(theme: defaultDarkPresentationTheme, editing: false, title: nil, accentColor: UIColor(rgb: 0x007aff), backgroundColors: [], bubbleColors: [], wallpaper: nil, baseColor: nil) private extension PresentationThemeBaseColor { -/* - - Оранжевая с красным - https://t.me/bg/9LW_RcoOSVACAAAAFTk3DTyXN-M?bg_color=fec496~dd6cb9~962fbf~4f5bd5&intensity=-40 - - Голубая с розовым - https://t.me/bg/9iklpvIPQVABAAAAORQXKur_Eyc?bg_color=8adbf2~888dec~e39fea~679ced&intensity=-30 - - Мятная - https://t.me/bg/CJNyxPMgSVAEAAAAvW9sMwc51cw?bg_color=7fa381~fff5c5~336f55~fbe37d&intensity=-20 - - Синяя с розовым - https://t.me/bg/9LW_RcoOSVACAAAAFTk3DTyXN-M?bg_color=fec496~dd6cb9~962fbf~4f5bd5&intensity=-40 - -*/ - var colorWallpaper: (BuiltinWallpaperData, Int32, [UInt32])? { switch self { case .blue: @@ -53,7 +37,7 @@ private extension PresentationThemeBaseColor { } } -public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: (UIColor, UIColor?)?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { +public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { if (theme.referenceTheme != .night) { return theme } @@ -67,13 +51,13 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit var bubbleColors = bubbleColors var monochrome = false - if bubbleColors == nil, editing { + if bubbleColors.isEmpty, editing { let accentColor = accentColor ?? UIColor(rgb: 0xffffff) if accentColor.rgb == 0xffffff { monochrome = true - bubbleColors = (UIColor(rgb: 0x313131), UIColor(rgb: 0x313131)) + bubbleColors = [UIColor(rgb: 0x313131).rgb, UIColor(rgb: 0x313131).rgb] } else { - bubbleColors = (accentColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98), accentColor) + bubbleColors = [accentColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98).rgb, accentColor.rgb] } } @@ -138,17 +122,16 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit } } - var outgoingBubbleFillColor: UIColor? - var outgoingBubbleFillGradientColor: UIColor? + var outgoingBubbleFillColors: [UIColor]? var outgoingPrimaryTextColor: UIColor? var outgoingSecondaryTextColor: UIColor? var outgoingLinkTextColor: UIColor? var outgoingScamColor: UIColor? var outgoingCheckColor: UIColor? - if let bubbleColors = bubbleColors { - var topBubbleColor = bubbleColors.0 - var bottomBubbleColor = bubbleColors.1 ?? bubbleColors.0 + if !bubbleColors.isEmpty { + var topBubbleColor = UIColor(rgb: bubbleColors[0]) + var bottomBubbleColor = UIColor(rgb: bubbleColors.last ?? bubbleColors[0]) if topBubbleColor.rgb != bottomBubbleColor.rgb { let topBubbleColorLightness = topBubbleColor.lightness @@ -162,8 +145,7 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit } } - outgoingBubbleFillColor = topBubbleColor - outgoingBubbleFillGradientColor = bottomBubbleColor + outgoingBubbleFillColors = bubbleColors.map(UIColor.init(rgb:)) let lightnessColor = topBubbleColor.mixedWith(bottomBubbleColor, alpha: 0.5) if lightnessColor.lightness > 0.7 { @@ -210,15 +192,13 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit outgoing: chat.message.outgoing.withUpdated( bubble: chat.message.outgoing.bubble.withUpdated( withWallpaper: chat.message.outgoing.bubble.withWallpaper.withUpdated( - fill: outgoingBubbleFillColor, - gradientFill: outgoingBubbleFillGradientColor, - highlightedFill: outgoingBubbleFillColor?.withMultipliedBrightnessBy(1.421), + fill: outgoingBubbleFillColors, + highlightedFill: outgoingBubbleFillColors?.first?.withMultipliedBrightnessBy(1.421), stroke: .clear ), withoutWallpaper: chat.message.outgoing.bubble.withoutWallpaper.withUpdated( - fill: outgoingBubbleFillColor, - gradientFill: outgoingBubbleFillGradientColor, - highlightedFill: outgoingBubbleFillColor?.withMultipliedBrightnessBy(1.421), + fill: outgoingBubbleFillColors, + highlightedFill: outgoingBubbleFillColors?.first?.withMultipliedBrightnessBy(1.421), stroke: .clear ) ), @@ -230,7 +210,7 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, - mediaControlInnerBackgroundColor: outgoingBubbleFillColor, + mediaControlInnerBackgroundColor: outgoingBubbleFillColors?.first, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, @@ -455,9 +435,9 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati let incomingBubbleAlpha: CGFloat = 0.9 let message = PresentationThemeChatMessage( - incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1D1D1D, alpha: incomingBubbleAlpha), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1D1D1D, alpha: incomingBubbleAlpha), highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628), shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.4), mediaControlInnerBackgroundColor: UIColor(rgb: 0x262628), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff, alpha: 0.12), separator: UIColor(rgb: 0x000000), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), - outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x61BCF9), gradientFill: UIColor(rgb: 0x007AFF), highlightedFill: UIColor(rgb: 0x61BCF9), stroke: .clear, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x61BCF9), gradientFill: UIColor(rgb: 0x007AFF), highlightedFill: UIColor(rgb: 0x61BCF9), stroke: .clear, shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x1f1f1f), highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f), shadow: nil)), + incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x1D1D1D, alpha: incomingBubbleAlpha)], highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x1D1D1D, alpha: incomingBubbleAlpha)], highlightedFill: UIColor(rgb: 0x353539), stroke: UIColor(rgb: 0x262628), shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.4), mediaControlInnerBackgroundColor: UIColor(rgb: 0x262628), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x1f1f1f).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0x737373), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff, alpha: 0.12), separator: UIColor(rgb: 0x000000), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), + outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x61BCF9), UIColor(rgb: 0x007AFF)], highlightedFill: UIColor(rgb: 0x61BCF9), stroke: .clear, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x61BCF9), UIColor(rgb: 0x007AFF)], highlightedFill: UIColor(rgb: 0x61BCF9), stroke: .clear, shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x1f1f1f)], highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x1f1f1f)], highlightedFill: UIColor(rgb: 0x2a2a2a), stroke: UIColor(rgb: 0x1f1f1f), shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0xffffff), infoLinkTextColor: UIColor(rgb: 0xffffff), outgoingCheckColor: UIColor(rgb: 0xffffff), diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index 23341096d1..745b6ebf9f 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: (UIColor, UIColor?)?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { +public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper forcedWallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { if (theme.referenceTheme != .nightAccent) { return theme } @@ -75,7 +75,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme var suggestedWallpaper: TelegramWallpaper? var bubbleColors = bubbleColors - if bubbleColors == nil, editing { + if bubbleColors.isEmpty, editing { if let accentColor = accentColor { if let baseColor = baseColor, let (variant, intensity, colors) = baseColor.colorWallpaper, !colors.isEmpty { suggestedWallpaper = defaultBuiltinWallpaper(data: variant, colors: colors, intensity: intensity) @@ -88,7 +88,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme let accentColor = accentColor ?? defaultDarkTintedAccentColor let bottomColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.731, brightness: 0.59) let topColor = bottomColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98) - bubbleColors = (topColor, bottomColor) + bubbleColors = [topColor.rgb, bottomColor.rgb] } if let initialAccentColor = accentColor { @@ -268,8 +268,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme defaultWallpaper = forcedWallpaper } - var outgoingBubbleFillColor: UIColor? - var outgoingBubbleFillGradientColor: UIColor? + var outgoingBubbleFillColors: [UIColor]? var outgoingPrimaryTextColor: UIColor? var outgoingSecondaryTextColor: UIColor? var outgoingLinkTextColor: UIColor? @@ -278,11 +277,10 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme var highlightedIncomingBubbleColor: UIColor? var highlightedOutgoingBubbleColor: UIColor? - if let bubbleColors = bubbleColors { - outgoingBubbleFillColor = bubbleColors.0 - outgoingBubbleFillGradientColor = bubbleColors.1 ?? bubbleColors.0 + if !bubbleColors.isEmpty { + outgoingBubbleFillColors = bubbleColors.map(UIColor.init(rgb:)) - let lightnessColor = bubbleColors.0.mixedWith(bubbleColors.1 ?? bubbleColors.0, alpha: 0.5) + let lightnessColor = UIColor(rgb: bubbleColors[0]).mixedWith(UIColor(rgb: bubbleColors.last ?? bubbleColors[0]), alpha: 0.5) if lightnessColor.lightness > 0.7 { outgoingPrimaryTextColor = UIColor(rgb: 0x000000) outgoingSecondaryTextColor = UIColor(rgb: 0x000000, alpha: 0.5) @@ -298,7 +296,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme } highlightedIncomingBubbleColor = accentColor?.withMultiplied(hue: 1.03, saturation: 0.463, brightness: 0.29) - highlightedOutgoingBubbleColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.019, saturation: 0.609, brightness: 0.63) + highlightedOutgoingBubbleColor = outgoingBubbleFillColors?.first?.withMultiplied(hue: 1.019, saturation: 0.609, brightness: 0.63) } let incomingFillColor = mainBackgroundColor?.withMultipliedAlpha(0.9) @@ -309,14 +307,12 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme incoming: chat.message.incoming.withUpdated( bubble: chat.message.incoming.bubble.withUpdated( withWallpaper: chat.message.outgoing.bubble.withWallpaper.withUpdated( - fill: incomingFillColor, - gradientFill: incomingFillColor, + fill: incomingFillColor.flatMap({ [$0] }), highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor ), withoutWallpaper: chat.message.outgoing.bubble.withoutWallpaper.withUpdated( - fill: incomingFillColor, - gradientFill: incomingFillColor, + fill: incomingFillColor.flatMap({ [$0] }), highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor ) @@ -352,14 +348,12 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme outgoing: chat.message.outgoing.withUpdated( bubble: chat.message.outgoing.bubble.withUpdated( withWallpaper: chat.message.outgoing.bubble.withWallpaper.withUpdated( - fill: outgoingBubbleFillColor, - gradientFill: outgoingBubbleFillGradientColor, + fill: outgoingBubbleFillColors, highlightedFill: highlightedOutgoingBubbleColor, stroke: .clear ), withoutWallpaper: chat.message.outgoing.bubble.withoutWallpaper.withUpdated( - fill: outgoingBubbleFillColor, - gradientFill: outgoingBubbleFillGradientColor, + fill: outgoingBubbleFillColors, highlightedFill: highlightedOutgoingBubbleColor, stroke: .clear ) @@ -372,7 +366,7 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, - mediaControlInnerBackgroundColor: outgoingBubbleFillColor, + mediaControlInnerBackgroundColor: outgoingBubbleFillColors?.first, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, @@ -384,11 +378,11 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme ), freeform: chat.message.freeform.withUpdated( withWallpaper: chat.message.freeform.withWallpaper.withUpdated( - fill: mainBackgroundColor, + fill: mainBackgroundColor.flatMap({ [$0] }), highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor ), withoutWallpaper: chat.message.freeform.withoutWallpaper.withUpdated( - fill: mainBackgroundColor, + fill: mainBackgroundColor.flatMap({ [$0] }), highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor ) @@ -509,7 +503,9 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres let mainFreeTextColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.097, brightness: 0.56) let outgoingBubbleFillGradientColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.731, brightness: 0.59) - let outgoingBubbleFillColor = outgoingBubbleFillGradientColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98) + + let outgoingBubbleFillColors: [UIColor] = [outgoingBubbleFillGradientColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98), outgoingBubbleFillGradientColor] + let outgoingScamColor = UIColor(rgb: 0xffffff) let outgoingPrimaryTextColor = UIColor(rgb: 0xffffff) let outgoingSecondaryTextColor = UIColor(rgb: 0xffffff, alpha: 0.5) @@ -700,9 +696,9 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres let incomingFillColor = mainBackgroundColor.withMultipliedAlpha(0.9) let message = PresentationThemeChatMessage( - incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: incomingFillColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: incomingFillColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: UIColor(rgb: 0xff6767), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), mediaControlInnerBackgroundColor: mainBackgroundColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor, barIconForeground: .white, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor), - outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor, shadow: nil)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor, barIconForeground: .clear, barPositive: outgoingPrimaryTextColor, barNegative: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil)), + incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [incomingFillColor], highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [incomingFillColor], highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: UIColor(rgb: 0xff6767), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), mediaControlInnerBackgroundColor: mainBackgroundColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor, barIconForeground: .white, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor), + outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColors, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColors[0], shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColors, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColors[0], shadow: nil)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColors[0], pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor, barIconForeground: .clear, barPositive: outgoingPrimaryTextColor, barNegative: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [mainBackgroundColor], highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [mainBackgroundColor], highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor, shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0xffffff), infoLinkTextColor: accentColor, outgoingCheckColor: outgoingCheckColor, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index c0adf9e41d..fb99997026 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: (UIColor, UIColor?)?, wallpaper forcedWallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor?) -> PresentationTheme { +public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, title: String?, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper forcedWallpaper: TelegramWallpaper? = nil, serviceBackgroundColor: UIColor?) -> PresentationTheme { if (theme.referenceTheme != .day && theme.referenceTheme != .dayClassic) { return theme } @@ -52,14 +52,14 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti var suggestedWallpaper: TelegramWallpaper? var bubbleColors = bubbleColors - if bubbleColors == nil, editing { + if bubbleColors.isEmpty, editing { if day { let accentColor = accentColor ?? defaultDayAccentColor - bubbleColors = (accentColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98), accentColor) + bubbleColors = [accentColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98).rgb, accentColor.rgb] } else { if let accentColor = accentColor, !accentColor.alpha.isZero { let hsb = accentColor.hsb - bubbleColors = (UIColor(hue: hsb.0, saturation: (hsb.1 > 0.0 && hsb.2 > 0.0) ? 0.14 : 0.0, brightness: 0.79 + hsb.2 * 0.21, alpha: 1.0), nil) + bubbleColors = [UIColor(hue: hsb.0, saturation: (hsb.1 > 0.0 && hsb.2 > 0.0) ? 0.14 : 0.0, brightness: 0.79 + hsb.2 * 0.21, alpha: 1.0).rgb] if accentColor.lightness > 0.705 { outgoingAccent = UIColor(hue: hsb.0, saturation: min(1.0, hsb.1 * 1.1), brightness: min(hsb.2, 0.6), alpha: 1.0) } else { @@ -68,7 +68,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti suggestedWallpaper = .gradient(TelegramWallpaper.Gradient(id: nil, colors: defaultBuiltinWallpaperGradientColors.map(\.rgb), settings: WallpaperSettings())) } else { - bubbleColors = (UIColor(rgb: 0xe1ffc7), nil) + bubbleColors = [UIColor(rgb: 0xe1ffc7).rgb] suggestedWallpaper = .gradient(TelegramWallpaper.Gradient(id: nil, colors: defaultBuiltinWallpaperGradientColors.map(\.rgb), settings: WallpaperSettings())) } } @@ -105,8 +105,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti } var incomingBubbleStrokeColor: UIColor? - var outgoingBubbleFillColor: UIColor? - var outgoingBubbleFillGradientColor: UIColor? + var outgoingBubbleFillColors: [UIColor]? var outgoingBubbleHighlightedFill: UIColor? var outgoingBubbleStrokeColor: UIColor? var outgoingPrimaryTextColor: UIColor? @@ -133,11 +132,11 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti outgoingBubbleStrokeColor = bubbleStrokeColor } - if let bubbleColors = bubbleColors { - var topBubbleColor = bubbleColors.0 - var bottomBubbleColor = bubbleColors.1 ?? bubbleColors.0 + if !bubbleColors.isEmpty { + //var topBubbleColor = UIColor(rgb: bubbleColors[0]) + //var bottomBubbleColor = UIColor(rgb: bubbleColors.last ?? bubbleColors[0]) - if topBubbleColor.rgb != bottomBubbleColor.rgb { + /*if topBubbleColor.rgb != bottomBubbleColor.rgb { let topBubbleColorLightness = topBubbleColor.lightness let bottomBubbleColorLightness = bottomBubbleColor.lightness if abs(topBubbleColorLightness - bottomBubbleColorLightness) > 0.7 { @@ -147,23 +146,22 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti bottomBubbleColor = bottomBubbleColor.withMultiplied(hue: 1.0, saturation: 1.0, brightness: 0.85) } } - } + }*/ - outgoingBubbleFillColor = topBubbleColor - outgoingBubbleFillGradientColor = bottomBubbleColor + outgoingBubbleFillColors = bubbleColors.map(UIColor.init(rgb:)) if day { outgoingBubbleStrokeColor = .clear } - outgoingBubbleHighlightedFill = outgoingBubbleFillColor?.withMultiplied(hue: 1.054, saturation: 1.589, brightness: 0.96) + outgoingBubbleHighlightedFill = outgoingBubbleFillColors?.first?.withMultiplied(hue: 1.054, saturation: 1.589, brightness: 0.96) - let lightnessColor = bubbleColors.0.mixedWith(bubbleColors.1 ?? bubbleColors.0, alpha: 0.5) + let lightnessColor = UIColor.average(of: bubbleColors.map(UIColor.init(rgb:))) if lightnessColor.lightness > 0.705 { let hueFactor: CGFloat = 0.75 let saturationFactor: CGFloat = 1.1 outgoingPrimaryTextColor = UIColor(rgb: 0x000000) - outgoingSecondaryTextColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.344 * hueFactor, saturation: 4.554 * saturationFactor, brightness: 0.549).withAlphaComponent(0.8) + outgoingSecondaryTextColor = outgoingBubbleFillColors?.first?.withMultiplied(hue: 1.344 * hueFactor, saturation: 4.554 * saturationFactor, brightness: 0.549).withAlphaComponent(0.8) if let outgoingAccent = outgoingAccent { outgoingAccentTextColor = outgoingAccent @@ -192,13 +190,13 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti } outgoingPendingActivityColor = outgoingCheckColor - outgoingFileDescriptionColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.257 * hueFactor, saturation: 1.842, brightness: 0.698) - outgoingFileDurationColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.344 * hueFactor, saturation: 4.554, brightness: 0.549).withAlphaComponent(0.8) - outgoingMediaPlaceholderColor = outgoingBubbleFillColor?.withMultiplied(hue: 0.998, saturation: 1.129, brightness: 0.949) - outgoingPollsButtonColor = outgoingBubbleFillColor?.withMultiplied(hue: 1.207 * hueFactor, saturation: 1.721, brightness: 0.851) + outgoingFileDescriptionColor = outgoingBubbleFillColors?.first?.withMultiplied(hue: 1.257 * hueFactor, saturation: 1.842, brightness: 0.698) + outgoingFileDurationColor = outgoingBubbleFillColors?.first?.withMultiplied(hue: 1.344 * hueFactor, saturation: 4.554, brightness: 0.549).withAlphaComponent(0.8) + outgoingMediaPlaceholderColor = outgoingBubbleFillColors?.first?.withMultiplied(hue: 0.998, saturation: 1.129, brightness: 0.949) + outgoingPollsButtonColor = outgoingBubbleFillColors?.first?.withMultiplied(hue: 1.207 * hueFactor, saturation: 1.721, brightness: 0.851) if day { - if let distance = outgoingBubbleFillColor?.distance(to: UIColor(rgb: 0xffffff)), distance < 200 { + if let distance = outgoingBubbleFillColors?.first?.distance(to: UIColor(rgb: 0xffffff)), distance < 200 { outgoingBubbleStrokeColor = UIColor(rgb: 0xc8c7cc) } } @@ -214,7 +212,7 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti outgoingFileTitleColor = outgoingPrimaryTextColor outgoingFileDescriptionColor = outgoingSecondaryTextColor outgoingFileDurationColor = outgoingSecondaryTextColor - outgoingMediaPlaceholderColor = outgoingBubbleFillColor?.withMultipliedBrightnessBy(0.95) + outgoingMediaPlaceholderColor = outgoingBubbleFillColors?.first?.withMultipliedBrightnessBy(0.95) outgoingPollsButtonColor = outgoingSecondaryTextColor outgoingPollsProgressColor = outgoingPrimaryTextColor outgoingSelectionBaseColor = UIColor(rgb: 0xffffff) @@ -268,14 +266,12 @@ public func customizeDefaultDayTheme(theme: PresentationTheme, editing: Bool, ti outgoing: chat.message.outgoing.withUpdated( bubble: chat.message.outgoing.bubble.withUpdated( withWallpaper: chat.message.outgoing.bubble.withWallpaper.withUpdated( - fill: outgoingBubbleFillColor, - gradientFill: outgoingBubbleFillGradientColor, + fill: outgoingBubbleFillColors, highlightedFill: outgoingBubbleHighlightedFill, stroke: outgoingBubbleStrokeColor ), withoutWallpaper: chat.message.outgoing.bubble.withoutWallpaper.withUpdated( - fill: outgoingBubbleFillColor, - gradientFill: outgoingBubbleFillGradientColor, + fill: outgoingBubbleFillColors, highlightedFill: outgoingBubbleHighlightedFill, stroke: outgoingBubbleStrokeColor ) @@ -532,7 +528,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio let message = PresentationThemeChatMessage( incoming: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor, shadow: nil)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xffffff)], highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xffffff)], highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: bubbleStrokeColor, shadow: nil)), primaryTextColor: UIColor(rgb: 0x000000), secondaryTextColor: UIColor(rgb: 0x525252, alpha: 0.6), linkTextColor: UIColor(rgb: 0x004bad), @@ -554,7 +550,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x596e89, alpha: 0.35)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: .clear), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0x007ee5, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0x007ee5)), outgoing: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe1ffc7), highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe1ffc7), highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor, shadow: nil)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xe1ffc7)], highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xe1ffc7)], highlightedFill: UIColor(rgb: 0xc8ffa6), stroke: bubbleStrokeColor, shadow: nil)), primaryTextColor: UIColor(rgb: 0x000000), secondaryTextColor: UIColor(rgb: 0x008c09, alpha: 0.8), linkTextColor: UIColor(rgb: 0x004bad), @@ -578,7 +574,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xbbde9f), textSelectionKnobColor: UIColor(rgb: 0x3fc33b)), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5), shadow: nil)), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xffffff)], highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xffffff)], highlightedFill: UIColor(rgb: 0xd9f4ff), stroke: UIColor(rgb: 0x86a9c9, alpha: 0.5), shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0x000000), infoLinkTextColor: UIColor(rgb: 0x004bad), outgoingCheckColor: UIColor(rgb: 0x19c700), @@ -597,7 +593,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio let messageDay = PresentationThemeChatMessage( incoming: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xffffff), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xffffff), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xf1f1f4), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xf1f1f4), shadow: nil)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xffffff)], highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xffffff), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xf1f1f4)], highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xf1f1f4), shadow: nil)), primaryTextColor: UIColor(rgb: 0x000000), secondaryTextColor: UIColor(rgb: 0x525252, alpha: 0.6), linkTextColor: UIColor(rgb: 0x004bad), @@ -622,7 +618,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio textSelectionColor: UIColor(rgb: 0x007ee5, alpha: 0.3), textSelectionKnobColor: UIColor(rgb: 0x007ee5)), outgoing: PresentationThemePartedColors( - bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x57b2e0), gradientFill: UIColor(rgb: 0x007ee5), highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0x57b2e0), gradientFill: UIColor(rgb: 0x007ee5), highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear, shadow: nil)), + bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x57b2e0), UIColor(rgb: 0x007ee5)], highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear, shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0x57b2e0), UIColor(rgb: 0x007ee5)], highlightedFill: UIColor(rgb: 0x57b2e0).withMultipliedBrightnessBy(0.7), stroke: .clear, shadow: nil)), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.65), linkTextColor: UIColor(rgb: 0xffffff), @@ -646,7 +642,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio actionButtonsTextColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0xffffff), withoutWallpaper: UIColor(rgb: 0x007ee5)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff)), - freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe5e5ea), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: UIColor(rgb: 0xe5e5ea), highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea), shadow: nil)), + freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xe5e5ea)], highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea), shadow: nil), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: [UIColor(rgb: 0xe5e5ea)], highlightedFill: UIColor(rgb: 0xdadade), stroke: UIColor(rgb: 0xe5e5ea), shadow: nil)), infoPrimaryTextColor: UIColor(rgb: 0x000000), infoLinkTextColor: UIColor(rgb: 0x004bad), outgoingCheckColor: UIColor(rgb: 0xffffff), diff --git a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift index db916a3486..c4e162eaea 100644 --- a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift @@ -19,8 +19,8 @@ public func makeDefaultPresentationTheme(reference: PresentationBuiltinThemeRefe return theme } -public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool, title: String? = nil, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: (UIColor, UIColor?)?, wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { - if accentColor == nil && bubbleColors == nil && backgroundColors.isEmpty && wallpaper == nil { +public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool, title: String? = nil, accentColor: UIColor?, backgroundColors: [UInt32], bubbleColors: [UInt32], wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil) -> PresentationTheme { + if accentColor == nil && bubbleColors.isEmpty && backgroundColors.isEmpty && wallpaper == nil { return theme } switch theme.referenceTheme { @@ -35,10 +35,10 @@ public func customizePresentationTheme(_ theme: PresentationTheme, editing: Bool 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.flatMap { (UIColor(argb: $0.top), UIColor(argb: $0.bottom)) }, wallpaper: settings.wallpaper) + return customizePresentationTheme(defaultTheme, editing: true, title: title, accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors, wallpaper: settings.wallpaper) } -public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, extendingThemeReference: PresentationThemeReference? = nil, accentColor: UIColor? = nil, backgroundColors: [UInt32] = [], bubbleColors: (UIColor, UIColor?)? = nil, 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] = [], wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { let theme: PresentationTheme switch themeReference { case let .builtin(reference): @@ -52,7 +52,7 @@ public func makePresentationTheme(mediaBox: MediaBox, themeReference: Presentati } 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 ?? settings.messageColors.flatMap { (UIColor(argb: $0.top), UIColor(argb: $0.bottom)) }, 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, wallpaper: wallpaper ?? settings.wallpaper, serviceBackgroundColor: serviceBackgroundColor, preview: preview) { theme = loadedTheme } else { return nil diff --git a/submodules/TelegramPresentationData/Sources/PresentationData.swift b/submodules/TelegramPresentationData/Sources/PresentationData.swift index 1c84b844d6..61181b1072 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationData.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationData.swift @@ -292,7 +292,7 @@ public func currentPresentationDataAndSettings(accountManager: AccountManager, s } let effectiveColors = themeSettings.themeSpecificAccentColors[effectiveTheme.index] - let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveColors?.color, bubbleColors: effectiveColors?.customBubbleColors, baseColor: effectiveColors?.baseColor) ?? defaultPresentationTheme + let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveColors?.color, bubbleColors: effectiveColors?.customBubbleColors ?? [], baseColor: effectiveColors?.baseColor) ?? defaultPresentationTheme let effectiveChatWallpaper: TelegramWallpaper = (themeSettings.themeSpecificChatWallpapers[coloredThemeIndex(reference: effectiveTheme, accentColor: effectiveColors)] ?? themeSettings.themeSpecificChatWallpapers[effectiveTheme.index]) ?? theme.chat.defaultWallpaper @@ -583,7 +583,7 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI if let themeSpecificWallpaper = themeSpecificWallpaper { currentWallpaper = themeSpecificWallpaper } else { - let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: themeSettings.theme, accentColor: currentColors?.color, bubbleColors: currentColors?.customBubbleColors, wallpaper: currentColors?.wallpaper, baseColor: currentColors?.baseColor) ?? defaultPresentationTheme + let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: themeSettings.theme, accentColor: currentColors?.color, bubbleColors: currentColors?.customBubbleColors ?? [], wallpaper: currentColors?.wallpaper, baseColor: currentColors?.baseColor) ?? defaultPresentationTheme currentWallpaper = theme.chat.defaultWallpaper } @@ -619,7 +619,7 @@ public func updatedPresentationData(accountManager: AccountManager, applicationI effectiveColors = nil } - let themeValue = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveColors?.color, bubbleColors: effectiveColors?.customBubbleColors, wallpaper: effectiveColors?.wallpaper, baseColor: effectiveColors?.baseColor, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme + let themeValue = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: effectiveTheme, accentColor: effectiveColors?.color, bubbleColors: effectiveColors?.customBubbleColors ?? [], wallpaper: effectiveColors?.wallpaper, baseColor: effectiveColors?.baseColor, serviceBackgroundColor: serviceBackgroundColor) ?? defaultPresentationTheme if autoNightModeTriggered && !switchedToNightModeWallpaper { switch effectiveChatWallpaper { diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index 71b1a44f13..5a718a657c 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -635,22 +635,20 @@ public struct PresentationThemeBubbleShadow { } public final class PresentationThemeBubbleColorComponents { - public let fill: UIColor - public let gradientFill: UIColor + public let fill: [UIColor] public let highlightedFill: UIColor public let stroke: UIColor public let shadow: PresentationThemeBubbleShadow? - public init(fill: UIColor, gradientFill: UIColor? = nil, highlightedFill: UIColor, stroke: UIColor, shadow: PresentationThemeBubbleShadow?) { + public init(fill: [UIColor], highlightedFill: UIColor, stroke: UIColor, shadow: PresentationThemeBubbleShadow?) { self.fill = fill - self.gradientFill = gradientFill ?? fill self.highlightedFill = highlightedFill self.stroke = stroke self.shadow = shadow } - public func withUpdated(fill: UIColor? = nil, gradientFill: UIColor? = nil, highlightedFill: UIColor? = nil, stroke: UIColor? = nil) -> PresentationThemeBubbleColorComponents { - return PresentationThemeBubbleColorComponents(fill: fill ?? self.fill, gradientFill: gradientFill ?? self.gradientFill, highlightedFill: highlightedFill ?? self.highlightedFill, stroke: stroke ?? self.stroke, shadow: self.shadow) + public func withUpdated(fill: [UIColor]? = nil, highlightedFill: UIColor? = nil, stroke: UIColor? = nil) -> PresentationThemeBubbleColorComponents { + return PresentationThemeBubbleColorComponents(fill: fill ?? self.fill, highlightedFill: highlightedFill ?? self.highlightedFill, stroke: stroke ?? self.stroke, shadow: self.shadow) } } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index 1a04568e4a..2b4e950af7 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -33,6 +33,37 @@ private func encodeColor(_ values: inout KeyedEncodingContainer, _ val } } +private func decodeColorList(_ values: KeyedDecodingContainer, _ key: Key) throws -> [UIColor] { + let colorValues = try values.decode([String].self, forKey: key) + + var result: [UIColor] = [] + for value in colorValues { + if value.lowercased() == "clear" { + result.append(UIColor.clear) + } else if let color = UIColor(hexString: value) { + result.append(color) + } else { + throw PresentationThemeDecodingError.generic + } + } + + return result +} + +private func encodeColorList(_ values: inout KeyedEncodingContainer, _ colors: [UIColor], _ key: Key) throws { + var stringList: [String] = [] + for value in colors { + if value == UIColor.clear { + stringList.append("clear") + } else if value.alpha < 1.0 { + stringList.append(String(format: "%08x", value.argb)) + } else { + stringList.append(String(format: "%06x", value.rgb)) + } + } + try values.encode(stringList, forKey: key) +} + extension TelegramWallpaper: Codable { public init(from decoder: Decoder) throws { let values = try decoder.singleValueContainer() @@ -1070,22 +1101,30 @@ extension PresentationThemeBubbleColorComponents: Codable { case highlightedBg case stroke case shadow + case bgList } public convenience init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".") - - var fillColor = try decodeColor(values, .bg) - var gradientColor = try decodeColor(values, .gradientBg, decoder: decoder, fallbackKey: "\(codingPath).bg") - if gradientColor.rgb != fillColor.rgb { - fillColor = fillColor.withAlphaComponent(1.0) - gradientColor = gradientColor.withAlphaComponent(1.0) + + let fill: [UIColor] + + if let bgList = try? decodeColorList(values, .bgList) { + fill = bgList + } else { + var fillColor = try decodeColor(values, .bg) + var gradientColor = try decodeColor(values, .gradientBg, decoder: decoder, fallbackKey: "\(codingPath).bg") + if gradientColor.rgb != fillColor.rgb { + fillColor = fillColor.withAlphaComponent(1.0) + gradientColor = gradientColor.withAlphaComponent(1.0) + } + + fill = [fillColor, gradientColor] } - + self.init( - fill: fillColor, - gradientFill: gradientColor, + fill: fill, highlightedFill: try decodeColor(values, .highlightedBg), stroke: try decodeColor(values, .stroke), shadow: try? values.decode(PresentationThemeBubbleShadow.self, forKey: .shadow) @@ -1094,8 +1133,17 @@ extension PresentationThemeBubbleColorComponents: Codable { public func encode(to encoder: Encoder) throws { var values = encoder.container(keyedBy: CodingKeys.self) - try encodeColor(&values, self.fill, .bg) - try encodeColor(&values, self.gradientFill, .gradientBg) + if self.fill.count <= 2 { + if self.fill.count > 1 { + try encodeColor(&values, self.fill[0], .bg) + try encodeColor(&values, self.fill[1], .gradientBg) + } else { + try encodeColor(&values, self.fill[0], .bg) + try encodeColor(&values, self.fill[0], .gradientBg) + } + } else { + try encodeColorList(&values, self.fill, .bgList) + } try encodeColor(&values, self.highlightedFill, .highlightedBg) try encodeColor(&values, self.stroke, .stroke) } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift index 4e654f2613..a0e1b155b6 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeEssentialGraphics.swift @@ -199,18 +199,23 @@ public final class PrincipalThemeEssentialGraphics { let incoming: PresentationThemeBubbleColorComponents = wallpaper.isEmpty ? theme.message.incoming.bubble.withoutWallpaper : theme.message.incoming.bubble.withWallpaper let outgoing: PresentationThemeBubbleColorComponents = wallpaper.isEmpty ? theme.message.outgoing.bubble.withoutWallpaper : theme.message.outgoing.bubble.withWallpaper - var incomingGradientColors: (UIColor, UIColor)? - if incoming.fill.rgb != incoming.gradientFill.rgb { - incomingGradientColors = (incoming.fill, incoming.gradientFill) + var incomingGradientColors: [UIColor]? + if Set(incoming.fill.map(\.argb)).count > 1 { + incomingGradientColors = incoming.fill } if let incomingGradientColors = incomingGradientColors { self.incomingBubbleGradientImage = generateImage(CGSize(width: 1.0, height: 512.0), opaque: true, scale: 1.0, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - var locations: [CGFloat] = [0.0, 1.0] - let colors = [incomingGradientColors.0.cgColor, incomingGradientColors.1.cgColor] as NSArray + var locations: [CGFloat] = [] + var colors: [CGColor] = [] + for i in 0 ..< incomingGradientColors.count { + let t = CGFloat(i) / CGFloat(incomingGradientColors.count - 1) + locations.append(t) + colors.append(incomingGradientColors[i].cgColor) + } let colorSpace = deviceColorSpace - let gradient = CGGradient(colorsSpace: colorSpace, colors: colors, locations: &locations)! + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)! context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) }) @@ -218,18 +223,23 @@ public final class PrincipalThemeEssentialGraphics { self.incomingBubbleGradientImage = nil } - var outgoingGradientColors: (UIColor, UIColor)? - if outgoing.fill.rgb != outgoing.gradientFill.rgb { - outgoingGradientColors = (outgoing.fill, outgoing.gradientFill) + var outgoingGradientColors: [UIColor]? + if Set(outgoing.fill.map(\.argb)).count > 1 { + outgoingGradientColors = outgoing.fill } if let outgoingGradientColors = outgoingGradientColors { self.outgoingBubbleGradientImage = generateImage(CGSize(width: 1.0, height: 512.0), opaque: true, scale: 1.0, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - var locations: [CGFloat] = [0.0, 1.0] - let colors = [outgoingGradientColors.0.cgColor, outgoingGradientColors.1.cgColor] as NSArray + var locations: [CGFloat] = [] + var colors: [CGColor] = [] + for i in 0 ..< outgoingGradientColors.count { + let t = CGFloat(i) / CGFloat(outgoingGradientColors.count - 1) + locations.append(t) + colors.append(outgoingGradientColors[i].cgColor) + } let colorSpace = deviceColorSpace - let gradient = CGGradient(colorsSpace: colorSpace, colors: colors, locations: &locations)! + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)! context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) }) @@ -249,73 +259,73 @@ public final class PrincipalThemeEssentialGraphics { if preview { self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingExtractedMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: UIColor.black, strokeColor: UIColor.clear, neighbors: .extracted, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingExtractedMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .extracted, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor, width: 11.0)! self.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor, width: 11.0)! self.chatMessageBackgroundIncomingHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBothHighlightedImage = emptyImage self.chatMessageBackgroundIncomingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingMergedSideHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = emptyImage self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = emptyImage - self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = emptyImage self.checkMediaFullImage = emptyImage self.checkMediaPartialImage = emptyImage @@ -361,70 +371,70 @@ public final class PrincipalThemeEssentialGraphics { } else { self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundIncomingExtractedMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .extracted, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedBothHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) self.chatMessageBackgroundOutgoingExtractedMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .extracted, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingExtractedOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .none, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBottomOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBottomShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBottomHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundIncomingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundIncomingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundIncomingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundIncomingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill[0], strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundOutgoingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) - self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) - self.chatMessageBackgroundOutgoingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) + self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) + self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true) + self.chatMessageBackgroundOutgoingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill[0], strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true) self.chatMessageBackgroundIncomingMergedSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.highlightedFill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.highlightedFill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true) diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index f2e693ae52..5ad361316f 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -152,14 +152,14 @@ public struct PresentationResourcesChat { public static func chatInstantVideoBackgroundImage(_ theme: PresentationTheme, wallpaper: Bool) -> UIImage? { let key: PresentationResourceKey = !wallpaper ? PresentationResourceKey.chatInstantVideoWithoutWallpaperBackgroundImage : PresentationResourceKey.chatInstantVideoWithWallpaperBackgroundImage return theme.image(key.rawValue, { theme in - return generateInstantVideoBackground(fillColor: theme.chat.message.freeform.withWallpaper.fill, strokeColor: theme.chat.message.freeform.withWallpaper.stroke) + return generateInstantVideoBackground(fillColor: theme.chat.message.freeform.withWallpaper.fill[0], strokeColor: theme.chat.message.freeform.withWallpaper.stroke) }) } public static func chatActionPhotoBackgroundImage(_ theme: PresentationTheme, wallpaper: Bool) -> UIImage? { let key: PresentationResourceKey = !wallpaper ? PresentationResourceKey.chatActionPhotoWithoutWallpaperBackgroundImage : PresentationResourceKey.chatActionPhotoWithWallpaperBackgroundImage return theme.image(key.rawValue, { theme in - return generateActionPhotoBackground(fillColor: theme.chat.message.freeform.withWallpaper.fill, strokeColor: theme.chat.message.freeform.withWallpaper.stroke) + return generateActionPhotoBackground(fillColor: theme.chat.message.freeform.withWallpaper.fill[0], strokeColor: theme.chat.message.freeform.withWallpaper.stroke) }) } @@ -178,7 +178,7 @@ public struct PresentationResourcesChat { public static func chatInfoItemBackgroundImageWithoutWallpaper(_ theme: PresentationTheme) -> UIImage? { return theme.image(PresentationResourceKey.chatInfoItemBackgroundImageWithoutWallpaper.rawValue, { theme in - return messageSingleBubbleLikeImage(fillColor: theme.chat.message.incoming.bubble.withoutWallpaper.fill, strokeColor: theme.chat.message.incoming.bubble.withoutWallpaper.stroke) + return messageSingleBubbleLikeImage(fillColor: theme.chat.message.incoming.bubble.withoutWallpaper.fill[0], strokeColor: theme.chat.message.incoming.bubble.withoutWallpaper.stroke) }) } @@ -186,7 +186,7 @@ public struct PresentationResourcesChat { let key: PresentationResourceKey = !wallpaper ? PresentationResourceKey.chatInfoItemBackgroundImageWithoutWallpaper : PresentationResourceKey.chatInfoItemBackgroundImageWithWallpaper return theme.image(key.rawValue, { theme in let components: PresentationThemeBubbleColorComponents = wallpaper ? theme.chat.message.incoming.bubble.withWallpaper : theme.chat.message.incoming.bubble.withoutWallpaper - return messageSingleBubbleLikeImage(fillColor: components.fill, strokeColor: components.stroke) + return messageSingleBubbleLikeImage(fillColor: components.fill[0], strokeColor: components.stroke) }) } @@ -827,7 +827,7 @@ public struct PresentationResourcesChat { public static func chatMessageAttachedContentHighlightedButtonIconInstantIncoming(_ theme: PresentationTheme, wallpaper: Bool) -> UIImage? { let key: PresentationResourceKey = !wallpaper ? PresentationResourceKey.chatMessageAttachedContentHighlightedButtonIconInstantIncomingWithoutWallpaper : PresentationResourceKey.chatMessageAttachedContentHighlightedButtonIconInstantIncomingWithWallpaper return theme.image(key.rawValue, { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/AttachedContentInstantIcon"), color: bubbleColorComponents(theme: theme, incoming: true, wallpaper: wallpaper).fill) + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/AttachedContentInstantIcon"), color: bubbleColorComponents(theme: theme, incoming: true, wallpaper: wallpaper).fill[0]) }) } @@ -840,7 +840,7 @@ public struct PresentationResourcesChat { public static func chatMessageAttachedContentHighlightedButtonIconInstantOutgoing(_ theme: PresentationTheme, wallpaper: Bool) -> UIImage? { let key: PresentationResourceKey = !wallpaper ? PresentationResourceKey.chatMessageAttachedContentHighlightedButtonIconInstantOutgoingWithoutWallpaper : PresentationResourceKey.chatMessageAttachedContentHighlightedButtonIconInstantOutgoingWithWallpaper return theme.image(key.rawValue, { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/AttachedContentInstantIcon"), color: bubbleColorComponents(theme: theme, incoming: false, wallpaper: wallpaper).fill) + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/AttachedContentInstantIcon"), color: bubbleColorComponents(theme: theme, incoming: false, wallpaper: wallpaper).fill[0]) }) } diff --git a/submodules/TelegramUI/Images.xcassets/Chat/OverscrollFolder.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/OverscrollFolder.imageset/Contents.json new file mode 100644 index 0000000000..e8bb9f9c6d --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/OverscrollFolder.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Folder.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/OverscrollFolder.imageset/Folder.svg b/submodules/TelegramUI/Images.xcassets/Chat/OverscrollFolder.imageset/Folder.svg new file mode 100644 index 0000000000..458fe8b374 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/OverscrollFolder.imageset/Folder.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift index 13e9f7a1ea..2a0b71c431 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift @@ -386,7 +386,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail if nextType == nil { if MFMailComposeViewController.canSendMail(), let controller = controller { let formattedNumber = formatPhoneNumber(number) - strongSelf.presentEmailComposeController(address: "sms@stel.com", subject: strongSelf.presentationData.strings.Login_EmailCodeSubject(formattedNumber).string, body: strongSelf.presentationData.strings.Login_EmailCodeBody(formattedNumber).string, from: controller) + strongSelf.presentEmailComposeController(address: "reports@stel.com", subject: strongSelf.presentationData.strings.Login_EmailCodeSubject(formattedNumber).string, body: strongSelf.presentationData.strings.Login_EmailCodeBody(formattedNumber).string, from: controller) } else { controller?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: strongSelf.presentationData.strings.Login_EmailNotConfiguredError, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 3c3df97a34..c2245fb985 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -214,7 +214,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G public weak var parentController: ViewController? - private let currentChatListFilter: ChatListFilterData? + private let currentChatListFilter: Int32? public var peekActions: ChatControllerPeekActions = .standard private var didSetup3dTouch: Bool = false @@ -465,7 +465,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private var nextChannelToReadDisposable: Disposable? - public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic = Atomic(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: ChatListFilterData? = nil) { + public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic = Atomic(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil) { let _ = ChatControllerCount.modify { value in return value + 1 } @@ -3314,7 +3314,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info { if strongSelf.nextChannelToReadDisposable == nil { strongSelf.nextChannelToReadDisposable = (combineLatest(queue: .mainQueue(), - strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id, filter: strongSelf.currentChatListFilter.flatMap(chatListFilterPredicate)), + strongSelf.context.engine.peers.getNextUnreadChannel(peerId: channel.id, chatListFilterId: strongSelf.currentChatListFilter, getFilterPredicate: chatListFilterPredicate), ApplicationSpecificNotice.getNextChatSuggestionTip(accountManager: strongSelf.context.sharedContext.accountManager) ) |> then(.complete() |> delay(1.0, queue: .mainQueue())) @@ -3324,8 +3324,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } strongSelf.chatDisplayNode.historyNode.offerNextChannelToRead = true - strongSelf.chatDisplayNode.historyNode.nextChannelToRead = nextPeer.flatMap { nextPeer -> (peer: EnginePeer, unreadCount: Int) in - return (peer: nextPeer.peer, unreadCount: nextPeer.unreadCount) + strongSelf.chatDisplayNode.historyNode.nextChannelToRead = nextPeer.flatMap { nextPeer -> (peer: EnginePeer, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation) in + return (peer: nextPeer.peer, unreadCount: nextPeer.unreadCount, location: nextPeer.location) } strongSelf.chatDisplayNode.historyNode.nextChannelToReadDisplayName = nextChatSuggestionTip >= 3 @@ -7075,7 +7075,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) - self.chatDisplayNode.historyNode.openNextChannelToRead = { [weak self] peer in + self.chatDisplayNode.historyNode.openNextChannelToRead = { [weak self] peer, location in guard let strongSelf = self else { return } @@ -7086,6 +7086,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G titleViewSnapshotState: strongSelf.chatTitleView?.prepareSnapshotState(), avatarSnapshotState: (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState() ) + + var nextFolderId: Int32? + switch location { + case let .folder(id, _): + nextFolderId = id + case .same: + nextFolderId = strongSelf.currentChatListFilter + default: + nextFolderId = nil + } + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: strongSelf.currentChatListFilter, completion: { nextController in (nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState) })) diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index ce37ef212e..3cfa3dea3c 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -549,13 +549,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { var isSelectionGestureEnabled = true private var overscrollView: ComponentHostView? - var nextChannelToRead: (peer: EnginePeer, unreadCount: Int)? + var nextChannelToRead: (peer: EnginePeer, unreadCount: Int, location: TelegramEngine.NextUnreadChannelLocation)? var offerNextChannelToRead: Bool = false var nextChannelToReadDisplayName: Bool = false private var currentOverscrollExpandProgress: CGFloat = 0.0 private var freezeOverscrollControl: Bool = false private var feedback: HapticFeedback? - var openNextChannelToRead: ((EnginePeer) -> Void)? + var openNextChannelToRead: ((EnginePeer, TelegramEngine.NextUnreadChannelLocation) -> Void)? private let clientId: Atomic @@ -1171,9 +1171,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { guard let strongSelf = self else { return } - if let channel = strongSelf.nextChannelToRead?.peer, strongSelf.currentOverscrollExpandProgress >= 0.99 { + if let nextChannelToRead = strongSelf.nextChannelToRead, strongSelf.currentOverscrollExpandProgress >= 0.99 { strongSelf.freezeOverscrollControl = true - strongSelf.openNextChannelToRead?(channel) + strongSelf.openNextChannelToRead?(nextChannelToRead.peer, nextChannelToRead.location) } } @@ -1239,36 +1239,59 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.currentOverscrollExpandProgress = expandProgress } - if expandProgress < 0.1 || self.nextChannelToRead == nil { - chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: nil) - } else if expandProgress >= 0.99 { - //TODO:localize - let text: String = "Release to go to the next unread channel" - if chatControllerNode.inputPanelOverscrollNode?.text != text { - chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: text, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 1)) + if let nextChannelToRead = self.nextChannelToRead { + let swipeText: (String, [(Int, NSRange)]) + let releaseText: (String, [(Int, NSRange)]) + switch nextChannelToRead.location { + case .same: + swipeText = (self.currentPresentationData.strings.Chat_NextChannelSameLocationSwipeProgress, []) + releaseText = (self.currentPresentationData.strings.Chat_NextChannelSameLocationSwipeAction, []) + case .archived: + swipeText = (self.currentPresentationData.strings.Chat_NextChannelArchivedSwipeProgress, []) + releaseText = (self.currentPresentationData.strings.Chat_NextChannelArchivedSwipeAction, []) + case .unarchived: + swipeText = (self.currentPresentationData.strings.Chat_NextChannelUnarchivedSwipeProgress, []) + releaseText = (self.currentPresentationData.strings.Chat_NextChannelUnarchivedSwipeAction, []) + case let .folder(_, title): + swipeText = self.currentPresentationData.strings.Chat_NextChannelFolderSwipeProgress(title)._tuple + releaseText = self.currentPresentationData.strings.Chat_NextChannelFolderSwipeAction(title)._tuple + } + + if expandProgress < 0.1 { + chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: nil) + } else if expandProgress >= 0.99 { + if chatControllerNode.inputPanelOverscrollNode?.text.0 != swipeText.0 { + chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: swipeText, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 1)) + } + } else { + if chatControllerNode.inputPanelOverscrollNode?.text.0 != releaseText.0 { + chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: releaseText, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 2)) + } } } else { - //TODO:localize - let text: String = "Swipe up to go to the next unread channel" - if chatControllerNode.inputPanelOverscrollNode?.text != text { - chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: ChatInputPanelOverscrollNode(text: text, color: self.currentPresentationData.theme.theme.rootController.navigationBar.secondaryTextColor, priority: 2)) - } + chatControllerNode.setChatInputPanelOverscrollNode(overscrollNode: nil) } - let overscrollSize = overscrollView.update( + let overscrollFrame = CGRect(origin: CGPoint(x: 0.0, y: self.insets.top), size: CGSize(width: self.bounds.width, height: 94.0)) + + let _ = overscrollView.update( transition: .immediate, component: AnyComponent(ChatOverscrollControl( backgroundColor: selectDateFillStaticColor(theme: self.currentPresentationData.theme.theme, wallpaper: self.currentPresentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: self.currentPresentationData.theme.theme.chat.serviceMessage.dateTextColor, wallpaper: self.currentPresentationData.theme.wallpaper), peer: self.nextChannelToRead?.peer, unreadCount: self.nextChannelToRead?.unreadCount ?? 0, + location: self.nextChannelToRead?.location ?? .same, context: self.context, - expandDistance: expandDistance + expandDistance: expandDistance, + absoluteRect: CGRect(origin: CGPoint(x: overscrollFrame.minX, y: self.bounds.height - overscrollFrame.minY), size: overscrollFrame.size), + absoluteSize: self.bounds.size, + wallpaperNode: chatControllerNode.backgroundNode )), environment: {}, containerSize: CGSize(width: self.bounds.width, height: 200.0) ) - overscrollView.frame = CGRect(origin: CGPoint(x: floor((self.bounds.width - overscrollSize.width) / 2.0), y: self.insets.top), size: overscrollSize) + overscrollView.frame = overscrollFrame } else if let overscrollView = self.overscrollView { self.overscrollView = nil overscrollView.removeFromSuperview() diff --git a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift index 841078d66d..c65e5bc8f6 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift @@ -731,7 +731,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } titleColor = presentationData.theme.theme.chat.message.incoming.accentTextColor let bubbleColor = bubbleColorComponents(theme: presentationData.theme.theme, incoming: true, wallpaper: !presentationData.theme.wallpaper.isEmpty) - titleHighlightedColor = bubbleColor.fill + titleHighlightedColor = bubbleColor.fill[0] } else { buttonImage = PresentationResourcesChat.chatMessageAttachedContentButtonOutgoing(presentationData.theme.theme)! buttonHighlightedImage = PresentationResourcesChat.chatMessageAttachedContentHighlightedButtonOutgoing(presentationData.theme.theme)! @@ -741,7 +741,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } titleColor = presentationData.theme.theme.chat.message.outgoing.accentTextColor let bubbleColor = bubbleColorComponents(theme: presentationData.theme.theme, incoming: false, wallpaper: !presentationData.theme.wallpaper.isEmpty) - titleHighlightedColor = bubbleColor.fill + titleHighlightedColor = bubbleColor.fill[0] } let (buttonWidth, continueLayout) = makeButtonLayout(constrainedSize.width, buttonImage, buttonHighlightedImage, buttonIconImage, buttonHighlightedIconImage, actionTitle, titleColor, titleHighlightedColor) boundingSize.width = max(buttonWidth, boundingSize.width) diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleContentCalclulateImageCorners.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleContentCalclulateImageCorners.swift index 7d3fbc07f6..a99c5992df 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleContentCalclulateImageCorners.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleContentCalclulateImageCorners.swift @@ -77,7 +77,7 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat case .None: colors = chatPresentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper } - if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + if colors.fill[0] == colors.stroke || colors.stroke.alpha.isZero { bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) } else { bubbleInsets = layoutConstants.bubble.strokeInsets @@ -110,7 +110,7 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat if case .color = chatPresentationData.theme.wallpaper { let colors: PresentationThemeBubbleColorComponents colors = chatPresentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper - if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + if colors.fill[0] == colors.stroke || colors.stroke.alpha.isZero { bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) } else { bubbleInsets = layoutConstants.bubble.strokeInsets @@ -135,7 +135,7 @@ func chatMessageBubbleImageContentCorners(relativeContentPosition position: Chat if case .color = chatPresentationData.theme.wallpaper { let colors: PresentationThemeBubbleColorComponents colors = chatPresentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper - if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + if colors.fill[0] == colors.stroke || colors.stroke.alpha.isZero { bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) } else { bubbleInsets = layoutConstants.bubble.strokeInsets diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index ef39095ec0..c641cd4923 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -371,7 +371,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode selectionBackgroundFrame = selectionBackgroundFrame.inset(by: selectionInsets) let bubbleColor = graphics.hasWallpaper ? messageTheme.bubble.withWallpaper.fill : messageTheme.bubble.withoutWallpaper.fill - let selectionColor = bubbleColor.withAlphaComponent(1.0).mixedWith(messageTheme.accentTextColor.withAlphaComponent(1.0), alpha: 0.08) + let selectionColor = bubbleColor[0].withAlphaComponent(1.0).mixedWith(messageTheme.accentTextColor.withAlphaComponent(1.0), alpha: 0.08) self.selectionBackgroundNode?.backgroundColor = selectionColor self.selectionBackgroundNode?.frame = selectionBackgroundFrame diff --git a/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift index f9cc25ac81..fb63b3b837 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift @@ -224,7 +224,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { titleColor = item.presentationData.theme.theme.chat.message.incoming.accentTextColor let bubbleColors = bubbleColorComponents(theme: item.presentationData.theme.theme, incoming: true, wallpaper: !item.presentationData.theme.wallpaper.isEmpty) - titleHighlightedColor = bubbleColors.fill + titleHighlightedColor = bubbleColors.fill[0] avatarPlaceholderColor = item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor } else { buttonImage = PresentationResourcesChat.chatMessageAttachedContentButtonOutgoing(item.presentationData.theme.theme)! @@ -232,7 +232,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { titleColor = item.presentationData.theme.theme.chat.message.outgoing.accentTextColor let bubbleColors = bubbleColorComponents(theme: item.presentationData.theme.theme, incoming: false, wallpaper: !item.presentationData.theme.wallpaper.isEmpty) - titleHighlightedColor = bubbleColors.fill + titleHighlightedColor = bubbleColors.fill[0] avatarPlaceholderColor = item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor } diff --git a/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift index 7e901a3377..e5d284ab45 100644 --- a/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift @@ -131,7 +131,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { } else { colors = item.presentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper } - if colors.fill == colors.stroke || colors.stroke.alpha.isZero { + if colors.fill[0] == colors.stroke || colors.stroke.alpha.isZero { bubbleInsets = UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) } else { bubbleInsets = layoutConstants.bubble.strokeInsets diff --git a/submodules/TelegramUI/Sources/ChatMessageUnsupportedBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageUnsupportedBubbleContentNode.swift index db5623a2eb..db3b94620b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageUnsupportedBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageUnsupportedBubbleContentNode.swift @@ -48,13 +48,13 @@ final class ChatMessageUnsupportedBubbleContentNode: ChatMessageBubbleContentNod buttonHighlightedImage = PresentationResourcesChat.chatMessageAttachedContentHighlightedButtonIncoming(presentationData.theme.theme)! titleColor = presentationData.theme.theme.chat.message.incoming.accentTextColor let bubbleColor = bubbleColorComponents(theme: presentationData.theme.theme, incoming: true, wallpaper: !presentationData.theme.wallpaper.isEmpty) - titleHighlightedColor = bubbleColor.fill + titleHighlightedColor = bubbleColor.fill[0] } else { buttonImage = PresentationResourcesChat.chatMessageAttachedContentButtonOutgoing(presentationData.theme.theme)! buttonHighlightedImage = PresentationResourcesChat.chatMessageAttachedContentHighlightedButtonOutgoing(presentationData.theme.theme)! titleColor = presentationData.theme.theme.chat.message.outgoing.accentTextColor let bubbleColor = bubbleColorComponents(theme: presentationData.theme.theme, incoming: false, wallpaper: !presentationData.theme.wallpaper.isEmpty) - titleHighlightedColor = bubbleColor.fill + titleHighlightedColor = bubbleColor.fill[0] } let (buttonWidth, continueActionButtonLayout) = makeButtonLayout(constrainedSize.width, buttonImage, buttonHighlightedImage, nil, nil, presentationData.strings.Conversation_UpdateTelegram, titleColor, titleHighlightedColor) diff --git a/submodules/TelegramUI/Sources/ChatOverscrollControl.swift b/submodules/TelegramUI/Sources/ChatOverscrollControl.swift index f8c47db4c9..fe2646605e 100644 --- a/submodules/TelegramUI/Sources/ChatOverscrollControl.swift +++ b/submodules/TelegramUI/Sources/ChatOverscrollControl.swift @@ -6,6 +6,9 @@ import TelegramCore import Postbox import AccountContext import AvatarNode +import TextFormat +import Markdown +import WallpaperBackgroundNode final class BlurredRoundedRectangle: Component { let color: UIColor @@ -314,11 +317,24 @@ final class BadgeComponent: CombinedComponent { let count: Int let backgroundColor: UIColor let foregroundColor: UIColor + let rect: CGRect + let withinSize: CGSize + let wallpaperNode: WallpaperBackgroundNode? - init(count: Int, backgroundColor: UIColor, foregroundColor: UIColor) { + init( + count: Int, + backgroundColor: UIColor, + foregroundColor: UIColor, + rect: CGRect, + withinSize: CGSize, + wallpaperNode: WallpaperBackgroundNode? + ) { self.count = count self.backgroundColor = backgroundColor self.foregroundColor = foregroundColor + self.rect = rect + self.withinSize = withinSize + self.wallpaperNode = wallpaperNode } static func ==(lhs: BadgeComponent, rhs: BadgeComponent) -> Bool { @@ -331,11 +347,20 @@ final class BadgeComponent: CombinedComponent { if !lhs.foregroundColor.isEqual(rhs.foregroundColor) { return false } + if lhs.rect != rhs.rect { + return false + } + if lhs.withinSize != rhs.withinSize { + return false + } + if lhs.wallpaperNode != rhs.wallpaperNode { + return false + } return true } static var body: Body { - let background = Child(BlurredRoundedRectangle.self) + let background = Child(WallpaperBlurComponent.self) let text = Child(Text.self) return { context in @@ -353,13 +378,20 @@ final class BadgeComponent: CombinedComponent { let backgroundSize = CGSize(width: max(height, text.size.width + 8.0), height: height) let background = background.update( - component: BlurredRoundedRectangle(color: context.component.backgroundColor), + component: WallpaperBlurComponent( + rect: CGRect(origin: context.component.rect.origin, size: backgroundSize), + withinSize: context.component.withinSize, + color: context.component.backgroundColor, + wallpaperNode: context.component.wallpaperNode + ), availableSize: backgroundSize, transition: .immediate ) context.add(background .position(CGPoint(x: backgroundSize.width / 2.0, y: backgroundSize.height / 2.0)) + .cornerRadius(min(backgroundSize.width, backgroundSize.height) / 2.0) + .clipsToBounds(true) ) context.add(text @@ -400,11 +432,24 @@ final class AvatarComponent: Component { let context: AccountContext let peer: EnginePeer let badge: Badge? + let rect: CGRect + let withinSize: CGSize + let wallpaperNode: WallpaperBackgroundNode? - init(context: AccountContext, peer: EnginePeer, badge: Badge?) { + init( + context: AccountContext, + peer: EnginePeer, + badge: Badge?, + rect: CGRect, + withinSize: CGSize, + wallpaperNode: WallpaperBackgroundNode? + ) { self.context = context self.peer = peer self.badge = badge + self.rect = rect + self.withinSize = withinSize + self.wallpaperNode = wallpaperNode } static func ==(lhs: AvatarComponent, rhs: AvatarComponent) -> Bool { @@ -417,6 +462,15 @@ final class AvatarComponent: Component { if lhs.badge != rhs.badge { return false } + if lhs.rect != rhs.rect { + return false + } + if lhs.withinSize != rhs.withinSize { + return false + } + if lhs.wallpaperNode !== rhs.wallpaperNode { + return false + } return true } @@ -458,7 +512,10 @@ final class AvatarComponent: Component { component: AnyComponent(BadgeComponent( count: badge.count, backgroundColor: badge.backgroundColor, - foregroundColor: badge.foregroundColor + foregroundColor: badge.foregroundColor, + rect: CGRect(origin: component.rect.offsetBy(dx: 0.0, dy: 0.0).origin, size: CGSize()), + withinSize: component.withinSize, + wallpaperNode: component.wallpaperNode )), environment: {}, containerSize: CGSize(width: 100.0, height: 100.0 @@ -505,13 +562,115 @@ final class AvatarComponent: Component { } } +private final class WallpaperBlurNode: ASDisplayNode { + private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? + private let colorNode: ASDisplayNode + + override init() { + self.colorNode = ASDisplayNode() + + super.init() + + self.addSubnode(self.colorNode) + } + + func update(rect: CGRect, within size: CGSize, color: UIColor, wallpaperNode: WallpaperBackgroundNode?, transition: ContainedViewLayoutTransition) { + var transition = transition + if self.backgroundNode == nil { + if let backgroundNode = wallpaperNode?.makeBubbleBackground(for: .free) { + self.backgroundNode = backgroundNode + self.insertSubnode(backgroundNode, at: 0) + transition = .immediate + } + } + + self.colorNode.backgroundColor = color + transition.updateFrame(node: self.colorNode, frame: CGRect(origin: CGPoint(), size: rect.size)) + + if let backgroundNode = self.backgroundNode { + transition.updateFrame(node: backgroundNode, frame: CGRect(origin: CGPoint(), size: rect.size)) + backgroundNode.update(rect: rect, within: size, transition: transition) + } + } +} + +private final class WallpaperBlurComponent: Component { + let rect: CGRect + let withinSize: CGSize + let color: UIColor + let wallpaperNode: WallpaperBackgroundNode? + + init( + rect: CGRect, + withinSize: CGSize, + color: UIColor, + wallpaperNode: WallpaperBackgroundNode? + ) { + self.rect = rect + self.withinSize = withinSize + self.color = color + self.wallpaperNode = wallpaperNode + } + + static func ==(lhs: WallpaperBlurComponent, rhs: WallpaperBlurComponent) -> Bool { + if lhs.rect != rhs.rect { + return false + } + if lhs.withinSize != rhs.withinSize { + return false + } + if !lhs.color.isEqual(rhs.color) { + return false + } + if lhs.wallpaperNode !== rhs.wallpaperNode { + return false + } + return true + } + + final class View: UIView { + private let background: WallpaperBlurNode + + init() { + self.background = WallpaperBlurNode() + + super.init(frame: CGRect()) + + self.addSubview(self.background.view) + } + + required init?(coder aDecoder: NSCoder) { + preconditionFailure() + } + + func update(component: WallpaperBlurComponent, availableSize: CGSize, transition: Transition) -> CGSize { + transition.setFrame(view: self.background.view, frame: CGRect(origin: CGPoint(), size: availableSize)) + self.background.update(rect: component.rect, within: component.withinSize, color: component.color, wallpaperNode: component.wallpaperNode, transition: .immediate) + + return availableSize + } + } + + func makeView() -> View { + return View() + } + + func update(view: View, availableSize: CGSize, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, transition: transition) + } +} + final class OverscrollContentsComponent: Component { let context: AccountContext let backgroundColor: UIColor let foregroundColor: UIColor let peer: EnginePeer? let unreadCount: Int + let location: TelegramEngine.NextUnreadChannelLocation let expandOffset: CGFloat + let absoluteRect: CGRect + let absoluteSize: CGSize + let wallpaperNode: WallpaperBackgroundNode? init( context: AccountContext, @@ -519,14 +678,22 @@ final class OverscrollContentsComponent: Component { foregroundColor: UIColor, peer: EnginePeer?, unreadCount: Int, - expandOffset: CGFloat + location: TelegramEngine.NextUnreadChannelLocation, + expandOffset: CGFloat, + absoluteRect: CGRect, + absoluteSize: CGSize, + wallpaperNode: WallpaperBackgroundNode? ) { self.context = context self.backgroundColor = backgroundColor self.foregroundColor = foregroundColor self.peer = peer self.unreadCount = unreadCount + self.location = location self.expandOffset = expandOffset + self.absoluteRect = absoluteRect + self.absoluteSize = absoluteSize + self.wallpaperNode = wallpaperNode } static func ==(lhs: OverscrollContentsComponent, rhs: OverscrollContentsComponent) -> Bool { @@ -545,15 +712,28 @@ final class OverscrollContentsComponent: Component { if lhs.unreadCount != rhs.unreadCount { return false } + if lhs.location != rhs.location { + return false + } if lhs.expandOffset != rhs.expandOffset { return false } + if lhs.absoluteRect != rhs.absoluteRect { + return false + } + if lhs.absoluteSize != rhs.absoluteSize { + return false + } + if lhs.wallpaperNode !== rhs.wallpaperNode { + return false + } return true } final class View: UIView { private let backgroundScalingContainer: ASDisplayNode - private let backgroundNode: NavigationBackgroundNode + private let backgroundNode: WallpaperBlurNode + private let backgroundFolderMask: UIImageView private let backgroundClippingNode: ASDisplayNode private let avatarView = ComponentHostView() private let checkView = ComponentHostView() @@ -564,7 +744,7 @@ final class OverscrollContentsComponent: Component { private let arrowOffsetContainer: ASDisplayNode private let titleOffsetContainer: ASDisplayNode - private let titleBackgroundNode: NavigationBackgroundNode + private let titleBackgroundNode: WallpaperBlurNode private let titleNode: ImmediateTextNode private var isFullyExpanded: Bool = false @@ -573,8 +753,12 @@ final class OverscrollContentsComponent: Component { init() { self.backgroundScalingContainer = ASDisplayNode() - self.backgroundNode = NavigationBackgroundNode(color: .clear) + self.backgroundNode = WallpaperBlurNode() self.backgroundNode.clipsToBounds = true + + self.backgroundFolderMask = UIImageView() + self.backgroundFolderMask.image = UIImage(bundleImageName: "Chat/OverscrollFolder")?.stretchableImage(withLeftCapWidth: 0, topCapHeight: 40) + self.backgroundClippingNode = ASDisplayNode() self.backgroundClippingNode.clipsToBounds = true self.arrowNode = ASImageNode() @@ -584,7 +768,8 @@ final class OverscrollContentsComponent: Component { self.arrowOffsetContainer = ASDisplayNode() self.titleOffsetContainer = ASDisplayNode() - self.titleBackgroundNode = NavigationBackgroundNode(color: .clear) + self.titleBackgroundNode = WallpaperBlurNode() + self.titleBackgroundNode.clipsToBounds = true self.titleNode = ImmediateTextNode() super.init(frame: CGRect()) @@ -620,36 +805,53 @@ final class OverscrollContentsComponent: Component { self.checkView.isHidden = false } - let fullHeight: CGFloat = 90.0 - let backgroundWidth: CGFloat = 50.0 - let minBackgroundHeight: CGFloat = backgroundWidth + 34.0 + let fullHeight: CGFloat = 94.0 + let backgroundWidth: CGFloat = 56.0 + let minBackgroundHeight: CGFloat = backgroundWidth + 5.0 let avatarInset: CGFloat = 6.0 let isFullyExpanded = component.expandOffset >= fullHeight - let backgroundHeight: CGFloat = max(minBackgroundHeight, min(fullHeight, component.expandOffset)) + let isFolderMask: Bool + switch component.location { + case .archived, .folder: + isFolderMask = true + default: + isFolderMask = false + } + + let expandProgress: CGFloat = max(0.1, min(1.0, component.expandOffset / fullHeight)) + + func interpolate(from: CGFloat, to: CGFloat, value: CGFloat) -> CGFloat { + return (1.0 - value) * from + value * to + } + + let backgroundHeight: CGFloat = interpolate(from: minBackgroundHeight, to: fullHeight, value: expandProgress) let backgroundFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - backgroundWidth) / 2.0), y: fullHeight - backgroundHeight), size: CGSize(width: backgroundWidth, height: backgroundHeight)) - let expandProgress: CGFloat = max(0.1, min(1.0, component.expandOffset / minBackgroundHeight)) let alphaProgress: CGFloat = max(0.0, min(1.0, component.expandOffset / 10.0)) let maxAvatarScale: CGFloat = 1.0 - let avatarExpandProgress: CGFloat = max(0.01, min(maxAvatarScale, component.expandOffset / fullHeight)) + var avatarExpandProgress: CGFloat = max(0.01, min(maxAvatarScale, component.expandOffset / fullHeight)) + avatarExpandProgress *= expandProgress + + let avatarOffsetProgress = interpolate(from: 0.1, to: 1.0, value: avatarExpandProgress) transition.setAlpha(view: self.backgroundScalingContainer.view, alpha: alphaProgress) transition.setFrame(view: self.backgroundScalingContainer.view, frame: CGRect(origin: CGPoint(x: floor(availableSize.width / 2.0), y: fullHeight), size: CGSize(width: 0.0, height: 0.0))) transition.setSublayerTransform(view: self.backgroundScalingContainer.view, transform: CATransform3DMakeScale(expandProgress, expandProgress, 1.0)) transition.setFrame(view: self.backgroundNode.view, frame: CGRect(origin: CGPoint(x: 0.0, y: fullHeight - backgroundFrame.size.height), size: backgroundFrame.size)) - self.backgroundNode.updateColor(color: component.backgroundColor, transition: .immediate) - self.backgroundNode.update(size: backgroundFrame.size, cornerRadius: backgroundWidth / 2.0, transition: .immediate) + self.backgroundNode.update(rect: backgroundFrame.offsetBy(dx: component.absoluteRect.minX, dy: component.absoluteRect.minY), within: component.absoluteSize, color: component.backgroundColor, wallpaperNode: component.wallpaperNode, transition: .immediate) + self.backgroundFolderMask.frame = CGRect(origin: CGPoint(), size: backgroundFrame.size) - self.avatarView.frame = CGRect(origin: CGPoint(x: floor(-backgroundWidth / 2.0), y: floor(-backgroundWidth / 2.0)), size: CGSize(width: backgroundWidth, height: backgroundWidth)) + let avatarFrame = CGRect(origin: CGPoint(x: floor(-backgroundWidth / 2.0), y: floor(-backgroundWidth / 2.0)), size: CGSize(width: backgroundWidth, height: backgroundWidth)) + self.avatarView.frame = avatarFrame transition.setFrame(view: self.avatarOffsetContainer.view, frame: CGRect()) transition.setFrame(view: self.avatarScalingContainer.view, frame: CGRect()) - transition.setFrame(view: self.avatarExtraScalingContainer.view, frame: CGRect(origin: CGPoint(x: availableSize.width / 2.0, y: fullHeight - backgroundWidth / 2.0), size: CGSize()).offsetBy(dx: 0.0, dy: (1.0 - avatarExpandProgress) * backgroundWidth * 0.5)) + transition.setFrame(view: self.avatarExtraScalingContainer.view, frame: CGRect(origin: CGPoint(x: availableSize.width / 2.0, y: fullHeight - backgroundWidth / 2.0), size: CGSize()).offsetBy(dx: 0.0, dy: (1.0 - avatarOffsetProgress) * backgroundWidth * 0.5)) transition.setSublayerTransform(view: self.avatarScalingContainer.view, transform: CATransform3DMakeScale(avatarExpandProgress, avatarExpandProgress, 1.0)) let titleText: String @@ -664,13 +866,14 @@ final class OverscrollContentsComponent: Component { let titleBackgroundSize = CGSize(width: titleSize.width + 18.0, height: titleSize.height + 8.0) let titleBackgroundFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleBackgroundSize.width) / 2.0), y: fullHeight - titleBackgroundSize.height - 8.0), size: titleBackgroundSize) self.titleBackgroundNode.frame = titleBackgroundFrame - self.titleBackgroundNode.updateColor(color: component.backgroundColor, transition: .immediate) - self.titleBackgroundNode.update(size: titleBackgroundFrame.size, cornerRadius: titleBackgroundFrame.size.height / 2.0, transition: .immediate) + self.titleBackgroundNode.update(rect: titleBackgroundFrame.offsetBy(dx: component.absoluteRect.minX, dy: component.absoluteRect.minY), within: component.absoluteSize, color: component.backgroundColor, wallpaperNode: component.wallpaperNode, transition: .immediate) + self.titleBackgroundNode.cornerRadius = min(titleBackgroundFrame.width, titleBackgroundFrame.height) / 2.0 self.titleNode.frame = titleSize.centered(in: titleBackgroundFrame) let backgroundClippingFrame = CGRect(origin: CGPoint(x: floor(-backgroundWidth / 2.0), y: -fullHeight), size: CGSize(width: backgroundWidth, height: isFullyExpanded ? backgroundWidth : fullHeight)) - self.backgroundClippingNode.cornerRadius = backgroundWidth / 2.0 - self.backgroundNode.cornerRadius = backgroundWidth / 2.0 + self.backgroundClippingNode.cornerRadius = isFolderMask ? 10.0 : backgroundWidth / 2.0 + self.backgroundNode.cornerRadius = isFolderMask ? 0.0 : backgroundWidth / 2.0 + self.backgroundNode.view.mask = isFolderMask ? self.backgroundFolderMask : nil if !(self.validForegroundColor?.isEqual(component.foregroundColor) ?? false) { self.validForegroundColor = component.foregroundColor @@ -713,7 +916,7 @@ final class OverscrollContentsComponent: Component { transformTransition = .immediate } - let checkSize: CGFloat = 50.0 + let checkSize: CGFloat = 56.0 self.checkView.frame = CGRect(origin: CGPoint(x: floor(-checkSize / 2.0), y: floor(-checkSize / 2.0)), size: CGSize(width: checkSize, height: checkSize)) let _ = self.checkView.update( transition: Transition(animation: transformTransition.isAnimated ? .curve(duration: 0.2, curve: .easeInOut) : .none), @@ -732,7 +935,10 @@ final class OverscrollContentsComponent: Component { component: AnyComponent(AvatarComponent( context: component.context, peer: peer, - badge: isFullyExpanded ? AvatarComponent.Badge(count: component.unreadCount, backgroundColor: component.backgroundColor, foregroundColor: component.foregroundColor) : nil + badge: isFullyExpanded ? AvatarComponent.Badge(count: component.unreadCount, backgroundColor: component.backgroundColor, foregroundColor: component.foregroundColor) : nil, + rect: avatarFrame.offsetBy(dx: self.avatarExtraScalingContainer.frame.midX + component.absoluteRect.minX, dy: self.avatarExtraScalingContainer.frame.midY + component.absoluteRect.minY), + withinSize: component.absoluteSize, + wallpaperNode: component.wallpaperNode )), environment: {}, containerSize: self.avatarView.bounds.size @@ -769,23 +975,35 @@ final class ChatOverscrollControl: CombinedComponent { let foregroundColor: UIColor let peer: EnginePeer? let unreadCount: Int + let location: TelegramEngine.NextUnreadChannelLocation let context: AccountContext let expandDistance: CGFloat + let absoluteRect: CGRect + let absoluteSize: CGSize + let wallpaperNode: WallpaperBackgroundNode? init( backgroundColor: UIColor, foregroundColor: UIColor, peer: EnginePeer?, unreadCount: Int, + location: TelegramEngine.NextUnreadChannelLocation, context: AccountContext, - expandDistance: CGFloat + expandDistance: CGFloat, + absoluteRect: CGRect, + absoluteSize: CGSize, + wallpaperNode: WallpaperBackgroundNode? ) { self.backgroundColor = backgroundColor self.foregroundColor = foregroundColor self.peer = peer self.unreadCount = unreadCount + self.location = location self.context = context self.expandDistance = expandDistance + self.absoluteRect = absoluteRect + self.absoluteSize = absoluteSize + self.wallpaperNode = wallpaperNode } static func ==(lhs: ChatOverscrollControl, rhs: ChatOverscrollControl) -> Bool { @@ -801,12 +1019,24 @@ final class ChatOverscrollControl: CombinedComponent { if lhs.unreadCount != rhs.unreadCount { return false } + if lhs.location != rhs.location { + return false + } if lhs.context !== rhs.context { return false } if lhs.expandDistance != rhs.expandDistance { return false } + if lhs.absoluteRect != rhs.absoluteRect { + return false + } + if lhs.absoluteSize != rhs.absoluteSize { + return false + } + if lhs.wallpaperNode !== rhs.wallpaperNode { + return false + } return true } @@ -821,7 +1051,11 @@ final class ChatOverscrollControl: CombinedComponent { foregroundColor: context.component.foregroundColor, peer: context.component.peer, unreadCount: context.component.unreadCount, - expandOffset: context.component.expandDistance + location: context.component.location, + expandOffset: context.component.expandDistance, + absoluteRect: context.component.absoluteRect, + absoluteSize: context.component.absoluteSize, + wallpaperNode: context.component.wallpaperNode ), availableSize: context.availableSize, transition: context.transition @@ -839,18 +1073,22 @@ final class ChatOverscrollControl: CombinedComponent { } final class ChatInputPanelOverscrollNode: ASDisplayNode { - let text: String + let text: (String, [(Int, NSRange)]) let priority: Int private let titleNode: ImmediateTextNode - init(text: String, color: UIColor, priority: Int) { + init(text: (String, [(Int, NSRange)]), color: UIColor, priority: Int) { self.text = text self.priority = priority self.titleNode = ImmediateTextNode() super.init() - self.titleNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: color) + let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: color) + let bold = MarkdownAttributeSet(font: Font.bold(14.0), textColor: color) + + self.titleNode.attributedText = addAttributesToStringWithRanges(text, body: body, argumentAttributes: [0: bold]) + self.addSubnode(self.titleNode) } diff --git a/submodules/TelegramUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/Sources/ChatSendMessageActionSheetControllerNode.swift index dac19b9c0f..784ef26bc8 100644 --- a/submodules/TelegramUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -267,7 +267,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let outgoing: PresentationThemeBubbleColorComponents = self.presentationData.chatWallpaper.isEmpty ? self.presentationData.theme.chat.message.outgoing.bubble.withoutWallpaper : self.presentationData.theme.chat.message.outgoing.bubble.withWallpaper let maxCornerRadius = self.presentationData.chatBubbleCorners.mainRadius - self.messageBackgroundNode.image = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: maxCornerRadius, incoming: false, fillColor: outgoing.gradientFill, strokeColor: outgoing.fill == outgoing.gradientFill ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) + self.messageBackgroundNode.image = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: maxCornerRadius, incoming: false, fillColor: outgoing.fill.last ?? outgoing.fill[0], strokeColor: outgoing.fill.count > 1 ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) self.view.addSubview(self.effectView) self.addSubnode(self.dimNode) @@ -370,7 +370,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let outgoing: PresentationThemeBubbleColorComponents = self.presentationData.chatWallpaper.isEmpty ? self.presentationData.theme.chat.message.outgoing.bubble.withoutWallpaper : self.presentationData.theme.chat.message.outgoing.bubble.withWallpaper let maxCornerRadius = self.presentationData.chatBubbleCorners.mainRadius - self.messageBackgroundNode.image = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: maxCornerRadius, incoming: false, fillColor: outgoing.gradientFill, strokeColor: outgoing.fill == outgoing.gradientFill ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) + self.messageBackgroundNode.image = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: maxCornerRadius, incoming: false, fillColor: outgoing.fill.last ?? outgoing.fill[0], strokeColor: outgoing.fill.count > 1 ? outgoing.stroke : .clear, neighbors: .none, theme: self.presentationData.theme.chat, wallpaper: self.presentationData.chatWallpaper, knockout: false) for node in self.contentNodes { node.updateTheme(presentationData.theme) diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index ff61025692..84c8380770 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -388,7 +388,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur navigationController?.pushViewController(previewController) } } else if let settings = dataAndTheme.1 { - if let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors.flatMap { (UIColor(argb: $0.top), UIColor(argb: $0.bottom)) }, wallpaper: settings.wallpaper) { + if let theme = makePresentationTheme(mediaBox: context.sharedContext.accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors, wallpaper: settings.wallpaper) { let previewController = ThemePreviewController(context: context, previewTheme: theme, source: .theme(dataAndTheme.2)) navigationController?.pushViewController(previewController) } diff --git a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift index 8f5d568e00..a61efc7de9 100644 --- a/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/PresentationThemeSettings.swift @@ -407,13 +407,13 @@ public enum PresentationThemeBaseColor: Int32, CaseIterable { public struct PresentationThemeAccentColor: PostboxCoding, Equatable { public static func == (lhs: PresentationThemeAccentColor, rhs: PresentationThemeAccentColor) -> Bool { - return lhs.index == rhs.index && lhs.baseColor == rhs.baseColor && lhs.accentColor == rhs.accentColor && lhs.bubbleColors?.0 == rhs.bubbleColors?.0 && lhs.bubbleColors?.1 == rhs.bubbleColors?.1 + return lhs.index == rhs.index && lhs.baseColor == rhs.baseColor && lhs.accentColor == rhs.accentColor && lhs.bubbleColors == rhs.bubbleColors } public var index: Int32 public var baseColor: PresentationThemeBaseColor public var accentColor: UInt32? - public var bubbleColors: (UInt32, UInt32?)? + public var bubbleColors: [UInt32] public var wallpaper: TelegramWallpaper? public var themeIndex: Int64? @@ -425,11 +425,11 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { } self.baseColor = baseColor self.accentColor = nil - self.bubbleColors = nil + self.bubbleColors = [] self.wallpaper = nil } - public init(index: Int32, baseColor: PresentationThemeBaseColor, accentColor: UInt32? = nil, bubbleColors: (UInt32, UInt32?)? = nil, wallpaper: TelegramWallpaper? = nil) { + public init(index: Int32, baseColor: PresentationThemeBaseColor, accentColor: UInt32? = nil, bubbleColors: [UInt32] = [], wallpaper: TelegramWallpaper? = nil) { self.index = index self.baseColor = baseColor self.accentColor = accentColor @@ -441,7 +441,7 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { self.index = -1 self.baseColor = .theme self.accentColor = nil - self.bubbleColors = nil + self.bubbleColors = [] self.wallpaper = nil self.themeIndex = themeIndex } @@ -450,15 +450,22 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { self.index = decoder.decodeInt32ForKey("i", orElse: -1) self.baseColor = PresentationThemeBaseColor(rawValue: decoder.decodeInt32ForKey("b", orElse: 0)) ?? .blue self.accentColor = decoder.decodeOptionalInt32ForKey("c").flatMap { UInt32(bitPattern: $0) } - if let bubbleTopColor = decoder.decodeOptionalInt32ForKey("bt") { - if let bubbleBottomColor = decoder.decodeOptionalInt32ForKey("bb") { - self.bubbleColors = (UInt32(bitPattern: bubbleTopColor), UInt32(bitPattern: bubbleBottomColor)) - } else { - self.bubbleColors = (UInt32(bitPattern: bubbleTopColor), nil) - } + + let bubbleColors = decoder.decodeInt32ArrayForKey("bubbleColors") + if !bubbleColors.isEmpty { + self.bubbleColors = bubbleColors.map(UInt32.init(bitPattern:)) } else { - self.bubbleColors = nil + if let bubbleTopColor = decoder.decodeOptionalInt32ForKey("bt") { + if let bubbleBottomColor = decoder.decodeOptionalInt32ForKey("bb") { + self.bubbleColors = [UInt32(bitPattern: bubbleTopColor), UInt32(bitPattern: bubbleBottomColor)] + } else { + self.bubbleColors = [UInt32(bitPattern: bubbleTopColor)] + } + } else { + self.bubbleColors = [] + } } + self.wallpaper = decoder.decodeObjectForKey("w", decoder: { TelegramWallpaper(decoder: $0) }) as? TelegramWallpaper self.themeIndex = decoder.decodeOptionalInt64ForKey("t") } @@ -471,17 +478,7 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { } else { encoder.encodeNil(forKey: "c") } - if let bubbleColors = self.bubbleColors { - encoder.encodeInt32(Int32(bitPattern: bubbleColors.0), forKey: "bt") - if let bubbleBottomColor = bubbleColors.1 { - encoder.encodeInt32(Int32(bitPattern: bubbleBottomColor), forKey: "bb") - } else { - encoder.encodeNil(forKey: "bb") - } - } else { - encoder.encodeNil(forKey: "bt") - encoder.encodeNil(forKey: "bb") - } + encoder.encodeInt32Array(self.bubbleColors.map(Int32.init(bitPattern:)), forKey: "bubbleColors") if let wallpaper = self.wallpaper { encoder.encodeObject(wallpaper, forKey: "w") } else { @@ -502,28 +499,12 @@ public struct PresentationThemeAccentColor: PostboxCoding, Equatable { } } - public var customBubbleColors: (UIColor, UIColor?)? { - if let bubbleColors = self.bubbleColors { - if let bottomColor = bubbleColors.1 { - return (UIColor(rgb: UInt32(bitPattern: bubbleColors.0)), UIColor(rgb: UInt32(bitPattern: bottomColor))) - } else { - return (UIColor(rgb: UInt32(bitPattern: bubbleColors.0)), nil) - } - } else { - return nil - } + public var customBubbleColors: [UInt32] { + return self.bubbleColors } - public var plainBubbleColors: (UIColor, UIColor)? { - if let bubbleColors = self.bubbleColors { - if let bottomColor = bubbleColors.1 { - return (UIColor(rgb: UInt32(bitPattern: bubbleColors.0)), UIColor(rgb: UInt32(bitPattern: bottomColor))) - } else { - return (UIColor(rgb: UInt32(bitPattern: bubbleColors.0)), UIColor(rgb: UInt32(bitPattern: bubbleColors.0))) - } - } else { - return nil - } + public var plainBubbleColors: [UInt32] { + return self.bubbleColors } public func withUpdatedWallpaper(_ wallpaper: TelegramWallpaper?) -> PresentationThemeAccentColor { diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index d6ae34201c..678db0363b 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -94,19 +94,24 @@ public final class WallpaperBackgroundNode: ASDisplayNode { case .incoming: self.contentNode.image = graphics.incomingBubbleGradientImage if graphics.incomingBubbleGradientImage == nil { - self.contentNode.backgroundColor = bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill + self.contentNode.backgroundColor = bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill[0] } else { self.contentNode.backgroundColor = nil } - needsCleanBackground = bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill.alpha <= 0.99 || bubbleTheme.chat.message.incoming.bubble.withWallpaper.gradientFill.alpha <= 0.99 + needsCleanBackground = bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill.contains(where: { $0.alpha <= 0.99 }) case .outgoing: - self.contentNode.image = graphics.outgoingBubbleGradientImage - if graphics.outgoingBubbleGradientImage == nil { - self.contentNode.backgroundColor = bubbleTheme.chat.message.outgoing.bubble.withWallpaper.fill - } else { + if backgroundNode.outgoingBubbleGradientBackgroundNode != nil { + self.contentNode.image = nil self.contentNode.backgroundColor = nil + } else { + self.contentNode.image = graphics.outgoingBubbleGradientImage + if graphics.outgoingBubbleGradientImage == nil { + self.contentNode.backgroundColor = bubbleTheme.chat.message.outgoing.bubble.withWallpaper.fill[0] + } else { + self.contentNode.backgroundColor = nil + } + needsCleanBackground = bubbleTheme.chat.message.outgoing.bubble.withWallpaper.fill.contains(where: { $0.alpha <= 0.99 }) } - needsCleanBackground = bubbleTheme.chat.message.outgoing.bubble.withWallpaper.fill.alpha <= 0.99 || bubbleTheme.chat.message.outgoing.bubble.withWallpaper.gradientFill.alpha <= 0.99 case .free: self.contentNode.image = nil self.contentNode.backgroundColor = nil @@ -147,6 +152,16 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } + var gradientBackgroundSource: GradientBackgroundNode? = backgroundNode.gradientBackgroundNode + + if case .outgoing = self.bubbleType { + if let outgoingBubbleGradientBackgroundNode = backgroundNode.outgoingBubbleGradientBackgroundNode { + gradientBackgroundSource = outgoingBubbleGradientBackgroundNode + needsWallpaperBackground = false + needsGradientBackground = true + } + } + if needsWallpaperBackground { if self.cleanWallpaperNode == nil { let cleanWallpaperNode = ASImageNode() @@ -168,7 +183,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { } } - if needsGradientBackground, let gradientBackgroundNode = backgroundNode.gradientBackgroundNode { + if needsGradientBackground, let gradientBackgroundNode = gradientBackgroundSource { if self.gradientWallpaperNode == nil { let gradientWallpaperNode = GradientBackgroundNode.CloneNode(parentNode: gradientBackgroundNode) gradientWallpaperNode.frame = self.bounds @@ -277,6 +292,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { private var blurredBackgroundContents: UIImage? private var gradientBackgroundNode: GradientBackgroundNode? + private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode? private let patternImageNode: ASImageNode private var isGeneratingPatternImage: Bool = false @@ -735,6 +751,11 @@ public final class WallpaperBackgroundNode: ASDisplayNode { gradientBackgroundNode.updateLayout(size: size, transition: transition) } + if let outgoingBubbleGradientBackgroundNode = self.outgoingBubbleGradientBackgroundNode { + transition.updateFrame(node: outgoingBubbleGradientBackgroundNode, frame: CGRect(origin: CGPoint(), size: size)) + outgoingBubbleGradientBackgroundNode.updateLayout(size: size, transition: transition) + } + self.loadPatternForSizeIfNeeded(size: size, transition: transition) if isFirstLayout && !self.frame.isEmpty { @@ -744,6 +765,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode { public func animateEvent(transition: ContainedViewLayoutTransition, extendAnimation: Bool = false) { self.gradientBackgroundNode?.animateEvent(transition: transition, extendAnimation: extendAnimation) + self.outgoingBubbleGradientBackgroundNode?.animateEvent(transition: transition, extendAnimation: extendAnimation) } public func updateBubbleTheme(bubbleTheme: PresentationTheme, bubbleCorners: PresentationChatBubbleCorners) { @@ -751,6 +773,20 @@ 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 self.outgoingBubbleGradientBackgroundNode == nil { + let outgoingBubbleGradientBackgroundNode = GradientBackgroundNode() + if let size = self.validLayout { + outgoingBubbleGradientBackgroundNode.frame = CGRect(origin: CGPoint(), size: size) + outgoingBubbleGradientBackgroundNode.updateLayout(size: size, transition: .immediate) + } + self.outgoingBubbleGradientBackgroundNode = outgoingBubbleGradientBackgroundNode + } + self.outgoingBubbleGradientBackgroundNode?.updateColors(colors: bubbleTheme.chat.message.outgoing.bubble.withoutWallpaper.fill) + } else if let _ = self.outgoingBubbleGradientBackgroundNode { + self.outgoingBubbleGradientBackgroundNode = nil + } + self.updateBubbles() } } @@ -789,14 +825,14 @@ public final class WallpaperBackgroundNode: ASDisplayNode { if graphics.incomingBubbleGradientImage != nil { return true } - if bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill.alpha <= 0.99 { + if bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill.contains(where: { $0.alpha <= 0.99 }) { return !hasPlainWallpaper } case .outgoing: if graphics.outgoingBubbleGradientImage != nil { return true } - if bubbleTheme.chat.message.outgoing.bubble.withWallpaper.fill.alpha <= 0.99 { + if bubbleTheme.chat.message.outgoing.bubble.withWallpaper.fill.contains(where: { $0.alpha <= 0.99 }) { return !hasPlainWallpaper } case .free: diff --git a/submodules/WallpaperResources/Sources/WallpaperResources.swift b/submodules/WallpaperResources/Sources/WallpaperResources.swift index d27283c899..c7404cd746 100644 --- a/submodules/WallpaperResources/Sources/WallpaperResources.swift +++ b/submodules/WallpaperResources/Sources/WallpaperResources.swift @@ -1001,16 +1001,22 @@ public func drawThemeImage(context c: CGContext, theme: PresentationTheme, wallp c.translateBy(x: -114.0, y: -32.0) let _ = try? drawSvgPath(c, path: "M98.0061174,0 C106.734138,0 113.82927,6.99200411 113.996965,15.6850616 L114,16 C114,24.836556 106.830179,32 98.0061174,32 L21.9938826,32 C18.2292665,32 14.7684355,30.699197 12.0362474,28.5221601 C8.56516444,32.1765452 -1.77635684e-15,31.9985981 -1.77635684e-15,31.9985981 C5.69252399,28.6991366 5.98604874,24.4421608 5.99940747,24.1573436 L6,24.1422468 L6,16 C6,7.163444 13.1698213,0 21.9938826,0 L98.0061174,0 ") - if incoming.fill.rgb != incoming.gradientFill.rgb { + if Set(incoming.fill.map(\.rgb)).count > 1 { c.clip() - - let gradientColors = [incoming.fill.withAlphaComponent(1.0), incoming.gradientFill.withAlphaComponent(1.0)].map { $0.cgColor } as CFArray - var locations: [CGFloat] = [0.0, 1.0] + + var colors: [CGColor] = [] + var locations: [CGFloat] = [] + for i in 0 ..< incoming.fill.count { + let t = CGFloat(i) / CGFloat(incoming.fill.count - 1) + locations.append(t) + colors.append(incoming.fill[i].cgColor) + } + let colorSpace = CGColorSpaceCreateDeviceRGB() - let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)! + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)! c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 32.0), options: CGGradientDrawingOptions()) } else { - c.setFillColor(incoming.fill.cgColor) + c.setFillColor(incoming.fill[0].cgColor) c.setStrokeColor(incoming.stroke.cgColor) c.strokePath() @@ -1027,16 +1033,22 @@ public func drawThemeImage(context c: CGContext, theme: PresentationTheme, wallp c.translateBy(x: 0, y: -32.0) let _ = try? drawSvgPath(c, path: "M98.0061174,0 C106.734138,0 113.82927,6.99200411 113.996965,15.6850616 L114,16 C114,24.836556 106.830179,32 98.0061174,32 L21.9938826,32 C18.2292665,32 14.7684355,30.699197 12.0362474,28.5221601 C8.56516444,32.1765452 -1.77635684e-15,31.9985981 -1.77635684e-15,31.9985981 C5.69252399,28.6991366 5.98604874,24.4421608 5.99940747,24.1573436 L6,24.1422468 L6,16 C6,7.163444 13.1698213,0 21.9938826,0 L98.0061174,0 ") - if outgoing.fill.rgb != outgoing.gradientFill.rgb { + if Set(outgoing.fill.map(\.rgb)).count > 1 { c.clip() - - let gradientColors = [outgoing.fill.withAlphaComponent(1.0), outgoing.gradientFill.withAlphaComponent(1.0)].map { $0.cgColor } as CFArray - var locations: [CGFloat] = [0.0, 1.0] + + var colors: [CGColor] = [] + var locations: [CGFloat] = [] + for i in 0 ..< outgoing.fill.count { + let t = CGFloat(i) / CGFloat(outgoing.fill.count - 1) + locations.append(t) + colors.append(outgoing.fill[i].cgColor) + } + let colorSpace = CGColorSpaceCreateDeviceRGB() - let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)! + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as NSArray, locations: &locations)! c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: 32.0), options: CGGradientDrawingOptions()) } else { - c.setFillColor(outgoing.fill.cgColor) + c.setFillColor(outgoing.fill[0].cgColor) c.setStrokeColor(outgoing.stroke.cgColor) c.strokePath() @@ -1132,7 +1144,7 @@ public func themeImage(account: Account, accountManager: AccountManager, source: } } case let .settings(settings): - theme = .single((makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors.flatMap { (UIColor(argb: $0.top), UIColor(argb: $0.bottom)) }, wallpaper: settings.wallpaper, serviceBackgroundColor: nil, preview: false), nil)) + theme = .single((makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors, wallpaper: settings.wallpaper, serviceBackgroundColor: nil, preview: false), nil)) } enum WallpaperImage { @@ -1280,7 +1292,7 @@ public func themeImage(account: Account, accountManager: AccountManager, source: } public func themeIconImage(account: Account, accountManager: AccountManager, theme: PresentationThemeReference, color: PresentationThemeAccentColor?, wallpaper: TelegramWallpaper? = nil) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { - let colorsSignal: Signal<((UIColor, UIColor?, [UInt32]), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> + let colorsSignal: Signal<((UIColor, UIColor?, [UInt32]), [UIColor], [UIColor], UIImage?, Int32?), NoError> var reference: MediaResourceReference? if case let .local(theme) = theme { @@ -1294,7 +1306,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the themeSignal = .single(makeDefaultPresentationTheme(reference: theme, serviceBackgroundColor: nil)) } else if case let .cloud(theme) = theme, let settings = theme.theme.settings { themeSignal = Signal { subscriber in - let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors.flatMap { (UIColor(argb: $0.top), UIColor(argb: $0.bottom)) }, wallpaper: settings.wallpaper, serviceBackgroundColor: nil, preview: false) + let theme = makePresentationTheme(mediaBox: accountManager.mediaBox, themeReference: .builtin(PresentationBuiltinThemeReference(baseTheme: settings.baseTheme)), accentColor: UIColor(argb: settings.accentColor), backgroundColors: [], bubbleColors: settings.messageColors, wallpaper: settings.wallpaper, serviceBackgroundColor: nil, preview: false) subscriber.putNext(theme) subscriber.putCompletion() @@ -1314,13 +1326,13 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the } colorsSignal = themeSignal - |> mapToSignal { theme -> Signal<((UIColor, UIColor?, [UInt32]), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in + |> mapToSignal { theme -> Signal<((UIColor, UIColor?, [UInt32]), [UIColor], [UIColor], UIImage?, Int32?), NoError> in if let theme = theme { - var wallpaperSignal: Signal<((UIColor, UIColor?, [UInt32]), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> = .complete() + var wallpaperSignal: Signal<((UIColor, UIColor?, [UInt32]), [UIColor], [UIColor], UIImage?, Int32?), NoError> = .complete() var rotation: Int32? var backgroundColor: (UIColor, UIColor?, [UInt32]) - let incomingColor = (theme.chat.message.incoming.bubble.withoutWallpaper.fill, theme.chat.message.incoming.bubble.withoutWallpaper.gradientFill) - let outgoingColor = (theme.chat.message.outgoing.bubble.withoutWallpaper.fill, theme.chat.message.outgoing.bubble.withoutWallpaper.gradientFill) + let incomingColors = theme.chat.message.incoming.bubble.withoutWallpaper.fill + let outgoingColors = theme.chat.message.outgoing.bubble.withoutWallpaper.fill let wallpaper = wallpaper ?? theme.chat.defaultWallpaper switch wallpaper { case .builtin: @@ -1364,7 +1376,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the var convertedRepresentations: [ImageRepresentationWithReference] = [] convertedRepresentations.append(ImageRepresentationWithReference(representation: TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 100, height: 100), resource: file.file.resource, progressiveSizes: [], immediateThumbnailData: nil), reference: .wallpaper(wallpaper: .slug(file.slug), resource: file.file.resource))) return wallpaperDatas(account: account, accountManager: accountManager, fileReference: .standalone(media: file.file), representations: convertedRepresentations, alwaysShowThumbnailFirst: false, thumbnail: false, onlyFullSize: true, autoFetchFullSize: true, synchronousLoad: false) - |> mapToSignal { _, fullSizeData, complete -> Signal<((UIColor, UIColor?, [UInt32]), (UIColor, UIColor), (UIColor, UIColor), UIImage?, Int32?), NoError> in + |> mapToSignal { _, fullSizeData, complete -> Signal<((UIColor, UIColor?, [UInt32]), [UIColor], [UIColor], UIImage?, Int32?), NoError> in guard complete, let fullSizeData = fullSizeData else { return .complete() } @@ -1374,9 +1386,9 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the if wallpaper.wallpaper.isPattern { if !file.settings.colors.isEmpty, let intensity = file.settings.intensity { if intensity < 0 { - return .single(((.black, nil, []), incomingColor, outgoingColor, nil, rotation)) + return .single(((.black, nil, []), incomingColors, outgoingColors, nil, rotation)) } else { - return .single((effectiveBackgroundColor, incomingColor, outgoingColor, nil, rotation)) + return .single((effectiveBackgroundColor, incomingColors, outgoingColors, nil, rotation)) } } else { return .complete() @@ -1385,13 +1397,13 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the return accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedBlurredWallpaperRepresentation(), complete: true, fetch: true) |> mapToSignal { _ in if let image = UIImage(data: fullSizeData) { - return .single((backgroundColor, incomingColor, outgoingColor, image, rotation)) + return .single((backgroundColor, incomingColors, outgoingColors, image, rotation)) } else { return .complete() } } } else if let image = UIImage(data: fullSizeData) { - return .single((backgroundColor, incomingColor, outgoingColor, image, rotation)) + return .single((backgroundColor, incomingColors, outgoingColors, image, rotation)) } else { return .complete() } @@ -1401,7 +1413,7 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the } } } - return .single((backgroundColor, incomingColor, outgoingColor, nil, rotation)) + return .single((backgroundColor, incomingColors, outgoingColors, nil, rotation)) |> then(wallpaperSignal) } else { return .complete() @@ -1456,10 +1468,10 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the } } - let incomingColors = [colors.1.0, colors.1.1] + let incomingColors = colors.1 let incoming = generateGradientTintedImage(image: UIImage(bundleImageName: "Settings/ThemeBubble"), colors: incomingColors) - let outgoingColors = [colors.2.0, colors.2.1] + let outgoingColors = colors.2 let outgoing = generateGradientTintedImage(image: UIImage(bundleImageName: "Settings/ThemeBubble"), colors: outgoingColors) c.translateBy(x: drawingRect.width / 2.0, y: drawingRect.height / 2.0)