SettingsView.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import SwiftUI
  2. struct SettingsView: View {
  3. @Bindable var viewModel: SettingsViewModel
  4. @EnvironmentObject private var subscriptions: SubscriptionManager
  5. @EnvironmentObject private var appRating: AppRatingManager
  6. @Environment(AppearanceManager.self) private var appearance
  7. private enum Layout {
  8. static let horizontalPadding: CGFloat = 24
  9. }
  10. var body: some View {
  11. VStack(spacing: 0) {
  12. header
  13. ScrollView {
  14. VStack(alignment: .leading, spacing: 12) {
  15. appearanceSection
  16. shareSection
  17. linksSection
  18. }
  19. .frame(maxWidth: .infinity, alignment: .leading)
  20. .padding(.horizontal, Layout.horizontalPadding)
  21. .padding(.top, 12)
  22. .padding(.bottom, 24)
  23. }
  24. }
  25. .background(AppTheme.background)
  26. }
  27. private var header: some View {
  28. VStack(spacing: 0) {
  29. HStack(spacing: 14) {
  30. ModernSidebarIconView(kind: .settings, size: 40)
  31. VStack(alignment: .leading, spacing: 2) {
  32. Text("Settings")
  33. .font(.system(size: 18, weight: .semibold))
  34. .foregroundStyle(AppTheme.textPrimary)
  35. Text("Manage app preferences")
  36. .font(.system(size: 11))
  37. .foregroundStyle(AppTheme.textSecondary)
  38. }
  39. Spacer()
  40. }
  41. .padding(.horizontal, 24)
  42. .padding(.vertical, 16)
  43. FullWidthDivider()
  44. }
  45. }
  46. private var appearanceSection: some View {
  47. PostFormCard(
  48. title: "Appearance",
  49. subtitle: "Customize how the app looks"
  50. ) {
  51. SettingsToggleRow(
  52. icon: "moon.fill",
  53. title: "Dark Mode",
  54. subtitle: appearance.isDarkMode ? "On" : "Off",
  55. isOn: Binding(
  56. get: { appearance.isDarkMode },
  57. set: { appearance.isDarkMode = $0 }
  58. )
  59. )
  60. }
  61. }
  62. private var shareSection: some View {
  63. PostFormCard(
  64. title: "Share",
  65. subtitle: "Spread the word about \(AppLinks.appName)"
  66. ) {
  67. VStack(spacing: 8) {
  68. SettingsShareAppButton(
  69. message: viewModel.shareMessage,
  70. url: viewModel.shareURL
  71. )
  72. if subscriptions.hasPremiumAccess {
  73. SettingsLinkRow(
  74. icon: "star.fill",
  75. title: "Rate App",
  76. subtitle: "Leave a review on the App Store"
  77. ) {
  78. appRating.requestReviewFromSettings()
  79. }
  80. }
  81. }
  82. }
  83. }
  84. private var linksSection: some View {
  85. PostFormCard(
  86. title: "About",
  87. subtitle: "Website, legal, and help resources"
  88. ) {
  89. VStack(spacing: 8) {
  90. SettingsLinkRow(
  91. icon: "globe",
  92. title: "Website",
  93. subtitle: AppLinks.website.host
  94. ) {
  95. viewModel.openWebsite()
  96. }
  97. SettingsLinkRow(
  98. icon: "hand.raised.fill",
  99. title: "Privacy Policy",
  100. subtitle: "How we handle your data"
  101. ) {
  102. viewModel.openPrivacyPolicy()
  103. }
  104. SettingsLinkRow(
  105. icon: "doc.text.fill",
  106. title: "Terms & Conditions",
  107. subtitle: "Terms of service"
  108. ) {
  109. viewModel.openTermsAndConditions()
  110. }
  111. SettingsLinkRow(
  112. icon: "lifepreserver.fill",
  113. title: "Support",
  114. subtitle: "Get help or send feedback"
  115. ) {
  116. viewModel.openSupport()
  117. }
  118. }
  119. }
  120. }
  121. }
  122. #Preview {
  123. SettingsView(viewModel: SettingsViewModel())
  124. .environmentObject(SubscriptionManager())
  125. .environmentObject(AppRatingManager())
  126. .environment(AppearanceManager.shared)
  127. .frame(width: 800, height: 600)
  128. }