From 7575450121c4280efd802490fbe8b5fd57646336 Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Tue, 15 Feb 2022 22:16:01 -0800 Subject: [PATCH] use scroll view delegate to watch scroll changes and update nav bar visibility --- .../Sources/Views/Article/WebAppView.swift | 3 + .../Views/Article/WebAppViewCoordinator.swift | 44 ++++++++++++- .../Views/Article/WebAppWrapperView.swift | 5 +- .../LinkedItemDetail/LinkItemDetailView.swift | 64 ++++++++++++++++++- 4 files changed, 111 insertions(+), 5 deletions(-) diff --git a/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift b/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift index dbe50286e..6d7286f2c 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift @@ -10,6 +10,7 @@ import WebKit let rawAuthCookie: String? let openLinkAction: (URL) -> Void let webViewActionHandler: (WKScriptMessage) -> Void + let navBarVisibilityRatioUpdater: (Double) -> Void @Binding var annotation: String @Binding var annotationSaveTransactionID: UUID? @Binding var sendIncreaseFontSignal: Bool @@ -33,6 +34,7 @@ import WebKit webView.isOpaque = false webView.backgroundColor = UIColor.clear webView.configuration.userContentController = contentController + webView.scrollView.delegate = context.coordinator for action in WebViewAction.allCases { webView.configuration.userContentController.add(context.coordinator, name: action.rawValue) @@ -53,6 +55,7 @@ import WebKit context.coordinator.linkHandler = openLinkAction context.coordinator.webViewActionHandler = webViewActionHandler + context.coordinator.updateNavBarVisibilityRatio = navBarVisibilityRatioUpdater return webView } diff --git a/apple/OmnivoreKit/Sources/Views/Article/WebAppViewCoordinator.swift b/apple/OmnivoreKit/Sources/Views/Article/WebAppViewCoordinator.swift index 28609f510..c8f9837bd 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/WebAppViewCoordinator.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/WebAppViewCoordinator.swift @@ -1,6 +1,4 @@ -// import Models import SwiftUI -// import Utils import WebKit final class WebAppViewCoordinator: NSObject { @@ -8,6 +6,10 @@ final class WebAppViewCoordinator: NSObject { var linkHandler: (URL) -> Void = { _ in } var needsReload = true var lastSavedAnnotationID: UUID? + var updateNavBarVisibilityRatio: (Double) -> Void = { _ in } + private var yOffsetAtStartOfDrag: Double? + private var lastYOffset: Double = 0 + private var hasDragged = false override init() { super.init() @@ -34,6 +36,44 @@ extension WebAppViewCoordinator: WKNavigationDelegate { } } +extension WebAppViewCoordinator: UIScrollViewDelegate { + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + hasDragged = true + yOffsetAtStartOfDrag = scrollView.contentOffset.y + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard hasDragged else { return } + + let yOffset = scrollView.contentOffset.y + + if yOffset <= 0 { + updateNavBarVisibilityRatio(1) + return + } + + if yOffset < 30 { + updateNavBarVisibilityRatio(1) // yOffset / 30) + return + } + + guard let yOffsetAtStartOfDrag = yOffsetAtStartOfDrag else { return } + + if yOffset > yOffsetAtStartOfDrag { + let translation = yOffset - yOffsetAtStartOfDrag + let ratio = 0.0 // translation < 30 ? translation / 30 : 0 + updateNavBarVisibilityRatio(ratio) + } + } + + func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if decelerate, scrollView.contentOffset.y < (yOffsetAtStartOfDrag ?? 0) { + updateNavBarVisibilityRatio(1) + } + yOffsetAtStartOfDrag = nil + } +} + struct WebViewConfig { let url: URL let themeId: String diff --git a/apple/OmnivoreKit/Sources/Views/Article/WebAppWrapperView.swift b/apple/OmnivoreKit/Sources/Views/Article/WebAppWrapperView.swift index f8bae2f3f..f87b67573 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/WebAppWrapperView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/WebAppWrapperView.swift @@ -35,9 +35,11 @@ public struct WebAppWrapperView: View { @State private var annotation = String() @State var annotationSaveTransactionID: UUID? @State var safariWebLink: SafariWebLink? + let navBarVisibilityRatioUpdater: (Double) -> Void - public init(viewModel: WebAppWrapperViewModel) { + public init(viewModel: WebAppWrapperViewModel, navBarVisibilityRatioUpdater: ((Double) -> Void)? = nil) { self.viewModel = viewModel + self.navBarVisibilityRatioUpdater = navBarVisibilityRatioUpdater ?? { _ in } } public var body: some View { @@ -53,6 +55,7 @@ public struct WebAppWrapperView: View { #endif }, webViewActionHandler: webViewActionHandler, + navBarVisibilityRatioUpdater: navBarVisibilityRatioUpdater, annotation: $annotation, annotationSaveTransactionID: $annotationSaveTransactionID, sendIncreaseFontSignal: $viewModel.sendIncreaseFontSignal, diff --git a/apple/OmnivoreKit/Sources/Views/LinkedItemDetail/LinkItemDetailView.swift b/apple/OmnivoreKit/Sources/Views/LinkedItemDetail/LinkItemDetailView.swift index 0af2bd8e2..bb26f31f6 100644 --- a/apple/OmnivoreKit/Sources/Views/LinkedItemDetail/LinkItemDetailView.swift +++ b/apple/OmnivoreKit/Sources/Views/LinkedItemDetail/LinkItemDetailView.swift @@ -25,8 +25,11 @@ public final class LinkItemDetailViewModel: ObservableObject { } public struct LinkItemDetailView: View { + @Environment(\.presentationMode) var presentationMode: Binding + @ObservedObject private var viewModel: LinkItemDetailViewModel @State private var showFontSizePopover = false + @State private var navBarVisibilityRatio = 1.0 public init(viewModel: LinkItemDetailViewModel) { self.viewModel = viewModel @@ -51,12 +54,69 @@ public struct LinkItemDetailView: View { } public var body: some View { - innerBody #if os(iOS) - .navigationBarTitleDisplayMode(.inline) + if UIDevice.isIPhone, !viewModel.item.isPDF { + compactInnerBody + } else { + innerBody + } + #else + innerBody #endif } + @ViewBuilder private var compactInnerBody: some View { + VStack { + withAnimation { + HStack(alignment: .center) { + Button( + action: { self.presentationMode.wrappedValue.dismiss() }, + label: { + Image(systemName: "chevron.backward") + .font(.appTitleThree) + .foregroundColor(.appGrayTextContrast) + .padding(.horizontal) + .padding(.bottom, 5) + } + ) + Spacer() + Button( + action: { showFontSizePopover = true }, + label: { + Image(systemName: "textformat.size") + } + ) + .padding(.horizontal) + #if os(iOS) + .fittedPopover(isPresented: $showFontSizePopover) { + FontSizeAdjustmentPopoverView( + increaseFontAction: { viewModel.webAppWrapperViewModel?.sendIncreaseFontSignal = true }, + decreaseFontAction: { viewModel.webAppWrapperViewModel?.sendDecreaseFontSignal = true } + ) + } + #endif + } + .scaleEffect(x: 1, y: navBarVisibilityRatio) + .frame(height: 30 * navBarVisibilityRatio) + } + if let webAppWrapperViewModel = viewModel.webAppWrapperViewModel { + WebAppWrapperView( + viewModel: webAppWrapperViewModel, + navBarVisibilityRatioUpdater: { + print($0) + navBarVisibilityRatio = $0 + } + ) + } else { + Spacer() + .onAppear { + viewModel.performActionSubject.send(.load) + } + } + } + .navigationBarHidden(true) + } + @ViewBuilder private var innerBody: some View { if let pdfURL = viewModel.item.pdfURL { #if os(iOS)