From a8762c5be65a8fcbbd4fb2603265eb45345cb154 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 08:31:12 -0800 Subject: [PATCH 01/10] move UIViewController extension file into Utils --- .../Sources/{Binders => Utils}/UIViewControllerExtensions.swift | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apple/OmnivoreKit/Sources/{Binders => Utils}/UIViewControllerExtensions.swift (100%) diff --git a/apple/OmnivoreKit/Sources/Binders/UIViewControllerExtensions.swift b/apple/OmnivoreKit/Sources/Utils/UIViewControllerExtensions.swift similarity index 100% rename from apple/OmnivoreKit/Sources/Binders/UIViewControllerExtensions.swift rename to apple/OmnivoreKit/Sources/Utils/UIViewControllerExtensions.swift From 53df427fcb2d836a0ad4e807408cbf87120d78b0 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 08:31:51 -0800 Subject: [PATCH 02/10] remove unused settings view --- apple/Sources/MainApp.swift | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/apple/Sources/MainApp.swift b/apple/Sources/MainApp.swift index 78536872c..9bf3d593c 100644 --- a/apple/Sources/MainApp.swift +++ b/apple/Sources/MainApp.swift @@ -42,9 +42,6 @@ struct MainApp: App { WindowGroup { RootView(pdfViewerProvider: nil, intercomProvider: nil) } -// Settings { -// SettingsView() -// } #endif } @@ -52,18 +49,3 @@ struct MainApp: App { AnyView(PDFViewer(pdfURL: url, viewModel: viewModel)) } } - -struct SettingsView: View { - var appVersion: String { - Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" - } - - var body: some View { - VStack { - Text("Omnivore") - .font(.largeTitle) - Text("Omnivore Version: \(appVersion)") - } - .frame(width: 600, height: 600) - } -} From a2b968f991e4c1d248ef79b92b62e5c6646ab50b Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 08:38:25 -0800 Subject: [PATCH 03/10] remove apple waitlist code --- .../Sources/Binders/RootViewModel.swift | 65 ++++----- .../Binders/Scenes/WaitlistScene.swift | 39 ------ .../Sources/Models/UserProfile.swift | 3 - .../Authentication/Authenticator.swift | 5 - .../DataService/Queries/ViewerPublisher.swift | 1 - .../RegistrationViews/WaitlistView.swift | 125 ------------------ 6 files changed, 23 insertions(+), 215 deletions(-) delete mode 100644 apple/OmnivoreKit/Sources/Binders/Scenes/WaitlistScene.swift delete mode 100644 apple/OmnivoreKit/Sources/Views/RegistrationViews/WaitlistView.swift diff --git a/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift b/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift index 9cb448341..0afd577ad 100644 --- a/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift +++ b/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift @@ -29,21 +29,6 @@ public final class RootViewModel: ObservableObject { registerFonts() } - func updateWaitlistStatus() { - services.dataService.viewerPublisher().sink( - receiveCompletion: { completion in - guard case let .failure(error) = completion else { return } - print(error) - }, - receiveValue: { [weak self] viewer in - guard let self = self else { return } - let isWaitlisted = viewer.isWaitlisted - self.services.authenticator.updateWaitlistStatus(isWaitlistedUser: isWaitlisted) - } - ) - .store(in: &subscriptions) - } - func configurePDFProvider(pdfViewerProvider: @escaping (URL, PDFViewerViewModel) -> AnyView) { PDFProvider.pdfViewerProvider = { [weak self] url, feedItem in guard let self = self else { return AnyView(Text("")) } @@ -163,34 +148,30 @@ public struct RootView: View { @ViewBuilder private var innerBody: some View { if authenticator.isLoggedIn { - if authenticator.isWaitlisted { - WaitlistView(viewModel: WaitlistViewModel.make(services: viewModel.services)) - } else { - PrimaryContentView(viewModel: primaryViewModel) - .onAppear { - viewModel.updateWaitlistStatus() - viewModel.triggerPushNotificationRequestIfNeeded() + PrimaryContentView(viewModel: primaryViewModel) + .onAppear { + viewModel.triggerPushNotificationRequestIfNeeded() + } + #if os(iOS) + .fullScreenCover(item: $viewModel.webLinkPath, content: { safariLinkPath in + NavigationView { + FullScreenWebAppView( + viewModel: viewModel.webAppWrapperViewModel(webLinkPath: safariLinkPath.path), + handleClose: { viewModel.webLinkPath = nil } + ) } - #if os(iOS) - .fullScreenCover(item: $viewModel.webLinkPath, content: { safariLinkPath in - NavigationView { - FullScreenWebAppView( - viewModel: viewModel.webAppWrapperViewModel(webLinkPath: safariLinkPath.path), - handleClose: { viewModel.webLinkPath = nil } - ) - } - }) - #endif - .snackBar( - isShowing: $viewModel.showSnackbar, - text: Text(viewModel.snackbarMessage ?? "") - ) - #if os(iOS) - .customAlert(isPresented: $viewModel.showPushNotificationPrimer) { - pushNotificationPrimerView - } - #endif - } + }) + #endif + .snackBar( + isShowing: $viewModel.showSnackbar, + text: Text(viewModel.snackbarMessage ?? "") + ) + #if os(iOS) + .customAlert(isPresented: $viewModel.showPushNotificationPrimer) { + pushNotificationPrimerView + } + #endif + } else { WelcomeView(viewModel: WelcomeViewModel.make(services: viewModel.services)) .accessibilityElement() diff --git a/apple/OmnivoreKit/Sources/Binders/Scenes/WaitlistScene.swift b/apple/OmnivoreKit/Sources/Binders/Scenes/WaitlistScene.swift deleted file mode 100644 index 06230803b..000000000 --- a/apple/OmnivoreKit/Sources/Binders/Scenes/WaitlistScene.swift +++ /dev/null @@ -1,39 +0,0 @@ -import Models -import Services -import SwiftUI -import Utils -import Views - -extension WaitlistViewModel { - static func make(services: Services) -> WaitlistViewModel { - let viewModel = WaitlistViewModel() - viewModel.bind(services: services) - return viewModel - } - - func bind(services: Services) { - performActionSubject.sink { [weak self] action in - switch action { - case .logout: - services.authenticator.logout() - case .checkStatus: - self?.updateWaitlistStatus(services: services) - } - } - .store(in: &subscriptions) - } - - private func updateWaitlistStatus(services: Services) { - services.dataService.viewerPublisher().sink( - receiveCompletion: { completion in - guard case let .failure(error) = completion else { return } - print(error) - }, - receiveValue: { viewer in - let isWaitlisted = viewer.isWaitlisted - services.authenticator.updateWaitlistStatus(isWaitlistedUser: isWaitlisted) - } - ) - .store(in: &subscriptions) - } -} diff --git a/apple/OmnivoreKit/Sources/Models/UserProfile.swift b/apple/OmnivoreKit/Sources/Models/UserProfile.swift index 4d9e64ca7..d3588df5c 100644 --- a/apple/OmnivoreKit/Sources/Models/UserProfile.swift +++ b/apple/OmnivoreKit/Sources/Models/UserProfile.swift @@ -50,19 +50,16 @@ public struct Viewer { public let username: String public let name: String public let profileImageURL: String? - public let isWaitlisted: Bool public init( username: String, name: String, profileImageURL: String?, - isWaitlisted: Bool, userID: String ) { self.username = username self.name = name self.profileImageURL = profileImageURL - self.isWaitlisted = isWaitlisted self.userID = userID } } diff --git a/apple/OmnivoreKit/Sources/Services/Authentication/Authenticator.swift b/apple/OmnivoreKit/Sources/Services/Authentication/Authenticator.swift index 1b0d29fb3..d973530bb 100644 --- a/apple/OmnivoreKit/Sources/Services/Authentication/Authenticator.swift +++ b/apple/OmnivoreKit/Sources/Services/Authentication/Authenticator.swift @@ -14,7 +14,6 @@ public final class Authenticator: ObservableObject { } @Published public internal(set) var isLoggedIn: Bool - @Published public internal(set) var isWaitlisted = false let networker: Networker @@ -58,10 +57,6 @@ public final class Authenticator: ObservableObject { return !authToken.isEmpty } - public func updateWaitlistStatus(isWaitlistedUser: Bool) { - isWaitlisted = isWaitlistedUser - } - private func clearCookies() { HTTPCookieStorage.shared.removeCookies(since: Date.distantPast) diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Queries/ViewerPublisher.swift b/apple/OmnivoreKit/Sources/Services/DataService/Queries/ViewerPublisher.swift index 2f0089b4d..7b91e2c50 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Queries/ViewerPublisher.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Queries/ViewerPublisher.swift @@ -30,7 +30,6 @@ extension DataService { profileImageURL: try $0.profile( selection: .init { try $0.pictureUrl() } ), - isWaitlisted: try !($0.isFullUser() ?? false), userID: try $0.id() ) } diff --git a/apple/OmnivoreKit/Sources/Views/RegistrationViews/WaitlistView.swift b/apple/OmnivoreKit/Sources/Views/RegistrationViews/WaitlistView.swift deleted file mode 100644 index 2422c9cf0..000000000 --- a/apple/OmnivoreKit/Sources/Views/RegistrationViews/WaitlistView.swift +++ /dev/null @@ -1,125 +0,0 @@ -import Combine -import Models -import SwiftUI - -public final class WaitlistViewModel: ObservableObject { - public enum Action { - case logout - case checkStatus - } - - public var subscriptions = Set() - public let performActionSubject = PassthroughSubject() - - public init() {} -} - -public struct WaitlistView: View { - @Environment(\.horizontalSizeClass) var horizontalSizeClass - @ObservedObject private var viewModel: WaitlistViewModel - - public init(viewModel: WaitlistViewModel) { - self.viewModel = viewModel - } - - @ViewBuilder func userInteractiveView(width: CGFloat) -> some View { - waitlistButtonView - .frame(width: width) - .zIndex(2) - } - - var titleLogo: some View { - Image.omnivoreTitleLogo - .renderingMode(.template) - .foregroundColor(.appGrayTextContrast) - .frame(height: 40) - } - - var waitlistButtonView: some View { - VStack(alignment: .center, spacing: 32) { - Text("Your username has been reserved. We will inform you by email when we open up Omnivore to more users.") - .font(.appHeadline) - .multilineTextAlignment(.center) - .frame(maxWidth: 300) - - BorderedButton(color: .appGrayTextContrast, text: "Check Status") { - viewModel.performActionSubject.send(.checkStatus) - } - .frame(width: 220) - - BorderedButton(color: .appGrayTextContrast, text: "Logout") { - viewModel.performActionSubject.send(.logout) - } - .frame(width: 220) - } - .padding(.horizontal, horizontalSizeClass == .compact ? 16 : 80) - .padding(.top, horizontalSizeClass == .compact ? 16 : 0) - } - - @ViewBuilder func splitColorBackground(width: CGFloat) -> some View { - HStack(spacing: 0) { - Color.systemBackground.frame(width: width * 0.5) - Color.appBackground.frame(width: width * 0.5) - } - .edgesIgnoringSafeArea(.all) - } - - @ViewBuilder func largeBackgroundImage(width: CGFloat) -> some View { - Image.readingIllustrationXXL - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: width) - .clipped() - .edgesIgnoringSafeArea([.vertical, .trailing]) - } - - @ViewBuilder func primaryContent() -> some View { - if horizontalSizeClass == .compact { - GeometryReader { geometry in - ZStack(alignment: .leading) { - Color.systemBackground - .edgesIgnoringSafeArea(.all) - - if geometry.size.width < geometry.size.height { - VStack { - Color.appDeepBackground.frame(height: 100) - Spacer() - } - .edgesIgnoringSafeArea(.all) - } - - VStack { - if geometry.size.width < geometry.size.height { - RegistrationHeroImageView( - tapGestureHandler: {} - ) - } - userInteractiveView(width: geometry.size.width) - Spacer() - } - } - } - } else { - GeometryReader { geometry in - ZStack(alignment: .leading) { - splitColorBackground(width: geometry.size.width) - - VStack { - titleLogo - Spacer() - } - .padding() - - HStack(spacing: 0) { - userInteractiveView(width: geometry.size.width * 0.5) - largeBackgroundImage(width: geometry.size.width * 0.5) - } - } - } - } - } - - public var body: some View { - primaryContent() - } -} From da212e8e462d5906fe864e6a8ac60b961cd679f0 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 08:56:12 -0800 Subject: [PATCH 04/10] remove tab bar from compact apple views --- .../Binders/Scenes/PrimaryContentScene.swift | 14 +------ .../PrimaryContentCategory.swift | 17 -------- .../PrimaryContentView.swift | 39 +++++++------------ 3 files changed, 14 insertions(+), 56 deletions(-) diff --git a/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift b/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift index 2b30e926d..1dfe9b3fb 100644 --- a/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift +++ b/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift @@ -4,21 +4,9 @@ import Views extension PrimaryContentViewModel { static func make(services: Services) -> PrimaryContentViewModel { - let viewModel = PrimaryContentViewModel( + PrimaryContentViewModel( homeFeedViewModel: HomeFeedViewModel.make(services: services), profileContainerViewModel: ProfileContainerViewModel.make(services: services) ) - viewModel.bind(services: services) - return viewModel - } - - func bind(services _: Services) { - performActionSubject.sink { action in - switch action { - case .nothing: - break - } - } - .store(in: &subscriptions) } } diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift index 0b08f0c3b..822cea342 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift @@ -56,20 +56,3 @@ enum PrimaryContentCategory: Identifiable, Hashable, Equatable { hasher.combine(id) } } - -struct TabIcon: View { - let isSelected: Bool - let primaryContentCategory: PrimaryContentCategory - - var body: some View { - if isSelected { - Label { - Text(primaryContentCategory.title) - } icon: { - primaryContentCategory.selectedImage - } - } else { - primaryContentCategory.listLabel - } - } -} diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift index 2298b168c..5be1f3e29 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift @@ -3,29 +3,20 @@ import Models import SwiftUI public final class PrimaryContentViewModel: ObservableObject { - let categories: [PrimaryContentCategory] - - public enum Action { - case nothing - } - - public var subscriptions = Set() - public let performActionSubject = PassthroughSubject() + let homeFeedViewModel: HomeFeedViewModel + let profileContainerViewModel: ProfileContainerViewModel public init( homeFeedViewModel: HomeFeedViewModel, profileContainerViewModel: ProfileContainerViewModel ) { - self.categories = [ - .feed(viewModel: homeFeedViewModel), - .profile(viewModel: profileContainerViewModel) - ] + self.homeFeedViewModel = homeFeedViewModel + self.profileContainerViewModel = profileContainerViewModel } } public struct PrimaryContentView: View { @ObservedObject private var viewModel: PrimaryContentViewModel - @State private var currentTab = 0 public init(viewModel: PrimaryContentViewModel) { self.viewModel = viewModel @@ -45,27 +36,23 @@ public struct PrimaryContentView: View { // iphone view container private var compactView: some View { - TabView(selection: $currentTab) { - ForEach(viewModel.categories.indices, id: \.self) { index in - viewModel.categories[index].destinationView - .tabItem { - TabIcon(isSelected: currentTab == index, primaryContentCategory: viewModel.categories[index]) - } - .tag(index) - } - } - .accentColor(.appGrayTextContrast) + HomeFeedView(viewModel: viewModel.homeFeedViewModel) } // ipad and mac view container private var regularView: some View { - NavigationView { + let categories = [ + PrimaryContentCategory.feed(viewModel: viewModel.homeFeedViewModel), + PrimaryContentCategory.profile(viewModel: viewModel.profileContainerViewModel) + ] + + return NavigationView { // The first column is the sidebar. - PrimaryContentSidebar(categories: viewModel.categories) + PrimaryContentSidebar(categories: categories) .navigationTitle("Categories") // Initial Content of second column - if let destinationView = viewModel.categories.first?.destinationView { + if let destinationView = categories.first?.destinationView { destinationView } else { Text("Select a Category") From 27b60c9cdfe462e8e3e5af4a6a1d9d8cc495ae25 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 09:14:45 -0800 Subject: [PATCH 05/10] move primary content view into binders package --- .../Sources/Binders/RootViewModel.swift | 2 +- .../Binders/Scenes/PrimaryContentScene.swift | 12 ------------ .../Views}/PrimaryContentView.swift | 16 +++++++--------- .../PrimaryContentCategory.swift | 12 ++++++------ 4 files changed, 14 insertions(+), 28 deletions(-) delete mode 100644 apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift rename apple/OmnivoreKit/Sources/{Views/PrimaryContainerViews => Binders/Views}/PrimaryContentView.swift (85%) diff --git a/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift b/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift index 0afd577ad..18f7fcb3f 100644 --- a/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift +++ b/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift @@ -127,7 +127,7 @@ public struct RootView: View { let rootViewModel = RootViewModel() self.viewModel = rootViewModel self.authenticator = rootViewModel.services.authenticator - self.primaryViewModel = PrimaryContentViewModel.make(services: rootViewModel.services) + self.primaryViewModel = PrimaryContentViewModel(services: rootViewModel.services) #if DEBUG if CommandLine.arguments.contains("--uitesting") { diff --git a/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift b/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift deleted file mode 100644 index 1dfe9b3fb..000000000 --- a/apple/OmnivoreKit/Sources/Binders/Scenes/PrimaryContentScene.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Services -import SwiftUI -import Views - -extension PrimaryContentViewModel { - static func make(services: Services) -> PrimaryContentViewModel { - PrimaryContentViewModel( - homeFeedViewModel: HomeFeedViewModel.make(services: services), - profileContainerViewModel: ProfileContainerViewModel.make(services: services) - ) - } -} diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift b/apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift similarity index 85% rename from apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift rename to apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift index 5be1f3e29..103f6f355 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentView.swift +++ b/apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift @@ -1,22 +1,20 @@ -import Combine import Models +import Services import SwiftUI +import Views -public final class PrimaryContentViewModel: ObservableObject { +public final class PrimaryContentViewModel { let homeFeedViewModel: HomeFeedViewModel let profileContainerViewModel: ProfileContainerViewModel - public init( - homeFeedViewModel: HomeFeedViewModel, - profileContainerViewModel: ProfileContainerViewModel - ) { - self.homeFeedViewModel = homeFeedViewModel - self.profileContainerViewModel = profileContainerViewModel + public init(services: Services) { + self.homeFeedViewModel = HomeFeedViewModel.make(services: services) + self.profileContainerViewModel = ProfileContainerViewModel.make(services: services) } } public struct PrimaryContentView: View { - @ObservedObject private var viewModel: PrimaryContentViewModel + private let viewModel: PrimaryContentViewModel public init(viewModel: PrimaryContentViewModel) { self.viewModel = viewModel diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift index 822cea342..13919d14e 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/PrimaryContentCategory.swift @@ -1,14 +1,14 @@ import SwiftUI -enum PrimaryContentCategory: Identifiable, Hashable, Equatable { +public enum PrimaryContentCategory: Identifiable, Hashable, Equatable { case feed(viewModel: HomeFeedViewModel) case profile(viewModel: ProfileContainerViewModel) - static func == (lhs: PrimaryContentCategory, rhs: PrimaryContentCategory) -> Bool { + public static func == (lhs: PrimaryContentCategory, rhs: PrimaryContentCategory) -> Bool { lhs.id == rhs.id } - var id: String { + public var id: String { title } @@ -39,11 +39,11 @@ enum PrimaryContentCategory: Identifiable, Hashable, Equatable { } } - var listLabel: some View { + public var listLabel: some View { Label { Text(title) } icon: { image.renderingMode(.template) } } - @ViewBuilder var destinationView: some View { + @ViewBuilder public var destinationView: some View { switch self { case let .feed(viewModel: viewModel): HomeFeedView(viewModel: viewModel) @@ -52,7 +52,7 @@ enum PrimaryContentCategory: Identifiable, Hashable, Equatable { } } - func hash(into hasher: inout Hasher) { + public func hash(into hasher: inout Hasher) { hasher.combine(id) } } From 578dd80be0e1c289f940af08bd30f4e0be646ebd Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 09:23:00 -0800 Subject: [PATCH 06/10] remove the PrimaryContentViewModel --- .../Sources/Binders/RootViewModel.swift | 5 +---- .../Binders/Views/PrimaryContentView.swift | 16 ++++------------ 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift b/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift index 18f7fcb3f..f64616d46 100644 --- a/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift +++ b/apple/OmnivoreKit/Sources/Binders/RootViewModel.swift @@ -118,8 +118,6 @@ public struct RootView: View { @ObservedObject private var viewModel: RootViewModel @ObservedObject private var authenticator: Authenticator - private var primaryViewModel: PrimaryContentViewModel - public init( pdfViewerProvider: ((URL, PDFViewerViewModel) -> AnyView)?, intercomProvider: IntercomProvider? @@ -127,7 +125,6 @@ public struct RootView: View { let rootViewModel = RootViewModel() self.viewModel = rootViewModel self.authenticator = rootViewModel.services.authenticator - self.primaryViewModel = PrimaryContentViewModel(services: rootViewModel.services) #if DEBUG if CommandLine.arguments.contains("--uitesting") { @@ -148,7 +145,7 @@ public struct RootView: View { @ViewBuilder private var innerBody: some View { if authenticator.isLoggedIn { - PrimaryContentView(viewModel: primaryViewModel) + PrimaryContentView(services: viewModel.services) .onAppear { viewModel.triggerPushNotificationRequestIfNeeded() } diff --git a/apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift b/apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift index 103f6f355..3c6fa23be 100644 --- a/apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift +++ b/apple/OmnivoreKit/Sources/Binders/Views/PrimaryContentView.swift @@ -3,7 +3,7 @@ import Services import SwiftUI import Views -public final class PrimaryContentViewModel { +public struct PrimaryContentView: View { let homeFeedViewModel: HomeFeedViewModel let profileContainerViewModel: ProfileContainerViewModel @@ -11,14 +11,6 @@ public final class PrimaryContentViewModel { self.homeFeedViewModel = HomeFeedViewModel.make(services: services) self.profileContainerViewModel = ProfileContainerViewModel.make(services: services) } -} - -public struct PrimaryContentView: View { - private let viewModel: PrimaryContentViewModel - - public init(viewModel: PrimaryContentViewModel) { - self.viewModel = viewModel - } public var body: some View { #if os(iOS) @@ -34,14 +26,14 @@ public struct PrimaryContentView: View { // iphone view container private var compactView: some View { - HomeFeedView(viewModel: viewModel.homeFeedViewModel) + HomeFeedView(viewModel: homeFeedViewModel) } // ipad and mac view container private var regularView: some View { let categories = [ - PrimaryContentCategory.feed(viewModel: viewModel.homeFeedViewModel), - PrimaryContentCategory.profile(viewModel: viewModel.profileContainerViewModel) + PrimaryContentCategory.feed(viewModel: homeFeedViewModel), + PrimaryContentCategory.profile(viewModel: profileContainerViewModel) ] return NavigationView { From a9580bb006249f740e164ff14380220271e6e700 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 09:31:56 -0800 Subject: [PATCH 07/10] add bar button item to navigate to profile on iphone --- .../Views/PrimaryContainerViews/HomeFeedView.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift index 5c9010888..ade88c42a 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift @@ -259,6 +259,14 @@ public struct HomeFeedView: View { if UIDevice.isIPhone { NavigationView { conditionalInnerBody + .toolbar { + ToolbarItem { + Button( + action: { print("Profile") }, + label: { Image.profileTab.padding() } + ) + } + } } } else { conditionalInnerBody From 762747be95dbf34d76aaeae9175c057344ee3f97 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 09:41:19 -0800 Subject: [PATCH 08/10] add navigation link to show profile view from home feed tab bar item --- .../Sources/Views/PrimaryContainerViews/HomeFeedView.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift index ade88c42a..0fb5d0dde 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift @@ -261,13 +261,14 @@ public struct HomeFeedView: View { conditionalInnerBody .toolbar { ToolbarItem { - Button( - action: { print("Profile") }, + NavigationLink( + destination: { EmptyView() }, label: { Image.profileTab.padding() } ) } } } + .accentColor(.appGrayTextContrast) } else { conditionalInnerBody } From 9b04a162c7c774b5794d05c2bfd1f855dad2d495 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 09:51:45 -0800 Subject: [PATCH 09/10] load profile view model from home view model --- .../Sources/Binders/Scenes/HomeFeedScene.swift | 4 ++++ .../Views/PrimaryContainerViews/HomeFeedView.swift | 7 +++++-- .../Profile/ProfileContainerView.swift | 12 ++---------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/apple/OmnivoreKit/Sources/Binders/Scenes/HomeFeedScene.swift b/apple/OmnivoreKit/Sources/Binders/Scenes/HomeFeedScene.swift index 820cbf624..5f4541645 100644 --- a/apple/OmnivoreKit/Sources/Binders/Scenes/HomeFeedScene.swift +++ b/apple/OmnivoreKit/Sources/Binders/Scenes/HomeFeedScene.swift @@ -11,6 +11,10 @@ extension HomeFeedViewModel { LinkItemDetailViewModel.make(feedItem: feedItem, services: services) } + if UIDevice.isIPhone { + viewModel.profileContainerViewModel = ProfileContainerViewModel.make(services: services) + } + viewModel.bind(services: services) viewModel.loadItems(dataService: services.dataService, searchQuery: nil, isRefresh: false) return viewModel diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift index 0fb5d0dde..d3360d2b1 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift @@ -6,6 +6,7 @@ import Utils public final class HomeFeedViewModel: ObservableObject { let detailViewModelCreator: (FeedItem) -> LinkItemDetailViewModel var currentDetailViewModel: LinkItemDetailViewModel? + public var profileContainerViewModel: ProfileContainerViewModel? @Published public var items = [FeedItem]() @Published public var isLoading = false @@ -256,13 +257,15 @@ public struct HomeFeedView: View { public var body: some View { #if os(iOS) - if UIDevice.isIPhone { + if UIDevice.isIPhone, let profileContainerViewModel = viewModel.profileContainerViewModel { NavigationView { conditionalInnerBody .toolbar { ToolbarItem { NavigationLink( - destination: { EmptyView() }, + destination: { + ProfileContainerView(viewModel: profileContainerViewModel) + }, label: { Image.profileTab.padding() } ) } diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/Profile/ProfileContainerView.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/Profile/ProfileContainerView.swift index 9ac0769d7..3c3a9fc16 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/Profile/ProfileContainerView.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/Profile/ProfileContainerView.swift @@ -30,16 +30,8 @@ public struct ProfileContainerView: View { public var body: some View { #if os(iOS) - if UIDevice.isIPhone { - NavigationView { - Form { - innerBody - } - } - } else { - Form { - innerBody - } + Form { + innerBody } #elseif os(macOS) List { From 44b6236c8355d250a40a88987744909bb93dbe9f Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 23 Feb 2022 13:34:18 -0800 Subject: [PATCH 10/10] update profile bar button item image --- .../OmnivoreKit/Sources/Views/Images/Images.swift | 1 + .../_profile.imageset/Contents.json | 15 +++++++++++++++ .../_profile.imageset/user-circle-gear.svg | 1 + .../PrimaryContainerViews/HomeFeedView.swift | 7 ++++++- 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/Contents.json create mode 100644 apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/user-circle-gear.svg diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.swift b/apple/OmnivoreKit/Sources/Views/Images/Images.swift index b2a966e51..9f9526a5a 100644 --- a/apple/OmnivoreKit/Sources/Views/Images/Images.swift +++ b/apple/OmnivoreKit/Sources/Views/Images/Images.swift @@ -15,5 +15,6 @@ extension Image { static var homeTab: Image { Image("_homeTab", bundle: .module) } static var homeTabSelected: Image { Image("_homeTabSelected", bundle: .module) } static var profileTab: Image { Image("_profileTab", bundle: .module) } + static var profile: Image { Image("_profile", bundle: .module) } static var profileTabSelected: Image { Image("_profileTabSelected", bundle: .module) } } diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/Contents.json b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/Contents.json new file mode 100644 index 000000000..8eb42e0b3 --- /dev/null +++ b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "user-circle-gear.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/user-circle-gear.svg b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/user-circle-gear.svg new file mode 100644 index 000000000..89da59a7c --- /dev/null +++ b/apple/OmnivoreKit/Sources/Views/Images/Images.xcassets/_profile.imageset/user-circle-gear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift index d3360d2b1..cea24590e 100644 --- a/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift +++ b/apple/OmnivoreKit/Sources/Views/PrimaryContainerViews/HomeFeedView.swift @@ -266,7 +266,12 @@ public struct HomeFeedView: View { destination: { ProfileContainerView(viewModel: profileContainerViewModel) }, - label: { Image.profileTab.padding() } + label: { + Image.profile + .resizable() + .frame(width: 26, height: 26) + .padding() + } ) } }