mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-11 05:45:48 +00:00
* ios: fix applying theme when no global theme editer yet * base color * added check for base --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
114 lines
5.6 KiB
Swift
114 lines
5.6 KiB
Swift
//
|
|
// ChatWallpaper.swift
|
|
// SimpleX (iOS)
|
|
//
|
|
// Created by Avently on 14.06.2024.
|
|
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
import SimpleXChat
|
|
|
|
struct ChatViewBackground: ViewModifier {
|
|
@Environment(\.colorScheme) var colorScheme
|
|
var image: Image
|
|
var imageType: WallpaperType
|
|
var background: Color
|
|
var tint: Color
|
|
|
|
func body(content: Content) -> some View {
|
|
// Workaround a problem (SwiftUI bug?) when wallpaper is not updated when user changes global theme in iOS settings from dark to light and vice versa
|
|
if colorScheme == .light {
|
|
back(content)
|
|
} else {
|
|
back(content)
|
|
}
|
|
}
|
|
|
|
func back(_ content: Content) -> some View {
|
|
content.background(
|
|
Canvas { context, size in
|
|
var image = context.resolve(image)
|
|
let rect = CGRectMake(0, 0, size.width, size.height)
|
|
func repeatDraw(_ imageScale: CGFloat) {
|
|
// Prevent range bounds crash and dividing by zero
|
|
if size.height == 0 || size.width == 0 || image.size.height == 0 || image.size.width == 0 { return }
|
|
image.shading = .color(tint)
|
|
let scale = imageScale * 2.5 // scale wallpaper for iOS
|
|
for h in 0 ... Int(size.height / image.size.height / scale) {
|
|
for w in 0 ... Int(size.width / image.size.width / scale) {
|
|
let rect = CGRectMake(CGFloat(w) * image.size.width * scale, CGFloat(h) * image.size.height * scale, image.size.width * scale, image.size.height * scale)
|
|
context.draw(image, in: rect, style: FillStyle())
|
|
}
|
|
}
|
|
}
|
|
context.fill(Path(rect), with: .color(background))
|
|
switch imageType {
|
|
case let WallpaperType.preset(filename, scale):
|
|
repeatDraw(CGFloat((scale ?? 1) * (PresetWallpaper.from(filename)?.scale ?? 1)))
|
|
case let WallpaperType.image(_, scale, scaleType):
|
|
let scaleType = scaleType ?? WallpaperScaleType.fill
|
|
switch scaleType {
|
|
case WallpaperScaleType.repeat: repeatDraw(CGFloat(scale ?? 1))
|
|
case WallpaperScaleType.fill: fallthrough
|
|
case WallpaperScaleType.fit:
|
|
let scale = scaleType.computeScaleFactor(image.size, size)
|
|
let scaledWidth = (image.size.width * scale.0)
|
|
let scaledHeight = (image.size.height * scale.1)
|
|
context.draw(image, in: CGRectMake(((size.width - scaledWidth) / 2), ((size.height - scaledHeight) / 2), scaledWidth, scaledHeight), style: FillStyle())
|
|
if case WallpaperScaleType.fit = scaleType {
|
|
if scaledWidth < size.width {
|
|
// has black lines at left and right sides
|
|
var x = (size.width - scaledWidth) / 2
|
|
while x > 0 {
|
|
context.draw(image, in: CGRectMake((x - scaledWidth), ((size.height - scaledHeight) / 2), scaledWidth, scaledHeight), style: FillStyle())
|
|
x -= scaledWidth
|
|
}
|
|
x = size.width - (size.width - scaledWidth) / 2
|
|
while x < size.width {
|
|
context.draw(image, in: CGRectMake(x, ((size.height - scaledHeight) / 2), scaledWidth, scaledHeight), style: FillStyle())
|
|
|
|
x += scaledWidth
|
|
}
|
|
} else {
|
|
// has black lines at top and bottom sides
|
|
var y = (size.height - scaledHeight) / 2
|
|
while y > 0 {
|
|
context.draw(image, in: CGRectMake(((size.width - scaledWidth) / 2), (y - scaledHeight), scaledWidth, scaledHeight), style: FillStyle())
|
|
y -= scaledHeight
|
|
}
|
|
y = size.height - (size.height - scaledHeight) / 2
|
|
while y < size.height {
|
|
context.draw(image, in: CGRectMake(((size.width - scaledWidth) / 2), y, scaledWidth, scaledHeight), style: FillStyle())
|
|
y += scaledHeight
|
|
}
|
|
}
|
|
}
|
|
context.fill(Path(rect), with: .color(tint))
|
|
}
|
|
case WallpaperType.empty: ()
|
|
}
|
|
}
|
|
).ignoresSafeArea(.all)
|
|
}
|
|
}
|
|
|
|
extension PresetWallpaper {
|
|
public func toType(_ base: DefaultTheme, _ scale: Float? = nil) -> WallpaperType {
|
|
let scale = if let scale {
|
|
scale
|
|
} else if let type = ChatModel.shared.currentUser?.uiThemes?.preferredMode(base.mode == DefaultThemeMode.dark)?.wallpaper?.toAppWallpaper().type, type.sameType(WallpaperType.preset(filename, nil)) {
|
|
type.scale
|
|
} else if let scale = themeOverridesDefault.get().first(where: { $0.wallpaper != nil && $0.wallpaper!.preset == filename && $0.base == base })?.wallpaper?.scale {
|
|
scale
|
|
} else {
|
|
Float(1.0)
|
|
}
|
|
return WallpaperType.preset(
|
|
filename,
|
|
scale
|
|
)
|
|
}
|
|
}
|