FrontPageView.swift 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import SwiftUI
  2. struct FrontPageView: View {
  3. @EnvironmentObject private var subscriptions: SubscriptionManager
  4. @State private var viewModel = FrontPageViewModel()
  5. @State private var paywallViewModel = PaywallViewModel()
  6. @State private var postGeneratorViewModel = PostGeneratorViewModel()
  7. @State private var titleOptimizerViewModel = TitleOptimizerViewModel()
  8. @State private var commentWriterViewModel = CommentWriterViewModel()
  9. var body: some View {
  10. ZStack {
  11. HStack(spacing: 0) {
  12. SidebarView(
  13. viewModel: viewModel,
  14. isPremium: subscriptions.hasPremiumAccess
  15. )
  16. mainContent
  17. .frame(maxWidth: .infinity, maxHeight: .infinity)
  18. .environment(\.requirePremiumAccess, {
  19. if subscriptions.hasPremiumAccess { return true }
  20. viewModel.showPaywall()
  21. return false
  22. })
  23. }
  24. if viewModel.isPaywallPresented {
  25. PaywallView(viewModel: paywallViewModel) {
  26. viewModel.dismissPaywall()
  27. }
  28. .frame(maxWidth: .infinity, maxHeight: .infinity)
  29. .ignoresSafeArea()
  30. .zIndex(1)
  31. .transition(.opacity)
  32. }
  33. }
  34. .animation(.easeInOut(duration: 0.2), value: viewModel.isPaywallPresented)
  35. .onChange(of: subscriptions.hasPremiumAccess) { hasPremium in
  36. if hasPremium {
  37. viewModel.dismissPaywall()
  38. }
  39. }
  40. .frame(minWidth: AppWindow.minWidth, minHeight: AppWindow.minHeight)
  41. .background(AppTheme.background)
  42. }
  43. @ViewBuilder
  44. private var mainContent: some View {
  45. ZStack {
  46. RedditWebView(
  47. url: viewModel.redditLoadURL,
  48. reloadTrigger: viewModel.redditReloadTrigger
  49. )
  50. .id("reddit-webview")
  51. .frame(maxWidth: .infinity, maxHeight: .infinity)
  52. .allowsHitTesting(viewModel.isRedditActive)
  53. .accessibilityHidden(!viewModel.isRedditActive)
  54. if viewModel.isSettingsActive {
  55. SettingsView()
  56. } else if !viewModel.isRedditActive, let item = viewModel.selectedNavItem {
  57. toolContent(for: item)
  58. }
  59. }
  60. .background(AppTheme.background)
  61. }
  62. @ViewBuilder
  63. private func toolContent(for item: SidebarNavItem) -> some View {
  64. switch item.iconKind {
  65. case .postGenerator:
  66. PostGeneratorView(viewModel: postGeneratorViewModel) { url in
  67. viewModel.openReddit(at: url)
  68. }
  69. case .titleOptimizer:
  70. TitleOptimizerView(viewModel: titleOptimizerViewModel)
  71. case .commentWriter:
  72. CommentWriterView(viewModel: commentWriterViewModel) { url in
  73. viewModel.openReddit(at: url)
  74. }
  75. default:
  76. ToolPlaceholderView(item: item)
  77. }
  78. }
  79. }
  80. private struct ToolPlaceholderView: View {
  81. let item: SidebarNavItem
  82. var body: some View {
  83. VStack(spacing: 12) {
  84. ModernSidebarIconView(kind: item.iconKind, size: 56)
  85. Text(item.title)
  86. .font(.system(size: 20, weight: .semibold))
  87. .foregroundStyle(AppTheme.textPrimary)
  88. Text(item.subtitle)
  89. .font(.system(size: 13))
  90. .foregroundStyle(AppTheme.textSecondary)
  91. }
  92. .frame(maxWidth: .infinity, maxHeight: .infinity)
  93. .background(AppTheme.background)
  94. }
  95. }
  96. #Preview {
  97. FrontPageView()
  98. .environmentObject(SubscriptionManager())
  99. .frame(width: AppWindow.width, height: AppWindow.height)
  100. }