mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Theme updates
This commit is contained in:
parent
648f2e50c2
commit
6428ae2754
@ -156,7 +156,7 @@ public final class GradientBackgroundNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var phase: Int = 0
|
private var phase: Int = 0
|
||||||
|
|
||||||
private let contentView: UIImageView
|
public let contentView: UIImageView
|
||||||
private var validPhase: Int?
|
private var validPhase: Int?
|
||||||
private var invalidated: Bool = false
|
private var invalidated: Bool = false
|
||||||
|
|
||||||
|
@ -20,8 +20,6 @@ public func guessMimeTypeByFileExtension(_ ext: String) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, context: AccountContext, peer: Peer, chatLocation: ChatLocation, captionsEnabled: Bool = true, storeCreatedAssets: Bool = true, showFileTooltip: Bool = false, initialCaption: String, hasSchedule: Bool, presentWebSearch: (() -> Void)?, presentSelectionLimitExceeded: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?) {
|
public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, context: AccountContext, peer: Peer, chatLocation: ChatLocation, captionsEnabled: Bool = true, storeCreatedAssets: Bool = true, showFileTooltip: Bool = false, initialCaption: String, hasSchedule: Bool, presentWebSearch: (() -> Void)?, presentSelectionLimitExceeded: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, presentStickers: @escaping (@escaping (TelegramMediaFile, Bool, UIView, CGRect) -> Void) -> TGPhotoPaintStickersScreen?) {
|
||||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
|
||||||
|
|
||||||
let paintStickersContext = LegacyPaintStickersContext(context: context)
|
let paintStickersContext = LegacyPaintStickersContext(context: context)
|
||||||
paintStickersContext.presentStickersController = { completion in
|
paintStickersContext.presentStickersController = { completion in
|
||||||
return presentStickers({ file, animated, view, rect in
|
return presentStickers({ file, animated, view, rect in
|
||||||
|
@ -75,10 +75,12 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
self.imageNode.frame = CGRect(origin: CGPoint(), size: size)
|
self.imageNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
|
|
||||||
var colors: [UInt32] = []
|
var colors: [UInt32] = []
|
||||||
|
var intensity: CGFloat = 0.5
|
||||||
if case let .gradient(value, _) = wallpaper {
|
if case let .gradient(value, _) = wallpaper {
|
||||||
colors = value
|
colors = value
|
||||||
} else if case let .file(file) = wallpaper {
|
} else if case let .file(file) = wallpaper {
|
||||||
colors = file.settings.colors
|
colors = file.settings.colors
|
||||||
|
intensity = CGFloat(file.settings.intensity ?? 50) / 100.0
|
||||||
} else if case let .color(color) = wallpaper {
|
} else if case let .color(color) = wallpaper {
|
||||||
colors = [color]
|
colors = [color]
|
||||||
}
|
}
|
||||||
@ -93,7 +95,11 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
self.insertSubnode(gradientNode, belowSubnode: self.imageNode)
|
self.insertSubnode(gradientNode, belowSubnode: self.imageNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if intensity < 0.0 {
|
||||||
|
self.imageNode.layer.compositingFilter = nil
|
||||||
|
} else {
|
||||||
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
||||||
|
}
|
||||||
self.backgroundNode.image = nil
|
self.backgroundNode.image = nil
|
||||||
} else {
|
} else {
|
||||||
if let gradientNode = self.gradientNode {
|
if let gradientNode = self.gradientNode {
|
||||||
@ -101,13 +107,17 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
gradientNode.removeFromSupernode()
|
gradientNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
|
||||||
if colors.count >= 2 {
|
if intensity < 0.0 {
|
||||||
|
self.imageNode.layer.compositingFilter = nil
|
||||||
|
} else {
|
||||||
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
||||||
|
}
|
||||||
|
|
||||||
|
if colors.count >= 2 {
|
||||||
self.backgroundNode.image = generateGradientImage(size: CGSize(width: 80.0, height: 80.0), colors: colors.map(UIColor.init(rgb:)), locations: [0.0, 1.0], direction: .vertical)
|
self.backgroundNode.image = generateGradientImage(size: CGSize(width: 80.0, height: 80.0), colors: colors.map(UIColor.init(rgb:)), locations: [0.0, 1.0], direction: .vertical)
|
||||||
self.backgroundNode.backgroundColor = nil
|
self.backgroundNode.backgroundColor = nil
|
||||||
} else if colors.count >= 1 {
|
} else if colors.count >= 1 {
|
||||||
self.backgroundNode.image = nil
|
self.backgroundNode.image = nil
|
||||||
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
|
||||||
self.backgroundNode.backgroundColor = UIColor(rgb: colors[0])
|
self.backgroundNode.backgroundColor = UIColor(rgb: colors[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -147,24 +157,20 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
|||||||
|
|
||||||
let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
||||||
if wallpaper.isPattern {
|
if wallpaper.isPattern {
|
||||||
var patternColors: [UIColor] = []
|
|
||||||
var patternColor = UIColor(rgb: 0xd6e2ee, alpha: 0.5)
|
|
||||||
var patternIntensity: CGFloat = 0.5
|
var patternIntensity: CGFloat = 0.5
|
||||||
if !file.settings.colors.isEmpty {
|
if !file.settings.colors.isEmpty {
|
||||||
if let intensity = file.settings.intensity {
|
if let intensity = file.settings.intensity {
|
||||||
patternIntensity = CGFloat(intensity) / 100.0
|
patternIntensity = CGFloat(intensity) / 100.0
|
||||||
}
|
}
|
||||||
patternColor = UIColor(rgb: file.settings.colors[0], alpha: patternIntensity)
|
|
||||||
patternColors.append(patternColor)
|
|
||||||
|
|
||||||
if file.settings.colors.count >= 2 {
|
|
||||||
patternColors.append(UIColor(rgb: file.settings.colors[1], alpha: patternIntensity))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if patternIntensity < 0.0 {
|
||||||
|
self.imageNode.alpha = 1.0
|
||||||
|
self.arguments = PatternWallpaperArguments(colors: [.black], rotation: nil, customPatternColor: UIColor(white: 0.0, alpha: 1.0 + patternIntensity))
|
||||||
|
} else {
|
||||||
self.imageNode.alpha = CGFloat(file.settings.intensity ?? 50) / 100.0
|
self.imageNode.alpha = CGFloat(file.settings.intensity ?? 50) / 100.0
|
||||||
|
|
||||||
self.arguments = PatternWallpaperArguments(colors: [.clear], rotation: nil, customPatternColor: UIColor(white: 0.0, alpha: 1.0))
|
self.arguments = PatternWallpaperArguments(colors: [.clear], rotation: nil, customPatternColor: UIColor(white: 0.0, alpha: 1.0))
|
||||||
|
}
|
||||||
imageSignal = patternWallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, representations: convertedRepresentations, mode: .thumbnail, autoFetchFullSize: true)
|
imageSignal = patternWallpaperImage(account: context.account, accountManager: context.sharedContext.accountManager, representations: convertedRepresentations, mode: .thumbnail, autoFetchFullSize: true)
|
||||||
} else {
|
} else {
|
||||||
self.imageNode.alpha = 1.0
|
self.imageNode.alpha = 1.0
|
||||||
|
@ -246,7 +246,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
self.messagesContainerNode = ASDisplayNode()
|
self.messagesContainerNode = ASDisplayNode()
|
||||||
self.messagesContainerNode.clipsToBounds = true
|
self.messagesContainerNode.clipsToBounds = true
|
||||||
self.messagesContainerNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
|
self.messagesContainerNode.transform = CATransform3DMakeScale(-1.0, -1.0, 1.0)
|
||||||
|
|
||||||
self.colorPanelNode = WallpaperColorPanelNode(theme: self.theme, strings: self.presentationData.strings)
|
self.colorPanelNode = WallpaperColorPanelNode(theme: self.theme, strings: self.presentationData.strings)
|
||||||
self.patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: self.theme, strings: self.presentationData.strings)
|
self.patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: self.theme, strings: self.presentationData.strings)
|
||||||
@ -400,12 +400,15 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.backgroundNode.update(wallpaper: self.wallpaper)
|
||||||
|
self.backgroundNode.updateBubbleTheme(bubbleTheme: self.theme, bubbleCorners: self.presentationData.chatBubbleCorners)
|
||||||
|
|
||||||
self.stateDisposable = (self.statePromise.get()
|
self.stateDisposable = (self.statePromise.get()
|
||||||
|> deliverOn(self.queue)
|
|> deliverOn(self.queue)
|
||||||
|> mapToThrottled { next -> Signal<ThemeColorState, NoError> in
|
|> mapToThrottled { next -> Signal<ThemeColorState, NoError> in
|
||||||
return .single(next) |> then(.complete() |> delay(0.0166667, queue: self.queue))
|
return .single(next) |> then(.complete() |> delay(0.0166667, queue: self.queue))
|
||||||
}
|
}
|
||||||
|> map { [weak self] state -> (PresentationTheme?, TelegramWallpaper, UIColor, [UInt32], PatternWallpaperArguments, Bool) in
|
|> map { state -> (PresentationTheme?, TelegramWallpaper, UIColor, [UInt32], PatternWallpaperArguments, Bool) in
|
||||||
let accentColor = state.accentColor
|
let accentColor = state.accentColor
|
||||||
var backgroundColors = state.backgroundColors
|
var backgroundColors = state.backgroundColors
|
||||||
let messagesColors = state.messagesColors
|
let messagesColors = state.messagesColors
|
||||||
@ -494,6 +497,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
strongSelf.serviceBackgroundColorPromise.set(.single(serviceBackgroundColor))
|
strongSelf.serviceBackgroundColorPromise.set(.single(serviceBackgroundColor))
|
||||||
|
|
||||||
strongSelf.backgroundNode.update(wallpaper: wallpaper)
|
strongSelf.backgroundNode.update(wallpaper: wallpaper)
|
||||||
|
strongSelf.backgroundNode.updateBubbleTheme(bubbleTheme: strongSelf.theme, bubbleCorners: strongSelf.presentationData.chatBubbleCorners)
|
||||||
|
|
||||||
strongSelf.ready.set(.single(true))
|
strongSelf.ready.set(.single(true))
|
||||||
|
|
||||||
@ -871,7 +875,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
itemNode = node
|
itemNode = node
|
||||||
apply().1(ListViewItemApply(isOnScreen: true))
|
apply().1(ListViewItemApply(isOnScreen: true))
|
||||||
})
|
})
|
||||||
itemNode!.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
//itemNode!.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||||
messageNodes.append(itemNode!)
|
messageNodes.append(itemNode!)
|
||||||
self.messagesContainerNode.addSubnode(itemNode!)
|
self.messagesContainerNode.addSubnode(itemNode!)
|
||||||
}
|
}
|
||||||
@ -881,9 +885,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
var bottomOffset: CGFloat = 9.0 + bottomInset
|
var bottomOffset: CGFloat = 9.0 + bottomInset
|
||||||
if let messageNodes = self.messageNodes {
|
if let messageNodes = self.messageNodes {
|
||||||
for itemNode in messageNodes {
|
for itemNode in messageNodes {
|
||||||
|
let previousFrame = itemNode.frame
|
||||||
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size))
|
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size))
|
||||||
bottomOffset += itemNode.frame.height
|
bottomOffset += itemNode.frame.height
|
||||||
itemNode.updateFrame(itemNode.frame, within: layout.size)
|
itemNode.updateFrame(itemNode.frame, within: layout.size)
|
||||||
|
if case let .animated(duration, curve) = transition {
|
||||||
|
itemNode.applyAbsoluteOffset(value: CGPoint(x: 0.0, y: -itemNode.frame.minY + previousFrame.minY), animationCurve: curve, duration: duration)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -893,7 +901,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
headerItem.updateNode(dateHeaderNode, previous: nil, next: headerItem)
|
||||||
} else {
|
} else {
|
||||||
dateHeaderNode = headerItem.node()
|
dateHeaderNode = headerItem.node()
|
||||||
dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
//dateHeaderNode.subnodeTransform = CATransform3DMakeScale(-1.0, 1.0, 1.0)
|
||||||
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
self.messagesContainerNode.addSubnode(dateHeaderNode)
|
||||||
self.dateHeaderNode = dateHeaderNode
|
self.dateHeaderNode = dateHeaderNode
|
||||||
}
|
}
|
||||||
@ -954,7 +962,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
self.chatListBackgroundNode.frame = CGRect(x: bounds.width, y: 0.0, width: bounds.width, height: bounds.height)
|
self.chatListBackgroundNode.frame = CGRect(x: bounds.width, y: 0.0, width: bounds.width, height: bounds.height)
|
||||||
|
|
||||||
transition.updateFrame(node: self.messagesContainerNode, frame: CGRect(x: 0.0, y: navigationBarHeight, width: bounds.width, height: bounds.height - bottomInset - navigationBarHeight))
|
transition.updateBounds(node: self.messagesContainerNode, bounds: CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height))
|
||||||
|
transition.updatePosition(node: self.messagesContainerNode, position: CGRect(x: 0.0, y: 0.0, width: bounds.width, height: bounds.height).center)
|
||||||
|
|
||||||
let backgroundSize = CGSize(width: bounds.width, height: bounds.height - (colorPanelHeight - colorPanelOffset))
|
let backgroundSize = CGSize(width: bounds.width, height: bounds.height - (colorPanelHeight - colorPanelOffset))
|
||||||
transition.updateFrame(node: self.backgroundContainerNode, frame: CGRect(origin: CGPoint(), size: backgroundSize))
|
transition.updateFrame(node: self.backgroundContainerNode, frame: CGRect(origin: CGPoint(), size: backgroundSize))
|
||||||
@ -967,12 +976,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
transition.updateBounds(node: self.backgroundWrapperNode, bounds: CGRect(origin: CGPoint(), size: layout.size))
|
transition.updateBounds(node: self.backgroundWrapperNode, bounds: CGRect(origin: CGPoint(), size: layout.size))
|
||||||
|
|
||||||
let displayOptionButtons = self.state.section == .background
|
let displayOptionButtons = self.state.section == .background
|
||||||
var messagesBottomInset: CGFloat = 0.0
|
var messagesBottomInset: CGFloat = bottomInset
|
||||||
|
|
||||||
if displayOptionButtons {
|
if displayOptionButtons {
|
||||||
messagesBottomInset = 46.0
|
messagesBottomInset += 46.0
|
||||||
} else if chatListPreviewAvailable {
|
} else if chatListPreviewAvailable {
|
||||||
messagesBottomInset = 37.0
|
messagesBottomInset += 37.0
|
||||||
}
|
}
|
||||||
self.updateChatsLayout(layout: layout, topInset: navigationBarHeight, transition: transition)
|
self.updateChatsLayout(layout: layout, topInset: navigationBarHeight, transition: transition)
|
||||||
self.updateMessagesLayout(layout: layout, bottomInset: messagesBottomInset, transition: messagesTransition)
|
self.updateMessagesLayout(layout: layout, bottomInset: messagesBottomInset, transition: messagesTransition)
|
||||||
|
@ -375,7 +375,9 @@ final class ThemeGridController: ViewController {
|
|||||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.donePressed))
|
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.donePressed))
|
||||||
self.searchContentNode?.setIsEnabled(false, animated: true)
|
self.searchContentNode?.setIsEnabled(false, animated: true)
|
||||||
self.controllerNode.updateState { state in
|
self.controllerNode.updateState { state in
|
||||||
return state.withUpdatedEditing(true)
|
var state = state
|
||||||
|
state.editing = true
|
||||||
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +386,9 @@ final class ThemeGridController: ViewController {
|
|||||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed))
|
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed))
|
||||||
self.searchContentNode?.setIsEnabled(true, animated: true)
|
self.searchContentNode?.setIsEnabled(true, animated: true)
|
||||||
self.controllerNode.updateState { state in
|
self.controllerNode.updateState { state in
|
||||||
return state.withUpdatedEditing(false)
|
var state = state
|
||||||
|
state.editing = false
|
||||||
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import GridMessageSelectionNode
|
|||||||
final class ThemeGridControllerItem: GridItem {
|
final class ThemeGridControllerItem: GridItem {
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let wallpaper: TelegramWallpaper
|
let wallpaper: TelegramWallpaper
|
||||||
|
let wallpaperId: ThemeGridControllerEntry.StableId
|
||||||
let index: Int
|
let index: Int
|
||||||
let editable: Bool
|
let editable: Bool
|
||||||
let selected: Bool
|
let selected: Bool
|
||||||
@ -19,9 +20,10 @@ final class ThemeGridControllerItem: GridItem {
|
|||||||
|
|
||||||
let section: GridSection? = nil
|
let section: GridSection? = nil
|
||||||
|
|
||||||
init(context: AccountContext, wallpaper: TelegramWallpaper, index: Int, editable: Bool, selected: Bool, interaction: ThemeGridControllerInteraction) {
|
init(context: AccountContext, wallpaper: TelegramWallpaper, wallpaperId: ThemeGridControllerEntry.StableId, index: Int, editable: Bool, selected: Bool, interaction: ThemeGridControllerInteraction) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.wallpaper = wallpaper
|
self.wallpaper = wallpaper
|
||||||
|
self.wallpaperId = wallpaperId
|
||||||
self.index = index
|
self.index = index
|
||||||
self.editable = editable
|
self.editable = editable
|
||||||
self.selected = selected
|
self.selected = selected
|
||||||
@ -30,7 +32,7 @@ final class ThemeGridControllerItem: GridItem {
|
|||||||
|
|
||||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
||||||
let node = ThemeGridControllerItemNode()
|
let node = ThemeGridControllerItemNode()
|
||||||
node.setup(context: self.context, wallpaper: self.wallpaper, editable: self.editable, selected: self.selected, interaction: self.interaction, synchronousLoad: synchronousLoad)
|
node.setup(item: self, synchronousLoad: synchronousLoad)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,7 @@ final class ThemeGridControllerItem: GridItem {
|
|||||||
assertionFailure()
|
assertionFailure()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
node.setup(context: self.context, wallpaper: self.wallpaper, editable: self.editable, selected: self.selected, interaction: self.interaction, synchronousLoad: false)
|
node.setup(item: self, synchronousLoad: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,11 +49,11 @@ final class ThemeGridControllerItemNode: GridItemNode {
|
|||||||
private let wallpaperNode: SettingsThemeWallpaperNode
|
private let wallpaperNode: SettingsThemeWallpaperNode
|
||||||
private var selectionNode: GridMessageSelectionNode?
|
private var selectionNode: GridMessageSelectionNode?
|
||||||
|
|
||||||
private var currentState: (AccountContext, TelegramWallpaper, Bool, Bool, Bool)?
|
private var item: ThemeGridControllerItem?
|
||||||
private var interaction: ThemeGridControllerInteraction?
|
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
self.wallpaperNode = SettingsThemeWallpaperNode()
|
self.wallpaperNode = SettingsThemeWallpaperNode()
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.wallpaperNode)
|
self.addSubnode(self.wallpaperNode)
|
||||||
@ -64,50 +66,35 @@ final class ThemeGridControllerItemNode: GridItemNode {
|
|||||||
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(context: AccountContext, wallpaper: TelegramWallpaper, editable: Bool, selected: Bool, interaction: ThemeGridControllerInteraction, synchronousLoad: Bool) {
|
func setup(item: ThemeGridControllerItem, synchronousLoad: Bool) {
|
||||||
self.interaction = interaction
|
self.item = item
|
||||||
|
|
||||||
if self.currentState == nil || self.currentState!.0 !== context || wallpaper != self.currentState!.1 || selected != self.currentState!.2 || synchronousLoad != self.currentState!.3 || editable != self.currentState!.4 {
|
|
||||||
self.currentState = (context, wallpaper, selected, synchronousLoad, editable)
|
|
||||||
self.updateSelectionState(animated: false)
|
self.updateSelectionState(animated: false)
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||||
if case .ended = recognizer.state {
|
if case .ended = recognizer.state {
|
||||||
if let (_, wallpaper, _, _, _) = self.currentState {
|
if let item = self.item {
|
||||||
self.interaction?.openWallpaper(wallpaper)
|
item.interaction.openWallpaper(item.wallpaper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSelectionState(animated: Bool) {
|
func updateSelectionState(animated: Bool) {
|
||||||
if let (context, wallpaper, _, _, editable) = self.currentState {
|
if let item = self.item {
|
||||||
var editing = false
|
let (editing, selectedIds) = item.interaction.selectionState
|
||||||
var id: Int64?
|
|
||||||
if case let .file(file) = wallpaper {
|
if editing && item.editable {
|
||||||
id = file.id
|
let selected = selectedIds.contains(item.wallpaperId)
|
||||||
} else if case .image = wallpaper {
|
|
||||||
id = 0
|
|
||||||
}
|
|
||||||
var selectedIndices = Set<Int64>()
|
|
||||||
if let interaction = self.interaction {
|
|
||||||
let (active, indices) = interaction.selectionState
|
|
||||||
editing = active
|
|
||||||
selectedIndices = indices
|
|
||||||
}
|
|
||||||
if let id = id, editing && editable {
|
|
||||||
let selected = selectedIndices.contains(id)
|
|
||||||
|
|
||||||
if let selectionNode = self.selectionNode {
|
if let selectionNode = self.selectionNode {
|
||||||
selectionNode.updateSelected(selected, animated: animated)
|
selectionNode.updateSelected(selected, animated: animated)
|
||||||
selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
|
selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
|
||||||
} else {
|
} else {
|
||||||
let theme = context.sharedContext.currentPresentationData.with { $0 }.theme
|
let theme = item.context.sharedContext.currentPresentationData.with { $0 }.theme
|
||||||
let selectionNode = GridMessageSelectionNode(theme: theme, toggle: { [weak self] value in
|
let selectionNode = GridMessageSelectionNode(theme: theme, toggle: { [weak self] value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.interaction?.toggleWallpaperSelection(id, value)
|
strongSelf.item?.interaction.toggleWallpaperSelection(item.wallpaperId, value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -139,8 +126,8 @@ final class ThemeGridControllerItemNode: GridItemNode {
|
|||||||
super.layout()
|
super.layout()
|
||||||
|
|
||||||
let bounds = self.bounds
|
let bounds = self.bounds
|
||||||
if let (context, wallpaper, selected, synchronousLoad, _) = self.currentState {
|
if let item = self.item {
|
||||||
self.wallpaperNode.setWallpaper(context: context, wallpaper: wallpaper, selected: selected, size: bounds.size, synchronousLoad: synchronousLoad)
|
self.wallpaperNode.setWallpaper(context: item.context, wallpaper: item.wallpaper, selected: item.selected, size: bounds.size, synchronousLoad: false)
|
||||||
self.selectionNode?.frame = CGRect(origin: CGPoint(), size: bounds.size)
|
self.selectionNode?.frame = CGRect(origin: CGPoint(), size: bounds.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,36 +18,18 @@ import SearchUI
|
|||||||
import WallpaperResources
|
import WallpaperResources
|
||||||
|
|
||||||
struct ThemeGridControllerNodeState: Equatable {
|
struct ThemeGridControllerNodeState: Equatable {
|
||||||
let editing: Bool
|
var editing: Bool
|
||||||
var selectedIndices: Set<Int64>
|
var selectedIds: Set<ThemeGridControllerEntry.StableId>
|
||||||
|
|
||||||
func withUpdatedEditing(_ editing: Bool) -> ThemeGridControllerNodeState {
|
|
||||||
return ThemeGridControllerNodeState(editing: editing, selectedIndices: editing ? self.selectedIndices : Set())
|
|
||||||
}
|
|
||||||
|
|
||||||
func withUpdatedSelectedIndices(_ selectedIndices: Set<Int64>) -> ThemeGridControllerNodeState {
|
|
||||||
return ThemeGridControllerNodeState(editing: self.editing, selectedIndices: selectedIndices)
|
|
||||||
}
|
|
||||||
|
|
||||||
static func ==(lhs: ThemeGridControllerNodeState, rhs: ThemeGridControllerNodeState) -> Bool {
|
|
||||||
if lhs.editing != rhs.editing {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lhs.selectedIndices != rhs.selectedIndices {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ThemeGridControllerInteraction {
|
final class ThemeGridControllerInteraction {
|
||||||
let openWallpaper: (TelegramWallpaper) -> Void
|
let openWallpaper: (TelegramWallpaper) -> Void
|
||||||
let toggleWallpaperSelection: (Int64, Bool) -> Void
|
let toggleWallpaperSelection: (ThemeGridControllerEntry.StableId, Bool) -> Void
|
||||||
let deleteSelectedWallpapers: () -> Void
|
let deleteSelectedWallpapers: () -> Void
|
||||||
let shareSelectedWallpapers: () -> Void
|
let shareSelectedWallpapers: () -> Void
|
||||||
var selectionState: (Bool, Set<Int64>) = (false, Set())
|
var selectionState: (Bool, Set<ThemeGridControllerEntry.StableId>) = (false, Set())
|
||||||
|
|
||||||
init(openWallpaper: @escaping (TelegramWallpaper) -> Void, toggleWallpaperSelection: @escaping (Int64, Bool) -> Void, deleteSelectedWallpapers: @escaping () -> Void, shareSelectedWallpapers: @escaping () -> Void) {
|
init(openWallpaper: @escaping (TelegramWallpaper) -> Void, toggleWallpaperSelection: @escaping (ThemeGridControllerEntry.StableId, Bool) -> Void, deleteSelectedWallpapers: @escaping () -> Void, shareSelectedWallpapers: @escaping () -> Void) {
|
||||||
self.openWallpaper = openWallpaper
|
self.openWallpaper = openWallpaper
|
||||||
self.toggleWallpaperSelection = toggleWallpaperSelection
|
self.toggleWallpaperSelection = toggleWallpaperSelection
|
||||||
self.deleteSelectedWallpapers = deleteSelectedWallpapers
|
self.deleteSelectedWallpapers = deleteSelectedWallpapers
|
||||||
@ -55,7 +37,7 @@ final class ThemeGridControllerInteraction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct ThemeGridControllerEntry: Comparable, Identifiable {
|
struct ThemeGridControllerEntry: Comparable, Identifiable {
|
||||||
enum StableId: Hashable {
|
enum StableId: Hashable {
|
||||||
case builtin
|
case builtin
|
||||||
case color(UInt32)
|
case color(UInt32)
|
||||||
@ -64,14 +46,10 @@ private struct ThemeGridControllerEntry: Comparable, Identifiable {
|
|||||||
case image(String)
|
case image(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
let index: Int
|
var index: Int
|
||||||
let wallpaper: TelegramWallpaper
|
var wallpaper: TelegramWallpaper
|
||||||
let isEditable: Bool
|
var isEditable: Bool
|
||||||
let isSelected: Bool
|
var isSelected: Bool
|
||||||
|
|
||||||
static func ==(lhs: ThemeGridControllerEntry, rhs: ThemeGridControllerEntry) -> Bool {
|
|
||||||
return lhs.index == rhs.index && lhs.wallpaper == rhs.wallpaper && lhs.isEditable == rhs.isEditable && lhs.isSelected == rhs.isSelected
|
|
||||||
}
|
|
||||||
|
|
||||||
static func <(lhs: ThemeGridControllerEntry, rhs: ThemeGridControllerEntry) -> Bool {
|
static func <(lhs: ThemeGridControllerEntry, rhs: ThemeGridControllerEntry) -> Bool {
|
||||||
return lhs.index < rhs.index
|
return lhs.index < rhs.index
|
||||||
@ -97,7 +75,7 @@ private struct ThemeGridControllerEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func item(context: AccountContext, interaction: ThemeGridControllerInteraction) -> ThemeGridControllerItem {
|
func item(context: AccountContext, interaction: ThemeGridControllerInteraction) -> ThemeGridControllerItem {
|
||||||
return ThemeGridControllerItem(context: context, wallpaper: self.wallpaper, index: self.index, editable: self.isEditable, selected: self.isSelected, interaction: interaction)
|
return ThemeGridControllerItem(context: context, wallpaper: self.wallpaper, wallpaperId: self.stableId, index: self.index, editable: self.isEditable, selected: self.isSelected, interaction: interaction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,20 +127,19 @@ private func selectedWallpapers(entries: [ThemeGridControllerEntry]?, state: The
|
|||||||
}
|
}
|
||||||
var wallpapers: [TelegramWallpaper] = []
|
var wallpapers: [TelegramWallpaper] = []
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
if case let .file(file) = entry.wallpaper {
|
if state.selectedIds.contains(entry.stableId) {
|
||||||
if state.selectedIndices.contains(file.id) {
|
|
||||||
wallpapers.append(entry.wallpaper)
|
wallpapers.append(entry.wallpaper)
|
||||||
}
|
}
|
||||||
} else if case .image = entry.wallpaper {
|
|
||||||
if state.selectedIndices.contains(0) {
|
|
||||||
wallpapers.append(entry.wallpaper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return wallpapers
|
return wallpapers
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ThemeGridControllerNode: ASDisplayNode {
|
final class ThemeGridControllerNode: ASDisplayNode {
|
||||||
|
private struct Wallpaper: Equatable {
|
||||||
|
var wallpaper: TelegramWallpaper
|
||||||
|
var isLocal: Bool
|
||||||
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private var controllerInteraction: ThemeGridControllerInteraction?
|
private var controllerInteraction: ThemeGridControllerInteraction?
|
||||||
@ -176,7 +153,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
var requestDeactivateSearch: (() -> Void)?
|
var requestDeactivateSearch: (() -> Void)?
|
||||||
|
|
||||||
let ready = ValuePromise<Bool>()
|
let ready = ValuePromise<Bool>()
|
||||||
let wallpapersPromise: Promise<[TelegramWallpaper]>
|
private let wallpapersPromise: Promise<[Wallpaper]>
|
||||||
|
|
||||||
private var backgroundNode: ASDisplayNode
|
private var backgroundNode: ASDisplayNode
|
||||||
private var separatorNode: ASDisplayNode
|
private var separatorNode: ASDisplayNode
|
||||||
@ -196,7 +173,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var selectionPanel: ThemeGridSelectionPanelNode?
|
private var selectionPanel: ThemeGridSelectionPanelNode?
|
||||||
private var selectionPanelSeparatorNode: ASDisplayNode?
|
private var selectionPanelSeparatorNode: ASDisplayNode?
|
||||||
private var selectionPanelBackgroundNode: ASDisplayNode?
|
private var selectionPanelBackgroundNode: NavigationBackgroundNode?
|
||||||
|
|
||||||
let gridNode: GridNode
|
let gridNode: GridNode
|
||||||
private let leftOverlayNode: ASDisplayNode
|
private let leftOverlayNode: ASDisplayNode
|
||||||
@ -261,22 +238,12 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
self.resetDescriptionItemNode = ItemListTextItemNode()
|
self.resetDescriptionItemNode = ItemListTextItemNode()
|
||||||
self.resetDescriptionItem = ItemListTextItem(presentationData: ItemListPresentationData(presentationData), text: .plain(presentationData.strings.Wallpaper_ResetWallpapersInfo), sectionId: 0)
|
self.resetDescriptionItem = ItemListTextItem(presentationData: ItemListPresentationData(presentationData), text: .plain(presentationData.strings.Wallpaper_ResetWallpapersInfo), sectionId: 0)
|
||||||
|
|
||||||
self.currentState = ThemeGridControllerNodeState(editing: false, selectedIndices: Set())
|
self.currentState = ThemeGridControllerNodeState(editing: false, selectedIds: Set())
|
||||||
self.statePromise = ValuePromise(self.currentState, ignoreRepeated: true)
|
self.statePromise = ValuePromise(self.currentState, ignoreRepeated: true)
|
||||||
|
|
||||||
let defaultWallpaper = presentationData.theme.chat.defaultWallpaper
|
let defaultWallpaper = presentationData.theme.chat.defaultWallpaper
|
||||||
|
|
||||||
let wallpapersPromise = Promise<[TelegramWallpaper]>()
|
let wallpapersPromise = Promise<[Wallpaper]>()
|
||||||
wallpapersPromise.set(telegramWallpapers(postbox: context.account.postbox, network: context.account.network)
|
|
||||||
|> map { wallpapers in
|
|
||||||
var wallpapers = wallpapers
|
|
||||||
if !wallpapers.contains(where: {
|
|
||||||
$0.isBasicallyEqual(to: defaultWallpaper)
|
|
||||||
}) {
|
|
||||||
wallpapers.insert(defaultWallpaper, at: 0)
|
|
||||||
}
|
|
||||||
return wallpapers
|
|
||||||
})
|
|
||||||
self.wallpapersPromise = wallpapersPromise
|
self.wallpapersPromise = wallpapersPromise
|
||||||
|
|
||||||
let deletedWallpaperSlugsValue = Atomic<Set<String>>(value: Set())
|
let deletedWallpaperSlugsValue = Atomic<Set<String>>(value: Set())
|
||||||
@ -322,31 +289,47 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}, toggleWallpaperSelection: { [weak self] id, value in
|
}, toggleWallpaperSelection: { [weak self] id, value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.updateState { current in
|
strongSelf.updateState { state in
|
||||||
var updated = current.selectedIndices
|
var state = state
|
||||||
if value {
|
if value {
|
||||||
updated.insert(id)
|
state.selectedIds.insert(id)
|
||||||
} else {
|
} else {
|
||||||
updated.remove(id)
|
state.selectedIds.remove(id)
|
||||||
}
|
}
|
||||||
return current.withUpdatedSelectedIndices(updated)
|
return state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, deleteSelectedWallpapers: { [weak self] in
|
}, deleteSelectedWallpapers: { [weak self] in
|
||||||
let entries = previousEntries.with { $0 }
|
let entries = previousEntries.with { $0 }
|
||||||
if let strongSelf = self, let entries = entries {
|
if let strongSelf = self, let entries = entries {
|
||||||
deleteWallpapers(selectedWallpapers(entries: entries, state: strongSelf.currentState), { [weak self] in
|
let wallpapers = selectedWallpapers(entries: entries, state: strongSelf.currentState)
|
||||||
|
|
||||||
|
deleteWallpapers(wallpapers, { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
var updatedDeletedSlugs = deletedWallpaperSlugsValue.with { $0 }
|
var updatedDeletedSlugs = deletedWallpaperSlugsValue.with { $0 }
|
||||||
|
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
if case let .file(file) = entry.wallpaper, strongSelf.currentState.selectedIndices.contains(file.id) {
|
if case let .file(file) = entry.wallpaper, strongSelf.currentState.selectedIds.contains(entry.stableId) {
|
||||||
updatedDeletedSlugs.insert(file.slug)
|
updatedDeletedSlugs.insert(file.slug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = deletedWallpaperSlugsValue.swap(updatedDeletedSlugs)
|
let _ = deletedWallpaperSlugsValue.swap(updatedDeletedSlugs)
|
||||||
deletedWallpaperSlugsPromise.set(updatedDeletedSlugs)
|
deletedWallpaperSlugsPromise.set(updatedDeletedSlugs)
|
||||||
|
|
||||||
|
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction in
|
||||||
|
WallpapersState.update(transaction: transaction, { state in
|
||||||
|
var state = state
|
||||||
|
for wallpaper in wallpapers {
|
||||||
|
if let index = state.wallpapers.firstIndex(where: {
|
||||||
|
$0.isBasicallyEqual(to: wallpaper)
|
||||||
|
}) {
|
||||||
|
state.wallpapers.remove(at: index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}).start()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -358,7 +341,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
self.controllerInteraction = interaction
|
self.controllerInteraction = interaction
|
||||||
|
|
||||||
let transition = combineLatest(wallpapersPromise.get(), deletedWallpaperSlugsPromise.get(), context.sharedContext.presentationData)
|
let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperSlugsPromise.get(), context.sharedContext.presentationData)
|
||||||
|> map { wallpapers, deletedWallpaperSlugs, presentationData -> (ThemeGridEntryTransition, Bool) in
|
|> map { wallpapers, deletedWallpaperSlugs, presentationData -> (ThemeGridEntryTransition, Bool) in
|
||||||
var entries: [ThemeGridControllerEntry] = []
|
var entries: [ThemeGridControllerEntry] = []
|
||||||
var index = 1
|
var index = 1
|
||||||
@ -369,7 +352,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
} else if presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
} else if presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
||||||
isSelectedEditable = false
|
isSelectedEditable = false
|
||||||
}
|
}
|
||||||
entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: isSelectedEditable, isSelected: true), at: 0)
|
entries.insert(ThemeGridControllerEntry(index: 0, wallpaper: presentationData.chatWallpaper, isEditable: false, isSelected: true), at: 0)
|
||||||
|
|
||||||
var defaultWallpaper: TelegramWallpaper?
|
var defaultWallpaper: TelegramWallpaper?
|
||||||
if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
||||||
@ -397,17 +380,22 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
|
|
||||||
var sortedWallpapers: [TelegramWallpaper] = []
|
var sortedWallpapers: [TelegramWallpaper] = []
|
||||||
if presentationData.theme.overallDarkAppearance {
|
if presentationData.theme.overallDarkAppearance {
|
||||||
|
var localWallpapers: [TelegramWallpaper] = []
|
||||||
var darkWallpapers: [TelegramWallpaper] = []
|
var darkWallpapers: [TelegramWallpaper] = []
|
||||||
for wallpaper in wallpapers {
|
for wallpaper in wallpapers {
|
||||||
if case let .file(file) = wallpaper, file.isDark {
|
if wallpaper.isLocal {
|
||||||
darkWallpapers.append(wallpaper)
|
localWallpapers.append(wallpaper.wallpaper)
|
||||||
} else {
|
} else {
|
||||||
sortedWallpapers.append(wallpaper)
|
if case let .file(file) = wallpaper.wallpaper, file.isDark {
|
||||||
|
darkWallpapers.append(wallpaper.wallpaper)
|
||||||
|
} else {
|
||||||
|
sortedWallpapers.append(wallpaper.wallpaper)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sortedWallpapers = darkWallpapers + sortedWallpapers
|
}
|
||||||
|
sortedWallpapers = localWallpapers + darkWallpapers + sortedWallpapers
|
||||||
} else {
|
} else {
|
||||||
sortedWallpapers = wallpapers
|
sortedWallpapers = wallpapers.map(\.wallpaper)
|
||||||
}
|
}
|
||||||
|
|
||||||
for wallpaper in sortedWallpapers {
|
for wallpaper in sortedWallpapers {
|
||||||
@ -423,6 +411,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
if case .builtin = wallpaper {
|
if case .builtin = wallpaper {
|
||||||
isEditable = false
|
isEditable = false
|
||||||
}
|
}
|
||||||
|
if isDefault || presentationData.chatWallpaper.isBasicallyEqual(to: wallpaper) {
|
||||||
|
isEditable = false
|
||||||
|
}
|
||||||
if !selected && !isDefault {
|
if !selected && !isDefault {
|
||||||
let entry = ThemeGridControllerEntry(index: index, wallpaper: wallpaper, isEditable: isEditable, isSelected: false)
|
let entry = ThemeGridControllerEntry(index: index, wallpaper: wallpaper, isEditable: isEditable, isSelected: false)
|
||||||
if !entries.contains(where: { $0.stableId == entry.stableId }) {
|
if !entries.contains(where: { $0.stableId == entry.stableId }) {
|
||||||
@ -440,6 +431,8 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
strongSelf.enqueueTransition(transition)
|
strongSelf.enqueueTransition(transition)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.updateWallpapers()
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -522,7 +515,31 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateWallpapers() {
|
func updateWallpapers() {
|
||||||
self.wallpapersPromise.set(telegramWallpapers(postbox: self.context.account.postbox, network: self.context.account.network))
|
self.wallpapersPromise.set(combineLatest(queue: .mainQueue(),
|
||||||
|
telegramWallpapers(postbox: self.context.account.postbox, network: self.context.account.network),
|
||||||
|
self.context.sharedContext.accountManager.sharedData(keys: [SharedDataKeys.wallapersState])
|
||||||
|
)
|
||||||
|
|> map { remoteWallpapers, sharedData -> [Wallpaper] in
|
||||||
|
let localState = (sharedData.entries[SharedDataKeys.wallapersState] as? WallpapersState) ?? WallpapersState.default
|
||||||
|
|
||||||
|
var wallpapers: [Wallpaper] = []
|
||||||
|
for wallpaper in localState.wallpapers {
|
||||||
|
if !wallpapers.contains(where: {
|
||||||
|
$0.wallpaper.isBasicallyEqual(to: wallpaper)
|
||||||
|
}) {
|
||||||
|
wallpapers.append(Wallpaper(wallpaper: wallpaper, isLocal: true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for wallpaper in remoteWallpapers {
|
||||||
|
if !wallpapers.contains(where: {
|
||||||
|
$0.wallpaper.isBasicallyEqual(to: wallpaper)
|
||||||
|
}) {
|
||||||
|
wallpapers.append(Wallpaper(wallpaper: wallpaper, isLocal: false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallpapers
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePresentationData(_ presentationData: PresentationData) {
|
func updatePresentationData(_ presentationData: PresentationData) {
|
||||||
@ -562,7 +579,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
self.statePromise.set(state)
|
self.statePromise.set(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectionState = (self.currentState.editing, self.currentState.selectedIndices)
|
let selectionState = (self.currentState.editing, self.currentState.selectedIds)
|
||||||
if let interaction = self.controllerInteraction, interaction.selectionState != selectionState {
|
if let interaction = self.controllerInteraction, interaction.selectionState != selectionState {
|
||||||
let requestLayout = interaction.selectionState.0 != self.currentState.editing
|
let requestLayout = interaction.selectionState.0 != self.currentState.editing
|
||||||
self.controllerInteraction?.selectionState = selectionState
|
self.controllerInteraction?.selectionState = selectionState
|
||||||
@ -576,7 +593,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
if requestLayout, let (containerLayout, navigationBarHeight) = self.validLayout {
|
if requestLayout, let (containerLayout, navigationBarHeight) = self.validLayout {
|
||||||
self.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .animated(duration: 0.4, curve: .spring))
|
self.containerLayoutUpdated(containerLayout, navigationBarHeight: navigationBarHeight, transition: .animated(duration: 0.4, curve: .spring))
|
||||||
}
|
}
|
||||||
self.selectionPanel?.selectedIndices = selectionState.1
|
self.selectionPanel?.selectedIds = selectionState.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +695,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
if self.currentState.editing {
|
if self.currentState.editing {
|
||||||
let panelHeight: CGFloat
|
let panelHeight: CGFloat
|
||||||
if let selectionPanel = self.selectionPanel {
|
if let selectionPanel = self.selectionPanel {
|
||||||
selectionPanel.selectedIndices = self.currentState.selectedIndices
|
selectionPanel.selectedIds = self.currentState.selectedIds
|
||||||
panelHeight = selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: 0.0, transition: transition, metrics: layout.metrics)
|
panelHeight = selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: 0.0, transition: transition, metrics: layout.metrics)
|
||||||
transition.updateFrame(node: selectionPanel, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)))
|
transition.updateFrame(node: selectionPanel, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)))
|
||||||
if let selectionPanelSeparatorNode = self.selectionPanelSeparatorNode {
|
if let selectionPanelSeparatorNode = self.selectionPanelSeparatorNode {
|
||||||
@ -686,24 +703,21 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
if let selectionPanelBackgroundNode = self.selectionPanelBackgroundNode {
|
if let selectionPanelBackgroundNode = self.selectionPanelBackgroundNode {
|
||||||
transition.updateFrame(node: selectionPanelBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: insets.bottom + panelHeight)))
|
transition.updateFrame(node: selectionPanelBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: insets.bottom + panelHeight)))
|
||||||
|
selectionPanelBackgroundNode.update(size: selectionPanelBackgroundNode.bounds.size, transition: transition)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let selectionPanelBackgroundNode = ASDisplayNode()
|
let selectionPanelBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||||
selectionPanelBackgroundNode.isLayerBacked = true
|
|
||||||
selectionPanelBackgroundNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor
|
|
||||||
self.addSubnode(selectionPanelBackgroundNode)
|
self.addSubnode(selectionPanelBackgroundNode)
|
||||||
self.selectionPanelBackgroundNode = selectionPanelBackgroundNode
|
self.selectionPanelBackgroundNode = selectionPanelBackgroundNode
|
||||||
|
|
||||||
let selectionPanel = ThemeGridSelectionPanelNode(theme: self.presentationData.theme)
|
let selectionPanel = ThemeGridSelectionPanelNode(theme: self.presentationData.theme)
|
||||||
selectionPanel.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor
|
|
||||||
selectionPanel.controllerInteraction = self.controllerInteraction
|
selectionPanel.controllerInteraction = self.controllerInteraction
|
||||||
selectionPanel.selectedIndices = self.currentState.selectedIndices
|
selectionPanel.selectedIds = self.currentState.selectedIds
|
||||||
panelHeight = selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: 0.0, transition: .immediate, metrics: layout.metrics)
|
panelHeight = selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, maxHeight: 0.0, transition: .immediate, metrics: layout.metrics)
|
||||||
self.selectionPanel = selectionPanel
|
self.selectionPanel = selectionPanel
|
||||||
self.addSubnode(selectionPanel)
|
self.addSubnode(selectionPanel)
|
||||||
|
|
||||||
let selectionPanelSeparatorNode = ASDisplayNode()
|
let selectionPanelSeparatorNode = ASDisplayNode()
|
||||||
selectionPanelSeparatorNode.isLayerBacked = true
|
|
||||||
selectionPanelSeparatorNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelSeparatorColor
|
selectionPanelSeparatorNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelSeparatorColor
|
||||||
self.addSubnode(selectionPanelSeparatorNode)
|
self.addSubnode(selectionPanelSeparatorNode)
|
||||||
self.selectionPanelSeparatorNode = selectionPanelSeparatorNode
|
self.selectionPanelSeparatorNode = selectionPanelSeparatorNode
|
||||||
@ -713,6 +727,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
selectionPanelSeparatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height), size: CGSize(width: layout.size.width, height: UIScreenPixel))
|
selectionPanelSeparatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height), size: CGSize(width: layout.size.width, height: UIScreenPixel))
|
||||||
transition.updateFrame(node: selectionPanel, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)))
|
transition.updateFrame(node: selectionPanel, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight)))
|
||||||
transition.updateFrame(node: selectionPanelBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: insets.bottom + panelHeight)))
|
transition.updateFrame(node: selectionPanelBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: insets.bottom + panelHeight)))
|
||||||
|
selectionPanelBackgroundNode.update(size: selectionPanelBackgroundNode.bounds.size, transition: .immediate)
|
||||||
transition.updateFrame(node: selectionPanelSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
|
transition.updateFrame(node: selectionPanelSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - panelHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,6 +747,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
transition.updateFrame(node: selectionPanelBackgroundNode, frame: selectionPanelBackgroundNode.frame.offsetBy(dx: 0.0, dy: selectionPanel.bounds.size.height + insets.bottom), completion: { [weak selectionPanelSeparatorNode] _ in
|
transition.updateFrame(node: selectionPanelBackgroundNode, frame: selectionPanelBackgroundNode.frame.offsetBy(dx: 0.0, dy: selectionPanel.bounds.size.height + insets.bottom), completion: { [weak selectionPanelSeparatorNode] _ in
|
||||||
selectionPanelSeparatorNode?.removeFromSupernode()
|
selectionPanelSeparatorNode?.removeFromSupernode()
|
||||||
})
|
})
|
||||||
|
selectionPanelBackgroundNode.update(size: selectionPanelBackgroundNode.bounds.size, transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@ final class ThemeGridSelectionPanelNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var theme: PresentationTheme
|
private var theme: PresentationTheme
|
||||||
|
|
||||||
var selectedIndices = Set<Int64>() {
|
var selectedIds = Set<ThemeGridControllerEntry.StableId>() {
|
||||||
didSet {
|
didSet {
|
||||||
if oldValue != self.selectedIndices {
|
if oldValue != self.selectedIds {
|
||||||
self.deleteButton.isEnabled = !self.selectedIndices.isEmpty
|
self.deleteButton.isEnabled = !self.selectedIds.isEmpty
|
||||||
self.shareButton.isEnabled = !self.selectedIndices.isEmpty
|
self.shareButton.isEnabled = !self.selectedIds.isEmpty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,6 +475,18 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
let _ = installWallpaper(account: strongSelf.context.account, wallpaper: wallpaper).start()
|
let _ = installWallpaper(account: strongSelf.context.account, wallpaper: wallpaper).start()
|
||||||
|
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction in
|
||||||
|
WallpapersState.update(transaction: transaction, { state in
|
||||||
|
var state = state
|
||||||
|
if let index = state.wallpapers.firstIndex(where: {
|
||||||
|
$0.isBasicallyEqual(to: wallpaper)
|
||||||
|
}) {
|
||||||
|
state.wallpapers.remove(at: index)
|
||||||
|
}
|
||||||
|
state.wallpapers.insert(wallpaper, at: 0)
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
let applyWallpaper: (TelegramWallpaper) -> Void = { wallpaper in
|
let applyWallpaper: (TelegramWallpaper) -> Void = { wallpaper in
|
||||||
@ -808,9 +820,24 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
let patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: presentationData.theme, strings: presentationData.strings)
|
let patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: presentationData.theme, strings: presentationData.strings)
|
||||||
patternPanelNode.patternChanged = { [weak self] pattern, intensity, preview in
|
patternPanelNode.patternChanged = { [weak self] pattern, intensity, preview in
|
||||||
if let strongSelf = self, strongSelf.validLayout != nil, let patternInitialWallpaper = strongSelf.patternInitialWallpaper {
|
if let strongSelf = self, strongSelf.validLayout != nil, let patternInitialWallpaper = strongSelf.patternInitialWallpaper {
|
||||||
|
var colors: [UInt32] = []
|
||||||
|
switch patternInitialWallpaper {
|
||||||
|
case let .color(color):
|
||||||
|
colors = [color]
|
||||||
|
case let .file(file):
|
||||||
|
colors = file.settings.colors
|
||||||
|
case let .gradient(colorsValue, _):
|
||||||
|
colors = colorsValue
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
switch patternInitialWallpaper {
|
switch patternInitialWallpaper {
|
||||||
case .color, .file, .gradient:
|
case .color, .file, .gradient:
|
||||||
strongSelf.updateEntries(pattern: pattern, intensity: intensity, preview: preview)
|
if let pattern = pattern, case let .file(file) = pattern {
|
||||||
|
let newSettings = WallpaperSettings(blur: file.settings.blur, motion: file.settings.motion, colors: colors, intensity: intensity)
|
||||||
|
let newWallpaper = TelegramWallpaper.file(id: file.id, accessHash: file.accessHash, isCreator: file.isCreator, isDefault: file.isDefault, isPattern: pattern.isPattern, isDark: file.isDark, slug: file.slug, file: file.file, settings: newSettings)
|
||||||
|
strongSelf.updateEntries(wallpaper: newWallpaper, preview: preview)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -841,8 +868,8 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
|
|
||||||
var wallpaper: TelegramWallpaper = .gradient(colors, WallpaperSettings(blur: false, motion: false, colors: [], intensity: nil, rotation: nil))
|
var wallpaper: TelegramWallpaper = .gradient(colors, WallpaperSettings(blur: false, motion: false, colors: [], intensity: nil, rotation: nil))
|
||||||
|
|
||||||
if case .file = currentWallpaper {
|
if case let .file(file) = currentWallpaper {
|
||||||
wallpaper = currentWallpaper.withUpdatedSettings(WallpaperSettings(blur: false, motion: false, colors: colors, intensity: nil, rotation: nil))
|
wallpaper = currentWallpaper.withUpdatedSettings(WallpaperSettings(blur: false, motion: false, colors: colors, intensity: file.settings.intensity, rotation: file.settings.rotation))
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.updateEntries(wallpaper: wallpaper)
|
strongSelf.updateEntries(wallpaper: wallpaper)
|
||||||
|
@ -336,7 +336,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
case let .color(color):
|
case let .color(color):
|
||||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||||
contentSize = displaySize
|
contentSize = displaySize
|
||||||
signal = solidColorImage(UIColor(rgb: color))
|
signal = .single({ _ in nil })
|
||||||
fetchSignal = .complete()
|
fetchSignal = .complete()
|
||||||
statusSignal = .single(.Local)
|
statusSignal = .single(.Local)
|
||||||
subtitleSignal = .single(nil)
|
subtitleSignal = .single(nil)
|
||||||
@ -346,11 +346,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
case let .gradient(colors, settings):
|
case let .gradient(colors, settings):
|
||||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||||
contentSize = displaySize
|
contentSize = displaySize
|
||||||
if colors.count >= 2 {
|
signal = .single({ _ in nil })
|
||||||
signal = gradientImage([UIColor(rgb: colors[0]), UIColor(rgb: colors[1])], rotation: settings.rotation)
|
|
||||||
} else {
|
|
||||||
signal = solidColorImage(UIColor(rgb: colors[0]))
|
|
||||||
}
|
|
||||||
fetchSignal = .complete()
|
fetchSignal = .complete()
|
||||||
statusSignal = .single(.Local)
|
statusSignal = .single(.Local)
|
||||||
subtitleSignal = .single(nil)
|
subtitleSignal = .single(nil)
|
||||||
@ -389,7 +385,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
|
|
||||||
self.backgroundColor = patternColor.withAlphaComponent(1.0)
|
self.backgroundColor = patternColor.withAlphaComponent(1.0)
|
||||||
|
|
||||||
if let previousEntry = previousEntry, case let .wallpaper(wallpaper, _) = previousEntry, case let .file(previousFile) = wallpaper, file.id == previousFile.id && (file.settings.colors != previousFile.settings.colors || file.settings.intensity != previousFile.settings.intensity) && self.colorPreview == self.arguments.colorPreview {
|
/*if let previousEntry = previousEntry, case let .wallpaper(wallpaper, _) = previousEntry, case let .file(previousFile) = wallpaper, file.id == previousFile.id && (file.settings.colors != previousFile.settings.colors || file.settings.intensity != previousFile.settings.intensity) && self.colorPreview == self.arguments.colorPreview {
|
||||||
|
|
||||||
let makeImageLayout = self.imageNode.asyncLayout()
|
let makeImageLayout = self.imageNode.asyncLayout()
|
||||||
Queue.concurrentDefaultQueue().async {
|
Queue.concurrentDefaultQueue().async {
|
||||||
@ -405,15 +401,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
patternArguments = PatternWallpaperArguments(colors: patternColors, rotation: file.settings.rotation)
|
patternArguments = PatternWallpaperArguments(colors: patternColors, rotation: file.settings.rotation)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
self.colorPreview = self.arguments.colorPreview
|
self.colorPreview = self.arguments.colorPreview
|
||||||
|
|
||||||
if file.settings.colors.count >= 3 {
|
signal = .single({ _ in nil })
|
||||||
|
/*if file.settings.colors.count >= 3 {
|
||||||
signal = .single({ _ in nil })
|
signal = .single({ _ in nil })
|
||||||
} else {
|
} else {
|
||||||
signal = patternWallpaperImage(account: self.context.account, accountManager: self.context.sharedContext.accountManager, representations: convertedRepresentations, mode: .screen, autoFetchFullSize: true)
|
signal = patternWallpaperImage(account: self.context.account, accountManager: self.context.sharedContext.accountManager, representations: convertedRepresentations, mode: .screen, autoFetchFullSize: true)
|
||||||
}
|
}*/
|
||||||
colorSignal = chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: self.context.account.postbox.mediaBox)
|
colorSignal = chatServiceBackgroundColor(wallpaper: wallpaper, mediaBox: self.context.account.postbox.mediaBox)
|
||||||
|
|
||||||
isBlurrable = false
|
isBlurrable = false
|
||||||
|
@ -263,8 +263,8 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
sliderView.lineSize = 2.0
|
sliderView.lineSize = 2.0
|
||||||
sliderView.minimumValue = 0.0
|
sliderView.minimumValue = 0.0
|
||||||
sliderView.startValue = 0.0
|
sliderView.startValue = 0.0
|
||||||
sliderView.maximumValue = 100.0
|
sliderView.maximumValue = 200.0
|
||||||
sliderView.value = 40.0
|
sliderView.value = 150.0
|
||||||
sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
||||||
sliderView.backgroundColor = .clear
|
sliderView.backgroundColor = .clear
|
||||||
sliderView.backColor = self.theme.list.disclosureArrowColor
|
sliderView.backColor = self.theme.list.disclosureArrowColor
|
||||||
@ -312,7 +312,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.currentWallpaper = updatedWallpaper
|
strongSelf.currentWallpaper = updatedWallpaper
|
||||||
if let sliderView = strongSelf.sliderView {
|
if let sliderView = strongSelf.sliderView {
|
||||||
strongSelf.patternChanged?(updatedWallpaper, Int32(sliderView.value), false)
|
strongSelf.patternChanged?(updatedWallpaper, Int32(sliderView.value - 100.0), false)
|
||||||
}
|
}
|
||||||
if let subnodes = strongSelf.scrollNode.subnodes {
|
if let subnodes = strongSelf.scrollNode.subnodes {
|
||||||
for case let subnode as SettingsThemeWallpaperNode in subnodes {
|
for case let subnode as SettingsThemeWallpaperNode in subnodes {
|
||||||
@ -354,7 +354,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let wallpaper = self.currentWallpaper {
|
if let wallpaper = self.currentWallpaper {
|
||||||
self.patternChanged?(wallpaper, Int32(sliderView.value), sliderView.isTracking)
|
self.patternChanged?(wallpaper, Int32(sliderView.value - 100.0), sliderView.isTracking)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +368,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.currentWallpaper = wallpaper
|
self.currentWallpaper = wallpaper
|
||||||
self.sliderView?.value = CGFloat(intensity ?? 50)
|
self.sliderView?.value = CGFloat(intensity.flatMap { $0 + 100 } ?? 150)
|
||||||
|
|
||||||
self.scrollNode.view.contentOffset = CGPoint()
|
self.scrollNode.view.contentOffset = CGPoint()
|
||||||
|
|
||||||
@ -385,7 +385,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if initialWallpaper == nil, let wallpaper = self.currentWallpaper, let sliderView = self.sliderView {
|
if initialWallpaper == nil, let wallpaper = self.currentWallpaper, let sliderView = self.sliderView {
|
||||||
self.patternChanged?(wallpaper, Int32(sliderView.value), false)
|
self.patternChanged?(wallpaper, Int32(sliderView.value - 100.0), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let selectedNode = selectedNode {
|
if let selectedNode = selectedNode {
|
||||||
|
@ -349,6 +349,7 @@ private enum SharedDataKeyValues: Int32 {
|
|||||||
case autodownloadSettings = 5
|
case autodownloadSettings = 5
|
||||||
case themeSettings = 6
|
case themeSettings = 6
|
||||||
case countriesList = 7
|
case countriesList = 7
|
||||||
|
case wallapersState = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct SharedDataKeys {
|
public struct SharedDataKeys {
|
||||||
@ -393,6 +394,12 @@ public struct SharedDataKeys {
|
|||||||
key.setInt32(0, value: SharedDataKeyValues.countriesList.rawValue)
|
key.setInt32(0, value: SharedDataKeyValues.countriesList.rawValue)
|
||||||
return key
|
return key
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
public static let wallapersState: ValueBoxKey = {
|
||||||
|
let key = ValueBoxKey(length: 4)
|
||||||
|
key.setInt32(0, value: SharedDataKeyValues.wallapersState.rawValue)
|
||||||
|
return key
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 {
|
public func applicationSpecificItemCacheCollectionId(_ value: Int8) -> Int8 {
|
||||||
|
35
submodules/SyncCore/Sources/wallapersState.swift
Normal file
35
submodules/SyncCore/Sources/wallapersState.swift
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import Postbox
|
||||||
|
import SwiftSignalKit
|
||||||
|
|
||||||
|
public struct WallpapersState: PreferencesEntry, Equatable {
|
||||||
|
public var wallpapers: [TelegramWallpaper]
|
||||||
|
|
||||||
|
public static var `default`: WallpapersState {
|
||||||
|
return WallpapersState(wallpapers: [])
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(wallpapers: [TelegramWallpaper]) {
|
||||||
|
self.wallpapers = wallpapers
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(decoder: PostboxDecoder) {
|
||||||
|
self.wallpapers = decoder.decodeObjectArrayWithDecoderForKey("wallpapers")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(_ encoder: PostboxEncoder) {
|
||||||
|
encoder.encodeObjectArray(self.wallpapers, forKey: "wallpapers")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func isEqual(to: PreferencesEntry) -> Bool {
|
||||||
|
return self == (to as? WallpapersState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension WallpapersState {
|
||||||
|
static func update(transaction: AccountManagerModifier, _ f: (WallpapersState) -> WallpapersState) {
|
||||||
|
transaction.updateSharedData(SharedDataKeys.wallapersState, { current in
|
||||||
|
let item = (transaction.getSharedData(SharedDataKeys.wallapersState) as? WallpapersState) ?? WallpapersState(wallpapers: [])
|
||||||
|
return f(item)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -174,6 +174,7 @@ private var declaredEncodables: Void = {
|
|||||||
declareEncodable(CachedPeerExportedInvitations.self, f: { CachedPeerExportedInvitations(decoder: $0) })
|
declareEncodable(CachedPeerExportedInvitations.self, f: { CachedPeerExportedInvitations(decoder: $0) })
|
||||||
declareEncodable(ExportedInvitation.self, f: { ExportedInvitation(decoder: $0) })
|
declareEncodable(ExportedInvitation.self, f: { ExportedInvitation(decoder: $0) })
|
||||||
declareEncodable(CachedDisplayAsPeers.self, f: { CachedDisplayAsPeers(decoder: $0) })
|
declareEncodable(CachedDisplayAsPeers.self, f: { CachedDisplayAsPeers(decoder: $0) })
|
||||||
|
declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) })
|
||||||
|
|
||||||
return
|
return
|
||||||
}()
|
}()
|
||||||
|
@ -246,7 +246,7 @@ public final class PrincipalThemeEssentialGraphics {
|
|||||||
|
|
||||||
let emptyImage = UIImage()
|
let emptyImage = UIImage()
|
||||||
if preview {
|
if preview {
|
||||||
self.chatMessageBackgroundIncomingMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: UIColor.black, strokeColor: UIColor.clear, neighbors: .none, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
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.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.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.chatMessageBackgroundIncomingExtractedImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .extracted, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true)
|
||||||
@ -263,30 +263,33 @@ public final class PrincipalThemeEssentialGraphics {
|
|||||||
self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor, width: 11.0)!
|
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.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor, width: 11.0)!
|
||||||
self.chatMessageBackgroundIncomingHighlightedImage = emptyImage
|
self.chatMessageBackgroundIncomingHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundIncomingMergedTopMaskImage = 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.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.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.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.chatMessageBackgroundIncomingMergedTopHighlightedImage = emptyImage
|
self.chatMessageBackgroundIncomingMergedTopHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundIncomingMergedTopSideMaskImage = 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 = emptyImage
|
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 = emptyImage
|
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 = emptyImage
|
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.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = emptyImage
|
self.chatMessageBackgroundIncomingMergedTopSideHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundIncomingMergedBottomMaskImage = 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.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.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.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.chatMessageBackgroundIncomingMergedBottomHighlightedImage = emptyImage
|
self.chatMessageBackgroundIncomingMergedBottomHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundIncomingMergedBothMaskImage = 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 = emptyImage
|
|
||||||
self.chatMessageBackgroundIncomingMergedBothOutlineImage = emptyImage
|
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.chatMessageBackgroundIncomingMergedBothShadowImage = emptyImage
|
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.chatMessageBackgroundIncomingMergedBothHighlightedImage = emptyImage
|
self.chatMessageBackgroundIncomingMergedBothHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundIncomingMergedSideMaskImage = 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 = emptyImage
|
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 = emptyImage
|
|
||||||
self.chatMessageBackgroundIncomingMergedSideShadowImage = emptyImage
|
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.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.chatMessageBackgroundIncomingMergedSideHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundOutgoingHighlightedImage = 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.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)
|
||||||
@ -294,10 +297,10 @@ public final class PrincipalThemeEssentialGraphics {
|
|||||||
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.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.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.chatMessageBackgroundOutgoingMergedTopHighlightedImage = emptyImage
|
self.chatMessageBackgroundOutgoingMergedTopHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = 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 = emptyImage
|
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 = emptyImage
|
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 = emptyImage
|
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.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = emptyImage
|
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.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.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true)
|
||||||
@ -309,10 +312,9 @@ public final class PrincipalThemeEssentialGraphics {
|
|||||||
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.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.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.chatMessageBackgroundOutgoingMergedBothHighlightedImage = emptyImage
|
self.chatMessageBackgroundOutgoingMergedBothHighlightedImage = emptyImage
|
||||||
self.chatMessageBackgroundOutgoingMergedSideMaskImage = 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.chatMessageBackgroundOutgoingMergedSideImage = emptyImage
|
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.chatMessageBackgroundOutgoingMergedSideOutlineImage = emptyImage
|
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.chatMessageBackgroundOutgoingMergedSideShadowImage = emptyImage
|
|
||||||
self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = emptyImage
|
self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = emptyImage
|
||||||
self.checkMediaFullImage = emptyImage
|
self.checkMediaFullImage = emptyImage
|
||||||
self.checkMediaPartialImage = emptyImage
|
self.checkMediaPartialImage = emptyImage
|
||||||
|
@ -64,9 +64,10 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode {
|
|||||||
private weak var backgroundNode: WallpaperBackgroundNode?
|
private weak var backgroundNode: WallpaperBackgroundNode?
|
||||||
|
|
||||||
private var maskView: UIImageView?
|
private var maskView: UIImageView?
|
||||||
|
|
||||||
private var fixedMaskMode: Bool?
|
private var fixedMaskMode: Bool?
|
||||||
|
|
||||||
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
var hasImage: Bool {
|
var hasImage: Bool {
|
||||||
return self.backgroundContent != nil
|
return self.backgroundContent != nil
|
||||||
}
|
}
|
||||||
@ -145,12 +146,18 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode {
|
|||||||
case .incoming:
|
case .incoming:
|
||||||
if let backgroundContent = backgroundNode?.makeBubbleBackground(for: .incoming) {
|
if let backgroundContent = backgroundNode?.makeBubbleBackground(for: .incoming) {
|
||||||
backgroundContent.frame = self.bounds
|
backgroundContent.frame = self.bounds
|
||||||
|
if let (rect, containerSize) = self.absolutePosition {
|
||||||
|
backgroundContent.update(rect: rect, within: containerSize)
|
||||||
|
}
|
||||||
self.backgroundContent = backgroundContent
|
self.backgroundContent = backgroundContent
|
||||||
self.insertSubnode(backgroundContent, at: 0)
|
self.insertSubnode(backgroundContent, at: 0)
|
||||||
}
|
}
|
||||||
case .outgoing:
|
case .outgoing:
|
||||||
if let backgroundContent = backgroundNode?.makeBubbleBackground(for: .outgoing) {
|
if let backgroundContent = backgroundNode?.makeBubbleBackground(for: .outgoing) {
|
||||||
backgroundContent.frame = self.bounds
|
backgroundContent.frame = self.bounds
|
||||||
|
if let (rect, containerSize) = self.absolutePosition {
|
||||||
|
backgroundContent.update(rect: rect, within: containerSize)
|
||||||
|
}
|
||||||
self.backgroundContent = backgroundContent
|
self.backgroundContent = backgroundContent
|
||||||
self.insertSubnode(backgroundContent, at: 0)
|
self.insertSubnode(backgroundContent, at: 0)
|
||||||
}
|
}
|
||||||
@ -164,18 +171,15 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func update(rect: CGRect, within containerSize: CGSize) {
|
func update(rect: CGRect, within containerSize: CGSize) {
|
||||||
//self.backgroundContent.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize)
|
self.absolutePosition = (rect, containerSize)
|
||||||
self.backgroundContent?.update(rect: rect, within: containerSize)
|
self.backgroundContent?.update(rect: rect, within: containerSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
func offset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
|
func offset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) {
|
||||||
//let transition: ContainedViewLayoutTransition = .animated(duration: duration, curve: animationCurve)
|
|
||||||
//transition.animatePositionAdditive(node: self.backgroundContent, offset: CGPoint(x: -value.x, y: -value.y))
|
|
||||||
self.backgroundContent?.offset(value: value, animationCurve: animationCurve, duration: duration)
|
self.backgroundContent?.offset(value: value, animationCurve: animationCurve, duration: duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
func offsetSpring(value: CGFloat, duration: Double, damping: CGFloat) {
|
func offsetSpring(value: CGFloat, duration: Double, damping: CGFloat) {
|
||||||
//self.backgroundContent.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: 0.0, y: value)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: duration, initialVelocity: 0.0, damping: damping, additive: true)
|
|
||||||
self.backgroundContent?.offsetSpring(value: value, duration: duration, damping: damping)
|
self.backgroundContent?.offsetSpring(value: value, duration: duration, damping: damping)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
private weak var backgroundNode: WallpaperBackgroundNode?
|
private weak var backgroundNode: WallpaperBackgroundNode?
|
||||||
private var index: SparseBag<BubbleBackgroundNode>.Index?
|
private var index: SparseBag<BubbleBackgroundNode>.Index?
|
||||||
|
|
||||||
|
private var currentLayout: (rect: CGRect, containerSize: CGSize)?
|
||||||
|
|
||||||
init(backgroundNode: WallpaperBackgroundNode, bubbleType: BubbleType) {
|
init(backgroundNode: WallpaperBackgroundNode, bubbleType: BubbleType) {
|
||||||
self.backgroundNode = backgroundNode
|
self.backgroundNode = backgroundNode
|
||||||
self.bubbleType = bubbleType
|
self.bubbleType = bubbleType
|
||||||
@ -135,9 +137,15 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
cleanWallpaperNode.removeFromSupernode()
|
cleanWallpaperNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let (rect, containerSize) = self.currentLayout {
|
||||||
|
self.update(rect: rect, within: containerSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func update(rect: CGRect, within containerSize: CGSize) {
|
public func update(rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.currentLayout = (rect, containerSize)
|
||||||
|
|
||||||
self.contentNode.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize)
|
self.contentNode.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize)
|
||||||
if let cleanWallpaperNode = self.cleanWallpaperNode {
|
if let cleanWallpaperNode = self.cleanWallpaperNode {
|
||||||
cleanWallpaperNode.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize)
|
cleanWallpaperNode.frame = CGRect(origin: CGPoint(x: -rect.minX, y: -rect.minY), size: containerSize)
|
||||||
@ -183,6 +191,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
private let contentNode: ASDisplayNode
|
private let contentNode: ASDisplayNode
|
||||||
private var gradientBackgroundNode: GradientBackgroundNode?
|
private var gradientBackgroundNode: GradientBackgroundNode?
|
||||||
private let patternImageNode: TransformImageNode
|
private let patternImageNode: TransformImageNode
|
||||||
|
private var invertPattern: Bool = false
|
||||||
|
|
||||||
private var validLayout: CGSize?
|
private var validLayout: CGSize?
|
||||||
private var wallpaper: TelegramWallpaper?
|
private var wallpaper: TelegramWallpaper?
|
||||||
@ -255,7 +264,6 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
self.contentNode.contentMode = self.imageContentMode
|
self.contentNode.contentMode = self.imageContentMode
|
||||||
|
|
||||||
self.patternImageNode = TransformImageNode()
|
self.patternImageNode = TransformImageNode()
|
||||||
self.patternImageNode.layer.compositingFilter = "softLightBlendMode"
|
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -369,10 +377,31 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
let signal = patternWallpaperImage(account: self.context.account, accountManager: self.context.sharedContext.accountManager, representations: convertedRepresentations, mode: .screen, autoFetchFullSize: true)
|
let signal = patternWallpaperImage(account: self.context.account, accountManager: self.context.sharedContext.accountManager, representations: convertedRepresentations, mode: .screen, autoFetchFullSize: true)
|
||||||
self.patternImageNode.setSignal(signal)
|
self.patternImageNode.setSignal(signal)
|
||||||
}
|
}
|
||||||
self.patternImageNode.alpha = CGFloat(settings.intensity ?? 50) / 100.0
|
let intensity = CGFloat(settings.intensity ?? 50) / 100.0
|
||||||
|
if intensity < 0 {
|
||||||
|
self.patternImageNode.alpha = 1.0
|
||||||
|
self.patternImageNode.layer.compositingFilter = nil
|
||||||
|
} else {
|
||||||
|
self.patternImageNode.alpha = intensity
|
||||||
|
self.patternImageNode.layer.compositingFilter = "softLightBlendMode"
|
||||||
|
}
|
||||||
self.patternImageNode.isHidden = false
|
self.patternImageNode.isHidden = false
|
||||||
|
self.invertPattern = intensity < 0
|
||||||
|
if self.invertPattern {
|
||||||
|
self.backgroundColor = .black
|
||||||
|
let contentAlpha = abs(intensity)
|
||||||
|
self.gradientBackgroundNode?.contentView.alpha = contentAlpha
|
||||||
|
self.contentNode.alpha = contentAlpha
|
||||||
|
} else {
|
||||||
|
self.backgroundColor = nil
|
||||||
|
self.gradientBackgroundNode?.contentView.alpha = 1.0
|
||||||
|
self.contentNode.alpha = 1.0
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
self.patternImageNode.isHidden = true
|
self.patternImageNode.isHidden = true
|
||||||
|
self.backgroundColor = nil
|
||||||
|
self.gradientBackgroundNode?.contentView.alpha = 1.0
|
||||||
|
self.contentNode.alpha = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
self.updateBubbles()
|
self.updateBubbles()
|
||||||
@ -395,7 +424,16 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let makeImageLayout = self.patternImageNode.asyncLayout()
|
let makeImageLayout = self.patternImageNode.asyncLayout()
|
||||||
let applyImage = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: size, boundingSize: size, intrinsicInsets: UIEdgeInsets(), custom: PatternWallpaperArguments(colors: [.clear], rotation: nil, customPatternColor: .black, preview: false)))
|
let patternBackgroundColor: UIColor
|
||||||
|
let patternColor: UIColor
|
||||||
|
if self.invertPattern {
|
||||||
|
patternColor = .clear
|
||||||
|
patternBackgroundColor = .black
|
||||||
|
} else {
|
||||||
|
patternColor = .black
|
||||||
|
patternBackgroundColor = .clear
|
||||||
|
}
|
||||||
|
let applyImage = makeImageLayout(TransformImageArguments(corners: ImageCorners(), imageSize: size, boundingSize: size, intrinsicInsets: UIEdgeInsets(), custom: PatternWallpaperArguments(colors: [patternBackgroundColor], rotation: nil, customPatternColor: patternColor, preview: false)))
|
||||||
applyImage()
|
applyImage()
|
||||||
transition.updateFrame(node: self.patternImageNode, frame: CGRect(origin: CGPoint(), size: size))
|
transition.updateFrame(node: self.patternImageNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
@ -314,6 +314,9 @@ public struct PatternWallpaperArguments: TransformImageCustomArguments {
|
|||||||
let array = NSMutableArray()
|
let array = NSMutableArray()
|
||||||
array.addObjects(from: self.colors)
|
array.addObjects(from: self.colors)
|
||||||
array.add(NSNumber(value: self.rotation ?? 0))
|
array.add(NSNumber(value: self.rotation ?? 0))
|
||||||
|
if let customPatternColor = customPatternColor {
|
||||||
|
array.add(NSNumber(value: customPatternColor.argb))
|
||||||
|
}
|
||||||
array.add(NSNumber(value: self.preview))
|
array.add(NSNumber(value: self.preview))
|
||||||
return array
|
return array
|
||||||
}
|
}
|
||||||
@ -500,7 +503,11 @@ public func patternWallpaperImageInternal(thumbnailData: Data?, fullSizeData: Da
|
|||||||
c.interpolationQuality = customArguments.preview ? .low : .medium
|
c.interpolationQuality = customArguments.preview ? .low : .medium
|
||||||
c.clip(to: fittedRect, mask: image)
|
c.clip(to: fittedRect, mask: image)
|
||||||
|
|
||||||
|
if let customPatternColor = customArguments.customPatternColor, customPatternColor.alpha < 1.0 {
|
||||||
|
c.setBlendMode(.copy)
|
||||||
|
} else {
|
||||||
c.setBlendMode(.normal)
|
c.setBlendMode(.normal)
|
||||||
|
}
|
||||||
|
|
||||||
if colors.count >= 3 && customArguments.customPatternColor == nil {
|
if colors.count >= 3 && customArguments.customPatternColor == nil {
|
||||||
c.setBlendMode(.softLight)
|
c.setBlendMode(.softLight)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user