Animation updates

This commit is contained in:
Ali 2021-08-10 21:18:55 +02:00
parent e170f2fe5a
commit 904b048a34
46 changed files with 961 additions and 596 deletions

View File

@ -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";

View File

@ -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<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(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<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(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

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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()
}

View File

@ -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
}

View File

@ -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))

View File

@ -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)

View File

@ -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) {

View File

@ -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))
]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -207,6 +207,7 @@ class VoiceChatFullscreenParticipantItemNode: ItemListRevealOptionsItemNode {
didSet {
if self.isCurrentlyInHierarchy != oldValue {
self.highlightNode.isCurrentlyInHierarchy = self.isCurrentlyInHierarchy
self.audioLevelView?.isManuallyInHierarchy = self.isCurrentlyInHierarchy
}
}
}

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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
}
}

View File

@ -348,7 +348,9 @@ public func createTheme(account: Account, title: String, resource: MediaResource
return .generic
}
|> mapToSignal { apiTheme -> Signal<CreateThemeResult, CreateThemeError> 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<CreateThemeResult, CreateThemeError> 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)

View File

@ -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),

View File

@ -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,

View File

@ -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),

View File

@ -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

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -33,6 +33,37 @@ private func encodeColor<Key>(_ values: inout KeyedEncodingContainer<Key>, _ val
}
}
private func decodeColorList<Key>(_ values: KeyedDecodingContainer<Key>, _ 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<Key>(_ values: inout KeyedEncodingContainer<Key>, _ 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)
}

View File

@ -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)

View File

@ -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])
})
}

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Folder.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,3 @@
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 14.8492C0 12.2016 0 10.8779 0.20805 9.77516C1.12392 4.92093 4.92093 1.12392 9.77516 0.208051C10.8779 4.02331e-07 12.2016 0 14.8492 0H16.7574C19.4739 0 22.0791 1.07913 24 3C25.9209 4.92087 28.5261 6 31.2426 6H36.8C43.5206 6 46.8809 6 49.4479 7.30792C51.7058 8.4584 53.5416 10.2942 54.6921 12.5521C56 15.1191 56 18.4794 56 25.2V36.8C56 43.5206 56 46.8809 54.6921 49.4479C53.5416 51.7058 51.7058 53.5416 49.4479 54.6921C46.8809 56 43.5206 56 36.8 56H19.2C12.4794 56 9.11906 56 6.55211 54.6921C4.29417 53.5416 2.4584 51.7058 1.30792 49.4479C0 46.8809 0 43.5206 0 36.8V14.8492Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 744 B

View File

@ -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))
}

View File

@ -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<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(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<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(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)
}))

View File

@ -549,13 +549,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
var isSelectionGestureEnabled = true
private var overscrollView: ComponentHostView<Empty>?
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<Int32>
@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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<Empty>()
private let checkView = ComponentHostView<Empty>()
@ -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)
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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 {

View File

@ -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:

View File

@ -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)