mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-29 03:21:29 +00:00
Wallpaper fixes
This commit is contained in:
parent
da044344ab
commit
4e46f2f90e
@ -134,7 +134,7 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode {
|
|||||||
value = CGFloat(index)
|
value = CGFloat(index)
|
||||||
sliderView.value = value
|
sliderView.value = value
|
||||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||||
sliderView.backColor = item.theme.list.itemSecondaryTextColor
|
sliderView.backColor = item.theme.list.disclosureArrowColor
|
||||||
sliderView.trackColor = item.theme.list.itemAccentColor
|
sliderView.trackColor = item.theme.list.itemAccentColor
|
||||||
sliderView.knobImage = generateKnobImage()
|
sliderView.knobImage = generateKnobImage()
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode {
|
|||||||
if let sliderView = strongSelf.sliderView {
|
if let sliderView = strongSelf.sliderView {
|
||||||
if themeUpdated {
|
if themeUpdated {
|
||||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||||
sliderView.backColor = item.theme.list.itemSecondaryTextColor
|
sliderView.backColor = item.theme.list.disclosureArrowColor
|
||||||
sliderView.trackColor = item.theme.list.itemAccentColor
|
sliderView.trackColor = item.theme.list.itemAccentColor
|
||||||
sliderView.knobImage = generateKnobImage()
|
sliderView.knobImage = generateKnobImage()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,11 +51,13 @@ func imageHasTransparency(_ cgImage: CGImage) -> Bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if let (histogramBins, alphaBinIndex) = generateHistogram(cgImage: cgImage) {
|
if let (histogramBins, alphaBinIndex) = generateHistogram(cgImage: cgImage) {
|
||||||
|
let opaqueCount: vImagePixelCount = histogramBins[alphaBinIndex][255]
|
||||||
|
var transparentCount: vImagePixelCount = 0
|
||||||
for i in 0 ..< 255 {
|
for i in 0 ..< 255 {
|
||||||
if histogramBins[alphaBinIndex][i] > 0 {
|
transparentCount += histogramBins[alphaBinIndex][i]
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
let totalCount = opaqueCount + transparentCount
|
||||||
|
return Double(transparentCount) / Double(totalCount) > 0.02
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -369,7 +369,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for wallpaper in sortedWallpapers {
|
for wallpaper in sortedWallpapers {
|
||||||
if case let .file(file) = wallpaper, deletedWallpaperSlugs.contains(file.slug) {
|
if case let .file(file) = wallpaper, deletedWallpaperSlugs.contains(file.slug) || file.isPattern {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
let selected = areWallpapersEqual(presentationData.chatWallpaper, wallpaper)
|
let selected = areWallpapersEqual(presentationData.chatWallpaper, wallpaper)
|
||||||
|
|||||||
@ -80,7 +80,7 @@ final class ThemeGridSearchItemNode: GridItemNode {
|
|||||||
if let largestRepresentation = largestImageRepresentation(image.representations) {
|
if let largestRepresentation = largestImageRepresentation(image.representations) {
|
||||||
imageDimensions = largestRepresentation.dimensions
|
imageDimensions = largestRepresentation.dimensions
|
||||||
}
|
}
|
||||||
imageResource = imageRepresentationLargerThan(image.representations, size: CGSize(width: 200.0, height: 100.0))?.resource
|
imageResource = imageRepresentationLargerThan(image.representations, size: CGSize(width: 600.0, height: 600.0))?.resource
|
||||||
if let file = file {
|
if let file = file {
|
||||||
if let thumbnailRepresentation = smallestImageRepresentation(file.previewRepresentations) {
|
if let thumbnailRepresentation = smallestImageRepresentation(file.previewRepresentations) {
|
||||||
thumbnailDimensions = thumbnailRepresentation.dimensions
|
thumbnailDimensions = thumbnailRepresentation.dimensions
|
||||||
|
|||||||
@ -112,7 +112,7 @@ class ThemeSettingsBrightnessItemNode: ListViewItemNode {
|
|||||||
if let item = self.item, let params = self.layoutParams {
|
if let item = self.item, let params = self.layoutParams {
|
||||||
sliderView.value = CGFloat(item.value)
|
sliderView.value = CGFloat(item.value)
|
||||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||||
sliderView.backColor = item.theme.list.itemSecondaryTextColor
|
sliderView.backColor = item.theme.list.disclosureArrowColor
|
||||||
sliderView.trackColor = item.theme.list.itemAccentColor
|
sliderView.trackColor = item.theme.list.itemAccentColor
|
||||||
sliderView.knobImage = generateKnobImage()
|
sliderView.knobImage = generateKnobImage()
|
||||||
|
|
||||||
|
|||||||
@ -132,7 +132,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode {
|
|||||||
}
|
}
|
||||||
sliderView.value = value
|
sliderView.value = value
|
||||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||||
sliderView.backColor = item.theme.list.itemSecondaryTextColor
|
sliderView.backColor = item.theme.list.disclosureArrowColor
|
||||||
sliderView.trackColor = item.theme.list.itemAccentColor
|
sliderView.trackColor = item.theme.list.itemAccentColor
|
||||||
sliderView.knobImage = generateKnobImage()
|
sliderView.knobImage = generateKnobImage()
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode {
|
|||||||
if let sliderView = strongSelf.sliderView {
|
if let sliderView = strongSelf.sliderView {
|
||||||
if themeUpdated {
|
if themeUpdated {
|
||||||
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
sliderView.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||||
sliderView.backColor = item.theme.list.itemSecondaryTextColor
|
sliderView.backColor = item.theme.list.disclosureArrowColor
|
||||||
sliderView.trackColor = item.theme.list.itemAccentColor
|
sliderView.trackColor = item.theme.list.itemAccentColor
|
||||||
sliderView.knobImage = generateKnobImage()
|
sliderView.knobImage = generateKnobImage()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -382,7 +382,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
private let brightnessNode: WallpaperColorBrightnessNode
|
private let brightnessNode: WallpaperColorBrightnessNode
|
||||||
private let brightnessKnobNode: ASImageNode
|
private let brightnessKnobNode: ASImageNode
|
||||||
|
|
||||||
private let backgroundNode: WallpaperIntensityPickerNode
|
|
||||||
private let intensityNode: WallpaperIntensityPickerNode
|
private let intensityNode: WallpaperIntensityPickerNode
|
||||||
|
|
||||||
private let colorNode: WallpaperColorHueSaturationNode
|
private let colorNode: WallpaperColorHueSaturationNode
|
||||||
@ -409,7 +408,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
|
|
||||||
if newHSV != self.colorHSV {
|
if newHSV != self.colorHSV {
|
||||||
self.colorHSV = newHSV
|
self.colorHSV = newHSV
|
||||||
self.backgroundNode.value = 1.0 - self.colorHSV.2
|
|
||||||
self.update()
|
self.update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,7 +431,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
let value = self.adjustingPattern
|
let value = self.adjustingPattern
|
||||||
self.brightnessNode.isHidden = value
|
self.brightnessNode.isHidden = value
|
||||||
self.brightnessKnobNode.isHidden = value
|
self.brightnessKnobNode.isHidden = value
|
||||||
self.backgroundNode.isHidden = !value
|
|
||||||
self.intensityNode.isHidden = !value
|
self.intensityNode.isHidden = !value
|
||||||
self.setNeedsLayout()
|
self.setNeedsLayout()
|
||||||
}
|
}
|
||||||
@ -448,8 +445,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
self.colorNode.hitTestSlop = UIEdgeInsetsMake(-16.0, -16.0, -16.0, -16.0)
|
self.colorNode.hitTestSlop = UIEdgeInsetsMake(-16.0, -16.0, -16.0, -16.0)
|
||||||
self.colorKnobNode = WallpaperColorKnobNode()
|
self.colorKnobNode = WallpaperColorKnobNode()
|
||||||
|
|
||||||
self.backgroundNode = WallpaperIntensityPickerNode(theme: nil, title: strings.WallpaperPreview_PatternColor, bordered: true)
|
|
||||||
self.backgroundNode.isHidden = true
|
|
||||||
|
|
||||||
self.intensityNode = WallpaperIntensityPickerNode(theme: nil, title: strings.WallpaperPreview_PatternIntensity, bordered: true)
|
self.intensityNode = WallpaperIntensityPickerNode(theme: nil, title: strings.WallpaperPreview_PatternIntensity, bordered: true)
|
||||||
self.intensityNode.isHidden = true
|
self.intensityNode.isHidden = true
|
||||||
@ -462,7 +457,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
self.addSubnode(self.brightnessKnobNode)
|
self.addSubnode(self.brightnessKnobNode)
|
||||||
self.addSubnode(self.colorNode)
|
self.addSubnode(self.colorNode)
|
||||||
self.addSubnode(self.colorKnobNode)
|
self.addSubnode(self.colorKnobNode)
|
||||||
self.addSubnode(self.backgroundNode)
|
|
||||||
self.addSubnode(self.intensityNode)
|
self.addSubnode(self.intensityNode)
|
||||||
|
|
||||||
let valueChanged: (CGFloat, Bool) -> Void = { [weak self] value, ended in
|
let valueChanged: (CGFloat, Bool) -> Void = { [weak self] value, ended in
|
||||||
@ -480,14 +474,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.backgroundNode.valueChanged = { value in
|
|
||||||
valueChanged(value, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.backgroundNode.valueChangeEnded = { value in
|
|
||||||
valueChanged(value, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.intensityNode.valueChanged = { [weak self] value in
|
self.intensityNode.valueChanged = { [weak self] value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -530,7 +516,6 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
let min = self.colorHSV
|
let min = self.colorHSV
|
||||||
let max = patternColor(for: self.color, intensity: 1.0).hsv
|
let max = patternColor(for: self.color, intensity: 1.0).hsv
|
||||||
self.intensityNode.updateExtrema(min: min, max: max)
|
self.intensityNode.updateExtrema(min: min, max: max)
|
||||||
self.backgroundNode.updateExtrema(min: self.colorHSV, max: (self.colorHSV.0, self.colorHSV.1, 0.0))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateKnobLayout(size: CGSize, panningColor: Bool, transition: ContainedViewLayoutTransition) {
|
func updateKnobLayout(size: CGSize, panningColor: Bool, transition: ContainedViewLayoutTransition) {
|
||||||
@ -563,10 +548,9 @@ final class WallpaperColorPickerNode: ASDisplayNode {
|
|||||||
transition.updateFrame(node: self.brightnessNode, frame: CGRect(x: inset, y: size.height - 55.0, width: size.width - inset * 2.0, height: 29.0))
|
transition.updateFrame(node: self.brightnessNode, frame: CGRect(x: inset, y: size.height - 55.0, width: size.width - inset * 2.0, height: 29.0))
|
||||||
|
|
||||||
let slidersInset: CGFloat = 24.0
|
let slidersInset: CGFloat = 24.0
|
||||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(x: slidersInset, y: size.height - 103.0, width: size.width - slidersInset * 2.0, height: 50.0))
|
|
||||||
transition.updateFrame(node: self.intensityNode, frame: CGRect(x: slidersInset, y: size.height - 54.0, width: size.width - slidersInset * 2.0, height: 50.0))
|
transition.updateFrame(node: self.intensityNode, frame: CGRect(x: slidersInset, y: size.height - 54.0, width: size.width - slidersInset * 2.0, height: 50.0))
|
||||||
|
|
||||||
self.updateKnobLayout(size: size, panningColor: false, transition: transition)
|
self.updateKnobLayout(size: size, panningColor: false, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func colorTap(_ recognizer: UITapGestureRecognizer) {
|
@objc private func colorTap(_ recognizer: UITapGestureRecognizer) {
|
||||||
|
|||||||
@ -94,6 +94,12 @@ private func updatedFileWallpaper(id: Int64? = nil, accessHash: Int64? = nil, sl
|
|||||||
return .file(id: id ?? 0, accessHash: accessHash ?? 0, isCreator: false, isDefault: false, isPattern: isPattern, slug: slug, file: file, settings: WallpaperSettings(blur: false, motion: false, color: colorValue, intensity: intensityValue))
|
return .file(id: id ?? 0, accessHash: accessHash ?? 0, isCreator: false, isDefault: false, isPattern: isPattern, slug: slug, file: file, settings: WallpaperSettings(blur: false, motion: false, color: colorValue, intensity: intensityValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct WallpaperPatternTransition: Equatable {
|
||||||
|
let pattern: TelegramWallpaper
|
||||||
|
let intensity: Int32?
|
||||||
|
let preview: Bool
|
||||||
|
}
|
||||||
|
|
||||||
class WallpaperGalleryController: ViewController {
|
class WallpaperGalleryController: ViewController {
|
||||||
private var galleryNode: GalleryControllerNode {
|
private var galleryNode: GalleryControllerNode {
|
||||||
return self.displayNode as! GalleryControllerNode
|
return self.displayNode as! GalleryControllerNode
|
||||||
@ -118,6 +124,8 @@ class WallpaperGalleryController: ViewController {
|
|||||||
private var entries: [WallpaperGalleryEntry] = []
|
private var entries: [WallpaperGalleryEntry] = []
|
||||||
private var centralEntryIndex: Int?
|
private var centralEntryIndex: Int?
|
||||||
|
|
||||||
|
private let patternTransition = Promise<WallpaperPatternTransition?>()
|
||||||
|
|
||||||
private let centralItemSubtitle = Promise<String?>()
|
private let centralItemSubtitle = Promise<String?>()
|
||||||
private let centralItemStatus = Promise<MediaResourceStatus>()
|
private let centralItemStatus = Promise<MediaResourceStatus>()
|
||||||
private let centralItemAction = Promise<UIBarButtonItem?>()
|
private let centralItemAction = Promise<UIBarButtonItem?>()
|
||||||
@ -223,6 +231,12 @@ class WallpaperGalleryController: ViewController {
|
|||||||
strongSelf.navigationItem.rightBarButtonItem = barButton
|
strongSelf.navigationItem.rightBarButtonItem = barButton
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
self.centralItemAttributesDisposable.add(self.patternTransition.get().start(next: { [weak self] transition in
|
||||||
|
if let strongSelf = self, let transition = transition {
|
||||||
|
strongSelf.updateEntries(pattern: transition.pattern, intensity: transition.intensity, preview: transition.preview)
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
required init(coder aDecoder: NSCoder) {
|
required init(coder aDecoder: NSCoder) {
|
||||||
@ -437,21 +451,6 @@ class WallpaperGalleryController: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let entry = node.entry, case let .wallpaper(wallpaper) = entry {
|
|
||||||
var entryColor: UIColor = .white
|
|
||||||
switch wallpaper {
|
|
||||||
case let .color(color):
|
|
||||||
entryColor = UIColor(rgb: UInt32(bitPattern: color))
|
|
||||||
case let .file(file):
|
|
||||||
if let color = file.settings.color {
|
|
||||||
entryColor = UIColor(rgb: UInt32(bitPattern: color))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
self.patternPanelNode?.color = entryColor
|
|
||||||
}
|
|
||||||
|
|
||||||
if let (layout, bottomInset) = self.validLayout {
|
if let (layout, bottomInset) = self.validLayout {
|
||||||
self.updateMessagesLayout(layout: layout, bottomInset: bottomInset, transition: .immediate)
|
self.updateMessagesLayout(layout: layout, bottomInset: bottomInset, transition: .immediate)
|
||||||
}
|
}
|
||||||
@ -643,10 +642,13 @@ class WallpaperGalleryController: ViewController {
|
|||||||
if let patternPanelNode = self.patternPanelNode {
|
if let patternPanelNode = self.patternPanelNode {
|
||||||
currentPatternPanelNode = patternPanelNode
|
currentPatternPanelNode = patternPanelNode
|
||||||
} else {
|
} else {
|
||||||
|
let intensityValue = ThrottledValue<WallpaperPatternTransition?>(value: nil, interval: 0.01)
|
||||||
|
self.patternTransition.set(intensityValue.get())
|
||||||
|
|
||||||
let patternPanelNode = WallpaperPatternPanelNode(account: self.account, theme: presentationData.theme, strings: presentationData.strings)
|
let patternPanelNode = WallpaperPatternPanelNode(account: self.account, 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 {
|
if let strongSelf = self, strongSelf.validLayout != nil {
|
||||||
strongSelf.updateEntries(pattern: pattern, intensity: intensity, preview: preview)
|
intensityValue.set(value: WallpaperPatternTransition(pattern: pattern, intensity: intensity, preview: preview))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.patternPanelNode = patternPanelNode
|
self.patternPanelNode = patternPanelNode
|
||||||
|
|||||||
@ -15,6 +15,8 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
|||||||
private let colorNode: ASImageNode
|
private let colorNode: ASImageNode
|
||||||
private let textNode: ASTextNode
|
private let textNode: ASTextNode
|
||||||
|
|
||||||
|
private var textSize: CGSize?
|
||||||
|
|
||||||
private var _value: WallpaperOptionButtonValue
|
private var _value: WallpaperOptionButtonValue
|
||||||
override var isSelected: Bool {
|
override var isSelected: Bool {
|
||||||
get {
|
get {
|
||||||
@ -140,21 +142,32 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
|||||||
self.isUserInteractionEnabled = enabled
|
self.isUserInteractionEnabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
// override func measure(_ constrainedSize: CGSize) -> CGSize {
|
override func measure(_ constrainedSize: CGSize) -> CGSize {
|
||||||
// let size = self.textNode.measure(constrainedSize)
|
let size = self.textNode.measure(constrainedSize)
|
||||||
// return CGSize(width: size.width + 56.0, height: 30.0)
|
self.textSize = size
|
||||||
// }
|
return CGSize(width: ceil(size.width) + 52.0, height: 30.0)
|
||||||
|
}
|
||||||
|
|
||||||
override func layout() {
|
override func layout() {
|
||||||
super.layout()
|
super.layout()
|
||||||
|
|
||||||
self.backgroundNode.frame = self.bounds
|
self.backgroundNode.frame = self.bounds
|
||||||
|
|
||||||
let checkSize = CGSize(width: 18.0, height: 18.0)
|
guard let textSize = self.textSize else {
|
||||||
self.checkNode.frame = CGRect(origin: CGPoint(x: 12.0, y: 6.0), size: checkSize)
|
return
|
||||||
self.colorNode.frame = CGRect(origin: CGPoint(x: 12.0, y: 6.0), size: checkSize)
|
}
|
||||||
|
|
||||||
self.textNode.frame = CGRect(x: 39.0, y: 6.0 + UIScreenPixel, width: 100.0, height: 20.0)
|
let checkSize = CGSize(width: 18.0, height: 18.0)
|
||||||
|
let spacing: CGFloat = 9.0
|
||||||
|
let totalWidth = checkSize.width + spacing + textSize.width
|
||||||
|
let origin = floor((self.bounds.width - totalWidth) / 2.0)
|
||||||
|
|
||||||
|
self.checkNode.frame = CGRect(origin: CGPoint(x: origin, y: 6.0), size: checkSize)
|
||||||
|
self.colorNode.frame = CGRect(origin: CGPoint(x: origin, y: 6.0), size: checkSize)
|
||||||
|
|
||||||
|
if let textSize = self.textSize {
|
||||||
|
self.textNode.frame = CGRect(x: origin + checkSize.width + spacing, y: 6.0 + UIScreenPixel, width: textSize.width, height: textSize.height)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -639,7 +639,13 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateButtonsLayout(layout: ContainerViewLayout, offset: CGPoint, transition: ContainedViewLayoutTransition) {
|
func updateButtonsLayout(layout: ContainerViewLayout, offset: CGPoint, transition: ContainedViewLayoutTransition) {
|
||||||
let buttonSize = CGSize(width: 100.0, height: 30.0)
|
let patternButtonSize = self.patternButtonNode.measure(layout.size)
|
||||||
|
let colorButtonSize = self.colorButtonNode.measure(layout.size)
|
||||||
|
let blurButtonSize = self.blurButtonNode.measure(layout.size)
|
||||||
|
let motionButtonSize = self.motionButtonNode.measure(layout.size)
|
||||||
|
|
||||||
|
let maxButtonWidth = max(patternButtonSize.width, max(colorButtonSize.width, max(blurButtonSize.width, motionButtonSize.width)))
|
||||||
|
let buttonSize = CGSize(width: maxButtonWidth, height: 30.0)
|
||||||
let alpha = 1.0 - min(1.0, max(0.0, abs(offset.y) / 50.0))
|
let alpha = 1.0 - min(1.0, max(0.0, abs(offset.y) / 50.0))
|
||||||
|
|
||||||
var additionalYOffset: CGFloat = 0.0
|
var additionalYOffset: CGFloat = 0.0
|
||||||
@ -695,19 +701,18 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
|||||||
motionFrame = rightButtonFrame
|
motionFrame = rightButtonFrame
|
||||||
case let .file(file):
|
case let .file(file):
|
||||||
if file.isPattern {
|
if file.isPattern {
|
||||||
|
motionAlpha = 1.0
|
||||||
if self.arguments.isColorsList {
|
if self.arguments.isColorsList {
|
||||||
patternAlpha = 1.0
|
patternAlpha = 1.0
|
||||||
if self.patternButtonNode.isSelected {
|
if self.patternButtonNode.isSelected {
|
||||||
patternFrame = leftButtonFrame
|
patternFrame = leftButtonFrame
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
colorAlpha = 1.0
|
|
||||||
colorFrame = leftButtonFrame
|
|
||||||
}
|
|
||||||
if !self.arguments.isColorsList || self.patternButtonNode.isSelected {
|
|
||||||
motionAlpha = 1.0
|
|
||||||
motionFrame = rightButtonFrame
|
motionFrame = rightButtonFrame
|
||||||
}
|
}
|
||||||
|
// if !self.arguments.isColorsList || self.patternButtonNode.isSelected {
|
||||||
|
// motionAlpha = 1.0
|
||||||
|
// motionFrame = rightButtonFrame
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
blurAlpha = 1.0
|
blurAlpha = 1.0
|
||||||
blurFrame = leftButtonFrame
|
blurFrame = leftButtonFrame
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import SwiftSignalKit
|
|||||||
import Display
|
import Display
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
|
|
||||||
|
import LegacyComponents
|
||||||
|
|
||||||
private let itemSize = CGSize(width: 88.0, height: 88.0)
|
private let itemSize = CGSize(width: 88.0, height: 88.0)
|
||||||
private let inset: CGFloat = 12.0
|
private let inset: CGFloat = 12.0
|
||||||
|
|
||||||
@ -14,20 +16,14 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
private let topSeparatorNode: ASDisplayNode
|
private let topSeparatorNode: ASDisplayNode
|
||||||
|
|
||||||
private let scrollNode: ASScrollNode
|
private let scrollNode: ASScrollNode
|
||||||
private let intensityNode: WallpaperIntensityPickerNode
|
|
||||||
|
private let labelNode: ASTextNode
|
||||||
|
private var sliderView: TGPhotoEditorSliderView?
|
||||||
|
|
||||||
private var disposable: Disposable?
|
private var disposable: Disposable?
|
||||||
private var wallpapers: [TelegramWallpaper] = []
|
private var wallpapers: [TelegramWallpaper] = []
|
||||||
private var currentWallpaper: TelegramWallpaper?
|
private var currentWallpaper: TelegramWallpaper?
|
||||||
|
|
||||||
var color: UIColor = .white {
|
|
||||||
didSet {
|
|
||||||
let min = self.color.hsv
|
|
||||||
let max = patternColor(for: self.color, intensity: 1.0).hsv
|
|
||||||
self.intensityNode.updateExtrema(min: min, max: max)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var patternChanged: ((TelegramWallpaper, Int32?, Bool) -> Void)?
|
var patternChanged: ((TelegramWallpaper, Int32?, Bool) -> Void)?
|
||||||
|
|
||||||
init(account: Account, theme: PresentationTheme, strings: PresentationStrings) {
|
init(account: Account, theme: PresentationTheme, strings: PresentationStrings) {
|
||||||
@ -41,15 +37,16 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
|
|
||||||
self.scrollNode = ASScrollNode()
|
self.scrollNode = ASScrollNode()
|
||||||
|
|
||||||
self.intensityNode = WallpaperIntensityPickerNode(theme: theme, title: strings.WallpaperPreview_PatternIntensity, bordered: false)
|
self.labelNode = ASTextNode()
|
||||||
self.intensityNode.value = 0.4
|
self.labelNode.attributedText = NSAttributedString(string: strings.WallpaperPreview_PatternIntensity, font: Font.regular(14.0), textColor: theme.rootController.navigationBar.primaryTextColor)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.backgroundNode)
|
self.addSubnode(self.backgroundNode)
|
||||||
self.addSubnode(self.topSeparatorNode)
|
self.addSubnode(self.topSeparatorNode)
|
||||||
self.addSubnode(self.scrollNode)
|
self.addSubnode(self.scrollNode)
|
||||||
self.addSubnode(self.intensityNode)
|
|
||||||
|
self.addSubnode(self.labelNode)
|
||||||
|
|
||||||
self.disposable = ((telegramWallpapers(postbox: account.postbox, network: account.network)
|
self.disposable = ((telegramWallpapers(postbox: account.postbox, network: account.network)
|
||||||
|> map { wallpapers in
|
|> map { wallpapers in
|
||||||
@ -85,7 +82,9 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
node.pressed = { [weak self, weak node] in
|
node.pressed = { [weak self, weak node] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.currentWallpaper = updatedWallpaper
|
strongSelf.currentWallpaper = updatedWallpaper
|
||||||
strongSelf.patternChanged?(updatedWallpaper, Int32(strongSelf.intensityNode.value * 100), false)
|
if let sliderView = strongSelf.sliderView {
|
||||||
|
strongSelf.patternChanged?(updatedWallpaper, Int32(sliderView.value), 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 {
|
||||||
subnode.setSelected(node === subnode, animated: true)
|
subnode.setSelected(node === subnode, animated: true)
|
||||||
@ -103,18 +102,6 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
strongSelf.wallpapers = wallpapers
|
strongSelf.wallpapers = wallpapers
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
self.intensityNode.valueChanged = { [weak self] value in
|
|
||||||
if let strongSelf = self, let wallpaper = strongSelf.currentWallpaper {
|
|
||||||
strongSelf.patternChanged?(wallpaper, strongSelf.intensityNode.intensity, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.intensityNode.valueChangeEnded = { [weak self] value in
|
|
||||||
if let strongSelf = self, let wallpaper = strongSelf.currentWallpaper {
|
|
||||||
strongSelf.patternChanged?(wallpaper, strongSelf.intensityNode.intensity, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -127,12 +114,39 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
self.scrollNode.view.showsHorizontalScrollIndicator = false
|
self.scrollNode.view.showsHorizontalScrollIndicator = false
|
||||||
self.scrollNode.view.showsVerticalScrollIndicator = false
|
self.scrollNode.view.showsVerticalScrollIndicator = false
|
||||||
self.scrollNode.view.alwaysBounceHorizontal = true
|
self.scrollNode.view.alwaysBounceHorizontal = true
|
||||||
|
|
||||||
|
let sliderView = TGPhotoEditorSliderView()
|
||||||
|
//sliderView.enablePanHandling = true
|
||||||
|
sliderView.trackCornerRadius = 1.0
|
||||||
|
sliderView.lineSize = 2.0
|
||||||
|
sliderView.minimumValue = 0.0
|
||||||
|
sliderView.startValue = 0.0
|
||||||
|
sliderView.maximumValue = 100.0
|
||||||
|
sliderView.value = 40.0
|
||||||
|
sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
||||||
|
sliderView.backgroundColor = .clear
|
||||||
|
sliderView.backColor = self.theme.list.disclosureArrowColor
|
||||||
|
sliderView.trackColor = self.theme.list.itemAccentColor
|
||||||
|
|
||||||
|
self.view.addSubview(sliderView)
|
||||||
|
sliderView.addTarget(self, action: #selector(self.sliderValueChanged), for: .valueChanged)
|
||||||
|
self.sliderView = sliderView
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func sliderValueChanged() {
|
||||||
|
guard let sliderView = self.sliderView else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let wallpaper = self.currentWallpaper {
|
||||||
|
self.patternChanged?(wallpaper, Int32(sliderView.value), sliderView.isTracking)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func didAppear() {
|
func didAppear() {
|
||||||
if let wallpaper = self.wallpapers.first {
|
if let wallpaper = self.wallpapers.first {
|
||||||
self.currentWallpaper = wallpaper
|
self.currentWallpaper = wallpaper
|
||||||
self.intensityNode.value = 0.4
|
self.sliderView?.value = 40.0
|
||||||
|
|
||||||
self.scrollNode.view.contentOffset = CGPoint()
|
self.scrollNode.view.contentOffset = CGPoint()
|
||||||
|
|
||||||
@ -144,7 +158,9 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.patternChanged?(wallpaper, self.intensityNode.intensity, false)
|
if let wallpaper = self.currentWallpaper, let sliderView = self.sliderView {
|
||||||
|
self.patternChanged?(wallpaper, Int32(sliderView.value), false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,8 +169,12 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
|||||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
|
transition.updateFrame(node: self.backgroundNode, frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
|
||||||
transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: separatorHeight))
|
transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: separatorHeight))
|
||||||
transition.updateFrame(node: self.scrollNode, frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: 114.0))
|
transition.updateFrame(node: self.scrollNode, frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: 114.0))
|
||||||
transition.updateFrame(node: self.intensityNode, frame: CGRect(x: 16.0, y: 114.0 + 13.0, width: size.width - 16.0 * 2.0, height: 50.0))
|
|
||||||
|
let labelSize = self.labelNode.measure(self.bounds.size)
|
||||||
|
transition.updateFrame(node: labelNode, frame: CGRect(origin: CGPoint(x: 14.0, y: 128.0), size: labelSize))
|
||||||
|
|
||||||
|
self.sliderView?.frame = CGRect(origin: CGPoint(x: 15.0, y: 136.0), size: CGSize(width: size.width - 15.0 * 2.0, height: 44.0))
|
||||||
|
|
||||||
self.layoutItemNodes(transition: transition)
|
self.layoutItemNodes(transition: transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,81 +9,102 @@ private func wallpaperDatas(account: Account, fileReference: FileMediaReference?
|
|||||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
|
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = largestImageRepresentation(representations.map({ $0.representation })), let smallestIndex = representations.index(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.index(where: { $0.representation == largestRepresentation }) {
|
||||||
|
|
||||||
let maybeFullSize: Signal<MediaResourceData, NoError>
|
let maybeFullSize: Signal<MediaResourceData, NoError>
|
||||||
if thumbnail {
|
if thumbnail, let file = fileReference?.media {
|
||||||
maybeFullSize = account.postbox.mediaBox.cachedResourceRepresentation(largestRepresentation.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 320.0, height: 320.0), mode: .aspectFit), complete: false, fetch: false)
|
maybeFullSize = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: false, fetch: false)
|
||||||
} else {
|
} else {
|
||||||
maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource)
|
maybeFullSize = account.postbox.mediaBox.resourceData(largestRepresentation.resource)
|
||||||
}
|
}
|
||||||
let decodedThumbnailData = fileReference?.media.immediateThumbnailData.flatMap(decodeTinyThumbnail)
|
let decodedThumbnailData = fileReference?.media.immediateThumbnailData.flatMap(decodeTinyThumbnail)
|
||||||
|
|
||||||
let signal = maybeFullSize
|
let signal = maybeFullSize
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> mapToSignal { maybeData -> Signal<(Data?, Data?, Bool), NoError> in
|
|> mapToSignal { maybeData -> Signal<(Data?, Data?, Bool), NoError> in
|
||||||
if maybeData.complete {
|
if maybeData.complete {
|
||||||
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
let loadedData: Data? = try? Data(contentsOf: URL(fileURLWithPath: maybeData.path), options: [])
|
||||||
if alwaysShowThumbnailFirst, let decodedThumbnailData = decodedThumbnailData {
|
if alwaysShowThumbnailFirst, let decodedThumbnailData = decodedThumbnailData {
|
||||||
return .single((decodedThumbnailData, nil, false))
|
return .single((decodedThumbnailData, nil, false))
|
||||||
|> then(.complete() |> delay(0.05, queue: Queue.concurrentDefaultQueue()))
|
|> then(.complete() |> delay(0.05, queue: Queue.concurrentDefaultQueue()))
|
||||||
|> then(.single((nil, loadedData, true)))
|
|> then(.single((nil, loadedData, true)))
|
||||||
} else {
|
} else {
|
||||||
return .single((nil, loadedData, true))
|
return .single((nil, loadedData, true))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let fetchedThumbnail: Signal<FetchResourceSourceType, FetchResourceError>
|
||||||
|
if let _ = decodedThumbnailData {
|
||||||
|
fetchedThumbnail = .complete()
|
||||||
|
} else {
|
||||||
|
fetchedThumbnail = fetchedMediaResource(postbox: account.postbox, reference: representations[smallestIndex].reference)
|
||||||
|
}
|
||||||
|
|
||||||
|
let fetchedFullSize = fetchedMediaResource(postbox: account.postbox, reference: representations[largestIndex].reference)
|
||||||
|
|
||||||
|
let thumbnailData: Signal<Data?, NoError>
|
||||||
|
if let decodedThumbnailData = decodedThumbnailData {
|
||||||
|
thumbnailData = .single(decodedThumbnailData)
|
||||||
|
} else {
|
||||||
|
thumbnailData = Signal<Data?, NoError> { subscriber in
|
||||||
|
let fetchedDisposable = fetchedThumbnail.start()
|
||||||
|
let thumbnailDisposable = account.postbox.mediaBox.resourceData(smallestRepresentation.resource).start(next: { next in
|
||||||
|
subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []))
|
||||||
|
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
|
|
||||||
|
return ActionDisposable {
|
||||||
|
fetchedDisposable.dispose()
|
||||||
|
thumbnailDisposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullSizeData: Signal<(Data?, Bool), NoError>
|
||||||
|
if autoFetchFullSize {
|
||||||
|
fullSizeData = Signal<(Data?, Bool), NoError> { subscriber in
|
||||||
|
let fetchedFullSizeDisposable = fetchedFullSize.start()
|
||||||
|
|
||||||
|
let fullSizeDisposable = account.postbox.mediaBox.resourceData(largestRepresentation.resource).start(next: { next in
|
||||||
|
subscriber.putNext((next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete))
|
||||||
|
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
|
|
||||||
|
return ActionDisposable {
|
||||||
|
fetchedFullSizeDisposable.dispose()
|
||||||
|
fullSizeDisposable.dispose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let fetchedThumbnail: Signal<FetchResourceSourceType, FetchResourceError>
|
fullSizeData = account.postbox.mediaBox.resourceData(largestRepresentation.resource)
|
||||||
if let _ = decodedThumbnailData {
|
|> map { next -> (Data?, Bool) in
|
||||||
fetchedThumbnail = .complete()
|
return (next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete)
|
||||||
} else {
|
}
|
||||||
fetchedThumbnail = fetchedMediaResource(postbox: account.postbox, reference: representations[smallestIndex].reference)
|
}
|
||||||
|
|
||||||
|
if thumbnail, let file = fileReference?.media {
|
||||||
|
let betterThumbnailData = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedScaledImageRepresentation(size: CGSize(width: 720.0, height: 720.0), mode: .aspectFit), complete: false, fetch: true)
|
||||||
|
|> map { next -> (Data?, Bool) in
|
||||||
|
return (next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete)
|
||||||
}
|
}
|
||||||
|
|
||||||
let fetchedFullSize = fetchedMediaResource(postbox: account.postbox, reference: representations[largestIndex].reference)
|
return thumbnailData |> mapToSignal { thumbnailData in
|
||||||
|
return fullSizeData |> mapToSignal { (fullSizeData, complete) in
|
||||||
let thumbnail: Signal<Data?, NoError>
|
if complete {
|
||||||
if let decodedThumbnailData = decodedThumbnailData {
|
return .single((thumbnailData, fullSizeData, complete))
|
||||||
thumbnail = .single(decodedThumbnailData)
|
|> then(
|
||||||
} else {
|
betterThumbnailData |> map { (betterFullSizeData, complete) in
|
||||||
thumbnail = Signal<Data?, NoError> { subscriber in
|
return (thumbnailData, betterFullSizeData ?? fullSizeData, complete)
|
||||||
let fetchedDisposable = fetchedThumbnail.start()
|
})
|
||||||
let thumbnailDisposable = account.postbox.mediaBox.resourceData(smallestRepresentation.resource).start(next: { next in
|
} else {
|
||||||
subscriber.putNext(next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []))
|
return .single((thumbnailData, fullSizeData, complete))
|
||||||
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
|
||||||
|
|
||||||
return ActionDisposable {
|
|
||||||
fetchedDisposable.dispose()
|
|
||||||
thumbnailDisposable.dispose()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
let fullSizeData: Signal<(Data?, Bool), NoError>
|
|
||||||
|
return thumbnailData |> mapToSignal { thumbnailData in
|
||||||
if autoFetchFullSize {
|
|
||||||
fullSizeData = Signal<(Data?, Bool), NoError> { subscriber in
|
|
||||||
let fetchedFullSizeDisposable = fetchedFullSize.start()
|
|
||||||
let fullSizeDisposable = account.postbox.mediaBox.resourceData(largestRepresentation.resource).start(next: { next in
|
|
||||||
subscriber.putNext((next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete))
|
|
||||||
}, error: subscriber.putError, completed: subscriber.putCompletion)
|
|
||||||
|
|
||||||
return ActionDisposable {
|
|
||||||
fetchedFullSizeDisposable.dispose()
|
|
||||||
fullSizeDisposable.dispose()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fullSizeData = account.postbox.mediaBox.resourceData(largestRepresentation.resource)
|
|
||||||
|> map { next -> (Data?, Bool) in
|
|
||||||
return (next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: []), next.complete)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return thumbnail |> mapToSignal { thumbnailData in
|
|
||||||
return fullSizeData |> map { (fullSizeData, complete) in
|
return fullSizeData |> map { (fullSizeData, complete) in
|
||||||
return (thumbnailData, fullSizeData, complete)
|
return (thumbnailData, fullSizeData, complete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} |> filter({ $0.0 != nil || $0.1 != nil })
|
}
|
||||||
|
} |> filter({ $0.0 != nil || $0.1 != nil })
|
||||||
return signal
|
return signal
|
||||||
} else {
|
} else {
|
||||||
return .never()
|
return .never()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user