Refactor theme section and styles (#829)

Provide shortcut for section with single row. Redesign Settings
accordingly.
This commit is contained in:
Davide 2024-11-07 15:50:19 +01:00 committed by GitHub
parent 21c1bbdf0d
commit 8ef1e7fbe9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 66 additions and 68 deletions

View File

@ -103,8 +103,7 @@ private extension OnDemandView {
Text($0.localizedDescription)
}
}
.themeSection(footer: policyFooterDescription)
.themeRow(footer: policyFooterDescription)
.themeSectionWithSingleRow(footer: policyFooterDescription)
}
var policyFooterDescription: String {

View File

@ -41,6 +41,7 @@ struct AppleTVSection: View {
debugChanges()
return Group {
availableToggle
.themeRow(footer: footer)
purchaseButton
}
.themeSection(footer: footer)
@ -51,7 +52,6 @@ struct AppleTVSection: View {
private extension AppleTVSection {
var availableToggle: some View {
Toggle(Strings.Modules.General.Rows.appleTv(Strings.Unlocalized.appleTV), isOn: $profileEditor.isAvailableForTV)
.themeRow(footer: footer)
}
var purchaseButton: some View {

View File

@ -39,24 +39,17 @@ struct StorageSection: View {
var body: some View {
debugChanges()
return Group {
sharingToggle
}
.themeSection(
header: Strings.Global.storage,
footer: footer
)
return sharingToggle
.themeSectionWithSingleRow(
header: Strings.Global.storage,
footer: Strings.Modules.General.Sections.Storage.footer
)
}
}
private extension StorageSection {
var sharingToggle: some View {
Toggle(Strings.Modules.General.Rows.icloudSharing, isOn: $profileEditor.isShared)
.themeRow(footer: footer)
}
var footer: String {
Strings.Modules.General.Sections.Storage.footer
}
}

View File

@ -123,7 +123,7 @@ private extension VPNProviderServerView.ServersSubview {
Section {
Toggle(Strings.Providers.onlyFavorites, isOn: $filtersViewModel.onlyShowsFavorites)
}
Section {
Group {
if isFiltering || !servers.isEmpty {
if isFiltering {
ProgressView()
@ -134,9 +134,10 @@ private extension VPNProviderServerView.ServersSubview {
} else {
emptyView
}
} header: {
Text(filtersViewModel.filters.categoryName ?? Strings.Providers.Vpn.Category.any)
}
.themeSection(
header: filtersViewModel.filters.categoryName ?? Strings.Providers.Vpn.Category.any
)
}
}

View File

@ -45,42 +45,34 @@ struct SettingsSectionGroup: View {
private var isErasingiCloud = false
var body: some View {
Group {
#if os(macOS)
keepsInMenuToggle
#endif
#if os(iOS)
lockInBackgroundToggle
lockInBackgroundToggle
#endif
}
.themeSection(header: Strings.Global.general)
Group {
eraseCloudKitButton
.themeRow(footer: iCloudFooter)
}
.themeSection(
header: Strings.Unlocalized.iCloud,
footer: iCloudFooter
)
#if os(macOS)
keepsInMenuToggle
#endif
eraseCloudKitButton
}
}
private extension SettingsSectionGroup {
var keepsInMenuToggle: some View {
Toggle(Strings.Views.Settings.Rows.keepsInMenu, isOn: $keepsInMenu)
Toggle(Strings.Views.Settings.keepsInMenu, isOn: $keepsInMenu)
.themeSectionWithSingleRow(footer: Strings.Views.Settings.KeepsInMenu.footer)
}
var lockInBackgroundToggle: some View {
Toggle(Strings.Views.Settings.Rows.locksInBackground, isOn: $locksInBackground)
Toggle(Strings.Views.Settings.locksInBackground, isOn: $locksInBackground)
.themeSectionWithSingleRow(footer: Strings.Views.Settings.LocksInBackground.footer)
}
var eraseCloudKitButton: some View {
Button(Strings.Views.Settings.Rows.eraseIcloud, role: .destructive) {
Button(Strings.Views.Settings.eraseIcloud, role: .destructive) {
isConfirmingEraseiCloud = true
}
.themeConfirmation(
isPresented: $isConfirmingEraseiCloud,
title: Strings.Views.Settings.Rows.eraseIcloud,
title: Strings.Views.Settings.eraseIcloud,
isDestructive: true
) {
isErasingiCloud = true
@ -94,10 +86,11 @@ private extension SettingsSectionGroup {
isErasingiCloud = false
}
}
.themeSectionWithSingleRow(
header: Strings.Unlocalized.iCloud,
footer: Strings.Views.Settings.EraseIcloud.footer,
above: true
)
.disabled(isErasingiCloud)
}
var iCloudFooter: String {
Strings.Views.Settings.Sections.Icloud.footer
}
}

View File

@ -47,11 +47,10 @@ struct ProfileListView: View {
var body: some View {
List {
Section {
Group {
ForEach(headers, id: \.id, content: toggleButton(for:))
} header: {
Text(Strings.Views.Profiles.Folders.default)
}
.themeSection(header: Strings.Views.Profiles.Folders.default)
}
.listStyle(.grouped)
.scrollClipDisabled()

View File

@ -696,19 +696,23 @@ public enum Strings {
}
}
public enum Settings {
public enum Rows {
/// Erase iCloud store
public static let eraseIcloud = Strings.tr("Localizable", "views.settings.rows.erase_icloud", fallback: "Erase iCloud store")
/// Keep in menu bar
public static let keepsInMenu = Strings.tr("Localizable", "views.settings.rows.keeps_in_menu", fallback: "Keep in menu bar")
/// Lock in background
public static let locksInBackground = Strings.tr("Localizable", "views.settings.rows.locks_in_background", fallback: "Lock in background")
/// Erase iCloud store
public static let eraseIcloud = Strings.tr("Localizable", "views.settings.erase_icloud", fallback: "Erase iCloud store")
/// Keep in menu bar
public static let keepsInMenu = Strings.tr("Localizable", "views.settings.keeps_in_menu", fallback: "Keep in menu bar")
/// Lock in background
public static let locksInBackground = Strings.tr("Localizable", "views.settings.locks_in_background", fallback: "Lock in background")
public enum EraseIcloud {
/// To erase the iCloud store securely, do so on all your synced devices. This will not affect local profiles.
public static let footer = Strings.tr("Localizable", "views.settings.erase_icloud.footer", fallback: "To erase the iCloud store securely, do so on all your synced devices. This will not affect local profiles.")
}
public enum Sections {
public enum Icloud {
/// To erase the iCloud store securely, do so on all your synced devices. This will not affect local profiles.
public static let footer = Strings.tr("Localizable", "views.settings.sections.icloud.footer", fallback: "To erase the iCloud store securely, do so on all your synced devices. This will not affect local profiles.")
}
public enum KeepsInMenu {
/// Enable this to keep the app in the menu bar after closing it.
public static let footer = Strings.tr("Localizable", "views.settings.keeps_in_menu.footer", fallback: "Enable this to keep the app in the menu bar after closing it.")
}
public enum LocksInBackground {
/// Lock the app with FaceID when sent to the background.
public static let footer = Strings.tr("Localizable", "views.settings.locks_in_background.footer", fallback: "Lock the app with FaceID when sent to the background.")
}
}
}

View File

@ -130,10 +130,12 @@
"views.profile.rows.add_module" = "Add module";
"views.profile.module_list.section.footer" = "Drag modules to rearrange them, as their order determines priority.";
"views.settings.sections.icloud.footer" = "To erase the iCloud store securely, do so on all your synced devices. This will not affect local profiles.";
"views.settings.rows.keeps_in_menu" = "Keep in menu bar";
"views.settings.rows.locks_in_background" = "Lock in background";
"views.settings.rows.erase_icloud" = "Erase iCloud store";
"views.settings.keeps_in_menu" = "Keep in menu bar";
"views.settings.keeps_in_menu.footer" = "Enable this to keep the app in the menu bar after closing it.";
"views.settings.locks_in_background" = "Lock in background";
"views.settings.locks_in_background.footer" = "Lock the app with FaceID when sent to the background.";
"views.settings.erase_icloud" = "Erase iCloud store";
"views.settings.erase_icloud.footer" = "To erase the iCloud store securely, do so on all your synced devices. This will not affect local profiles.";
"views.about.title" = "About";
"views.about.sections.resources" = "Resources";

View File

@ -80,7 +80,7 @@ extension View {
}
public func themeForm() -> some View {
modifier(ThemeFormModifier())
formStyle(.grouped)
}
public func themeManualInput() -> some View {
@ -95,6 +95,20 @@ extension View {
modifier(ThemeRowWithFooterModifier(footer: footer))
}
public func themeSectionWithSingleRow(header: String? = nil, footer: String, above: Bool = false) -> some View {
Group {
if above {
EmptyView()
.themeRow(footer: footer)
self
} else {
themeRow(footer: footer)
}
}
.themeSection(header: header, footer: footer)
}
public func themeNavigationDetail() -> some View {
#if os(iOS)
navigationBarTitleDisplayMode(.inline)
@ -278,13 +292,6 @@ struct ThemeNavigationStackModifier: ViewModifier {
// MARK: - Content modifiers
struct ThemeFormModifier: ViewModifier {
func body(content: Content) -> some View {
content
.formStyle(.grouped)
}
}
struct ThemeManualInputModifier: ViewModifier {
}