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 let contentView: UIImageView
|
||||
public let contentView: UIImageView
|
||||
private var validPhase: Int?
|
||||
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?) {
|
||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
let paintStickersContext = LegacyPaintStickersContext(context: context)
|
||||
paintStickersContext.presentStickersController = { completion in
|
||||
return presentStickers({ file, animated, view, rect in
|
||||
|
@ -75,10 +75,12 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
self.imageNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
var colors: [UInt32] = []
|
||||
var intensity: CGFloat = 0.5
|
||||
if case let .gradient(value, _) = wallpaper {
|
||||
colors = value
|
||||
} else if case let .file(file) = wallpaper {
|
||||
colors = file.settings.colors
|
||||
intensity = CGFloat(file.settings.intensity ?? 50) / 100.0
|
||||
} else if case let .color(color) = wallpaper {
|
||||
colors = [color]
|
||||
}
|
||||
@ -93,7 +95,11 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
self.insertSubnode(gradientNode, belowSubnode: self.imageNode)
|
||||
}
|
||||
|
||||
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
||||
if intensity < 0.0 {
|
||||
self.imageNode.layer.compositingFilter = nil
|
||||
} else {
|
||||
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
||||
}
|
||||
self.backgroundNode.image = nil
|
||||
} else {
|
||||
if let gradientNode = self.gradientNode {
|
||||
@ -101,13 +107,17 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
gradientNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
if colors.count >= 2 {
|
||||
if intensity < 0.0 {
|
||||
self.imageNode.layer.compositingFilter = nil
|
||||
} else {
|
||||
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.backgroundColor = nil
|
||||
} else if colors.count >= 1 {
|
||||
self.backgroundNode.image = nil
|
||||
self.imageNode.layer.compositingFilter = "softLightBlendMode"
|
||||
self.backgroundNode.backgroundColor = UIColor(rgb: colors[0])
|
||||
}
|
||||
}
|
||||
@ -147,24 +157,20 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
|
||||
let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
|
||||
if wallpaper.isPattern {
|
||||
var patternColors: [UIColor] = []
|
||||
var patternColor = UIColor(rgb: 0xd6e2ee, alpha: 0.5)
|
||||
var patternIntensity: CGFloat = 0.5
|
||||
if !file.settings.colors.isEmpty {
|
||||
if let intensity = file.settings.intensity {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
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.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)
|
||||
} else {
|
||||
self.imageNode.alpha = 1.0
|
||||
|
@ -246,7 +246,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
|
||||
self.messagesContainerNode = ASDisplayNode()
|
||||
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.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()
|
||||
|> deliverOn(self.queue)
|
||||
|> mapToThrottled { next -> Signal<ThemeColorState, NoError> in
|
||||
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
|
||||
var backgroundColors = state.backgroundColors
|
||||
let messagesColors = state.messagesColors
|
||||
@ -494,6 +497,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
strongSelf.serviceBackgroundColorPromise.set(.single(serviceBackgroundColor))
|
||||
|
||||
strongSelf.backgroundNode.update(wallpaper: wallpaper)
|
||||
strongSelf.backgroundNode.updateBubbleTheme(bubbleTheme: strongSelf.theme, bubbleCorners: strongSelf.presentationData.chatBubbleCorners)
|
||||
|
||||
strongSelf.ready.set(.single(true))
|
||||
|
||||
@ -871,7 +875,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
itemNode = node
|
||||
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!)
|
||||
self.messagesContainerNode.addSubnode(itemNode!)
|
||||
}
|
||||
@ -881,9 +885,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
||||
var bottomOffset: CGFloat = 9.0 + bottomInset
|
||||
if let messageNodes = self.messageNodes {
|
||||
for itemNode in messageNodes {
|
||||
let previousFrame = itemNode.frame
|
||||
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(x: 0.0, y: bottomOffset), size: itemNode.frame.size))
|
||||
bottomOffset += itemNode.frame.height
|
||||
itemNode.updateFrame(itemNode.frame, within: layout.size)
|
||||
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)
|
||||
} else {
|
||||
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.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)
|
||||
|
||||
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))
|
||||
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))
|
||||
|
||||
let displayOptionButtons = self.state.section == .background
|
||||
var messagesBottomInset: CGFloat = 0.0
|
||||
var messagesBottomInset: CGFloat = bottomInset
|
||||
|
||||
if displayOptionButtons {
|
||||
messagesBottomInset = 46.0
|
||||
messagesBottomInset += 46.0
|
||||
} else if chatListPreviewAvailable {
|
||||
messagesBottomInset = 37.0
|
||||
messagesBottomInset += 37.0
|
||||
}
|
||||
self.updateChatsLayout(layout: layout, topInset: navigationBarHeight, transition: transition)
|
||||
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.searchContentNode?.setIsEnabled(false, animated: true)
|
||||
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.searchContentNode?.setIsEnabled(true, animated: true)
|
||||
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 {
|
||||
let context: AccountContext
|
||||
let wallpaper: TelegramWallpaper
|
||||
let wallpaperId: ThemeGridControllerEntry.StableId
|
||||
let index: Int
|
||||
let editable: Bool
|
||||
let selected: Bool
|
||||
@ -19,9 +20,10 @@ final class ThemeGridControllerItem: GridItem {
|
||||
|
||||
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.wallpaper = wallpaper
|
||||
self.wallpaperId = wallpaperId
|
||||
self.index = index
|
||||
self.editable = editable
|
||||
self.selected = selected
|
||||
@ -30,7 +32,7 @@ final class ThemeGridControllerItem: GridItem {
|
||||
|
||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
||||
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
|
||||
}
|
||||
|
||||
@ -39,7 +41,7 @@ final class ThemeGridControllerItem: GridItem {
|
||||
assertionFailure()
|
||||
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 var selectionNode: GridMessageSelectionNode?
|
||||
|
||||
private var currentState: (AccountContext, TelegramWallpaper, Bool, Bool, Bool)?
|
||||
private var interaction: ThemeGridControllerInteraction?
|
||||
private var item: ThemeGridControllerItem?
|
||||
|
||||
override init() {
|
||||
self.wallpaperNode = SettingsThemeWallpaperNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.wallpaperNode)
|
||||
@ -64,50 +66,35 @@ final class ThemeGridControllerItemNode: GridItemNode {
|
||||
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||
}
|
||||
|
||||
func setup(context: AccountContext, wallpaper: TelegramWallpaper, editable: Bool, selected: Bool, interaction: ThemeGridControllerInteraction, synchronousLoad: Bool) {
|
||||
self.interaction = interaction
|
||||
|
||||
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.setNeedsLayout()
|
||||
}
|
||||
func setup(item: ThemeGridControllerItem, synchronousLoad: Bool) {
|
||||
self.item = item
|
||||
self.updateSelectionState(animated: false)
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
if let (_, wallpaper, _, _, _) = self.currentState {
|
||||
self.interaction?.openWallpaper(wallpaper)
|
||||
if let item = self.item {
|
||||
item.interaction.openWallpaper(item.wallpaper)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateSelectionState(animated: Bool) {
|
||||
if let (context, wallpaper, _, _, editable) = self.currentState {
|
||||
var editing = false
|
||||
var id: Int64?
|
||||
if case let .file(file) = wallpaper {
|
||||
id = file.id
|
||||
} 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 item = self.item {
|
||||
let (editing, selectedIds) = item.interaction.selectionState
|
||||
|
||||
if editing && item.editable {
|
||||
let selected = selectedIds.contains(item.wallpaperId)
|
||||
|
||||
if let selectionNode = self.selectionNode {
|
||||
selectionNode.updateSelected(selected, animated: animated)
|
||||
selectionNode.frame = CGRect(origin: CGPoint(), size: self.bounds.size)
|
||||
} 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
|
||||
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()
|
||||
|
||||
let bounds = self.bounds
|
||||
if let (context, wallpaper, selected, synchronousLoad, _) = self.currentState {
|
||||
self.wallpaperNode.setWallpaper(context: context, wallpaper: wallpaper, selected: selected, size: bounds.size, synchronousLoad: synchronousLoad)
|
||||
if let item = self.item {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -18,36 +18,18 @@ import SearchUI
|
||||
import WallpaperResources
|
||||
|
||||
struct ThemeGridControllerNodeState: Equatable {
|
||||
let editing: Bool
|
||||
var selectedIndices: Set<Int64>
|
||||
|
||||
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
|
||||
}
|
||||
var editing: Bool
|
||||
var selectedIds: Set<ThemeGridControllerEntry.StableId>
|
||||
}
|
||||
|
||||
final class ThemeGridControllerInteraction {
|
||||
let openWallpaper: (TelegramWallpaper) -> Void
|
||||
let toggleWallpaperSelection: (Int64, Bool) -> Void
|
||||
let toggleWallpaperSelection: (ThemeGridControllerEntry.StableId, Bool) -> Void
|
||||
let deleteSelectedWallpapers: () -> 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.toggleWallpaperSelection = toggleWallpaperSelection
|
||||
self.deleteSelectedWallpapers = deleteSelectedWallpapers
|
||||
@ -55,7 +37,7 @@ final class ThemeGridControllerInteraction {
|
||||
}
|
||||
}
|
||||
|
||||
private struct ThemeGridControllerEntry: Comparable, Identifiable {
|
||||
struct ThemeGridControllerEntry: Comparable, Identifiable {
|
||||
enum StableId: Hashable {
|
||||
case builtin
|
||||
case color(UInt32)
|
||||
@ -64,14 +46,10 @@ private struct ThemeGridControllerEntry: Comparable, Identifiable {
|
||||
case image(String)
|
||||
}
|
||||
|
||||
let index: Int
|
||||
let wallpaper: TelegramWallpaper
|
||||
let isEditable: Bool
|
||||
let 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
|
||||
}
|
||||
var index: Int
|
||||
var wallpaper: TelegramWallpaper
|
||||
var isEditable: Bool
|
||||
var isSelected: Bool
|
||||
|
||||
static func <(lhs: ThemeGridControllerEntry, rhs: ThemeGridControllerEntry) -> Bool {
|
||||
return lhs.index < rhs.index
|
||||
@ -79,25 +57,25 @@ private struct ThemeGridControllerEntry: Comparable, Identifiable {
|
||||
|
||||
var stableId: StableId {
|
||||
switch self.wallpaper {
|
||||
case .builtin:
|
||||
return .builtin
|
||||
case let .color(color):
|
||||
return .color(color)
|
||||
case let .gradient(colors, _):
|
||||
return .gradient(colors)
|
||||
case let .file(id, _, _, _, _, _, _, _, settings):
|
||||
return .file(id, settings.colors, settings.intensity ?? 0)
|
||||
case let .image(representations, _):
|
||||
if let largest = largestImageRepresentation(representations) {
|
||||
return .image(largest.resource.id.uniqueId)
|
||||
} else {
|
||||
return .image("")
|
||||
}
|
||||
case .builtin:
|
||||
return .builtin
|
||||
case let .color(color):
|
||||
return .color(color)
|
||||
case let .gradient(colors, _):
|
||||
return .gradient(colors)
|
||||
case let .file(id, _, _, _, _, _, _, _, settings):
|
||||
return .file(id, settings.colors, settings.intensity ?? 0)
|
||||
case let .image(representations, _):
|
||||
if let largest = largestImageRepresentation(representations) {
|
||||
return .image(largest.resource.id.uniqueId)
|
||||
} else {
|
||||
return .image("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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] = []
|
||||
for entry in entries {
|
||||
if case let .file(file) = entry.wallpaper {
|
||||
if state.selectedIndices.contains(file.id) {
|
||||
wallpapers.append(entry.wallpaper)
|
||||
}
|
||||
} else if case .image = entry.wallpaper {
|
||||
if state.selectedIndices.contains(0) {
|
||||
wallpapers.append(entry.wallpaper)
|
||||
}
|
||||
if state.selectedIds.contains(entry.stableId) {
|
||||
wallpapers.append(entry.wallpaper)
|
||||
}
|
||||
}
|
||||
return wallpapers
|
||||
}
|
||||
|
||||
final class ThemeGridControllerNode: ASDisplayNode {
|
||||
private struct Wallpaper: Equatable {
|
||||
var wallpaper: TelegramWallpaper
|
||||
var isLocal: Bool
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private var presentationData: PresentationData
|
||||
private var controllerInteraction: ThemeGridControllerInteraction?
|
||||
@ -176,7 +153,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
var requestDeactivateSearch: (() -> Void)?
|
||||
|
||||
let ready = ValuePromise<Bool>()
|
||||
let wallpapersPromise: Promise<[TelegramWallpaper]>
|
||||
private let wallpapersPromise: Promise<[Wallpaper]>
|
||||
|
||||
private var backgroundNode: ASDisplayNode
|
||||
private var separatorNode: ASDisplayNode
|
||||
@ -196,7 +173,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
|
||||
private var selectionPanel: ThemeGridSelectionPanelNode?
|
||||
private var selectionPanelSeparatorNode: ASDisplayNode?
|
||||
private var selectionPanelBackgroundNode: ASDisplayNode?
|
||||
private var selectionPanelBackgroundNode: NavigationBackgroundNode?
|
||||
|
||||
let gridNode: GridNode
|
||||
private let leftOverlayNode: ASDisplayNode
|
||||
@ -261,22 +238,12 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
self.resetDescriptionItemNode = ItemListTextItemNode()
|
||||
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)
|
||||
|
||||
let defaultWallpaper = presentationData.theme.chat.defaultWallpaper
|
||||
|
||||
let wallpapersPromise = Promise<[TelegramWallpaper]>()
|
||||
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
|
||||
})
|
||||
let wallpapersPromise = Promise<[Wallpaper]>()
|
||||
self.wallpapersPromise = wallpapersPromise
|
||||
|
||||
let deletedWallpaperSlugsValue = Atomic<Set<String>>(value: Set())
|
||||
@ -322,31 +289,47 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
}
|
||||
}, toggleWallpaperSelection: { [weak self] id, value in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateState { current in
|
||||
var updated = current.selectedIndices
|
||||
strongSelf.updateState { state in
|
||||
var state = state
|
||||
if value {
|
||||
updated.insert(id)
|
||||
state.selectedIds.insert(id)
|
||||
} else {
|
||||
updated.remove(id)
|
||||
state.selectedIds.remove(id)
|
||||
}
|
||||
return current.withUpdatedSelectedIndices(updated)
|
||||
return state
|
||||
}
|
||||
}
|
||||
}, deleteSelectedWallpapers: { [weak self] in
|
||||
let entries = previousEntries.with { $0 }
|
||||
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 {
|
||||
var updatedDeletedSlugs = deletedWallpaperSlugsValue.with { $0 }
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
let _ = deletedWallpaperSlugsValue.swap(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
|
||||
|
||||
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
|
||||
var entries: [ThemeGridControllerEntry] = []
|
||||
var index = 1
|
||||
@ -369,7 +352,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
} else if presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
||||
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?
|
||||
if !presentationData.chatWallpaper.isBasicallyEqual(to: presentationData.theme.chat.defaultWallpaper) {
|
||||
@ -397,17 +380,22 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
|
||||
var sortedWallpapers: [TelegramWallpaper] = []
|
||||
if presentationData.theme.overallDarkAppearance {
|
||||
var localWallpapers: [TelegramWallpaper] = []
|
||||
var darkWallpapers: [TelegramWallpaper] = []
|
||||
for wallpaper in wallpapers {
|
||||
if case let .file(file) = wallpaper, file.isDark {
|
||||
darkWallpapers.append(wallpaper)
|
||||
if wallpaper.isLocal {
|
||||
localWallpapers.append(wallpaper.wallpaper)
|
||||
} 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 {
|
||||
sortedWallpapers = wallpapers
|
||||
sortedWallpapers = wallpapers.map(\.wallpaper)
|
||||
}
|
||||
|
||||
for wallpaper in sortedWallpapers {
|
||||
@ -423,6 +411,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
if case .builtin = wallpaper {
|
||||
isEditable = false
|
||||
}
|
||||
if isDefault || presentationData.chatWallpaper.isBasicallyEqual(to: wallpaper) {
|
||||
isEditable = false
|
||||
}
|
||||
if !selected && !isDefault {
|
||||
let entry = ThemeGridControllerEntry(index: index, wallpaper: wallpaper, isEditable: isEditable, isSelected: false)
|
||||
if !entries.contains(where: { $0.stableId == entry.stableId }) {
|
||||
@ -440,6 +431,8 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
strongSelf.enqueueTransition(transition)
|
||||
}
|
||||
})
|
||||
|
||||
self.updateWallpapers()
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -522,7 +515,31 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -562,7 +579,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
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 {
|
||||
let requestLayout = interaction.selectionState.0 != self.currentState.editing
|
||||
self.controllerInteraction?.selectionState = selectionState
|
||||
@ -576,7 +593,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
if requestLayout, let (containerLayout, navigationBarHeight) = self.validLayout {
|
||||
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 {
|
||||
let panelHeight: CGFloat
|
||||
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)
|
||||
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 {
|
||||
@ -686,24 +703,21 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
||||
}
|
||||
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)))
|
||||
selectionPanelBackgroundNode.update(size: selectionPanelBackgroundNode.bounds.size, transition: transition)
|
||||
}
|
||||
} else {
|
||||
let selectionPanelBackgroundNode = ASDisplayNode()
|
||||
selectionPanelBackgroundNode.isLayerBacked = true
|
||||
selectionPanelBackgroundNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor
|
||||
let selectionPanelBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor)
|
||||
self.addSubnode(selectionPanelBackgroundNode)
|
||||
self.selectionPanelBackgroundNode = selectionPanelBackgroundNode
|
||||
|
||||
let selectionPanel = ThemeGridSelectionPanelNode(theme: self.presentationData.theme)
|
||||
selectionPanel.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor
|
||||
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)
|
||||
self.selectionPanel = selectionPanel
|
||||
self.addSubnode(selectionPanel)
|
||||
|
||||
let selectionPanelSeparatorNode = ASDisplayNode()
|
||||
selectionPanelSeparatorNode.isLayerBacked = true
|
||||
selectionPanelSeparatorNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelSeparatorColor
|
||||
self.addSubnode(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))
|
||||
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)))
|
||||
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)))
|
||||
}
|
||||
|
||||
@ -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
|
||||
selectionPanelSeparatorNode?.removeFromSupernode()
|
||||
})
|
||||
selectionPanelBackgroundNode.update(size: selectionPanelBackgroundNode.bounds.size, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@ final class ThemeGridSelectionPanelNode: ASDisplayNode {
|
||||
|
||||
private var theme: PresentationTheme
|
||||
|
||||
var selectedIndices = Set<Int64>() {
|
||||
var selectedIds = Set<ThemeGridControllerEntry.StableId>() {
|
||||
didSet {
|
||||
if oldValue != self.selectedIndices {
|
||||
self.deleteButton.isEnabled = !self.selectedIndices.isEmpty
|
||||
self.shareButton.isEnabled = !self.selectedIndices.isEmpty
|
||||
if oldValue != self.selectedIds {
|
||||
self.deleteButton.isEnabled = !self.selectedIds.isEmpty
|
||||
self.shareButton.isEnabled = !self.selectedIds.isEmpty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -475,6 +475,18 @@ public class WallpaperGalleryController: ViewController {
|
||||
break
|
||||
}
|
||||
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
|
||||
@ -808,9 +820,24 @@ public class WallpaperGalleryController: ViewController {
|
||||
let patternPanelNode = WallpaperPatternPanelNode(context: self.context, theme: presentationData.theme, strings: presentationData.strings)
|
||||
patternPanelNode.patternChanged = { [weak self] pattern, intensity, preview in
|
||||
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 {
|
||||
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:
|
||||
break
|
||||
}
|
||||
@ -841,8 +868,8 @@ public class WallpaperGalleryController: ViewController {
|
||||
|
||||
var wallpaper: TelegramWallpaper = .gradient(colors, WallpaperSettings(blur: false, motion: false, colors: [], intensity: nil, rotation: nil))
|
||||
|
||||
if case .file = currentWallpaper {
|
||||
wallpaper = currentWallpaper.withUpdatedSettings(WallpaperSettings(blur: false, motion: false, colors: colors, intensity: nil, rotation: nil))
|
||||
if case let .file(file) = currentWallpaper {
|
||||
wallpaper = currentWallpaper.withUpdatedSettings(WallpaperSettings(blur: false, motion: false, colors: colors, intensity: file.settings.intensity, rotation: file.settings.rotation))
|
||||
}
|
||||
|
||||
strongSelf.updateEntries(wallpaper: wallpaper)
|
||||
|
@ -336,7 +336,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
case let .color(color):
|
||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||
contentSize = displaySize
|
||||
signal = solidColorImage(UIColor(rgb: color))
|
||||
signal = .single({ _ in nil })
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
subtitleSignal = .single(nil)
|
||||
@ -346,11 +346,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
case let .gradient(colors, settings):
|
||||
displaySize = CGSize(width: 1.0, height: 1.0)
|
||||
contentSize = displaySize
|
||||
if colors.count >= 2 {
|
||||
signal = gradientImage([UIColor(rgb: colors[0]), UIColor(rgb: colors[1])], rotation: settings.rotation)
|
||||
} else {
|
||||
signal = solidColorImage(UIColor(rgb: colors[0]))
|
||||
}
|
||||
signal = .single({ _ in nil })
|
||||
fetchSignal = .complete()
|
||||
statusSignal = .single(.Local)
|
||||
subtitleSignal = .single(nil)
|
||||
@ -389,7 +385,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
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()
|
||||
Queue.concurrentDefaultQueue().async {
|
||||
@ -405,15 +401,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
return
|
||||
} else {
|
||||
patternArguments = PatternWallpaperArguments(colors: patternColors, rotation: file.settings.rotation)
|
||||
}
|
||||
}*/
|
||||
|
||||
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 })
|
||||
} else {
|
||||
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)
|
||||
|
||||
isBlurrable = false
|
||||
|
@ -263,8 +263,8 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
sliderView.lineSize = 2.0
|
||||
sliderView.minimumValue = 0.0
|
||||
sliderView.startValue = 0.0
|
||||
sliderView.maximumValue = 100.0
|
||||
sliderView.value = 40.0
|
||||
sliderView.maximumValue = 200.0
|
||||
sliderView.value = 150.0
|
||||
sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
||||
sliderView.backgroundColor = .clear
|
||||
sliderView.backColor = self.theme.list.disclosureArrowColor
|
||||
@ -312,7 +312,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
if let strongSelf = self {
|
||||
strongSelf.currentWallpaper = updatedWallpaper
|
||||
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 {
|
||||
for case let subnode as SettingsThemeWallpaperNode in subnodes {
|
||||
@ -354,7 +354,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
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.sliderView?.value = CGFloat(intensity ?? 50)
|
||||
self.sliderView?.value = CGFloat(intensity.flatMap { $0 + 100 } ?? 150)
|
||||
|
||||
self.scrollNode.view.contentOffset = CGPoint()
|
||||
|
||||
@ -385,7 +385,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -349,6 +349,7 @@ private enum SharedDataKeyValues: Int32 {
|
||||
case autodownloadSettings = 5
|
||||
case themeSettings = 6
|
||||
case countriesList = 7
|
||||
case wallapersState = 8
|
||||
}
|
||||
|
||||
public struct SharedDataKeys {
|
||||
@ -393,6 +394,12 @@ public struct SharedDataKeys {
|
||||
key.setInt32(0, value: SharedDataKeyValues.countriesList.rawValue)
|
||||
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 {
|
||||
|
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(ExportedInvitation.self, f: { ExportedInvitation(decoder: $0) })
|
||||
declareEncodable(CachedDisplayAsPeers.self, f: { CachedDisplayAsPeers(decoder: $0) })
|
||||
declareEncodable(WallpapersState.self, f: { WallpapersState(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
|
@ -246,7 +246,7 @@ public final class PrincipalThemeEssentialGraphics {
|
||||
|
||||
let emptyImage = UIImage()
|
||||
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.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)
|
||||
@ -263,30 +263,33 @@ public final class PrincipalThemeEssentialGraphics {
|
||||
self.checkBubbleFullImage = generateCheckImage(partial: false, color: theme.message.outgoingCheckColor, width: 11.0)!
|
||||
self.checkBubblePartialImage = generateCheckImage(partial: true, color: theme.message.outgoingCheckColor, width: 11.0)!
|
||||
self.chatMessageBackgroundIncomingHighlightedImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopMaskImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: false), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: false), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopHighlightedImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopSideMaskImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopSideImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopSideShadowImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true)
|
||||
self.chatMessageBackgroundIncomingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true)
|
||||
self.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.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.chatMessageBackgroundIncomingMergedBottomHighlightedImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedBothMaskImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedBothImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedBothOutlineImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedBothShadowImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedBothMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .both, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
||||
|
||||
self.chatMessageBackgroundIncomingMergedBothImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true)
|
||||
self.chatMessageBackgroundIncomingMergedBothOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyOutline: true)
|
||||
self.chatMessageBackgroundIncomingMergedBothShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .both, theme: theme, wallpaper: wallpaper, knockout: incomingKnockout, extendedEdges: true, onlyShadow: true)
|
||||
self.chatMessageBackgroundIncomingMergedBothHighlightedImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedSideMaskImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedSideImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedSideOutlineImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedSideShadowImage = emptyImage
|
||||
self.chatMessageBackgroundIncomingMergedSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: .black, strokeColor: .clear, neighbors: .side, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
||||
self.chatMessageBackgroundIncomingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: true, fillColor: incoming.fill, strokeColor: incoming.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true)
|
||||
|
||||
self.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.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)
|
||||
@ -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.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.chatMessageBackgroundOutgoingMergedTopSideMaskImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .top(side: true), theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true)
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true)
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .top(side: true), theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true)
|
||||
self.chatMessageBackgroundOutgoingMergedTopSideHighlightedImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedBottomMaskImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: .black, strokeColor: .clear, neighbors: .bottom, theme: theme, wallpaper: .color(0xffffff), knockout: true, mask: true, extendedEdges: true)
|
||||
self.chatMessageBackgroundOutgoingMergedBottomImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .bottom, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true)
|
||||
@ -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.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.chatMessageBackgroundOutgoingMergedSideMaskImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedSideImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedSideOutlineImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedSideShadowImage = emptyImage
|
||||
self.chatMessageBackgroundOutgoingMergedSideImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true)
|
||||
self.chatMessageBackgroundOutgoingMergedSideOutlineImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyOutline: true)
|
||||
self.chatMessageBackgroundOutgoingMergedSideShadowImage = messageBubbleImage(maxCornerRadius: maxCornerRadius, minCornerRadius: minCornerRadius, incoming: false, fillColor: outgoing.fill, strokeColor: outgoing.stroke, neighbors: .side, theme: theme, wallpaper: wallpaper, knockout: outgoingKnockout, extendedEdges: true, onlyShadow: true)
|
||||
self.chatMessageBackgroundOutgoingMergedSideHighlightedImage = emptyImage
|
||||
self.checkMediaFullImage = emptyImage
|
||||
self.checkMediaPartialImage = emptyImage
|
||||
|
@ -64,8 +64,9 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode {
|
||||
private weak var backgroundNode: WallpaperBackgroundNode?
|
||||
|
||||
private var maskView: UIImageView?
|
||||
|
||||
private var fixedMaskMode: Bool?
|
||||
|
||||
private var absolutePosition: (CGRect, CGSize)?
|
||||
|
||||
var hasImage: Bool {
|
||||
return self.backgroundContent != nil
|
||||
@ -145,12 +146,18 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode {
|
||||
case .incoming:
|
||||
if let backgroundContent = backgroundNode?.makeBubbleBackground(for: .incoming) {
|
||||
backgroundContent.frame = self.bounds
|
||||
if let (rect, containerSize) = self.absolutePosition {
|
||||
backgroundContent.update(rect: rect, within: containerSize)
|
||||
}
|
||||
self.backgroundContent = backgroundContent
|
||||
self.insertSubnode(backgroundContent, at: 0)
|
||||
}
|
||||
case .outgoing:
|
||||
if let backgroundContent = backgroundNode?.makeBubbleBackground(for: .outgoing) {
|
||||
backgroundContent.frame = self.bounds
|
||||
if let (rect, containerSize) = self.absolutePosition {
|
||||
backgroundContent.update(rect: rect, within: containerSize)
|
||||
}
|
||||
self.backgroundContent = backgroundContent
|
||||
self.insertSubnode(backgroundContent, at: 0)
|
||||
}
|
||||
@ -164,18 +171,15 @@ final class ChatMessageBubbleBackdrop: ASDisplayNode {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,8 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
private weak var backgroundNode: WallpaperBackgroundNode?
|
||||
private var index: SparseBag<BubbleBackgroundNode>.Index?
|
||||
|
||||
private var currentLayout: (rect: CGRect, containerSize: CGSize)?
|
||||
|
||||
init(backgroundNode: WallpaperBackgroundNode, bubbleType: BubbleType) {
|
||||
self.backgroundNode = backgroundNode
|
||||
self.bubbleType = bubbleType
|
||||
@ -135,9 +137,15 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
cleanWallpaperNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
|
||||
if let (rect, containerSize) = self.currentLayout {
|
||||
self.update(rect: rect, within: containerSize)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
if let cleanWallpaperNode = self.cleanWallpaperNode {
|
||||
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 var gradientBackgroundNode: GradientBackgroundNode?
|
||||
private let patternImageNode: TransformImageNode
|
||||
private var invertPattern: Bool = false
|
||||
|
||||
private var validLayout: CGSize?
|
||||
private var wallpaper: TelegramWallpaper?
|
||||
@ -255,7 +264,6 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
self.contentNode.contentMode = self.imageContentMode
|
||||
|
||||
self.patternImageNode = TransformImageNode()
|
||||
self.patternImageNode.layer.compositingFilter = "softLightBlendMode"
|
||||
|
||||
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)
|
||||
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.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:
|
||||
self.patternImageNode.isHidden = true
|
||||
self.backgroundColor = nil
|
||||
self.gradientBackgroundNode?.contentView.alpha = 1.0
|
||||
self.contentNode.alpha = 1.0
|
||||
}
|
||||
|
||||
self.updateBubbles()
|
||||
@ -395,7 +424,16 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
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()
|
||||
transition.updateFrame(node: self.patternImageNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
|
@ -314,6 +314,9 @@ public struct PatternWallpaperArguments: TransformImageCustomArguments {
|
||||
let array = NSMutableArray()
|
||||
array.addObjects(from: self.colors)
|
||||
array.add(NSNumber(value: self.rotation ?? 0))
|
||||
if let customPatternColor = customPatternColor {
|
||||
array.add(NSNumber(value: customPatternColor.argb))
|
||||
}
|
||||
array.add(NSNumber(value: self.preview))
|
||||
return array
|
||||
}
|
||||
@ -500,7 +503,11 @@ public func patternWallpaperImageInternal(thumbnailData: Data?, fullSizeData: Da
|
||||
c.interpolationQuality = customArguments.preview ? .low : .medium
|
||||
c.clip(to: fittedRect, mask: image)
|
||||
|
||||
c.setBlendMode(.normal)
|
||||
if let customPatternColor = customArguments.customPatternColor, customPatternColor.alpha < 1.0 {
|
||||
c.setBlendMode(.copy)
|
||||
} else {
|
||||
c.setBlendMode(.normal)
|
||||
}
|
||||
|
||||
if colors.count >= 3 && customArguments.customPatternColor == nil {
|
||||
c.setBlendMode(.softLight)
|
||||
|
Loading…
x
Reference in New Issue
Block a user