mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Merge pull request #653 from omnivore-app/fix/web-reader-deep-link-ui
Use nav link to present deep link
This commit is contained in:
commit
a6bdf119a4
9 changed files with 51 additions and 68 deletions
|
|
@ -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<AnyCancellable>()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue