From e3df393d808368ea2ed7aaf2413795de4b274eed Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Thu, 19 Feb 2026 22:24:01 +1100 Subject: [PATCH 1/3] Fix #457 - Persist entry sorting preferences across app launches Changed sorting state from @State to @AppStorage in EntriesView to ensure user preferences are saved to UserDefaults. Also made sorting criteria mutually exclusive for a better UX. --- App/Features/Entry/EntriesView.swift | 17 ++++++++++++----- wallabag.xcodeproj/project.pbxproj | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/App/Features/Entry/EntriesView.swift b/App/Features/Entry/EntriesView.swift index 2822169d..4893d561 100644 --- a/App/Features/Entry/EntriesView.swift +++ b/App/Features/Entry/EntriesView.swift @@ -8,9 +8,9 @@ struct EntriesView: View { @Environment(WallabagPlusStore.self) private var wallabagPlusStore @EnvironmentObject var appState: AppState @StateObject var searchViewModel = SearchViewModel() - @State var entriesSortedById = true - @State var entriesSortedByReadingTime = false - @State var entriesSortedByAscending = false + @AppStorage("entriesSortedById") var entriesSortedById = true + @AppStorage("entriesSortedByReadingTime") var entriesSortedByReadingTime = false + @AppStorage("entriesSortedByAscending") var entriesSortedByAscending = false @State private var showPaywallWallabagPlus = false var body: some View { @@ -26,8 +26,15 @@ struct EntriesView: View { entriesSortedByAscending: entriesSortedByAscending ) } - .onChange(of: entriesSortedByReadingTime) { _, _ in - entriesSortedById = false + .onChange(of: entriesSortedById) { _, newValue in + if newValue { + entriesSortedByReadingTime = false + } + } + .onChange(of: entriesSortedByReadingTime) { _, newValue in + if newValue { + entriesSortedById = false + } } .toolbar { ToolbarItemGroup(placement: .navigationBarTrailing) { diff --git a/wallabag.xcodeproj/project.pbxproj b/wallabag.xcodeproj/project.pbxproj index 15c78f7d..91a7047d 100644 --- a/wallabag.xcodeproj/project.pbxproj +++ b/wallabag.xcodeproj/project.pbxproj @@ -1495,7 +1495,7 @@ repositoryURL = "https://github.com/RevenueCat/purchases-ios-spm.git"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 5.15.0; + minimumVersion = 5.16.0; }; }; /* End XCRemoteSwiftPackageReference section */ From 59beecfe40f597bd0026673ec17220b72a25aea1 Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 24 Feb 2026 13:53:14 +1100 Subject: [PATCH 2/3] Add option to pick theme (light/dark/auto). Moved language files and other resources into a sub-folder to clean up the structure a little. --- App/Features/Setting/AppSetting.swift | 10 +++++++ App/Features/Setting/SettingView.swift | 9 +++++++ App/Lib/Theme.swift | 25 ++++++++++++++++++ .../AppIcon.appiconset/Contents.json | 0 .../logo-icon-bg-white-lg.jpg | Bin .../AppIcon.appiconset/mac1024.png | Bin .../AppIcon.appiconset/mac128.png | Bin .../AppIcon.appiconset/mac16.png | Bin .../AppIcon.appiconset/mac256.png | Bin .../AppIcon.appiconset/mac32.png | Bin .../AppIcon.appiconset/mac512.png | Bin .../AppIcon.appiconset/mac64.png | Bin .../Assets.xcassets/Contents.json | 0 .../logo.imageset/Contents.json | 0 .../logo-icon-black-no-bg-lg.png | Bin .../logo-icon-white-no-bg-lg.png | Bin App/{ => Resources}/WallabagStoreKit.storekit | 0 App/Resources/ar.lproj/Localizable.strings | 7 +++++ .../cs.lproj/Localizable.strings | 7 +++++ App/Resources/da.lproj/Localizable.strings | 7 +++++ .../de.lproj/Localizable.strings | 7 +++++ .../en.lproj/Localizable.strings | 7 +++++ .../es.lproj/Localizable.strings | 13 +++++---- App/Resources/fa.lproj/Localizable.strings | 7 +++++ .../fr.lproj/Localizable.strings | 7 +++++ App/Resources/gl.lproj/Localizable.strings | 7 +++++ App/Resources/hi.lproj/Localizable.strings | 7 +++++ .../hr.lproj/Localizable.strings | 7 +++++ .../html-ressources/article.html | 0 .../html-ressources/justify.css | 0 App/{ => Resources}/html-ressources/main.css | 0 .../html-ressources/ratatouille.css | 0 App/Resources/hu.lproj/Localizable.strings | 7 +++++ .../it.lproj/Localizable.strings | 7 +++++ .../ja.lproj/Localizable.strings | 7 +++++ App/Resources/ko.lproj/Localizable.strings | 7 +++++ App/Resources/nb-NO.lproj/Localizable.strings | 7 +++++ .../nl.lproj/Localizable.strings | 7 +++++ App/Resources/oc.lproj/Localizable.strings | 7 +++++ App/Resources/pl.lproj/Localizable.strings | 7 +++++ App/Resources/pt.lproj/Localizable.strings | 7 +++++ App/Resources/ro.lproj/Localizable.strings | 7 +++++ .../ru.lproj/Localizable.strings | 7 +++++ App/Resources/sv.lproj/Localizable.strings | 7 +++++ App/Resources/th.lproj/Localizable.strings | 7 +++++ .../tr.lproj/Localizable.strings | 7 +++++ App/Resources/uk.lproj/Localizable.strings | 7 +++++ .../wallabag.xcdatamodeld/.xccurrentversion | 0 .../Shared.xcdatamodel/contents | 0 .../wallabagStore.xcdatamodel/contents | 0 .../zh-Hans.lproj/Localizable.strings | 7 +++++ .../zh-Hant.lproj/Localizable.strings | 7 +++++ App/WallabagApp.swift | 1 + App/ar.lproj/Localizable.strings | 1 - App/da.lproj/Localizable.strings | 1 - App/fa.lproj/Localizable.strings | 1 - App/gl.lproj/Localizable.strings | 1 - App/hi.lproj/Localizable.strings | 1 - App/hu.lproj/Localizable.strings | 1 - App/ko.lproj/Localizable.strings | 1 - App/nb-NO.lproj/Localizable.strings | 1 - App/oc.lproj/Localizable.strings | 1 - App/pl.lproj/Localizable.strings | 1 - App/pt.lproj/Localizable.strings | 1 - App/ro.lproj/Localizable.strings | 1 - App/sv.lproj/Localizable.strings | 1 - App/th.lproj/Localizable.strings | 1 - App/uk.lproj/Localizable.strings | 1 - .../SharedLib/Lib/WallabagUserDefaults.swift | 3 +++ wallabag.xcodeproj/project.pbxproj | 22 +++++++++++---- 70 files changed, 262 insertions(+), 25 deletions(-) create mode 100644 App/Lib/Theme.swift rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac1024.png (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac128.png (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac16.png (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac256.png (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac32.png (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac512.png (100%) rename App/{ => Resources}/Assets.xcassets/AppIcon.appiconset/mac64.png (100%) rename App/{ => Resources}/Assets.xcassets/Contents.json (100%) rename App/{ => Resources}/Assets.xcassets/logo.imageset/Contents.json (100%) rename App/{ => Resources}/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png (100%) rename App/{ => Resources}/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png (100%) rename App/{ => Resources}/WallabagStoreKit.storekit (100%) create mode 100644 App/Resources/ar.lproj/Localizable.strings rename App/{ => Resources}/cs.lproj/Localizable.strings (74%) create mode 100644 App/Resources/da.lproj/Localizable.strings rename App/{ => Resources}/de.lproj/Localizable.strings (91%) rename App/{ => Resources}/en.lproj/Localizable.strings (92%) rename App/{ => Resources}/es.lproj/Localizable.strings (53%) create mode 100644 App/Resources/fa.lproj/Localizable.strings rename App/{ => Resources}/fr.lproj/Localizable.strings (93%) create mode 100644 App/Resources/gl.lproj/Localizable.strings create mode 100644 App/Resources/hi.lproj/Localizable.strings rename App/{ => Resources}/hr.lproj/Localizable.strings (91%) rename App/{ => Resources}/html-ressources/article.html (100%) rename App/{ => Resources}/html-ressources/justify.css (100%) rename App/{ => Resources}/html-ressources/main.css (100%) rename App/{ => Resources}/html-ressources/ratatouille.css (100%) create mode 100644 App/Resources/hu.lproj/Localizable.strings rename App/{ => Resources}/it.lproj/Localizable.strings (89%) rename App/{ => Resources}/ja.lproj/Localizable.strings (92%) create mode 100644 App/Resources/ko.lproj/Localizable.strings create mode 100644 App/Resources/nb-NO.lproj/Localizable.strings rename App/{ => Resources}/nl.lproj/Localizable.strings (89%) create mode 100644 App/Resources/oc.lproj/Localizable.strings create mode 100644 App/Resources/pl.lproj/Localizable.strings create mode 100644 App/Resources/pt.lproj/Localizable.strings create mode 100644 App/Resources/ro.lproj/Localizable.strings rename App/{ => Resources}/ru.lproj/Localizable.strings (90%) create mode 100644 App/Resources/sv.lproj/Localizable.strings create mode 100644 App/Resources/th.lproj/Localizable.strings rename App/{ => Resources}/tr.lproj/Localizable.strings (91%) create mode 100644 App/Resources/uk.lproj/Localizable.strings rename App/{ => Resources}/wallabag.xcdatamodeld/.xccurrentversion (100%) rename App/{ => Resources}/wallabag.xcdatamodeld/Shared.xcdatamodel/contents (100%) rename App/{ => Resources}/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents (100%) rename App/{ => Resources}/zh-Hans.lproj/Localizable.strings (91%) rename App/{ => Resources}/zh-Hant.lproj/Localizable.strings (91%) delete mode 100644 App/ar.lproj/Localizable.strings delete mode 100644 App/da.lproj/Localizable.strings delete mode 100644 App/fa.lproj/Localizable.strings delete mode 100644 App/gl.lproj/Localizable.strings delete mode 100644 App/hi.lproj/Localizable.strings delete mode 100644 App/hu.lproj/Localizable.strings delete mode 100644 App/ko.lproj/Localizable.strings delete mode 100644 App/nb-NO.lproj/Localizable.strings delete mode 100644 App/oc.lproj/Localizable.strings delete mode 100644 App/pl.lproj/Localizable.strings delete mode 100644 App/pt.lproj/Localizable.strings delete mode 100644 App/ro.lproj/Localizable.strings delete mode 100644 App/sv.lproj/Localizable.strings delete mode 100644 App/th.lproj/Localizable.strings delete mode 100644 App/uk.lproj/Localizable.strings diff --git a/App/Features/Setting/AppSetting.swift b/App/Features/Setting/AppSetting.swift index 264096e9..1ed67264 100644 --- a/App/Features/Setting/AppSetting.swift +++ b/App/Features/Setting/AppSetting.swift @@ -4,18 +4,28 @@ import SharedLib final class AppSetting: ObservableObject { @Published var webFontSizePercent: Double + @Published var theme: Theme private var cancellable = Set() init() { webFontSizePercent = WallabagUserDefaults.webFontSizePercent + theme = Theme(rawValue: WallabagUserDefaults.theme) ?? .auto $webFontSizePercent .sink(receiveValue: updateWebFontSizePercent) .store(in: &cancellable) + + $theme + .sink(receiveValue: updateTheme) + .store(in: &cancellable) } private func updateWebFontSizePercent(_ value: Double) { WallabagUserDefaults.webFontSizePercent = value } + + private func updateTheme(_ value: Theme) { + WallabagUserDefaults.theme = value.rawValue + } } diff --git a/App/Features/Setting/SettingView.swift b/App/Features/Setting/SettingView.swift index 4469c297..cf452046 100644 --- a/App/Features/Setting/SettingView.swift +++ b/App/Features/Setting/SettingView.swift @@ -1,3 +1,4 @@ +import Factory import SharedLib import SwiftUI @@ -7,9 +8,17 @@ struct SettingView: View { @AppStorage("badge") var badge: Bool = true @AppStorage("defaultMode") var defaultMode: String = RetrieveMode.allArticles.rawValue @AppStorage("itemPerPageDuringSync") var itemPerPageDuringSync: Int = 50 + @ObservedObject var appSetting: AppSetting = Container.shared.appSetting() var body: some View { Form { + Section("Appearance") { + Picker("Theme", selection: $appSetting.theme) { + ForEach(Theme.allCases) { theme in + Text(theme.name).tag(theme) + } + } + } Section("Entries list") { Toggle("Show image in list", isOn: $showImageInList) Picker("Default mode", selection: $defaultMode) { diff --git a/App/Lib/Theme.swift b/App/Lib/Theme.swift new file mode 100644 index 00000000..ed3fc472 --- /dev/null +++ b/App/Lib/Theme.swift @@ -0,0 +1,25 @@ +import SwiftUI + +enum Theme: String, CaseIterable, Identifiable { + case auto + case light + case dark + + var id: String { rawValue } + + var colorScheme: ColorScheme? { + switch self { + case .auto: return nil + case .light: return .light + case .dark: return .dark + } + } + + var name: LocalizedStringKey { + switch self { + case .auto: return "Auto" + case .light: return "Light" + case .dark: return "Dark" + } + } +} diff --git a/App/Assets.xcassets/AppIcon.appiconset/Contents.json b/App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/Contents.json rename to App/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/App/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg b/App/Resources/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg rename to App/Resources/Assets.xcassets/AppIcon.appiconset/logo-icon-bg-white-lg.jpg diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac1024.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac1024.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac1024.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac1024.png diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac128.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac128.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac128.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac128.png diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac16.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac16.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac16.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac16.png diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac256.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac256.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac256.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac256.png diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac32.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac32.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac32.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac32.png diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac512.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac512.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac512.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac512.png diff --git a/App/Assets.xcassets/AppIcon.appiconset/mac64.png b/App/Resources/Assets.xcassets/AppIcon.appiconset/mac64.png similarity index 100% rename from App/Assets.xcassets/AppIcon.appiconset/mac64.png rename to App/Resources/Assets.xcassets/AppIcon.appiconset/mac64.png diff --git a/App/Assets.xcassets/Contents.json b/App/Resources/Assets.xcassets/Contents.json similarity index 100% rename from App/Assets.xcassets/Contents.json rename to App/Resources/Assets.xcassets/Contents.json diff --git a/App/Assets.xcassets/logo.imageset/Contents.json b/App/Resources/Assets.xcassets/logo.imageset/Contents.json similarity index 100% rename from App/Assets.xcassets/logo.imageset/Contents.json rename to App/Resources/Assets.xcassets/logo.imageset/Contents.json diff --git a/App/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png b/App/Resources/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png similarity index 100% rename from App/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png rename to App/Resources/Assets.xcassets/logo.imageset/logo-icon-black-no-bg-lg.png diff --git a/App/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png b/App/Resources/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png similarity index 100% rename from App/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png rename to App/Resources/Assets.xcassets/logo.imageset/logo-icon-white-no-bg-lg.png diff --git a/App/WallabagStoreKit.storekit b/App/Resources/WallabagStoreKit.storekit similarity index 100% rename from App/WallabagStoreKit.storekit rename to App/Resources/WallabagStoreKit.storekit diff --git a/App/Resources/ar.lproj/Localizable.strings b/App/Resources/ar.lproj/Localizable.strings new file mode 100644 index 00000000..a7e6b9dd --- /dev/null +++ b/App/Resources/ar.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "المظهر"; +"Theme" = "السمة"; +"Auto" = "تلقائي"; +"Light" = "فاتح"; +"Dark" = "داكن"; diff --git a/App/cs.lproj/Localizable.strings b/App/Resources/cs.lproj/Localizable.strings similarity index 74% rename from App/cs.lproj/Localizable.strings rename to App/Resources/cs.lproj/Localizable.strings index 61a4f91f..8ae83ee8 100644 --- a/App/cs.lproj/Localizable.strings +++ b/App/Resources/cs.lproj/Localizable.strings @@ -17,3 +17,10 @@ // Menu "Menu" = "Nabídka"; + +// Theme +"Appearance" = "Vzhled"; +"Theme" = "Motiv"; +"Auto" = "Automaticky"; +"Light" = "Světlý"; +"Dark" = "Tmavý"; diff --git a/App/Resources/da.lproj/Localizable.strings b/App/Resources/da.lproj/Localizable.strings new file mode 100644 index 00000000..f790fd6e --- /dev/null +++ b/App/Resources/da.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Udseende"; +"Theme" = "Tema"; +"Auto" = "Auto"; +"Light" = "Lyst"; +"Dark" = "Mørkt"; diff --git a/App/de.lproj/Localizable.strings b/App/Resources/de.lproj/Localizable.strings similarity index 91% rename from App/de.lproj/Localizable.strings rename to App/Resources/de.lproj/Localizable.strings index 145857d7..e96b3c56 100644 --- a/App/de.lproj/Localizable.strings +++ b/App/Resources/de.lproj/Localizable.strings @@ -48,3 +48,10 @@ //Player "Select one entry" = "Eintrag auswählen"; + +// Theme +"Appearance" = "Erscheinungsbild"; +"Theme" = "Design"; +"Auto" = "Automatisch"; +"Light" = "Hell"; +"Dark" = "Dunkel"; diff --git a/App/en.lproj/Localizable.strings b/App/Resources/en.lproj/Localizable.strings similarity index 92% rename from App/en.lproj/Localizable.strings rename to App/Resources/en.lproj/Localizable.strings index c7343112..dfc7a36c 100644 --- a/App/en.lproj/Localizable.strings +++ b/App/Resources/en.lproj/Localizable.strings @@ -50,3 +50,10 @@ //Player "Select one entry" = "Select one entry"; + +// Theme +"Appearance" = "Appearance"; +"Theme" = "Theme"; +"Auto" = "Auto"; +"Light" = "Light"; +"Dark" = "Dark"; diff --git a/App/es.lproj/Localizable.strings b/App/Resources/es.lproj/Localizable.strings similarity index 53% rename from App/es.lproj/Localizable.strings rename to App/Resources/es.lproj/Localizable.strings index 8f55ba2c..84df2698 100644 --- a/App/es.lproj/Localizable.strings +++ b/App/Resources/es.lproj/Localizable.strings @@ -1,10 +1,13 @@ - - - - // Tip View "This application is developed on free time" = "Esta aplicación se desarrolla en tiempo libre."; -"Logout" = "Desconectarse"; +"Select one entry" = "Selecciona una entrada"; + +// Theme +"Appearance" = "Apariencia"; +"Theme" = "Tema"; +"Auto" = "Automático"; +"Light" = "Claro"; +"Dark" = "Oscuro"; "Setting" = "Configuración"; "About" = "Acerca de"; diff --git a/App/Resources/fa.lproj/Localizable.strings b/App/Resources/fa.lproj/Localizable.strings new file mode 100644 index 00000000..3e2e63de --- /dev/null +++ b/App/Resources/fa.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "ظاهر"; +"Theme" = "پوسته"; +"Auto" = "خودکار"; +"Light" = "روشن"; +"Dark" = "تیره"; diff --git a/App/fr.lproj/Localizable.strings b/App/Resources/fr.lproj/Localizable.strings similarity index 93% rename from App/fr.lproj/Localizable.strings rename to App/Resources/fr.lproj/Localizable.strings index ace35faf..76be5f7e 100644 --- a/App/fr.lproj/Localizable.strings +++ b/App/Resources/fr.lproj/Localizable.strings @@ -54,3 +54,10 @@ "Order by id" = "Trier par id"; "Order by reading time" = "Trier par temps de lecture"; "Sorting" = "Tri"; + +// Theme +"Appearance" = "Apparence"; +"Theme" = "Thème"; +"Auto" = "Auto"; +"Light" = "Clair"; +"Dark" = "Sombre"; diff --git a/App/Resources/gl.lproj/Localizable.strings b/App/Resources/gl.lproj/Localizable.strings new file mode 100644 index 00000000..154ca5da --- /dev/null +++ b/App/Resources/gl.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Aparencia"; +"Theme" = "Tema"; +"Auto" = "Auto"; +"Light" = "Claro"; +"Dark" = "Escuro"; diff --git a/App/Resources/hi.lproj/Localizable.strings b/App/Resources/hi.lproj/Localizable.strings new file mode 100644 index 00000000..1f4d7196 --- /dev/null +++ b/App/Resources/hi.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "दिखावट"; +"Theme" = "थीम"; +"Auto" = "ऑटो"; +"Light" = "हल्का"; +"Dark" = "गहरा"; diff --git a/App/hr.lproj/Localizable.strings b/App/Resources/hr.lproj/Localizable.strings similarity index 91% rename from App/hr.lproj/Localizable.strings rename to App/Resources/hr.lproj/Localizable.strings index 836379e5..60e0cf39 100644 --- a/App/hr.lproj/Localizable.strings +++ b/App/Resources/hr.lproj/Localizable.strings @@ -48,3 +48,10 @@ //Player "Select one entry" = "Odaberi unos"; + +// Theme +"Appearance" = "Izgled"; +"Theme" = "Tema"; +"Auto" = "Automatski"; +"Light" = "Svijetlo"; +"Dark" = "Tamno"; diff --git a/App/html-ressources/article.html b/App/Resources/html-ressources/article.html similarity index 100% rename from App/html-ressources/article.html rename to App/Resources/html-ressources/article.html diff --git a/App/html-ressources/justify.css b/App/Resources/html-ressources/justify.css similarity index 100% rename from App/html-ressources/justify.css rename to App/Resources/html-ressources/justify.css diff --git a/App/html-ressources/main.css b/App/Resources/html-ressources/main.css similarity index 100% rename from App/html-ressources/main.css rename to App/Resources/html-ressources/main.css diff --git a/App/html-ressources/ratatouille.css b/App/Resources/html-ressources/ratatouille.css similarity index 100% rename from App/html-ressources/ratatouille.css rename to App/Resources/html-ressources/ratatouille.css diff --git a/App/Resources/hu.lproj/Localizable.strings b/App/Resources/hu.lproj/Localizable.strings new file mode 100644 index 00000000..20a56ad8 --- /dev/null +++ b/App/Resources/hu.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Megjelenés"; +"Theme" = "Téma"; +"Auto" = "Automatikus"; +"Light" = "Világos"; +"Dark" = "Sötét"; diff --git a/App/it.lproj/Localizable.strings b/App/Resources/it.lproj/Localizable.strings similarity index 89% rename from App/it.lproj/Localizable.strings rename to App/Resources/it.lproj/Localizable.strings index 29ea2efa..6e91d6e9 100644 --- a/App/it.lproj/Localizable.strings +++ b/App/Resources/it.lproj/Localizable.strings @@ -33,3 +33,10 @@ // Menu "Menu" = "Menù"; + +// Theme +"Appearance" = "Aspetto"; +"Theme" = "Tema"; +"Auto" = "Automatico"; +"Light" = "Chiaro"; +"Dark" = "Scuro"; diff --git a/App/ja.lproj/Localizable.strings b/App/Resources/ja.lproj/Localizable.strings similarity index 92% rename from App/ja.lproj/Localizable.strings rename to App/Resources/ja.lproj/Localizable.strings index 7dc911dd..0dc8f6f5 100644 --- a/App/ja.lproj/Localizable.strings +++ b/App/Resources/ja.lproj/Localizable.strings @@ -42,3 +42,10 @@ "Loading..." = "読み込み中..."; "Don" = "寄付"; "Starred" = "スター"; + +// Theme +"Appearance" = "外観"; +"Theme" = "テーマ"; +"Auto" = "自動"; +"Light" = "ライト"; +"Dark" = "ダーク"; diff --git a/App/Resources/ko.lproj/Localizable.strings b/App/Resources/ko.lproj/Localizable.strings new file mode 100644 index 00000000..a422ac0c --- /dev/null +++ b/App/Resources/ko.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "모양"; +"Theme" = "테마"; +"Auto" = "자동"; +"Light" = "라이트"; +"Dark" = "다크"; diff --git a/App/Resources/nb-NO.lproj/Localizable.strings b/App/Resources/nb-NO.lproj/Localizable.strings new file mode 100644 index 00000000..bf5b369a --- /dev/null +++ b/App/Resources/nb-NO.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Utseende"; +"Theme" = "Tema"; +"Auto" = "Auto"; +"Light" = "Lyst"; +"Dark" = "Mørkt"; diff --git a/App/nl.lproj/Localizable.strings b/App/Resources/nl.lproj/Localizable.strings similarity index 89% rename from App/nl.lproj/Localizable.strings rename to App/Resources/nl.lproj/Localizable.strings index a0fcec4b..0de4d5b5 100644 --- a/App/nl.lproj/Localizable.strings +++ b/App/Resources/nl.lproj/Localizable.strings @@ -33,3 +33,10 @@ "Loading..." = "Laden..."; "But you can contribute financially by making a donation whenever you want to support the project." = "Maar u kunt ook financieel bijdragen door een donatie te doen u het project wilt steunen."; "Entries" = "Items"; + +// Theme +"Appearance" = "Weergave"; +"Theme" = "Thema"; +"Auto" = "Automatisch"; +"Light" = "Licht"; +"Dark" = "Donker"; diff --git a/App/Resources/oc.lproj/Localizable.strings b/App/Resources/oc.lproj/Localizable.strings new file mode 100644 index 00000000..48525484 --- /dev/null +++ b/App/Resources/oc.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Aparéncia"; +"Theme" = "Tèma"; +"Auto" = "Auto"; +"Light" = "Clar"; +"Dark" = "Escur"; diff --git a/App/Resources/pl.lproj/Localizable.strings b/App/Resources/pl.lproj/Localizable.strings new file mode 100644 index 00000000..c9c9c505 --- /dev/null +++ b/App/Resources/pl.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Wygląd"; +"Theme" = "Motyw"; +"Auto" = "Automatyczny"; +"Light" = "Jasny"; +"Dark" = "Ciemny"; diff --git a/App/Resources/pt.lproj/Localizable.strings b/App/Resources/pt.lproj/Localizable.strings new file mode 100644 index 00000000..34d79072 --- /dev/null +++ b/App/Resources/pt.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Aparência"; +"Theme" = "Tema"; +"Auto" = "Automático"; +"Light" = "Claro"; +"Dark" = "Escuro"; diff --git a/App/Resources/ro.lproj/Localizable.strings b/App/Resources/ro.lproj/Localizable.strings new file mode 100644 index 00000000..ff45459e --- /dev/null +++ b/App/Resources/ro.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Aspect"; +"Theme" = "Temă"; +"Auto" = "Auto"; +"Light" = "Luminos"; +"Dark" = "Întunecat"; diff --git a/App/ru.lproj/Localizable.strings b/App/Resources/ru.lproj/Localizable.strings similarity index 90% rename from App/ru.lproj/Localizable.strings rename to App/Resources/ru.lproj/Localizable.strings index 8756b7c3..e58278c0 100644 --- a/App/ru.lproj/Localizable.strings +++ b/App/Resources/ru.lproj/Localizable.strings @@ -40,3 +40,10 @@ // Search "Search" = "Поиск"; + +// Theme +"Appearance" = "Оформление"; +"Theme" = "Тема"; +"Auto" = "Автоматически"; +"Light" = "Светлая"; +"Dark" = "Темная"; diff --git a/App/Resources/sv.lproj/Localizable.strings b/App/Resources/sv.lproj/Localizable.strings new file mode 100644 index 00000000..2388486d --- /dev/null +++ b/App/Resources/sv.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Utseende"; +"Theme" = "Tema"; +"Auto" = "Auto"; +"Light" = "Ljust"; +"Dark" = "Mörkt"; diff --git a/App/Resources/th.lproj/Localizable.strings b/App/Resources/th.lproj/Localizable.strings new file mode 100644 index 00000000..7c3a73c2 --- /dev/null +++ b/App/Resources/th.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "ลักษณะ"; +"Theme" = "ธีม"; +"Auto" = "อัตโนมัติ"; +"Light" = "สว่าง"; +"Dark" = "มืด"; diff --git a/App/tr.lproj/Localizable.strings b/App/Resources/tr.lproj/Localizable.strings similarity index 91% rename from App/tr.lproj/Localizable.strings rename to App/Resources/tr.lproj/Localizable.strings index a997ae60..75ed142b 100644 --- a/App/tr.lproj/Localizable.strings +++ b/App/Resources/tr.lproj/Localizable.strings @@ -46,3 +46,10 @@ //Player "Select one entry" = "Bir makale seçin"; + +// Theme +"Appearance" = "Görünüm"; +"Theme" = "Tema"; +"Auto" = "Otomatik"; +"Light" = "Açık"; +"Dark" = "Koyu"; diff --git a/App/Resources/uk.lproj/Localizable.strings b/App/Resources/uk.lproj/Localizable.strings new file mode 100644 index 00000000..5824c154 --- /dev/null +++ b/App/Resources/uk.lproj/Localizable.strings @@ -0,0 +1,7 @@ + +// Theme +"Appearance" = "Вигляд"; +"Theme" = "Тема"; +"Auto" = "Авто"; +"Light" = "Світла"; +"Dark" = "Темна"; diff --git a/App/wallabag.xcdatamodeld/.xccurrentversion b/App/Resources/wallabag.xcdatamodeld/.xccurrentversion similarity index 100% rename from App/wallabag.xcdatamodeld/.xccurrentversion rename to App/Resources/wallabag.xcdatamodeld/.xccurrentversion diff --git a/App/wallabag.xcdatamodeld/Shared.xcdatamodel/contents b/App/Resources/wallabag.xcdatamodeld/Shared.xcdatamodel/contents similarity index 100% rename from App/wallabag.xcdatamodeld/Shared.xcdatamodel/contents rename to App/Resources/wallabag.xcdatamodeld/Shared.xcdatamodel/contents diff --git a/App/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents b/App/Resources/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents similarity index 100% rename from App/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents rename to App/Resources/wallabagStore.xcdatamodeld/wallabagStore.xcdatamodel/contents diff --git a/App/zh-Hans.lproj/Localizable.strings b/App/Resources/zh-Hans.lproj/Localizable.strings similarity index 91% rename from App/zh-Hans.lproj/Localizable.strings rename to App/Resources/zh-Hans.lproj/Localizable.strings index 3ab3abd5..c9fdca5e 100644 --- a/App/zh-Hans.lproj/Localizable.strings +++ b/App/Resources/zh-Hans.lproj/Localizable.strings @@ -48,3 +48,10 @@ //Player "Select one entry" = "选择一个条目"; + +// Theme +"Appearance" = "外观"; +"Theme" = "主题"; +"Auto" = "自动"; +"Light" = "浅色"; +"Dark" = "深色"; diff --git a/App/zh-Hant.lproj/Localizable.strings b/App/Resources/zh-Hant.lproj/Localizable.strings similarity index 91% rename from App/zh-Hant.lproj/Localizable.strings rename to App/Resources/zh-Hant.lproj/Localizable.strings index f6497a3d..6d005e55 100644 --- a/App/zh-Hant.lproj/Localizable.strings +++ b/App/Resources/zh-Hant.lproj/Localizable.strings @@ -42,3 +42,10 @@ // Menu "Menu" = "菜單"; + +// Theme +"Appearance" = "外觀"; +"Theme" = "主題"; +"Auto" = "自動"; +"Light" = "淺色"; +"Dark" = "深色"; diff --git a/App/WallabagApp.swift b/App/WallabagApp.swift index 97ddb7ad..13f4e43e 100644 --- a/App/WallabagApp.swift +++ b/App/WallabagApp.swift @@ -39,6 +39,7 @@ struct WallabagApp: App { .environment(errorHandler) .environmentObject(appSetting) .environment(\.managedObjectContext, coreData.viewContext) + .preferredColorScheme(appSetting.theme.colorScheme) } .onChange(of: scenePhase) { _, newScenePhase in if newScenePhase == .active { diff --git a/App/ar.lproj/Localizable.strings b/App/ar.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/ar.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/da.lproj/Localizable.strings b/App/da.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/da.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/fa.lproj/Localizable.strings b/App/fa.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/fa.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/gl.lproj/Localizable.strings b/App/gl.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/gl.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/hi.lproj/Localizable.strings b/App/hi.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/hi.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/hu.lproj/Localizable.strings b/App/hu.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/hu.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/ko.lproj/Localizable.strings b/App/ko.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/ko.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/nb-NO.lproj/Localizable.strings b/App/nb-NO.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/nb-NO.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/oc.lproj/Localizable.strings b/App/oc.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/oc.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/pl.lproj/Localizable.strings b/App/pl.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/pl.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/pt.lproj/Localizable.strings b/App/pt.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/pt.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/ro.lproj/Localizable.strings b/App/ro.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/ro.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/sv.lproj/Localizable.strings b/App/sv.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/sv.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/th.lproj/Localizable.strings b/App/th.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/th.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/App/uk.lproj/Localizable.strings b/App/uk.lproj/Localizable.strings deleted file mode 100644 index 8b137891..00000000 --- a/App/uk.lproj/Localizable.strings +++ /dev/null @@ -1 +0,0 @@ - diff --git a/SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift b/SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift index 5140d6b3..32dbd670 100644 --- a/SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift +++ b/SharedLib/Sources/SharedLib/Lib/WallabagUserDefaults.swift @@ -48,4 +48,7 @@ public enum WallabagUserDefaults { @GeneralSetting("itemPerPageDuringSync", defaultValue: 50) public static var itemPerPageDuringSync: Int + + @GeneralSetting("theme", defaultValue: "auto") + public static var theme: String } diff --git a/wallabag.xcodeproj/project.pbxproj b/wallabag.xcodeproj/project.pbxproj index 91a7047d..f6a36304 100644 --- a/wallabag.xcodeproj/project.pbxproj +++ b/wallabag.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 09644B5725C9810A000FFDA1 /* WallabagApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B5625C9810A000FFDA1 /* WallabagApp.swift */; }; 09644B5E25C98116000FFDA1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B5D25C98116000FFDA1 /* AppDelegate.swift */; }; 09644B7E25C98152000FFDA1 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B7D25C98152000FFDA1 /* AppState.swift */; }; + 09FA20240000000000000002 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09FA20240000000000000001 /* Theme.swift */; }; 09644B8C25C98176000FFDA1 /* Route.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B8825C98176000FFDA1 /* Route.swift */; }; 09644B9725C9819F000FFDA1 /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B9425C9819F000FFDA1 /* PlayerView.swift */; }; 09644B9825C9819F000FFDA1 /* PlayerPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09644B9525C9819F000FFDA1 /* PlayerPublisher.swift */; }; @@ -171,6 +172,7 @@ 09644B5625C9810A000FFDA1 /* WallabagApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WallabagApp.swift; sourceTree = ""; }; 09644B5D25C98116000FFDA1 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 09644B7D25C98152000FFDA1 /* AppState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = ""; }; + 09FA20240000000000000001 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; 09644B8825C98176000FFDA1 /* Route.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Route.swift; sourceTree = ""; }; 09644B9425C9819F000FFDA1 /* PlayerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = ""; }; 09644B9525C9819F000FFDA1 /* PlayerPublisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlayerPublisher.swift; sourceTree = ""; }; @@ -399,6 +401,7 @@ 09644B7D25C98152000FFDA1 /* AppState.swift */, 09644BD125C9833D000FFDA1 /* DependencyInjection.swift */, 09644BD325C9833D000FFDA1 /* WallabagError.swift */, + 09FA20240000000000000001 /* Theme.swift */, ); path = Lib; sourceTree = ""; @@ -744,6 +747,18 @@ name = Products; sourceTree = ""; }; + 09FA20300000000000000001 /* Resources */ = { + isa = PBXGroup; + children = ( + 09AD759C2624F93D00708A1E /* html-ressources */, + 09AD75C02624FEEE00708A1E /* Localizable.strings */, + 09644D1E25C98782000FFDA1 /* wallabagStore.xcdatamodeld */, + 0951C61729CC2EB000D8E8C6 /* Assets.xcassets */, + 099CD12E2B5019F40029E94A /* WallabagStoreKit.storekit */, + ); + path = Resources; + sourceTree = ""; + }; 09BFB28625C8348E00E12B4D /* App */ = { isa = PBXGroup; children = ( @@ -753,13 +768,9 @@ 097F824C25CB1B17006C85F6 /* Entity */, 09644D1625C9874D000FFDA1 /* Extension */, 09644B8425C98161000FFDA1 /* Features */, - 09AD759C2624F93D00708A1E /* html-ressources */, 09644B7C25C9814C000FFDA1 /* Lib */, - 09AD75C02624FEEE00708A1E /* Localizable.strings */, 09644BE425C98343000FFDA1 /* PropertyWrapper */, - 09644D1E25C98782000FFDA1 /* wallabagStore.xcdatamodeld */, - 0951C61729CC2EB000D8E8C6 /* Assets.xcassets */, - 099CD12E2B5019F40029E94A /* WallabagStoreKit.storekit */, + 09FA20300000000000000001 /* Resources */, ); path = App; sourceTree = ""; @@ -1067,6 +1078,7 @@ 09644BAF25C98213000FFDA1 /* RefreshButton.swift in Sources */, 09BE0AF42A9F45E900193FBF /* View+Extension.swift in Sources */, 09644C7025C985A9000FFDA1 /* ArchiveEntryButton.swift in Sources */, + 09FA20240000000000000002 /* Theme.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 890f83c3ee93ef2a234b4cf9fa910a56ccc28ee3 Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 24 Feb 2026 20:35:53 +1100 Subject: [PATCH 3/3] use #EnvironmentObject --- App/Features/Setting/SettingView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/App/Features/Setting/SettingView.swift b/App/Features/Setting/SettingView.swift index cf452046..8acafd73 100644 --- a/App/Features/Setting/SettingView.swift +++ b/App/Features/Setting/SettingView.swift @@ -8,7 +8,7 @@ struct SettingView: View { @AppStorage("badge") var badge: Bool = true @AppStorage("defaultMode") var defaultMode: String = RetrieveMode.allArticles.rawValue @AppStorage("itemPerPageDuringSync") var itemPerPageDuringSync: Int = 50 - @ObservedObject var appSetting: AppSetting = Container.shared.appSetting() + @EnvironmentObject var appSetting: AppSetting var body: some View { Form { @@ -44,5 +44,6 @@ struct SettingView: View { struct SettingView_Previews: PreviewProvider { static var previews: some View { SettingView() + .environmentObject(AppSetting()) } }