Theme fixes

This commit is contained in:
Ali 2021-05-31 16:27:07 +04:00
parent 735ee8a54b
commit 7e52c6c345
12 changed files with 150 additions and 190 deletions

View File

@ -166,7 +166,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
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))
self.arguments = PatternWallpaperArguments(colors: [.clear], 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))

View File

@ -156,9 +156,9 @@ final class ThemeAccentColorController: ViewController {
var coloredWallpaper: TelegramWallpaper?
if !state.backgroundColors.isEmpty {
if let patternWallpaper = state.patternWallpaper {
coloredWallpaper = patternWallpaper.withUpdatedSettings(WallpaperSettings(motion: state.motion, colors: state.backgroundColors, intensity: state.patternIntensity, rotation: state.rotation))
coloredWallpaper = patternWallpaper.withUpdatedSettings(WallpaperSettings(colors: state.backgroundColors, intensity: state.patternIntensity, rotation: state.rotation))
} else if state.backgroundColors.count >= 2 {
coloredWallpaper = .gradient(state.backgroundColors, WallpaperSettings(motion: state.motion, rotation: state.rotation))
coloredWallpaper = .gradient(state.backgroundColors, WallpaperSettings(rotation: state.rotation))
} else {
coloredWallpaper = .color(state.backgroundColors[0])
}
@ -602,7 +602,7 @@ final class ThemeAccentColorController: ViewController {
messageColors = nil
}
let initialState = ThemeColorState(section: strongSelf.section, accentColor: accentColor, initialWallpaper: initialWallpaper, backgroundColors: backgroundColors, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, motion: motion, defaultMessagesColor: defaultMessagesColor, messagesColors: messageColors, rotation: rotation)
let initialState = ThemeColorState(section: strongSelf.section, accentColor: accentColor, initialWallpaper: initialWallpaper, backgroundColors: backgroundColors, patternWallpaper: patternWallpaper, patternIntensity: patternIntensity, defaultMessagesColor: defaultMessagesColor, messagesColors: messageColors, rotation: rotation)
strongSelf.controllerNode.updateState({ _ in
return initialState

View File

@ -48,7 +48,6 @@ struct ThemeColorState {
fileprivate var previousPatternWallpaper: TelegramWallpaper?
var patternWallpaper: TelegramWallpaper?
var patternIntensity: Int32
var motion: Bool
var defaultMessagesColor: UIColor?
var messagesColors: (UIColor, UIColor?)?
@ -66,13 +65,12 @@ struct ThemeColorState {
self.previousPatternWallpaper = nil
self.patternWallpaper = nil
self.patternIntensity = 50
self.motion = false
self.defaultMessagesColor = nil
self.messagesColors = nil
self.rotation = 0
}
init(section: ThemeColorSection, accentColor: UIColor, initialWallpaper: TelegramWallpaper?, backgroundColors: [UInt32], patternWallpaper: TelegramWallpaper?, patternIntensity: Int32, motion: Bool, defaultMessagesColor: UIColor?, messagesColors: (UIColor, UIColor?)?, rotation: Int32 = 0) {
init(section: ThemeColorSection, accentColor: UIColor, initialWallpaper: TelegramWallpaper?, backgroundColors: [UInt32], patternWallpaper: TelegramWallpaper?, patternIntensity: Int32, defaultMessagesColor: UIColor?, messagesColors: (UIColor, UIColor?)?, rotation: Int32 = 0) {
self.section = section
self.colorPanelCollapsed = false
self.displayPatternPanel = false
@ -83,7 +81,6 @@ struct ThemeColorState {
self.previousPatternWallpaper = nil
self.patternWallpaper = patternWallpaper
self.patternIntensity = patternIntensity
self.motion = motion
self.defaultMessagesColor = defaultMessagesColor
self.messagesColors = messagesColors
self.rotation = rotation
@ -159,7 +156,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
private let scrollNode: ASScrollNode
private let pageControlBackgroundNode: ASDisplayNode
private let pageControlNode: PageControlNode
private var motionButtonNode: WallpaperOptionButtonNode
private var patternButtonNode: WallpaperOptionButtonNode
private let chatListBackgroundNode: ASDisplayNode
private var chatNodes: [ListViewItemNode]?
@ -233,8 +229,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
self.pageControlBackgroundNode.cornerRadius = 10.5
self.pageControlNode = PageControlNode(dotSpacing: 7.0, dotColor: .white, inactiveDotColor: UIColor.white.withAlphaComponent(0.4))
self.motionButtonNode = WallpaperOptionButtonNode(title: self.presentationData.strings.WallpaperPreview_Motion, value: .check(false))
self.patternButtonNode = WallpaperOptionButtonNode(title: self.presentationData.strings.WallpaperPreview_Pattern, value: .check(false))
self.chatListBackgroundNode = ASDisplayNode()
@ -280,7 +275,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
self.chatListBackgroundNode.addSubnode(self.maskNode)
self.addSubnode(self.pageControlBackgroundNode)
self.addSubnode(self.pageControlNode)
self.addSubnode(self.motionButtonNode)
self.addSubnode(self.patternButtonNode)
self.addSubnode(self.colorPanelNode)
self.addSubnode(self.patternPanelNode)
@ -292,21 +286,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
self.backgroundContainerNode.addSubnode(self.backgroundWrapperNode)
self.backgroundWrapperNode.addSubnode(self.backgroundNode)
self.motionButtonNode.addTarget(self, action: #selector(self.toggleMotion), forControlEvents: .touchUpInside)
self.patternButtonNode.addTarget(self, action: #selector(self.togglePattern), forControlEvents: .touchUpInside)
/*self.colorPanelNode.colorAdded = { [weak self] in
if let strongSelf = self {
strongSelf.signalBackgroundNode.contentAnimations = [.subsequentUpdates]
}
}
self.colorPanelNode.colorRemoved = { [weak self] in
if let strongSelf = self {
strongSelf.signalBackgroundNode.contentAnimations = [.subsequentUpdates]
}
}*/
self.colorPanelNode.colorsChanged = { [weak self] colors, ended in
if let strongSelf = self, let section = strongSelf.state.section {
@ -422,7 +403,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
if !backgroundColors.isEmpty {
if let patternWallpaper = state.patternWallpaper, case let .file(file) = patternWallpaper {
wallpaper = patternWallpaper.withUpdatedSettings(WallpaperSettings(motion: state.motion, colors: backgroundColors, intensity: state.patternIntensity, rotation: state.rotation))
wallpaper = patternWallpaper.withUpdatedSettings(WallpaperSettings(colors: backgroundColors, intensity: state.patternIntensity, rotation: state.rotation))
let dimensions = file.file.dimensions ?? PixelDimensions(width: 100, height: 100)
var convertedRepresentations: [ImageRepresentationWithReference] = []
@ -543,7 +524,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
strongSelf.patternPanelNode.serviceBackgroundColor = color
strongSelf.pageControlBackgroundNode.backgroundColor = color
strongSelf.patternButtonNode.buttonColor = color
strongSelf.motionButtonNode.buttonColor = color
}
})
}
@ -594,11 +574,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
self.patternButtonNode.setSelected(self.state.patternWallpaper != nil, animated: animated)
}
if previousState.motion != self.state.motion {
self.motionButtonNode.setSelected(self.state.motion, animated: animated)
self.setMotionEnabled(self.state.motion, animated: animated)
}
let sectionChanged = previousState.section != self.state.section
if sectionChanged, let section = self.state.section {
self.view.endEditing(true)
@ -1012,42 +987,19 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
transition.updateFrame(node: self.maskNode, frame: CGRect(x: 0.0, y: layout.size.height - bottomInset - 80.0, width: bounds.width, height: 80.0))
let patternButtonSize = self.patternButtonNode.measure(layout.size)
let motionButtonSize = self.motionButtonNode.measure(layout.size)
let maxButtonWidth = max(patternButtonSize.width, motionButtonSize.width)
let maxButtonWidth = patternButtonSize.width
let buttonSize = CGSize(width: maxButtonWidth, height: 30.0)
let leftButtonFrame = CGRect(origin: CGPoint(x: floor(layout.size.width / 2.0 - buttonSize.width - 10.0), y: layout.size.height - bottomInset - 44.0), size: buttonSize)
let centerButtonFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - buttonSize.width) / 2.0), y: layout.size.height - bottomInset - 44.0), size: buttonSize)
let rightButtonFrame = CGRect(origin: CGPoint(x: ceil(layout.size.width / 2.0 + 10.0), y: layout.size.height - bottomInset - 44.0), size: buttonSize)
var hasMotion: Bool = self.state.patternWallpaper != nil || self.state.displayPatternPanel
if self.state.backgroundColors.count >= 3 {
hasMotion = false
}
var patternAlpha: CGFloat = displayOptionButtons ? 1.0 : 0.0
var motionAlpha: CGFloat = displayOptionButtons && hasMotion ? 1.0 : 0.0
var patternFrame = hasMotion ? leftButtonFrame : centerButtonFrame
var motionFrame = hasMotion ? rightButtonFrame : centerButtonFrame
var patternFrame = centerButtonFrame
transition.updateFrame(node: self.patternButtonNode, frame: patternFrame)
transition.updateAlpha(node: self.patternButtonNode, alpha: patternAlpha)
transition.updateFrame(node: self.motionButtonNode, frame: motionFrame)
transition.updateAlpha(node: self.motionButtonNode, alpha: motionAlpha)
if isFirstLayout {
self.setMotionEnabled(self.state.motion, animated: false)
}
}
@objc private func toggleMotion() {
self.updateState({ current in
var updated = current
updated.motion = !updated.motion
return updated
}, animated: true)
}
@objc private func togglePattern() {
@ -1085,50 +1037,4 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
self.patternPanelNode.didAppear(initialWallpaper: wallpaper, intensity: self.state.patternIntensity)
}
}
private let motionAmount: CGFloat = 32.0
private func setMotionEnabled(_ enabled: Bool, animated: Bool) {
guard let (layout, _, _) = self.validLayout else {
return
}
if enabled {
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
horizontal.minimumRelativeValue = motionAmount
horizontal.maximumRelativeValue = -motionAmount
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
vertical.minimumRelativeValue = motionAmount
vertical.maximumRelativeValue = -motionAmount
let group = UIMotionEffectGroup()
group.motionEffects = [horizontal, vertical]
self.backgroundWrapperNode.view.addMotionEffect(group)
let scale = (layout.size.width + motionAmount * 2.0) / layout.size.width
if animated {
self.backgroundWrapperNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
self.backgroundWrapperNode.layer.animateScale(from: 1.0, to: scale, duration: 0.2)
} else {
self.backgroundWrapperNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
}
} else {
let position = self.backgroundWrapperNode.layer.presentation()?.position
for effect in self.backgroundWrapperNode.view.motionEffects {
self.backgroundWrapperNode.view.removeMotionEffect(effect)
}
let scale = (layout.size.width + motionAmount * 2.0) / layout.size.width
if animated {
self.backgroundWrapperNode.transform = CATransform3DIdentity
self.backgroundWrapperNode.layer.animateScale(from: scale, to: 1.0, duration: 0.2)
if let position = position {
self.backgroundWrapperNode.layer.animatePosition(from: position, to: self.backgroundWrapperNode.layer.position, duration: 0.2)
}
} else {
self.backgroundWrapperNode.transform = CATransform3DIdentity
}
}
}
}

View File

@ -246,8 +246,8 @@ final class ThemeGridControllerNode: ASDisplayNode {
let wallpapersPromise = Promise<[Wallpaper]>()
self.wallpapersPromise = wallpapersPromise
let deletedWallpaperSlugsValue = Atomic<Set<String>>(value: Set())
let deletedWallpaperSlugsPromise = ValuePromise<Set<String>>(Set())
let deletedWallpaperIdsValue = Atomic<Set<ThemeGridControllerEntry.StableId>>(value: Set())
let deletedWallpaperIdsPromise = ValuePromise<Set<ThemeGridControllerEntry.StableId>>(Set())
super.init()
@ -306,16 +306,16 @@ final class ThemeGridControllerNode: ASDisplayNode {
deleteWallpapers(wallpapers, { [weak self] in
if let strongSelf = self {
var updatedDeletedSlugs = deletedWallpaperSlugsValue.with { $0 }
var updatedDeletedIds = deletedWallpaperIdsValue.with { $0 }
for entry in entries {
if case let .file(file) = entry.wallpaper, strongSelf.currentState.selectedIds.contains(entry.stableId) {
updatedDeletedSlugs.insert(file.slug)
if strongSelf.currentState.selectedIds.contains(entry.stableId) {
updatedDeletedIds.insert(entry.stableId)
}
}
let _ = deletedWallpaperSlugsValue.swap(updatedDeletedSlugs)
deletedWallpaperSlugsPromise.set(updatedDeletedSlugs)
let _ = deletedWallpaperIdsValue.swap(updatedDeletedIds)
deletedWallpaperIdsPromise.set(updatedDeletedIds)
let _ = (strongSelf.context.sharedContext.accountManager.transaction { transaction in
WallpapersState.update(transaction: transaction, { state in
@ -341,8 +341,8 @@ final class ThemeGridControllerNode: ASDisplayNode {
})
self.controllerInteraction = interaction
let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperSlugsPromise.get(), context.sharedContext.presentationData)
|> map { wallpapers, deletedWallpaperSlugs, presentationData -> (ThemeGridEntryTransition, Bool) in
let transition = combineLatest(self.wallpapersPromise.get(), deletedWallpaperIdsPromise.get(), context.sharedContext.presentationData)
|> map { wallpapers, deletedWallpaperIds, presentationData -> (ThemeGridEntryTransition, Bool) in
var entries: [ThemeGridControllerEntry] = []
var index = 1
@ -399,7 +399,7 @@ final class ThemeGridControllerNode: ASDisplayNode {
}
for wallpaper in sortedWallpapers {
if case let .file(file) = wallpaper, deletedWallpaperSlugs.contains(file.slug) || (wallpaper.isPattern && file.settings.colors.isEmpty) {
if case let .file(file) = wallpaper, (wallpaper.isPattern && file.settings.colors.isEmpty) {
continue
}
let selected = presentationData.chatWallpaper.isBasicallyEqual(to: wallpaper)
@ -416,6 +416,9 @@ final class ThemeGridControllerNode: ASDisplayNode {
}
if !selected && !isDefault {
let entry = ThemeGridControllerEntry(index: index, wallpaper: wallpaper, isEditable: isEditable, isSelected: false)
if deletedWallpaperIds.contains(entry.stableId) {
continue
}
if !entries.contains(where: { $0.stableId == entry.stableId }) {
entries.append(entry)
index += 1

View File

@ -623,12 +623,12 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode {
}
let title = themeDisplayName(strings: item.strings, reference: theme)
var accentColor = item.themeSpecificAccentColors[theme.generalThemeReference.index]
if let customThemeIndex = accentColor?.themeIndex {
/*if let customThemeIndex = accentColor?.themeIndex {
if let customTheme = themes[customThemeIndex] {
theme = customTheme
}
accentColor = nil
}
}*/
var themeWallpaper: TelegramWallpaper?
if case let .cloud(theme) = theme {

View File

@ -308,6 +308,10 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
} else {
self.playButtonNode.setImage(self.playButtonRotateImage, for: [])
}
} else if case .color = wallpaper {
self.nativeNode.isHidden = false
self.nativeNode.update(wallpaper: wallpaper)
self.patternButtonNode.isSelected = false
} else {
self.nativeNode.isHidden = true
self.patternButtonNode.isSelected = false

View File

@ -596,7 +596,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
let (_, initialImageWidth, refineLayout) = contentImageLayout(context, presentationData, presentationData.dateTimeFormat, message, attributes, wallpaper, imageDateAndStatus, .full, associatedData.automaticDownloadPeerType, .constrained(CGSize(width: constrainedSize.width - horizontalInsets.left - horizontalInsets.right, height: constrainedSize.height)), layoutConstants, contentMode)
initialWidth = initialImageWidth + horizontalInsets.left + horizontalInsets.right
refineContentImageLayout = refineLayout
if case let .file(_, _, _, isTheme, _) = wallpaper.content, isTheme {
if case let .file(_, _, _, _, isTheme, _) = wallpaper.content, isTheme {
skipStandardStatus = true
}
}

View File

@ -419,7 +419,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
unboundSize = CGSize(width: floor(dimensions.cgSize.width * 0.5), height: floor(dimensions.cgSize.height * 0.5))
} else if let wallpaper = media as? WallpaperPreviewMedia {
switch wallpaper.content {
case let .file(file, _, _, isTheme, isSupported):
case let .file(file, _, _, _, isTheme, isSupported):
if let thumbnail = file.previewRepresentations.first, var dimensions = file.dimensions {
let dimensionsVertical = dimensions.width < dimensions.height
let thumbnailVertical = thumbnail.dimensions.width < thumbnail.dimensions.height
@ -570,14 +570,24 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
emptyColor = message.effectivelyIncoming(context.account.peerId) ? presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor
}
if let wallpaper = media as? WallpaperPreviewMedia {
if case let .file(_, patternColors, rotation, _, _) = wallpaper.content {
if case let .file(_, patternColors, rotation, intensity, _, _) = wallpaper.content {
var colors: [UIColor] = []
if patternColors.isEmpty {
colors.append(UIColor(rgb: 0xd6e2ee, alpha: 0.5))
var customPatternColor: UIColor? = nil
if let intensity = intensity, intensity < 0 {
if patternColors.isEmpty {
colors.append(UIColor(rgb: 0xd6e2ee, alpha: 0.5))
} else {
colors.append(contentsOf: patternColors.map(UIColor.init(rgb:)))
}
customPatternColor = UIColor(white: 0.0, alpha: 1.0 - CGFloat(abs(intensity)))
} else {
colors.append(contentsOf: patternColors.map(UIColor.init(rgb:)))
if patternColors.isEmpty {
colors.append(UIColor(rgb: 0xd6e2ee, alpha: 0.5))
} else {
colors.append(contentsOf: patternColors.map(UIColor.init(rgb:)))
}
}
patternArguments = PatternWallpaperArguments(colors: colors, rotation: rotation)
patternArguments = PatternWallpaperArguments(colors: colors, rotation: rotation, customPatternColor: customPatternColor)
}
}
@ -715,7 +725,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
} else if let wallpaper = media as? WallpaperPreviewMedia {
updateImageSignal = { synchronousLoad, _ in
switch wallpaper.content {
case let .file(file, _, _, isTheme, _):
case let .file(file, _, _, _, isTheme, _):
if isTheme {
return themeImage(account: context.account, accountManager: context.sharedContext.accountManager, source: .file(FileMediaReference.message(message: MessageReference(message), media: file)))
} else {
@ -738,7 +748,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
}
}
if case let .file(file, _, _, _, _) = wallpaper.content {
if case let .file(file, _, _, _, _, _) = wallpaper.content {
updatedFetchControls = FetchControls(fetch: { manual in
if let strongSelf = self {
strongSelf.fetchDisposable.set(messageMediaFileInteractiveFetched(context: context, message: message, file: file, userInitiated: manual).start())
@ -783,7 +793,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
}
} else if let wallpaper = media as? WallpaperPreviewMedia {
switch wallpaper.content {
case let .file(file, _, _, _, _):
case let .file(file, _, _, _, _, _):
updatedStatusSignal = messageMediaFileStatus(context: context, messageId: message.id, file: file)
|> map { resourceStatus -> (MediaResourceStatus, MediaResourceStatus?) in
return (resourceStatus, nil)

View File

@ -173,11 +173,13 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
} else if webpage.type == "telegram_background" {
var colors: [UInt32] = []
var rotation: Int32?
if let wallpaper = parseWallpaperUrl(webpage.url), case let .slug(_, _, colorsValue, intensity, rotationValue) = wallpaper {
var intensity: Int32?
if let wallpaper = parseWallpaperUrl(webpage.url), case let .slug(_, _, colorsValue, intensityValue, rotationValue) = wallpaper {
colors = colorsValue
rotation = rotationValue
intensity = intensityValue
}
let media = WallpaperPreviewMedia(content: .file(file, colors, rotation, false, false))
let media = WallpaperPreviewMedia(content: .file(file: file, colors: colors, rotation: rotation, intensity: intensity, false, false))
mediaAndFlags = (media, [.preferMediaAspectFilled])
if let fileSize = file.size {
badge = dataSizeString(fileSize, formatting: DataSizeStringFormatting(chatPresentationData: item.presentationData))
@ -251,7 +253,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
file = contentFile
}
if let file = file {
let media = WallpaperPreviewMedia(content: .file(file, [], nil, true, isSupported))
let media = WallpaperPreviewMedia(content: .file(file: file, colors: [], rotation: nil, intensity: nil, true, isSupported))
mediaAndFlags = (media, ChatMessageAttachedContentNodeMediaFlags())
} else if let settings = settings {
let media = WallpaperPreviewMedia(content: .themeSettings(settings))

View File

@ -5,7 +5,7 @@ import TelegramCore
import SyncCore
enum WallpaperPreviewMediaContent: Equatable {
case file(TelegramMediaFile, [UInt32], Int32?, Bool, Bool)
case file(file: TelegramMediaFile, colors: [UInt32], rotation: Int32?, intensity: Int32?, Bool, Bool)
case color(UIColor)
case gradient([UInt32], Int32?)
case themeSettings(TelegramThemeSettings)

View File

@ -428,7 +428,7 @@ public final class WallpaperBackgroundNode: ASDisplayNode {
let patternColor: UIColor
if self.invertPattern {
patternColor = .clear
patternBackgroundColor = .black
patternBackgroundColor = .clear
} else {
patternColor = .black
patternBackgroundColor = .clear

View File

@ -450,7 +450,7 @@ public func patternWallpaperImageInternal(thumbnailData: Data?, fullSizeData: Da
let context = DrawingContext(size: arguments.drawingSize, scale: fullSizeImage == nil ? 1.0 : scale, clear: !arguments.corners.isEmpty)
context.withFlippedContext { c in
c.setBlendMode(.copy)
if colors.count == 1 {
if customArguments.colors[0].alpha.isZero {
c.clear(arguments.drawingRect)
@ -486,53 +486,71 @@ public func patternWallpaperImageInternal(thumbnailData: Data?, fullSizeData: Da
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: arguments.drawingSize.height), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])
c.restoreGState()
}
let image = customArguments.preview ? (scaledSizeImage ?? fullSizeImage) : fullSizeImage
if let image = image {
var fittedSize = CGSize(width: image.width, height: image.height)
if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) {
fittedSize.width = arguments.boundingSize.width
}
if abs(fittedSize.height - arguments.boundingSize.height).isLessThanOrEqualTo(CGFloat(1.0)) {
fittedSize.height = arguments.boundingSize.height
}
fittedSize = fittedSize.aspectFilled(arguments.drawingRect.size)
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
c.interpolationQuality = customArguments.preview ? .low : .medium
c.clip(to: fittedRect, mask: image)
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)
c.setFillColor(UIColor(white: 0.0, alpha: 0.5).cgColor)
c.fill(arguments.drawingRect)
} else if colors.count == 1 {
c.setFillColor(customArguments.customPatternColor?.cgColor ?? patternColor(for: color, intensity: intensity, prominent: prominent).cgColor)
c.fill(arguments.drawingRect)
} else {
let gradientColors = colors.map { patternColor(for: $0, intensity: intensity, prominent: prominent).cgColor } as CFArray
let delta: CGFloat = 1.0 / (CGFloat(colors.count) - 1.0)
var locations: [CGFloat] = []
for i in 0 ..< colors.count {
locations.append(delta * CGFloat(i))
let overlayImage = generateImage(arguments.drawingRect.size, rotatedContext: { size, c in
c.clear(CGRect(origin: CGPoint(), size: size))
let image = customArguments.preview ? (scaledSizeImage ?? fullSizeImage) : fullSizeImage
if let image = image {
var fittedSize = CGSize(width: image.width, height: image.height)
if abs(fittedSize.width - arguments.boundingSize.width).isLessThanOrEqualTo(CGFloat(1.0)) {
fittedSize.width = arguments.boundingSize.width
}
if abs(fittedSize.height - arguments.boundingSize.height).isLessThanOrEqualTo(CGFloat(1.0)) {
fittedSize.height = arguments.boundingSize.height
}
fittedSize = fittedSize.aspectFilled(arguments.drawingRect.size)
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
if let customPatternColor = customArguments.customPatternColor, customPatternColor.alpha < 1.0 {
c.setBlendMode(.copy)
c.setFillColor(UIColor.black.cgColor)
c.fill(CGRect(origin: CGPoint(), size: size))
} else {
c.setBlendMode(.normal)
}
c.interpolationQuality = customArguments.preview ? .low : .medium
c.clip(to: fittedRect, mask: image)
if colors.count >= 3 && customArguments.customPatternColor == nil {
c.setFillColor(UIColor(white: 0.0, alpha: 0.5).cgColor)
c.fill(CGRect(origin: CGPoint(), size: arguments.drawingRect.size))
} else if colors.count == 1 {
c.setFillColor(customArguments.customPatternColor?.cgColor ?? patternColor(for: color, intensity: intensity, prominent: prominent).cgColor)
c.fill(CGRect(origin: CGPoint(), size: arguments.drawingRect.size))
} else {
let gradientColors = colors.map { patternColor(for: $0, intensity: intensity, prominent: prominent).cgColor } as CFArray
let delta: CGFloat = 1.0 / (CGFloat(colors.count) - 1.0)
var locations: [CGFloat] = []
for i in 0 ..< colors.count {
locations.append(delta * CGFloat(i))
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
c.translateBy(x: arguments.drawingSize.width / 2.0, y: arguments.drawingSize.height / 2.0)
c.rotate(by: CGFloat(customArguments.rotation ?? 0) * CGFloat.pi / -180.0)
c.translateBy(x: -arguments.drawingSize.width / 2.0, y: -arguments.drawingSize.height / 2.0)
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: arguments.drawingSize.height), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
c.translateBy(x: arguments.drawingSize.width / 2.0, y: arguments.drawingSize.height / 2.0)
c.rotate(by: CGFloat(customArguments.rotation ?? 0) * CGFloat.pi / -180.0)
c.translateBy(x: -arguments.drawingSize.width / 2.0, y: -arguments.drawingSize.height / 2.0)
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: arguments.drawingSize.height), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])
}
})
if let customPatternColor = customArguments.customPatternColor, customPatternColor.alpha < 1.0 {
c.setBlendMode(.normal)
} else {
c.setBlendMode(.softLight)
}
if let overlayImage = overlayImage {
c.translateBy(x: drawingRect.midX, y: drawingRect.midY)
c.scaleBy(x: 1.0, y: -1.0)
c.translateBy(x: -drawingRect.midX, y: -drawingRect.midY)
c.draw(overlayImage.cgImage!, in: drawingRect)
c.translateBy(x: drawingRect.midX, y: drawingRect.midY)
c.scaleBy(x: 1.0, y: -1.0)
c.translateBy(x: -drawingRect.midX, y: -drawingRect.midY)
}
}
addCorners(context, arguments: arguments)
@ -818,11 +836,16 @@ public func drawThemeImage(context c: CGContext, theme: PresentationTheme, wallp
c.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: drawingRect.height), end: CGPoint(x: 0.0, y: 0.0), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])
}
case let .file(file):
c.setFillColor(theme.chatList.backgroundColor.cgColor)
if let image = wallpaperImage, let cgImage = image.cgImage {
let size = image.size.aspectFilled(drawingRect.size)
c.draw(cgImage, in: CGRect(origin: CGPoint(x: (drawingRect.size.width - size.width) / 2.0, y: (drawingRect.size.height - size.height) / 2.0), size: size))
if file.isPattern, let intensity = file.settings.intensity, intensity < 0 {
c.setFillColor(UIColor.black.cgColor)
c.fill(CGRect(origin: CGPoint(), size: size))
} else {
if let image = wallpaperImage, let cgImage = image.cgImage {
let size = image.size.aspectFilled(drawingRect.size)
c.draw(cgImage, in: CGRect(origin: CGPoint(x: (drawingRect.size.width - size.width) / 2.0, y: (drawingRect.size.height - size.height) / 2.0), size: size))
}
}
c.setFillColor(theme.chatList.backgroundColor.cgColor)
default:
break
}
@ -1223,14 +1246,20 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the
}
rotation = settings.rotation
case let .file(file):
colors = file.settings.colors
if !file.settings.colors.isEmpty {
topBackgroundColor = UIColor(rgb: file.settings.colors[0])
if file.settings.colors.count >= 2 {
bottomBackgroundColor = UIColor(rgb: file.settings.colors[1])
if file.isPattern, let intensity = file.settings.intensity, intensity < 0 {
colors = [0x000000]
topBackgroundColor = .black
bottomBackgroundColor = .black
} else {
colors = file.settings.colors
if !file.settings.colors.isEmpty {
topBackgroundColor = UIColor(rgb: file.settings.colors[0])
if file.settings.colors.count >= 2 {
bottomBackgroundColor = UIColor(rgb: file.settings.colors[1])
}
}
rotation = file.settings.rotation
}
rotation = file.settings.rotation
default:
colors = [0xd6e2ee]
topBackgroundColor = UIColor(rgb: 0xd6e2ee)
@ -1297,7 +1326,9 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the
backgroundColor = (.black, nil, [])
case let .file(file):
rotation = file.settings.rotation
if !file.settings.colors.isEmpty {
if file.isPattern, let intensity = file.settings.intensity, intensity < 0 {
backgroundColor = (.black, nil, [])
} else if !file.settings.colors.isEmpty {
var bottomColor: UIColor?
if file.settings.colors.count >= 2 {
bottomColor = UIColor(rgb: file.settings.colors[1])
@ -1330,9 +1361,13 @@ public func themeIconImage(account: Account, accountManager: AccountManager, the
if wallpaper.wallpaper.isPattern {
if !file.settings.colors.isEmpty, let intensity = file.settings.intensity {
return accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperRepresentation(colors: file.settings.colors, intensity: intensity, rotation: file.settings.rotation), complete: true, fetch: true)
|> mapToSignal { _ in
return .single((effectiveBackgroundColor, incomingColor, outgoingColor, nil, rotation))
if intensity < 0 {
return .single(((.black, nil, []), incomingColor, outgoingColor, nil, rotation))
} else {
return accountManager.mediaBox.cachedResourceRepresentation(file.file.resource, representation: CachedPatternWallpaperRepresentation(colors: file.settings.colors, intensity: intensity, rotation: file.settings.rotation), complete: true, fetch: true)
|> mapToSignal { _ in
return .single((effectiveBackgroundColor, incomingColor, outgoingColor, nil, rotation))
}
}
} else {
return .complete()