ios: fix theme import file picker (#5048)

* ios: fix theme import file picker

* minor
This commit is contained in:
Arturs Krumins
2024-10-16 21:48:13 +03:00
committed by GitHub
parent 515a0ddfdd
commit d57abfcc93
2 changed files with 83 additions and 65 deletions

View File

@@ -16,6 +16,7 @@ struct UserWallpaperEditor: View {
@State var themeModeOverride: ThemeModeOverride
@State var applyToMode: DefaultThemeMode?
@State var showMore: Bool = false
@State var showFileImporter: Bool = false
@Binding var globalThemeUsed: Bool
var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void
@@ -125,24 +126,27 @@ struct UserWallpaperEditor: View {
CustomizeThemeColorsSection(editColor: { name in editColor(name, theme) })
ImportExportThemeSection(perChat: nil, perUser: ChatModel.shared.currentUser?.uiThemes) { imported in
let importedFromString = imported.wallpaper?.importFromString()
let importedType = importedFromString?.toAppWallpaper().type
let currentTheme = ThemeManager.currentColors(nil, nil, nil, themeOverridesDefault.get())
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, nil).colors
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
Task {
await MainActor.run {
themeModeOverride = res
}
await save(applyToMode, res)
}
}
ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: nil, perUser: ChatModel.shared.currentUser?.uiThemes)
} else {
AdvancedSettingsButton(theme.colors.primary) { showMore = true }
}
}
.modifier(
ThemeImporter(isPresented: $showFileImporter) { imported in
let importedFromString = imported.wallpaper?.importFromString()
let importedType = importedFromString?.toAppWallpaper().type
let currentTheme = ThemeManager.currentColors(nil, nil, nil, themeOverridesDefault.get())
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, nil).colors
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
Task {
await MainActor.run {
themeModeOverride = res
}
await save(applyToMode, res)
}
}
)
}
private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool {
@@ -216,6 +220,7 @@ struct ChatWallpaperEditor: View {
@State var themeModeOverride: ThemeModeOverride
@State var applyToMode: DefaultThemeMode?
@State var showMore: Bool = false
@State var showFileImporter: Bool = false
@Binding var globalThemeUsed: Bool
var save: (DefaultThemeMode?, ThemeModeOverride?) async -> Void
@@ -328,24 +333,27 @@ struct ChatWallpaperEditor: View {
CustomizeThemeColorsSection(editColor: editColor)
ImportExportThemeSection(perChat: themeModeOverride, perUser: ChatModel.shared.currentUser?.uiThemes) { imported in
let importedFromString = imported.wallpaper?.importFromString()
let importedType = importedFromString?.toAppWallpaper().type
let currentTheme = ThemeManager.currentColors(nil, nil, ChatModel.shared.currentUser?.uiThemes, themeOverridesDefault.get())
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, ChatModel.shared.currentUser?.uiThemes).colors
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
Task {
await MainActor.run {
themeModeOverride = res
}
await save(applyToMode, res)
}
}
ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: themeModeOverride, perUser: ChatModel.shared.currentUser?.uiThemes)
} else {
AdvancedSettingsButton(theme.colors.primary) { showMore = true }
}
}
.modifier(
ThemeImporter(isPresented: $showFileImporter) { imported in
let importedFromString = imported.wallpaper?.importFromString()
let importedType = importedFromString?.toAppWallpaper().type
let currentTheme = ThemeManager.currentColors(nil, nil, ChatModel.shared.currentUser?.uiThemes, themeOverridesDefault.get())
let type: WallpaperType? = if importedType?.sameType(currentTheme.wallpaper.type) == true { nil } else { importedType }
let colors = ThemeManager.currentThemeOverridesForExport(type, nil, ChatModel.shared.currentUser?.uiThemes).colors
let res = ThemeModeOverride(mode: imported.base.mode, colors: imported.colors, wallpaper: importedFromString).removeSameColors(imported.base, colorsToCompare: colors)
Task {
await MainActor.run {
themeModeOverride = res
}
await save(applyToMode, res)
}
}
)
}
private func onTypeCopyFromSameTheme(_ type: WallpaperType?) -> Bool {

View File

@@ -583,11 +583,14 @@ struct CustomizeThemeView: View {
}
}
ImportExportThemeSection(perChat: nil, perUser: nil, save: { theme in
ImportExportThemeSection(showFileImporter: $showFileImporter, perChat: nil, perUser: nil)
}
.modifier(
ThemeImporter(isPresented: $showFileImporter) { theme in
ThemeManager.saveAndApplyThemeOverrides(theme)
saveThemeToDatabase(nil)
})
}
}
)
/// When changing app theme, user overrides are hidden. User overrides will be returned back after closing Appearance screen, see ThemeDestinationPicker()
.interactiveDismissDisabled(true)
}
@@ -595,10 +598,9 @@ struct CustomizeThemeView: View {
struct ImportExportThemeSection: View {
@EnvironmentObject var theme: AppTheme
@Binding var showFileImporter: Bool
var perChat: ThemeModeOverride?
var perUser: ThemeModeOverrides?
var save: (ThemeOverrides) -> Void
@State private var showFileImporter = false
var body: some View {
Section {
@@ -626,39 +628,47 @@ struct ImportExportThemeSection: View {
} label: {
Text("Import theme").foregroundColor(theme.colors.primary)
}
.fileImporter(
isPresented: $showFileImporter,
allowedContentTypes: [.data/*.plainText*/],
allowsMultipleSelection: false
) { result in
if case let .success(files) = result, let fileURL = files.first {
do {
var fileSize: Int? = nil
if fileURL.startAccessingSecurityScopedResource() {
let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey])
fileSize = resourceValues.fileSize
}
if let fileSize = fileSize,
// Same as Android/desktop
fileSize <= 5_500_000 {
if let string = try? String(contentsOf: fileURL, encoding: .utf8), let theme: ThemeOverrides = decodeYAML("themeId: \(UUID().uuidString)\n" + string) {
save(theme)
logger.error("Saved theme from file")
} else {
logger.error("Error decoding theme file")
}
fileURL.stopAccessingSecurityScopedResource()
} else {
fileURL.stopAccessingSecurityScopedResource()
let prettyMaxFileSize = ByteCountFormatter.string(fromByteCount: 5_500_000, countStyle: .binary)
AlertManager.shared.showAlertMsg(
title: "Large file!",
message: "Currently maximum supported file size is \(prettyMaxFileSize)."
)
}
} catch {
logger.error("Appearance fileImporter error \(error.localizedDescription)")
}
}
}
struct ThemeImporter: ViewModifier {
@Binding var isPresented: Bool
var save: (ThemeOverrides) -> Void
func body(content: Content) -> some View {
content.fileImporter(
isPresented: $isPresented,
allowedContentTypes: [.data/*.plainText*/],
allowsMultipleSelection: false
) { result in
if case let .success(files) = result, let fileURL = files.first {
do {
var fileSize: Int? = nil
if fileURL.startAccessingSecurityScopedResource() {
let resourceValues = try fileURL.resourceValues(forKeys: [.fileSizeKey])
fileSize = resourceValues.fileSize
}
if let fileSize = fileSize,
// Same as Android/desktop
fileSize <= 5_500_000 {
if let string = try? String(contentsOf: fileURL, encoding: .utf8), let theme: ThemeOverrides = decodeYAML("themeId: \(UUID().uuidString)\n" + string) {
save(theme)
logger.error("Saved theme from file")
} else {
logger.error("Error decoding theme file")
}
fileURL.stopAccessingSecurityScopedResource()
} else {
fileURL.stopAccessingSecurityScopedResource()
let prettyMaxFileSize = ByteCountFormatter.string(fromByteCount: 5_500_000, countStyle: .binary)
AlertManager.shared.showAlertMsg(
title: "Large file!",
message: "Currently maximum supported file size is \(prettyMaxFileSize)."
)
}
} catch {
logger.error("Appearance fileImporter error \(error.localizedDescription)")
}
}
}