diff --git a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/ShareExtensionScene.swift b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/ShareExtensionScene.swift index b525b5a97..39696dd35 100644 --- a/apple/OmnivoreKit/Sources/App/AppExtensions/Share/ShareExtensionScene.swift +++ b/apple/OmnivoreKit/Sources/App/AppExtensions/Share/ShareExtensionScene.swift @@ -22,7 +22,7 @@ public extension PlatformViewController { final class ShareExtensionViewModel: ObservableObject { @Published var title: String? - @Published var status = ShareExtensionStatus.processing + @Published var status: ShareExtensionStatus = FeatureFlag.enableReadNow ? .processing : .success @Published var debugText: String? var subscriptions = Set() diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift index 441097c13..8fb2c0702 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewIOS.swift @@ -18,7 +18,16 @@ private let enableGrid = UIDevice.isIPad || FeatureFlag.enableGridCardsOnPhone } var body: some View { - Group { + ZStack { + if let linkRequest = viewModel.linkRequest { + NavigationLink( + destination: WebReaderLoadingContainer(requestID: linkRequest.serverID), + tag: linkRequest, + selection: $viewModel.linkRequest + ) { + EmptyView() + } + } HomeFeedView( prefersListLayout: $prefersListLayout, viewModel: viewModel @@ -86,7 +95,7 @@ private let enableGrid = UIDevice.isIPad || FeatureFlag.enableGridCardsOnPhone .navigationBarTitleDisplayMode(.inline) .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in // Don't refresh the list if the user is currently reading an article - if viewModel.selectedLinkItem == nil { + if viewModel.selectedLinkItem == nil || viewModel.linkRequest == nil { loadItems(isRefresh: true) } } @@ -97,6 +106,16 @@ private let enableGrid = UIDevice.isIPad || FeatureFlag.enableGridCardsOnPhone viewModel.pushFeedItem(item: linkedItem) viewModel.selectedLinkItem = linkedItem } + .onOpenURL { url in + withoutAnimation { + viewModel.linkRequest = nil + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { + if let linkRequestID = DeepLink.make(from: url)?.linkRequestID { + viewModel.linkRequest = LinkRequest(id: UUID(), serverID: linkRequestID) + } + } + } + } .formSheet(isPresented: $viewModel.snoozePresented) { SnoozeView( snoozePresented: $viewModel.snoozePresented, @@ -376,3 +395,17 @@ struct ScrollViewOffsetPreferenceKey: PreferenceKey { value += nextValue() } } + +#if os(iOS) + // Allows us to present a sheet without animation + // Used to configure full screen modal view coming from share extension read now button action + private extension View { + func withoutAnimation(_ completion: @escaping () -> Void) { + UIView.setAnimationsEnabled(false) + completion() + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { + UIView.setAnimationsEnabled(true) + } + } + } +#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift index 29bb67b85..a099b971f 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift @@ -20,6 +20,7 @@ import Views @Published var snoozePresented = false @Published var itemToSnoozeID: String? @Published var selectedLinkItem: LinkedItem? + @Published var linkRequest: LinkRequest? @Published var showLoadingBar = false @AppStorage(UserDefaultKey.lastSelectedLinkedItemFilter.rawValue) diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift index f11d72335..e25217235 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift @@ -147,7 +147,7 @@ struct LinkItemDetailView: View { viewModel.trackReadEvent() } } else { - WebReaderContainerView(item: viewModel.item, isPresentedModally: false) + WebReaderContainerView(item: viewModel.item) .navigationBarHidden(hideNavBar) .task { hideNavBar = true diff --git a/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift b/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift index a2ea86ff9..7dee98997 100644 --- a/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/RootView/RootView.swift @@ -4,11 +4,6 @@ import SwiftUI import Utils import Views -struct LinkRequest: Identifiable { - let id: UUID - let serverID: String -} - public struct RootView: View { let pdfViewerProvider: ((URL, PDFViewerViewModel) -> AnyView)? @StateObject private var viewModel = RootViewModel() @@ -51,17 +46,7 @@ struct InnerRootView: View { .onAppear { viewModel.triggerPushNotificationRequestIfNeeded() } - #if os(iOS) - .fullScreenCover(item: $viewModel.linkRequest) { _ in - NavigationView { - WebReaderLoadingContainer( - requestID: viewModel.linkRequest?.serverID ?? "", - handleClose: { viewModel.linkRequest = nil } - ) - } - } - #endif - .snackBar(isShowing: $viewModel.showSnackbar, message: viewModel.snackbarMessage) + .snackBar(isShowing: $viewModel.showSnackbar, message: viewModel.snackbarMessage) // Schedule the dismissal every time we present the snackbar. .onChange(of: viewModel.showSnackbar) { newValue in if newValue { @@ -95,18 +80,6 @@ struct InnerRootView: View { #endif } #if os(iOS) - .onOpenURL { url in - withoutAnimation { - if viewModel.linkRequest != nil { - viewModel.linkRequest = nil - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { - Task { await viewModel.onOpenURL(url: url) } - } - } else { - Task { await viewModel.onOpenURL(url: url) } - } - } - } .onReceive(NSNotification.operationSuccessPublisher) { notification in if let message = notification.userInfo?["message"] as? String { viewModel.showSnackbar = true @@ -134,17 +107,3 @@ struct InnerRootView: View { } #endif } - -#if os(iOS) - // Allows us to present a sheet without animation - // Used to configure full screen modal view coming from share extension read now button action - private extension View { - func withoutAnimation(_ completion: @escaping () -> Void) { - UIView.setAnimationsEnabled(false) - completion() - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { - UIView.setAnimationsEnabled(true) - } - } - } -#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/RootView/RootViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/RootView/RootViewModel.swift index 503af6986..cb037610f 100644 --- a/apple/OmnivoreKit/Sources/App/Views/RootView/RootViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/RootView/RootViewModel.swift @@ -15,7 +15,6 @@ public final class RootViewModel: ObservableObject { let services = Services() @Published public var showPushNotificationPrimer = false - @Published var linkRequest: LinkRequest? @Published var snackbarMessage: String? @Published var showSnackbar = false @@ -58,12 +57,6 @@ public final class RootViewModel: ObservableObject { ) } - @MainActor func onOpenURL(url: URL) async { - if let linkRequestID = DeepLink.make(from: url)?.linkRequestID { - linkRequest = LinkRequest(id: UUID(), serverID: linkRequestID) - } - } - func triggerPushNotificationRequestIfNeeded() { guard FeatureFlag.enablePushNotifications else { return } diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index b401782ea..754440c17 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -7,7 +7,6 @@ import WebKit #if os(iOS) struct WebReaderContainerView: View { let item: LinkedItem - let isPresentedModally: Bool @State private var showFontSizePopover = false @State private var showLabelsModal = false @@ -67,7 +66,7 @@ import WebKit Button( action: { self.presentationMode.wrappedValue.dismiss() }, label: { - Image(systemName: isPresentedModally ? "xmark" : "chevron.backward") + Image(systemName: "chevron.backward") .font(.appTitleTwo) .foregroundColor(.appGrayTextContrast) .padding(.horizontal) diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderLoadingContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderLoadingContainer.swift index efd41ef1a..087be99c0 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderLoadingContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderLoadingContainer.swift @@ -77,14 +77,13 @@ import Utils public struct WebReaderLoadingContainer: View { let requestID: String - let handleClose: () -> Void @EnvironmentObject var dataService: DataService @StateObject var viewModel = WebReaderLoadingContainerViewModel() public var body: some View { if let item = viewModel.item { - WebReaderContainerView(item: item, isPresentedModally: true) + WebReaderContainerView(item: item) .navigationBarHidden(true) .navigationViewStyle(.stack) .accentColor(.appGrayTextContrast) @@ -93,17 +92,6 @@ import Utils Text(errorMessage) } else { ProgressView() - .toolbar { - ToolbarItem(placement: .navigationBarLeading) { - Button( - action: handleClose, - label: { - Image(systemName: "xmark") - .foregroundColor(.appGrayTextContrast) - } - ) - } - } .task { await viewModel.loadItem(dataService: dataService, requestID: requestID) } } } diff --git a/apple/OmnivoreKit/Sources/Models/DeepLinkDecoder.swift b/apple/OmnivoreKit/Sources/Models/DeepLinkDecoder.swift index 157186df1..d64830071 100644 --- a/apple/OmnivoreKit/Sources/Models/DeepLinkDecoder.swift +++ b/apple/OmnivoreKit/Sources/Models/DeepLinkDecoder.swift @@ -1,5 +1,15 @@ import Foundation +public struct LinkRequest: Identifiable, Hashable { + public let id: UUID + public let serverID: String + + public init(id: UUID, serverID: String) { + self.id = id + self.serverID = serverID + } +} + public enum DeepLink { case webAppLinkRequest(requestID: String) }