diff --git a/apple/OmnivoreKit/Sources/App/PrimaryContentCategory.swift b/apple/OmnivoreKit/Sources/App/PrimaryContentCategory.swift index 60ddf6863..699c63cb9 100644 --- a/apple/OmnivoreKit/Sources/App/PrimaryContentCategory.swift +++ b/apple/OmnivoreKit/Sources/App/PrimaryContentCategory.swift @@ -40,7 +40,7 @@ enum PrimaryContentCategory: Identifiable, Hashable, Equatable { case .feed: HomeFeedView() case .profile: - ProfileContainerView() + ProfileView() } } diff --git a/apple/OmnivoreKit/Sources/App/Views/HomeFeedView.swift b/apple/OmnivoreKit/Sources/App/Views/HomeFeedView.swift index f87f7eadc..7f5d2fc46 100644 --- a/apple/OmnivoreKit/Sources/App/Views/HomeFeedView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/HomeFeedView.swift @@ -391,7 +391,7 @@ struct HomeFeedView: View { .toolbar { ToolbarItem { NavigationLink( - destination: { ProfileContainerView() }, + destination: { ProfileView() }, label: { Image.profile .resizable() diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/EmailsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/EmailsView.swift new file mode 100644 index 000000000..4036e1706 --- /dev/null +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/EmailsView.swift @@ -0,0 +1,53 @@ +import SwiftUI + +struct EmailsView: View { + let footerText = "Add PDFs to your library, or subscribe to emails using an Omnivore email address." + + @State var emails = [String]() + + var body: some View { + #if os(iOS) + Form { + innerBody + } + #elseif os(macOS) + List { + innerBody + } + .listStyle(InsetListStyle()) + #endif + } + + private var innerBody: some View { + Group { + Section(footer: Text(footerText)) { + Button( + action: { + withAnimation { + emails.insert("newemail@omnivore-relay.app\(emails.count)", at: 0) + } + }, + label: { + HStack { + Image(systemName: "plus.circle.fill").foregroundColor(.green) + Text("Create a new email address") + Spacer() + } + } + ) + } + + if !emails.isEmpty { + Section(header: Text("Existing Emails (Tap to copy)")) { + ForEach(emails, id: \.self) { email in + Button( + action: {}, + label: { Text(email) } + ) + } + } + } + } + .navigationTitle("Emails") + } +} diff --git a/apple/OmnivoreKit/Sources/Views/UserSettings/ProfileView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift similarity index 61% rename from apple/OmnivoreKit/Sources/Views/UserSettings/ProfileView.swift rename to apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift index 55706705e..b81554cb9 100644 --- a/apple/OmnivoreKit/Sources/Views/UserSettings/ProfileView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift @@ -1,31 +1,40 @@ +import Combine import Models +import Services import SwiftUI import Utils +import Views -public enum ProfileViewAction { - case loadProfileAction - case logout - case showIntercomMessenger +final class ProfileContainerViewModel: ObservableObject { + @Published var isLoading = false + @Published var profileCardData = ProfileCardData() + + var subscriptions = Set() + + func loadProfileData(dataService: DataService) { + dataService.viewerPublisher().sink( + receiveCompletion: { _ in }, + receiveValue: { [weak self] viewer in + self?.profileCardData = ProfileCardData( + name: viewer.name, + username: viewer.username, + imageURL: viewer.profileImageURL.flatMap { URL(string: $0) } + ) + } + ) + .store(in: &subscriptions) + } } -public struct ProfileView: View { +struct ProfileView: View { + @EnvironmentObject var authenticator: Authenticator + @EnvironmentObject var dataService: DataService + + @ObservedObject private var viewModel = ProfileContainerViewModel() + @State private var showLogoutConfirmation = false - let profileCardData: ProfileCardData - let webAppBaseURL: URL - let actionHandler: (ProfileViewAction) -> Void - - public init( - profileCardData: ProfileCardData, - webAppBaseURL: URL, - actionHandler: @escaping (ProfileViewAction) -> Void - ) { - self.profileCardData = profileCardData - self.webAppBaseURL = webAppBaseURL - self.actionHandler = actionHandler - } - - public var body: some View { + var body: some View { #if os(iOS) Form { innerBody @@ -41,28 +50,32 @@ public struct ProfileView: View { private var innerBody: some View { Group { Section { - ProfileCard(data: profileCardData) - .onAppear { actionHandler(.loadProfileAction) } + ProfileCard(data: viewModel.profileCardData) + .onAppear { viewModel.loadProfileData(dataService: dataService) } + } + + Section { + NavigationLink(destination: EmailsView()) { + Text("Emails") + } } Section { NavigationLink( - destination: BasicWebAppView.privacyPolicyWebView(baseURL: webAppBaseURL) + destination: BasicWebAppView.privacyPolicyWebView(baseURL: dataService.appEnvironment.webAppBaseURL) ) { Text("Privacy Policy") } NavigationLink( - destination: BasicWebAppView.termsConditionsWebView(baseURL: webAppBaseURL) + destination: BasicWebAppView.termsConditionsWebView(baseURL: dataService.appEnvironment.webAppBaseURL) ) { Text("Terms and Conditions") } #if os(iOS) Button( - action: { - actionHandler(.showIntercomMessenger) - }, + action: { DataService.showIntercomMessenger?() }, label: { Text("Feedback") } ) #endif @@ -87,7 +100,7 @@ public struct ProfileView: View { Alert( title: Text("Are you sure you want to logout?"), primaryButton: .destructive(Text("Confirm")) { - actionHandler(.logout) + authenticator.logout() }, secondaryButton: .cancel() ) diff --git a/apple/OmnivoreKit/Sources/App/Views/ProfileContainerView.swift b/apple/OmnivoreKit/Sources/App/Views/ProfileContainerView.swift deleted file mode 100644 index d69c4735d..000000000 --- a/apple/OmnivoreKit/Sources/App/Views/ProfileContainerView.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Combine -import Models -import Services -import SwiftUI -import Utils -import Views - -final class ProfileContainerViewModel: ObservableObject { - @Published var isLoading = false - @Published var profileCardData = ProfileCardData() - - var subscriptions = Set() - - func loadProfileData(dataService: DataService) { - dataService.viewerPublisher().sink( - receiveCompletion: { _ in }, - receiveValue: { [weak self] viewer in - self?.profileCardData = ProfileCardData( - name: viewer.name, - username: viewer.username, - imageURL: viewer.profileImageURL.flatMap { URL(string: $0) } - ) - } - ) - .store(in: &subscriptions) - } -} - -struct ProfileContainerView: View { - @EnvironmentObject var authenticator: Authenticator - @EnvironmentObject var dataService: DataService - - @ObservedObject private var viewModel = ProfileContainerViewModel() - - func actionHandler(action: ProfileViewAction) { - switch action { - case .loadProfileAction: - viewModel.loadProfileData(dataService: dataService) - case .logout: - authenticator.logout() - case .showIntercomMessenger: - DataService.showIntercomMessenger?() - } - } - - var body: some View { - ProfileView( - profileCardData: viewModel.profileCardData, - webAppBaseURL: dataService.appEnvironment.webAppBaseURL, - actionHandler: actionHandler - ) - } -}