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) Text($0.localizedDescription)
} }
} }
.themeSection(footer: policyFooterDescription) .themeSectionWithSingleRow(footer: policyFooterDescription)
.themeRow(footer: policyFooterDescription)
} }
var policyFooterDescription: String { var policyFooterDescription: String {

View File

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

View File

@ -39,24 +39,17 @@ struct StorageSection: View {
var body: some View { var body: some View {
debugChanges() debugChanges()
return Group { return sharingToggle
sharingToggle .themeSectionWithSingleRow(
} header: Strings.Global.storage,
.themeSection( footer: Strings.Modules.General.Sections.Storage.footer
header: Strings.Global.storage, )
footer: footer
)
} }
} }
private extension StorageSection { private extension StorageSection {
var sharingToggle: some View { var sharingToggle: some View {
Toggle(Strings.Modules.General.Rows.icloudSharing, isOn: $profileEditor.isShared) 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 { Section {
Toggle(Strings.Providers.onlyFavorites, isOn: $filtersViewModel.onlyShowsFavorites) Toggle(Strings.Providers.onlyFavorites, isOn: $filtersViewModel.onlyShowsFavorites)
} }
Section { Group {
if isFiltering || !servers.isEmpty { if isFiltering || !servers.isEmpty {
if isFiltering { if isFiltering {
ProgressView() ProgressView()
@ -134,9 +134,10 @@ private extension VPNProviderServerView.ServersSubview {
} else { } else {
emptyView 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 private var isErasingiCloud = false
var body: some View { var body: some View {
Group {
#if os(macOS)
keepsInMenuToggle
#endif
#if os(iOS) #if os(iOS)
lockInBackgroundToggle lockInBackgroundToggle
#endif #endif
} #if os(macOS)
.themeSection(header: Strings.Global.general) keepsInMenuToggle
Group { #endif
eraseCloudKitButton eraseCloudKitButton
.themeRow(footer: iCloudFooter)
}
.themeSection(
header: Strings.Unlocalized.iCloud,
footer: iCloudFooter
)
} }
} }
private extension SettingsSectionGroup { private extension SettingsSectionGroup {
var keepsInMenuToggle: some View { 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 { 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 { var eraseCloudKitButton: some View {
Button(Strings.Views.Settings.Rows.eraseIcloud, role: .destructive) { Button(Strings.Views.Settings.eraseIcloud, role: .destructive) {
isConfirmingEraseiCloud = true isConfirmingEraseiCloud = true
} }
.themeConfirmation( .themeConfirmation(
isPresented: $isConfirmingEraseiCloud, isPresented: $isConfirmingEraseiCloud,
title: Strings.Views.Settings.Rows.eraseIcloud, title: Strings.Views.Settings.eraseIcloud,
isDestructive: true isDestructive: true
) { ) {
isErasingiCloud = true isErasingiCloud = true
@ -94,10 +86,11 @@ private extension SettingsSectionGroup {
isErasingiCloud = false isErasingiCloud = false
} }
} }
.themeSectionWithSingleRow(
header: Strings.Unlocalized.iCloud,
footer: Strings.Views.Settings.EraseIcloud.footer,
above: true
)
.disabled(isErasingiCloud) .disabled(isErasingiCloud)
} }
var iCloudFooter: String {
Strings.Views.Settings.Sections.Icloud.footer
}
} }

View File

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

View File

@ -696,19 +696,23 @@ public enum Strings {
} }
} }
public enum Settings { public enum Settings {
public enum Rows { /// Erase iCloud store
/// Erase iCloud store public static let eraseIcloud = Strings.tr("Localizable", "views.settings.erase_icloud", fallback: "Erase iCloud store")
public static let eraseIcloud = Strings.tr("Localizable", "views.settings.rows.erase_icloud", fallback: "Erase iCloud store") /// Keep in menu bar
/// Keep in menu bar public static let keepsInMenu = Strings.tr("Localizable", "views.settings.keeps_in_menu", fallback: "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
/// Lock in background public static let locksInBackground = Strings.tr("Localizable", "views.settings.locks_in_background", fallback: "Lock in background")
public static let locksInBackground = Strings.tr("Localizable", "views.settings.rows.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 KeepsInMenu {
public enum Icloud { /// Enable this to keep the app in the menu bar after closing it.
/// 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.keeps_in_menu.footer", fallback: "Enable this to keep the app in the menu bar after closing it.")
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 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.rows.add_module" = "Add module";
"views.profile.module_list.section.footer" = "Drag modules to rearrange them, as their order determines priority."; "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.keeps_in_menu" = "Keep in menu bar";
"views.settings.rows.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.rows.locks_in_background" = "Lock in background"; "views.settings.locks_in_background" = "Lock in background";
"views.settings.rows.erase_icloud" = "Erase iCloud store"; "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.title" = "About";
"views.about.sections.resources" = "Resources"; "views.about.sections.resources" = "Resources";

View File

@ -80,7 +80,7 @@ extension View {
} }
public func themeForm() -> some View { public func themeForm() -> some View {
modifier(ThemeFormModifier()) formStyle(.grouped)
} }
public func themeManualInput() -> some View { public func themeManualInput() -> some View {
@ -95,6 +95,20 @@ extension View {
modifier(ThemeRowWithFooterModifier(footer: footer)) 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 { public func themeNavigationDetail() -> some View {
#if os(iOS) #if os(iOS)
navigationBarTitleDisplayMode(.inline) navigationBarTitleDisplayMode(.inline)
@ -278,13 +292,6 @@ struct ThemeNavigationStackModifier: ViewModifier {
// MARK: - Content modifiers // MARK: - Content modifiers
struct ThemeFormModifier: ViewModifier {
func body(content: Content) -> some View {
content
.formStyle(.grouped)
}
}
struct ThemeManualInputModifier: ViewModifier { struct ThemeManualInputModifier: ViewModifier {
} }