From ec308468fd2bda499841b2effdadd308fbb2f090 Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 21:14:07 +0900 Subject: [PATCH 1/7] =?UTF-8?q?ui:=20=EC=84=A4=EC=A0=95=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=ED=99=94=EB=A9=B4=20=EC=B9=B4=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/Localizable.xcstrings | 68 +++++++++ .../Sources/Settings/AccountCard.swift | 100 ++++++++++++ .../Sources/Settings/AppInformationCard.swift | 138 +++++++++++++++++ .../Sources/Settings/AppSettingsCard.swift | 97 ++++++++++++ .../Sources/Settings/SettingsView.swift | 143 +++++++----------- 5 files changed, 459 insertions(+), 87 deletions(-) create mode 100644 Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift create mode 100644 Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift create mode 100644 Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift diff --git a/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings b/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings index 98fbec8f..1969d187 100644 --- a/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings +++ b/Application/Presentation/PresentationShared/Resources/Localizable.xcstrings @@ -2699,6 +2699,23 @@ } } }, + "settings_account_section" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Account" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "계정" + } + } + } + }, "settings_alert_delete_account_message" : { "extractionState" : "manual", "localizations" : { @@ -2784,6 +2801,23 @@ } } }, + "settings_delete_account_subtitle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All data will be deleted." + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "모든 데이터가 삭제됩니다." + } + } + } + }, "settings_delete_account_action" : { "extractionState" : "manual", "localizations" : { @@ -2801,6 +2835,40 @@ } } }, + "settings_app_section" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "App Settings" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "앱 설정" + } + } + } + }, + "settings_information_section" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Storage & Information" + } + }, + "ko" : { + "stringUnit" : { + "state" : "translated", + "value" : "저장 공간 및 정보" + } + } + } + }, "settings_join_beta" : { "extractionState" : "manual", "localizations" : { diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift new file mode 100644 index 00000000..5550a8a0 --- /dev/null +++ b/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift @@ -0,0 +1,100 @@ +// +// AccountCard.swift +// ProfileTab +// +// Created by opfic on 9/24/26. +// + +import SwiftUI +import PresentationShared + +struct AccountCard: View { + let isNetworkConnected: Bool + let isLoading: Bool + let showsSignOutProgress: Bool + let onAccount: () -> Void + let onSignOut: () -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + Text("settings_account_section", bundle: PresentationResources.bundle) + .font(.title3) + .foregroundStyle(Color.primary) + .padding(.leading, 4) + + VStack(spacing: 0) { + Button(action: onAccount) { + HStack(spacing: 16) { + Image(systemName: "person.crop.circle") + .font(.title3) + .foregroundStyle(Color.accent) + .frame(width: 48, height: 48) + .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + Text(String(localized: "settings_account", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.primary) + + Spacer(minLength: 8) + + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(Color.textSecondary) + .accessibilityHidden(true) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .opacity(isNetworkConnected ? 1 : 0.5) + .accessibilityElement(children: .combine) + } + .buttonStyle(.plain) + .disabled(!isNetworkConnected) + + Divider() + .padding(.leading, 84) + .padding(.trailing, 20) + .accessibilityHidden(true) + + Button(action: onSignOut) { + HStack(spacing: 16) { + Image(systemName: "rectangle.portrait.and.arrow.right") + .font(.title3) + .foregroundStyle(Color.danger) + .frame(width: 48, height: 48) + .background(Color.danger.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + Text(String(localized: "settings_sign_out", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.danger) + + Spacer(minLength: 8) + + if showsSignOutProgress { + ProgressView() + } + + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(Color.textSecondary) + .accessibilityHidden(true) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .opacity(isNetworkConnected ? 1 : 0.5) + .accessibilityElement(children: .combine) + } + .buttonStyle(.plain) + .disabled(!isNetworkConnected || isLoading) + } + .background(Color.surface, in: RoundedRectangle(cornerRadius: 24)) + .overlay { + RoundedRectangle(cornerRadius: 24) + .strokeBorder(Color.border, lineWidth: 1) + } + } + } +} diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift new file mode 100644 index 00000000..0ac26af8 --- /dev/null +++ b/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift @@ -0,0 +1,138 @@ +// +// AppInformationCard.swift +// ProfileTab +// +// Created by opfic on 9/24/26. +// + +import SwiftUI +import PresentationShared + +struct AppInformationCard: View { + let appVersion: String? + let privacyPolicyURL: URL? + let betaTestURL: URL? + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + Text("settings_information_section", bundle: PresentationResources.bundle) + .font(.title3) + .foregroundStyle(Color.primary) + .padding(.leading, 4) + + VStack(spacing: 0) { + if let appVersion { + HStack(spacing: 16) { + Image(systemName: "info.circle") + .font(.title3) + .foregroundStyle(Color.accent) + .frame(width: 48, height: 48) + .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + Text(String(localized: "settings_version", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.primary) + + Spacer(minLength: 8) + + Text(appVersion) + .foregroundStyle(Color.textSecondary) + .multilineTextAlignment(.trailing) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .accessibilityElement(children: .combine) + } + + if let privacyPolicyURL { + if appVersion != nil { + Divider() + .padding(.leading, 84) + .padding(.trailing, 20) + .accessibilityHidden(true) + } + + Link(destination: privacyPolicyURL) { + HStack(spacing: 16) { + Image(systemName: "doc.text") + .font(.title3) + .foregroundStyle(Color.accent) + .frame(width: 48, height: 48) + .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + Text(String( + localized: "settings_privacy_policy", + bundle: PresentationResources.bundle + )) + .foregroundStyle(Color.primary) + + Spacer(minLength: 8) + + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(Color.textSecondary) + .accessibilityHidden(true) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .accessibilityElement(children: .combine) + } + .buttonStyle(.plain) + } + + if let betaTestURL { + if appVersion != nil || privacyPolicyURL != nil { + Divider() + .padding(.leading, 84) + .padding(.trailing, 20) + .accessibilityHidden(true) + } + + Link(destination: betaTestURL) { + HStack(spacing: 16) { + Image(systemName: "flask") + .font(.title3) + .foregroundStyle(Color.accent) + .frame(width: 48, height: 48) + .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + VStack(alignment: .leading, spacing: 4) { + Text(String(localized: "settings_join_beta", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.primary) + Text(String( + localized: "settings_join_beta_subtitle", + bundle: PresentationResources.bundle + )) + .font(.footnote) + .foregroundStyle(Color.textSecondary) + } + + Spacer(minLength: 8) + + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(Color.textSecondary) + .accessibilityHidden(true) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .accessibilityElement(children: .combine) + } + .buttonStyle(.plain) + } + } + .background(Color.surface, in: RoundedRectangle(cornerRadius: 24)) + .overlay { + RoundedRectangle(cornerRadius: 24) + .strokeBorder(Color.border, lineWidth: 1) + } + } + } +} diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift new file mode 100644 index 00000000..6b19a915 --- /dev/null +++ b/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift @@ -0,0 +1,97 @@ +// +// AppSettingsCard.swift +// ProfileTab +// +// Created by opfic on 9/24/26. +// + +import SwiftUI +import PresentationShared + +struct AppSettingsCard: View { + let themeName: String + let isNetworkConnected: Bool + let onTheme: () -> Void + let onNotifications: () -> Void + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + Text("settings_app_section", bundle: PresentationResources.bundle) + .font(.title3) + .foregroundStyle(Color.primary) + .padding(.leading, 4) + + VStack(spacing: 0) { + Button(action: onTheme) { + HStack(spacing: 16) { + Image(systemName: "desktopcomputer") + .font(.title3) + .foregroundStyle(Color.accent) + .frame(width: 48, height: 48) + .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + Text(String(localized: "settings_theme", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.primary) + + Spacer(minLength: 8) + + Text(themeName) + .foregroundStyle(Color.textSecondary) + .multilineTextAlignment(.trailing) + + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(Color.textSecondary) + .accessibilityHidden(true) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .accessibilityElement(children: .combine) + } + .buttonStyle(.plain) + + Divider() + .padding(.leading, 84) + .padding(.trailing, 20) + .accessibilityHidden(true) + + Button(action: onNotifications) { + HStack(spacing: 16) { + Image(systemName: "bell") + .font(.title3) + .foregroundStyle(Color.accent) + .frame(width: 48, height: 48) + .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .accessibilityHidden(true) + + Text(String(localized: "settings_notifications", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.primary) + + Spacer(minLength: 8) + + Image(systemName: "chevron.right") + .font(.footnote.weight(.semibold)) + .foregroundStyle(Color.textSecondary) + .accessibilityHidden(true) + } + .padding(.horizontal, 20) + .padding(.vertical, 16) + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .opacity(isNetworkConnected ? 1 : 0.5) + .accessibilityElement(children: .combine) + } + .buttonStyle(.plain) + .disabled(!isNetworkConnected) + } + .background(Color.surface, in: RoundedRectangle(cornerRadius: 24)) + .overlay { + RoundedRectangle(cornerRadius: 24) + .strokeBorder(Color.border, lineWidth: 1) + } + } + } +} diff --git a/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift b/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift index 55b5dd38..81338acb 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift @@ -13,101 +13,70 @@ struct SettingsView: View { @Bindable var store: StoreOf let onNavigate: (ProfileRoute) -> Void + private var privacyPolicyURL: URL? { + guard let policyString = store.policyURL else { return nil } + return URL(string: policyString) + } + var body: some View { - let connected = store.isNetworkConnected - Form { - Section { - Button { - onNavigate(.theme) - } label: { - HStack { - Text(String(localized: "settings_theme", bundle: PresentationResources.bundle)) - .foregroundStyle(Color.primary) - Spacer() - Text(store.theme.localizedName(in: PresentationResources.bundle)) - .foregroundStyle(Color.gray) - } - } + ScrollView { + LazyVStack(alignment: .leading, spacing: 32) { + AppSettingsCard( + themeName: store.theme.localizedName(in: PresentationResources.bundle), + isNetworkConnected: store.isNetworkConnected, + onTheme: { onNavigate(.theme) }, + onNotifications: { onNavigate(.pushNotification) } + ) - Button { - onNavigate(.pushNotification) - } label: { - Text(String(localized: "settings_notifications", bundle: PresentationResources.bundle)) - .foregroundStyle(connected ? Color.primary : Color.secondary) + if store.appVersion != nil || privacyPolicyURL != nil || store.betaTestURL != nil { + AppInformationCard( + appVersion: store.appVersion, + privacyPolicyURL: privacyPolicyURL, + betaTestURL: store.betaTestURL + ) } - .disabled(!connected) + AccountCard( + isNetworkConnected: store.isNetworkConnected, + isLoading: store.isLoading, + showsSignOutProgress: store.activeLoadingRow == .signOut, + onAccount: { onNavigate(.account) }, + onSignOut: { store.send(.setAlert(.signOut)) } + ) + + deleteAccountContent } - - Section { - if let appVersion = store.appVersion { - HStack { - Text(String(localized: "settings_version", bundle: PresentationResources.bundle)) - Spacer() - Text(appVersion) - } - } - if let policyString = store.policyURL, - let url = URL(string: policyString) { - Link(destination: url) { - Text(String(localized: "settings_privacy_policy", bundle: PresentationResources.bundle)) - .foregroundColor(Color.blue) - } - } - if let betaTestURL = store.betaTestURL { - Link(destination: betaTestURL) { - VStack(alignment: .leading) { - Text(String(localized: "settings_join_beta", bundle: PresentationResources.bundle)) - .foregroundStyle(Color.primary) - Text(String(localized: "settings_join_beta_subtitle", bundle: PresentationResources.bundle)) - .foregroundStyle(Color.gray) - .font(.caption) - } - } - } - } - - Section { - Button { - onNavigate(.account) - } label: { - Text(String(localized: "settings_account", bundle: PresentationResources.bundle)) - } - .disabled(!connected) - Button { - store.send(.setAlert(.signOut)) - } label: { - HStack { - Text(String(localized: "settings_sign_out", bundle: PresentationResources.bundle)) - .foregroundStyle(.red) - Spacer() - if store.activeLoadingRow == .signOut { - ProgressView() - } - } - } - .disabled(!connected || store.isLoading) - } - - HStack { - Spacer() - Button { - store.send(.setAlert(.deleteAuth)) - } label: { - if store.activeLoadingRow == .deleteAuth { - ProgressView() - } else { - Text(String(localized: "settings_delete_account", bundle: PresentationResources.bundle)) - .foregroundStyle(.red) - .font(.headline) - } - } - .disabled(!connected || store.isLoading) - Spacer() - } + .padding(.horizontal, 20) + .padding(.vertical, 24) } + .background(Color.appBackground) .navigationTitle(String(localized: "nav_settings", bundle: PresentationResources.bundle)) .navigationBarTitleDisplayMode(.inline) .prominentAlert(store, state: \.alert, action: \.alert) } + + private var deleteAccountContent: some View { + VStack(spacing: 16) { + Divider() + + Button { + store.send(.setAlert(.deleteAuth)) + } label: { + if store.activeLoadingRow == .deleteAuth { + ProgressView() + } else { + Text(String(localized: "settings_delete_account", bundle: PresentationResources.bundle)) + .foregroundStyle(Color.danger) + } + } + .buttonStyle(.plain) + .disabled(!store.isNetworkConnected || store.isLoading) + + Text("settings_delete_account_subtitle", bundle: PresentationResources.bundle) + .font(.footnote) + .foregroundStyle(Color.textSecondary) + } + .frame(maxWidth: .infinity) + .padding(.top, 24) + } } From 307e33e411838b61e956b7d04c76640c8766d24e Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 21:17:42 +0900 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/HomeTab/Sources/Category/CheckBox.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Application/Presentation/HomeTab/Sources/Category/CheckBox.swift b/Application/Presentation/HomeTab/Sources/Category/CheckBox.swift index 8eeec0d2..8e0c694f 100644 --- a/Application/Presentation/HomeTab/Sources/Category/CheckBox.swift +++ b/Application/Presentation/HomeTab/Sources/Category/CheckBox.swift @@ -30,7 +30,3 @@ struct CheckBox: View { .font(font) } } - -#Preview { - CheckBox(isChecked: true) -} From c28ce09f6e872f09cb7eb92988ce352c46152565 Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 21:59:20 +0900 Subject: [PATCH 3/7] =?UTF-8?q?refactor:=20NavigationBackButton=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Record/Detail/RecordDetailView.swift | 2 +- .../History/RecordVersionDetailView.swift | 2 +- .../History/RecordVersionHistoryView.swift | 22 +------------ .../Component/NavigationBackButton.swift | 32 +++++++++++++++++++ 4 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 Application/Presentation/PresentationShared/Sources/Common/Component/NavigationBackButton.swift diff --git a/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift b/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift index 21052d09..995c1345 100644 --- a/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/Detail/RecordDetailView.swift @@ -95,7 +95,7 @@ public struct RecordDetailView: View { private var topBar: some View { HStack { - RecordBackButton(action: dismiss.callAsFunction) + NavigationBackButton(action: dismiss.callAsFunction) .disabled(store.isRestoring) Spacer() } diff --git a/Application/Presentation/Development/Sources/Record/History/RecordVersionDetailView.swift b/Application/Presentation/Development/Sources/Record/History/RecordVersionDetailView.swift index 9f76507b..494592a6 100644 --- a/Application/Presentation/Development/Sources/Record/History/RecordVersionDetailView.swift +++ b/Application/Presentation/Development/Sources/Record/History/RecordVersionDetailView.swift @@ -51,7 +51,7 @@ struct RecordVersionDetailView: View { private var topBar: some View { HStack { - RecordBackButton(action: dismiss.callAsFunction) + NavigationBackButton(action: dismiss.callAsFunction) .disabled(store.isRestoring) Spacer() } diff --git a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift index e6dde50e..fdac4f37 100644 --- a/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift +++ b/Application/Presentation/Development/Sources/Record/History/RecordVersionHistoryView.swift @@ -47,7 +47,7 @@ struct RecordVersionHistoryView: View { private var topBar: some View { HStack { - RecordBackButton(action: dismiss.callAsFunction) + NavigationBackButton(action: dismiss.callAsFunction) Spacer() } .padding(.horizontal) @@ -264,26 +264,6 @@ struct RecordVersionBadge: View { } } -struct RecordBackButton: View { - let action: () -> Void - - var body: some View { - if #available(iOS 26.0, *) { - Button(action: action) { - Image(systemName: "chevron.left") - } - .topBarButtonStyle() - } else { - Button(action: action) { - Image(systemName: "chevron.left") - .font(.title3.weight(.semibold)) - .frame(width: 28, height: 28) - } - .adaptiveButtonStyle(shape: .circle, color: .surface, glassEffect: .enabled) - } - } -} - private struct VersionDestination: Identifiable { let version: DevelopmentRecord.Version var id: String { version.id } diff --git a/Application/Presentation/PresentationShared/Sources/Common/Component/NavigationBackButton.swift b/Application/Presentation/PresentationShared/Sources/Common/Component/NavigationBackButton.swift new file mode 100644 index 00000000..c0020d53 --- /dev/null +++ b/Application/Presentation/PresentationShared/Sources/Common/Component/NavigationBackButton.swift @@ -0,0 +1,32 @@ +// +// NavigationBackButton.swift +// PresentationShared +// +// Created by opfic on 9/24/26. +// + +import SwiftUI + +public struct NavigationBackButton: View { + private let action: () -> Void + + public init(action: @escaping () -> Void) { + self.action = action + } + + public var body: some View { + if #available(iOS 26.0, *) { + Button(action: action) { + Image(systemName: "chevron.left") + } + .topBarButtonStyle() + } else { + Button(action: action) { + Image(systemName: "chevron.left") + .font(.title3.weight(.semibold)) + .frame(width: 28, height: 28) + } + .adaptiveButtonStyle(shape: .circle, color: .surface, glassEffect: .enabled) + } + } +} From 8778e26aafea193993fc648d85394a0bc27dd7eb Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 21:59:38 +0900 Subject: [PATCH 4/7] =?UTF-8?q?ui:=20=EC=84=A4=EC=A0=95=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=ED=83=91=EB=B0=94=EC=99=80=20=EC=B9=B4=EB=93=9C=20?= =?UTF-8?q?=ED=91=9C=ED=98=84=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Settings/AccountCard.swift | 36 +++----- .../Sources/Settings/AppInformationCard.swift | 51 +++++------ .../Sources/Settings/AppSettingsCard.swift | 36 +++----- .../Sources/Settings/SettingsView.swift | 91 ++++++++++++------- 4 files changed, 111 insertions(+), 103 deletions(-) diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift index 5550a8a0..206fc257 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift @@ -9,6 +9,7 @@ import SwiftUI import PresentationShared struct AccountCard: View { + @ScaledMetric(relativeTo: .headline) private var iconSize = 36 let isNetworkConnected: Bool let isLoading: Bool let showsSignOutProgress: Bool @@ -18,18 +19,17 @@ struct AccountCard: View { var body: some View { VStack(alignment: .leading, spacing: 16) { Text("settings_account_section", bundle: PresentationResources.bundle) - .font(.title3) + .font(.title3.bold()) .foregroundStyle(Color.primary) - .padding(.leading, 4) VStack(spacing: 0) { Button(action: onAccount) { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "person.crop.circle") - .font(.title3) + .font(.headline) .foregroundStyle(Color.accent) - .frame(width: 48, height: 48) - .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_account", bundle: PresentationResources.bundle)) @@ -42,8 +42,7 @@ struct AccountCard: View { .foregroundStyle(Color.textSecondary) .accessibilityHidden(true) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) .opacity(isNetworkConnected ? 1 : 0.5) @@ -53,17 +52,17 @@ struct AccountCard: View { .disabled(!isNetworkConnected) Divider() - .padding(.leading, 84) - .padding(.trailing, 20) + .padding(.leading, 64) + .padding(.trailing, 16) .accessibilityHidden(true) Button(action: onSignOut) { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "rectangle.portrait.and.arrow.right") - .font(.title3) + .font(.headline) .foregroundStyle(Color.danger) - .frame(width: 48, height: 48) - .background(Color.danger.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.danger.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_sign_out", bundle: PresentationResources.bundle)) @@ -80,8 +79,7 @@ struct AccountCard: View { .foregroundStyle(Color.textSecondary) .accessibilityHidden(true) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) .opacity(isNetworkConnected ? 1 : 0.5) @@ -90,11 +88,7 @@ struct AccountCard: View { .buttonStyle(.plain) .disabled(!isNetworkConnected || isLoading) } - .background(Color.surface, in: RoundedRectangle(cornerRadius: 24)) - .overlay { - RoundedRectangle(cornerRadius: 24) - .strokeBorder(Color.border, lineWidth: 1) - } + .background(Color.surface, in: .rect(cornerRadius: 16)) } } } diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift index 0ac26af8..1d01cc92 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift @@ -9,6 +9,7 @@ import SwiftUI import PresentationShared struct AppInformationCard: View { + @ScaledMetric(relativeTo: .headline) private var iconSize = 36 let appVersion: String? let privacyPolicyURL: URL? let betaTestURL: URL? @@ -16,18 +17,17 @@ struct AppInformationCard: View { var body: some View { VStack(alignment: .leading, spacing: 16) { Text("settings_information_section", bundle: PresentationResources.bundle) - .font(.title3) + .font(.title3.bold()) .foregroundStyle(Color.primary) - .padding(.leading, 4) VStack(spacing: 0) { if let appVersion { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "info.circle") - .font(.title3) + .font(.headline) .foregroundStyle(Color.accent) - .frame(width: 48, height: 48) - .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_version", bundle: PresentationResources.bundle)) @@ -39,8 +39,7 @@ struct AppInformationCard: View { .foregroundStyle(Color.textSecondary) .multilineTextAlignment(.trailing) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .accessibilityElement(children: .combine) } @@ -48,18 +47,18 @@ struct AppInformationCard: View { if let privacyPolicyURL { if appVersion != nil { Divider() - .padding(.leading, 84) - .padding(.trailing, 20) + .padding(.leading, 64) + .padding(.trailing, 16) .accessibilityHidden(true) } Link(destination: privacyPolicyURL) { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "doc.text") - .font(.title3) + .font(.headline) .foregroundStyle(Color.accent) - .frame(width: 48, height: 48) - .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) Text(String( @@ -75,8 +74,7 @@ struct AppInformationCard: View { .foregroundStyle(Color.textSecondary) .accessibilityHidden(true) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) .accessibilityElement(children: .combine) @@ -87,18 +85,18 @@ struct AppInformationCard: View { if let betaTestURL { if appVersion != nil || privacyPolicyURL != nil { Divider() - .padding(.leading, 84) - .padding(.trailing, 20) + .padding(.leading, 64) + .padding(.trailing, 16) .accessibilityHidden(true) } Link(destination: betaTestURL) { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "flask") - .font(.title3) + .font(.headline) .foregroundStyle(Color.accent) - .frame(width: 48, height: 48) - .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 4) { @@ -119,8 +117,7 @@ struct AppInformationCard: View { .foregroundStyle(Color.textSecondary) .accessibilityHidden(true) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) .accessibilityElement(children: .combine) @@ -128,11 +125,7 @@ struct AppInformationCard: View { .buttonStyle(.plain) } } - .background(Color.surface, in: RoundedRectangle(cornerRadius: 24)) - .overlay { - RoundedRectangle(cornerRadius: 24) - .strokeBorder(Color.border, lineWidth: 1) - } + .background(Color.surface, in: .rect(cornerRadius: 16)) } } } diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift index 6b19a915..7974b70e 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift @@ -9,6 +9,7 @@ import SwiftUI import PresentationShared struct AppSettingsCard: View { + @ScaledMetric(relativeTo: .headline) private var iconSize = 36 let themeName: String let isNetworkConnected: Bool let onTheme: () -> Void @@ -17,18 +18,17 @@ struct AppSettingsCard: View { var body: some View { VStack(alignment: .leading, spacing: 16) { Text("settings_app_section", bundle: PresentationResources.bundle) - .font(.title3) + .font(.title3.bold()) .foregroundStyle(Color.primary) - .padding(.leading, 4) VStack(spacing: 0) { Button(action: onTheme) { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "desktopcomputer") - .font(.title3) + .font(.headline) .foregroundStyle(Color.accent) - .frame(width: 48, height: 48) - .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_theme", bundle: PresentationResources.bundle)) @@ -45,8 +45,7 @@ struct AppSettingsCard: View { .foregroundStyle(Color.textSecondary) .accessibilityHidden(true) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) .accessibilityElement(children: .combine) @@ -54,17 +53,17 @@ struct AppSettingsCard: View { .buttonStyle(.plain) Divider() - .padding(.leading, 84) - .padding(.trailing, 20) + .padding(.leading, 64) + .padding(.trailing, 16) .accessibilityHidden(true) Button(action: onNotifications) { - HStack(spacing: 16) { + HStack(spacing: 12) { Image(systemName: "bell") - .font(.title3) + .font(.headline) .foregroundStyle(Color.accent) - .frame(width: 48, height: 48) - .background(Color.accent.opacity(0.09), in: RoundedRectangle(cornerRadius: 16)) + .frame(width: iconSize, height: iconSize) + .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_notifications", bundle: PresentationResources.bundle)) @@ -77,8 +76,7 @@ struct AppSettingsCard: View { .foregroundStyle(Color.textSecondary) .accessibilityHidden(true) } - .padding(.horizontal, 20) - .padding(.vertical, 16) + .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) .opacity(isNetworkConnected ? 1 : 0.5) @@ -87,11 +85,7 @@ struct AppSettingsCard: View { .buttonStyle(.plain) .disabled(!isNetworkConnected) } - .background(Color.surface, in: RoundedRectangle(cornerRadius: 24)) - .overlay { - RoundedRectangle(cornerRadius: 24) - .strokeBorder(Color.border, lineWidth: 1) - } + .background(Color.surface, in: .rect(cornerRadius: 16)) } } } diff --git a/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift b/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift index 81338acb..a49145b8 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift @@ -10,6 +10,8 @@ import Domain import PresentationShared struct SettingsView: View { + @Environment(\.dismiss) private var dismiss + @ScaledMetric(relativeTo: .body) private var deleteAccountButtonHeight = CGFloat(22) @Bindable var store: StoreOf let onNavigate: (ProfileRoute) -> Void @@ -20,54 +22,79 @@ struct SettingsView: View { var body: some View { ScrollView { - LazyVStack(alignment: .leading, spacing: 32) { - AppSettingsCard( - themeName: store.theme.localizedName(in: PresentationResources.bundle), - isNetworkConnected: store.isNetworkConnected, - onTheme: { onNavigate(.theme) }, - onNotifications: { onNavigate(.pushNotification) } - ) + LazyVStack(alignment: .leading, spacing: 24, pinnedViews: [.sectionHeaders]) { + Section { + AppSettingsCard( + themeName: store.theme.localizedName(in: PresentationResources.bundle), + isNetworkConnected: store.isNetworkConnected, + onTheme: { onNavigate(.theme) }, + onNotifications: { onNavigate(.pushNotification) } + ) + + if store.appVersion != nil || privacyPolicyURL != nil || store.betaTestURL != nil { + AppInformationCard( + appVersion: store.appVersion, + privacyPolicyURL: privacyPolicyURL, + betaTestURL: store.betaTestURL + ) + } - if store.appVersion != nil || privacyPolicyURL != nil || store.betaTestURL != nil { - AppInformationCard( - appVersion: store.appVersion, - privacyPolicyURL: privacyPolicyURL, - betaTestURL: store.betaTestURL + AccountCard( + isNetworkConnected: store.isNetworkConnected, + isLoading: store.isLoading, + showsSignOutProgress: store.activeLoadingRow == .signOut, + onAccount: { onNavigate(.account) }, + onSignOut: { store.send(.setAlert(.signOut)) } ) + + deleteAccountContent + } header: { + topBar } + } + .toolbarVisibility(.hidden, for: .navigationBar) + .padding(.horizontal, 16) + .padding(.bottom, 24) + } + .background(Color.appBackground) + .prominentAlert(store, state: \.alert, action: \.alert) + } - AccountCard( - isNetworkConnected: store.isNetworkConnected, - isLoading: store.isLoading, - showsSignOutProgress: store.activeLoadingRow == .signOut, - onAccount: { onNavigate(.account) }, - onSignOut: { store.send(.setAlert(.signOut)) } - ) + private var topBar: some View { + ZStack { + Text(String(localized: "nav_settings", bundle: PresentationResources.bundle)) + .font(.headline) - deleteAccountContent + HStack { + NavigationBackButton(action: dismiss.callAsFunction) + Spacer() } - .padding(.horizontal, 20) - .padding(.vertical, 24) } + .padding(.vertical, 12) .background(Color.appBackground) - .navigationTitle(String(localized: "nav_settings", bundle: PresentationResources.bundle)) - .navigationBarTitleDisplayMode(.inline) - .prominentAlert(store, state: \.alert, action: \.alert) + .toolbarBackground(Color.appBackground) } private var deleteAccountContent: some View { VStack(spacing: 16) { - Divider() - Button { store.send(.setAlert(.deleteAuth)) } label: { - if store.activeLoadingRow == .deleteAuth { - ProgressView() - } else { - Text(String(localized: "settings_delete_account", bundle: PresentationResources.bundle)) - .foregroundStyle(Color.danger) + Group { + if store.activeLoadingRow == .deleteAuth { + ProgressView() + .tint(Color.danger) + } else { + Text(String(localized: "settings_delete_account", bundle: PresentationResources.bundle)) + .bold() + .foregroundStyle(Color.danger) + } } + .font(.system(.body)) + .contentShape(.rect(cornerRadius: 12)) + .frame(maxWidth: .infinity) + .frame(height: deleteAccountButtonHeight + 24) + .background(Color.surface, in: .rect(cornerRadius: 12)) } .buttonStyle(.plain) .disabled(!store.isNetworkConnected || store.isLoading) From b28c9ac1390fcba32705c8a30803f8911ab4ed80 Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 22:04:42 +0900 Subject: [PATCH 5/7] =?UTF-8?q?ui:=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=ED=83=91=EB=B0=94=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=ED=91=9C=ED=98=84=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Profile/ProfileView.swift | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift index 2f3d2fa9..1a293234 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/ProfileView.swift @@ -91,22 +91,12 @@ public struct ProfileView: View { Text("nav_profile", bundle: PresentationResources.bundle) .font(.largeTitle.bold()) Spacer() - if #available(iOS 26.0, *) { - Button { - path.append(.settings) - } label: { - Image(systemName: "gearshape") - } - .topBarButtonStyle() - } else { - Button { - path.append(.settings) - } label: { - Image(systemName: "gearshape") - .foregroundStyle(Color.textTertiary) - } - .adaptiveButtonStyle() + Button { + path.append(.settings) + } label: { + Image(systemName: "gearshape") } + .topBarButtonStyle() } } .padding(.bottom, 8) From 8670cdaba16be25ac8c1de5a7b77a67222d5a988 Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 22:07:46 +0900 Subject: [PATCH 6/7] =?UTF-8?q?ui:=20=ED=83=91=EB=B0=94=20=EC=83=81?= =?UTF-8?q?=EB=8B=A8=20=ED=8C=A8=EB=94=A9=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Presentation/ProfileTab/Sources/Settings/SettingsView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift b/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift index a49145b8..e77642ae 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/SettingsView.swift @@ -70,7 +70,7 @@ struct SettingsView: View { Spacer() } } - .padding(.vertical, 12) + .padding(.bottom, 12) .background(Color.appBackground) .toolbarBackground(Color.appBackground) } From 67481d5fe1e5761dd4449742bf0cbb45a074e620 Mon Sep 17 00:00:00 2001 From: opficdev Date: Thu, 24 Sep 2026 22:19:27 +0900 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20iconStyle=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeTab/Sources/Home/HomeView.swift | 29 ++++------------- .../Sources/Extension/View+IconStyle.swift | 32 +++++++++++++++++++ .../Sources/Profile/GoalSummaryCard.swift | 3 +- .../Sources/Profile/RecentActivityCard.swift | 6 ++-- .../Sources/Settings/AccountCard.swift | 6 ++-- .../Sources/Settings/AppInformationCard.swift | 9 ++---- .../Sources/Settings/AppSettingsCard.swift | 6 ++-- 7 files changed, 51 insertions(+), 40 deletions(-) create mode 100644 Application/Presentation/PresentationShared/Sources/Extension/View+IconStyle.swift diff --git a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift index f4e7f6c1..939822a1 100644 --- a/Application/Presentation/HomeTab/Sources/Home/HomeView.swift +++ b/Application/Presentation/HomeTab/Sources/Home/HomeView.swift @@ -12,7 +12,6 @@ import Domain import PresentationShared public struct HomeView: View { - @Environment(\.colorScheme) private var colorScheme @Environment(\.dynamicTypeSize) private var dynamicTypeSize @Environment(\.openWindow) private var openWindow @Environment(\.isiOSAppOnMac) private var isiOSAppOnMac @@ -341,14 +340,14 @@ public struct HomeView: View { private func todoCategoryRow(_ item: TodoCategoryItem) -> some View { NavigationLink(value: HomeRoute.category(item)) { VStack(spacing: 10) { - RoundedRectangle(cornerRadius: 20) - .fill(categoryIconBackground(item)) + Image(systemName: item.symbolName) + .font(.title2.bold()) .frame(width: categoryIconSize, height: categoryIconSize) - .overlay { - Image(systemName: item.symbolName) - .font(.title2.bold()) - .foregroundStyle(categoryIconForeground(item)) - } + .iconStyle( + color: item.color, + in: RoundedRectangle(cornerRadius: 20) + ) + .accessibilityHidden(true) Text(item.localizedName) .font(.subheadline) .foregroundStyle(Color.textSecondary) @@ -394,20 +393,6 @@ public struct HomeView: View { store.send(.view(.tapTodoCategory(todoCategory))) } } - private func categoryIconBackground(_ item: TodoCategoryItem) -> Color { - if colorScheme == .dark { - return item.color - } - - return item.color.opacity(0.12) - } - private func categoryIconForeground(_ item: TodoCategoryItem) -> Color { - if colorScheme == .dark { - return .white - } - - return item.color - } private func refreshDevelopmentGoals() { store.send(.view(.fetchData)) } diff --git a/Application/Presentation/PresentationShared/Sources/Extension/View+IconStyle.swift b/Application/Presentation/PresentationShared/Sources/Extension/View+IconStyle.swift new file mode 100644 index 00000000..2437c8d7 --- /dev/null +++ b/Application/Presentation/PresentationShared/Sources/Extension/View+IconStyle.swift @@ -0,0 +1,32 @@ +// +// View+IconStyle.swift +// PresentationShared +// +// Created by opfic on 9/24/26. +// + +import SwiftUI + +public extension View { + func iconStyle( + color: Color, + in shape: S + ) -> some View { + modifier(IconStyleModifier(color: color, shape: shape)) + } +} + +private struct IconStyleModifier: ViewModifier { + @Environment(\.colorScheme) private var colorScheme + let color: Color + let shape: S + + func body(content: Content) -> some View { + content + .foregroundStyle(colorScheme == .dark ? Color.white : color) + .background( + colorScheme == .dark ? color : color.opacity(0.12), + in: shape + ) + } +} diff --git a/Application/Presentation/ProfileTab/Sources/Profile/GoalSummaryCard.swift b/Application/Presentation/ProfileTab/Sources/Profile/GoalSummaryCard.swift index 7220ebdc..15deedb1 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/GoalSummaryCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/GoalSummaryCard.swift @@ -102,9 +102,8 @@ struct GoalSummaryCard: View { VStack(spacing: 8) { Image(systemName: symbol) .font(.subheadline.weight(.semibold)) - .foregroundStyle(color) .frame(width: 36, height: 36) - .background(Color.surface, in: .circle) + .iconStyle(color: color, in: Circle()) Text(title, bundle: PresentationResources.bundle) .font(.caption) .foregroundStyle(Color.textSecondary) diff --git a/Application/Presentation/ProfileTab/Sources/Profile/RecentActivityCard.swift b/Application/Presentation/ProfileTab/Sources/Profile/RecentActivityCard.swift index f8a11522..b561148d 100644 --- a/Application/Presentation/ProfileTab/Sources/Profile/RecentActivityCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Profile/RecentActivityCard.swift @@ -55,9 +55,11 @@ private struct RecentTodoCard: View { HStack(spacing: 12) { Image(systemName: category.symbolName) .font(.title3.weight(.semibold)) - .foregroundStyle(category.color) .frame(width: iconSize, height: iconSize) - .background(category.color.opacity(0.1), in: RoundedRectangle(cornerRadius: 12)) + .iconStyle( + color: category.color, + in: RoundedRectangle(cornerRadius: 12) + ) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 8) { diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift index 206fc257..f1eab7a6 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/AccountCard.swift @@ -27,9 +27,8 @@ struct AccountCard: View { HStack(spacing: 12) { Image(systemName: "person.crop.circle") .font(.headline) - .foregroundStyle(Color.accent) .frame(width: iconSize, height: iconSize) - .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .accent, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_account", bundle: PresentationResources.bundle)) @@ -60,9 +59,8 @@ struct AccountCard: View { HStack(spacing: 12) { Image(systemName: "rectangle.portrait.and.arrow.right") .font(.headline) - .foregroundStyle(Color.danger) .frame(width: iconSize, height: iconSize) - .background(Color.danger.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .danger, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_sign_out", bundle: PresentationResources.bundle)) diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift index 1d01cc92..c867129d 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/AppInformationCard.swift @@ -25,9 +25,8 @@ struct AppInformationCard: View { HStack(spacing: 12) { Image(systemName: "info.circle") .font(.headline) - .foregroundStyle(Color.accent) .frame(width: iconSize, height: iconSize) - .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .accent, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_version", bundle: PresentationResources.bundle)) @@ -56,9 +55,8 @@ struct AppInformationCard: View { HStack(spacing: 12) { Image(systemName: "doc.text") .font(.headline) - .foregroundStyle(Color.accent) .frame(width: iconSize, height: iconSize) - .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .accent, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) Text(String( @@ -94,9 +92,8 @@ struct AppInformationCard: View { HStack(spacing: 12) { Image(systemName: "flask") .font(.headline) - .foregroundStyle(Color.accent) .frame(width: iconSize, height: iconSize) - .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .accent, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) VStack(alignment: .leading, spacing: 4) { diff --git a/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift b/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift index 7974b70e..b255fb25 100644 --- a/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift +++ b/Application/Presentation/ProfileTab/Sources/Settings/AppSettingsCard.swift @@ -26,9 +26,8 @@ struct AppSettingsCard: View { HStack(spacing: 12) { Image(systemName: "desktopcomputer") .font(.headline) - .foregroundStyle(Color.accent) .frame(width: iconSize, height: iconSize) - .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .accent, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_theme", bundle: PresentationResources.bundle)) @@ -61,9 +60,8 @@ struct AppSettingsCard: View { HStack(spacing: 12) { Image(systemName: "bell") .font(.headline) - .foregroundStyle(Color.accent) .frame(width: iconSize, height: iconSize) - .background(Color.accent.opacity(0.09), in: .rect(cornerRadius: 10)) + .iconStyle(color: .accent, in: RoundedRectangle(cornerRadius: 10)) .accessibilityHidden(true) Text(String(localized: "settings_notifications", bundle: PresentationResources.bundle))