create omnivore email relay ui for apple apps

This commit is contained in:
Satindar Dhillon
2022-02-25 09:57:00 -08:00
parent 7babb90d7a
commit bf4e91ad52
5 changed files with 96 additions and 83 deletions

View File

@ -40,7 +40,7 @@ enum PrimaryContentCategory: Identifiable, Hashable, Equatable {
case .feed:
HomeFeedView()
case .profile:
ProfileContainerView()
ProfileView()
}
}

View File

@ -391,7 +391,7 @@ struct HomeFeedView: View {
.toolbar {
ToolbarItem {
NavigationLink(
destination: { ProfileContainerView() },
destination: { ProfileView() },
label: {
Image.profile
.resizable()

View File

@ -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")
}
}

View File

@ -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<AnyCancellable>()
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()
)

View File

@ -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<AnyCancellable>()
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
)
}
}