From 93a8d4a8903cfcfb4f490057da8593d6ca4d21ee Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Mon, 21 Mar 2022 22:45:24 -0700 Subject: [PATCH] split reader code into files. remove unused code --- .../App/Views/WebReader/WebReader.swift | 245 ----------------- .../Views/WebReader/WebReaderContainer.swift | 248 ++++++++++++++++++ .../WebReader/WebReaderCoordinator.swift | 28 -- 3 files changed, 248 insertions(+), 273 deletions(-) create mode 100644 apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift index d2ea272a6..646a18001 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift @@ -1,254 +1,9 @@ -import Combine import Models -import Services import SwiftUI -import UIKit import Utils import Views import WebKit -struct SafariWebLink: Identifiable { - let id: UUID - let url: URL -} - -final class WebReaderViewModel: ObservableObject { - @Published var isLoading = false - @Published var htmlContent: String? - - var subscriptions = Set() - - func loadContent(dataService: DataService, slug: String) { - isLoading = true - - guard let viewer = dataService.currentViewer else { return } - - dataService.articleContentPublisher(username: viewer.username, slug: slug).sink( - receiveCompletion: { [weak self] completion in - guard case .failure = completion else { return } - self?.isLoading = false - }, - receiveValue: { [weak self] htmlContent in - self?.htmlContent = htmlContent - } - ) - .store(in: &subscriptions) - } -} - -struct WebReaderContainerView: View { - let item: FeedItem - let homeFeedViewModel: HomeFeedViewModel - - @State private var showFontSizePopover = false - @State var showHighlightAnnotationModal = false - @State var safariWebLink: SafariWebLink? - @State private var navBarVisibilityRatio = 1.0 - @State private var showDeleteConfirmation = false - @State private var showOverlay = true - @State var increaseFontActionID: UUID? - @State var decreaseFontActionID: UUID? - - @EnvironmentObject var dataService: DataService - @EnvironmentObject var authenticator: Authenticator - @Environment(\.presentationMode) var presentationMode: Binding - @StateObject var viewModel = WebReaderViewModel() - - var fontAdjustmentPopoverView: some View { - FontSizeAdjustmentPopoverView( - increaseFontAction: { increaseFontActionID = UUID() }, - decreaseFontAction: { decreaseFontActionID = UUID() } - ) - } - - var navBariOS14: some View { - HStack(alignment: .center) { - Button( - action: { self.presentationMode.wrappedValue.dismiss() }, - label: { - Image(systemName: "chevron.backward") - .font(.appTitleTwo) - .foregroundColor(.appGrayTextContrast) - .padding(.horizontal) - } - ) - .scaleEffect(navBarVisibilityRatio) - Spacer() - Button( - action: { showFontSizePopover.toggle() }, - label: { - Image(systemName: "textformat.size") - .font(.appTitleTwo) - } - ) - .padding(.horizontal) - .scaleEffect(navBarVisibilityRatio) - } - .frame(height: readerViewNavBarHeight * navBarVisibilityRatio) - .opacity(navBarVisibilityRatio) - .background(Color.systemBackground) - .onTapGesture { - showFontSizePopover = false - } - } - - @available(macOS 12.0, *) - @available(iOS 15.0, *) - var navBar: some View { - HStack(alignment: .center) { - Button( - action: { self.presentationMode.wrappedValue.dismiss() }, - label: { - Image(systemName: "chevron.backward") - .font(.appTitleTwo) - .foregroundColor(.appGrayTextContrast) - .padding(.horizontal) - } - ) - .scaleEffect(navBarVisibilityRatio) - Spacer() - Button( - action: { showFontSizePopover.toggle() }, - label: { - Image(systemName: "textformat.size") - .font(.appTitleTwo) - } - ) - .padding(.horizontal) - .scaleEffect(navBarVisibilityRatio) - Menu( - content: { - Group { - Button( - action: { - homeFeedViewModel.setLinkArchived( - dataService: dataService, - linkId: item.id, - archived: !item.isArchived - ) - }, - label: { - Label( - item.isArchived ? "Unarchive" : "Archive", - systemImage: item.isArchived ? "tray.and.arrow.down.fill" : "archivebox" - ) - } - ) - Button( - action: { showDeleteConfirmation = true }, - label: { Label("Delete", systemImage: "trash") } - ) - } - }, - label: { - Image.profile - .padding(.horizontal) - .scaleEffect(navBarVisibilityRatio) - } - ) - } - .frame(height: readerViewNavBarHeight * navBarVisibilityRatio) - .opacity(navBarVisibilityRatio) - .background(Color.systemBackground) - .onTapGesture { - showFontSizePopover = false - } - .alert("Are you sure?", isPresented: $showDeleteConfirmation) { - Button("Remove Link", role: .destructive) { - homeFeedViewModel.removeLink(dataService: dataService, linkId: item.id) - } - Button("Cancel", role: .cancel, action: {}) - } - } - - var body: some View { - ZStack { - if let htmlContent = viewModel.htmlContent { - WebReader( - htmlContent: htmlContent, - item: item, - openLinkAction: { url in print(url) }, - webViewActionHandler: { _ in }, - navBarVisibilityRatioUpdater: { - if $0 < 1 { - showFontSizePopover = false - } - navBarVisibilityRatio = $0 - }, - authToken: authenticator.authToken ?? "", - appEnv: dataService.appEnvironment, - increaseFontActionID: $increaseFontActionID, - decreaseFontActionID: $decreaseFontActionID, - annotationSaveTransactionID: nil - ) - .overlay( - Group { - if showOverlay { - Color.systemBackground - .transition(.opacity) - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250)) { - withAnimation(.linear(duration: 0.2)) { - showOverlay = false - } - } - } - } - } - ) - } else { - Color.clear - .contentShape(Rectangle()) - .onAppear { - if !viewModel.isLoading { - viewModel.loadContent(dataService: dataService, slug: item.slug) - } - } - } - if showFontSizePopover { - VStack { - Color.clear - .contentShape(Rectangle()) - .frame(height: LinkItemDetailView.navBarHeight) - HStack { - Spacer() - fontAdjustmentPopoverView - .background(Color.appButtonBackground) - .cornerRadius(8) - .padding(.trailing, 44) - } - Spacer() - } - .background( - Color.clear - .contentShape(Rectangle()) - .onTapGesture { - showFontSizePopover = false - } - ) - } - if #available(iOS 15.0, *) { - VStack(spacing: 0) { - navBar - Spacer() - } - .navigationBarHidden(true) - } else { - VStack(spacing: 0) { - navBariOS14 - Spacer() - } - .navigationBarHidden(true) - } - - }.onDisappear { - // Clear the shared webview content when exiting - WebViewManager.shared().loadHTMLString("", baseURL: nil) - } - .navigationBarHidden(true) - } -} - struct WebReader: UIViewRepresentable { let htmlContent: String let item: FeedItem diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift new file mode 100644 index 000000000..6043fee81 --- /dev/null +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -0,0 +1,248 @@ +import Combine +import Models +import Services +import SwiftUI +import Views + +struct SafariWebLink: Identifiable { + let id: UUID + let url: URL +} + +// TODO: load highlights +final class WebReaderViewModel: ObservableObject { + @Published var isLoading = false + @Published var htmlContent: String? + + var subscriptions = Set() + + func loadContent(dataService: DataService, slug: String) { + isLoading = true + + guard let viewer = dataService.currentViewer else { return } + + dataService.articleContentPublisher(username: viewer.username, slug: slug).sink( + receiveCompletion: { [weak self] completion in + guard case .failure = completion else { return } + self?.isLoading = false + }, + receiveValue: { [weak self] htmlContent in + self?.htmlContent = htmlContent + } + ) + .store(in: &subscriptions) + } +} + +struct WebReaderContainerView: View { + let item: FeedItem + let homeFeedViewModel: HomeFeedViewModel + + @State private var showFontSizePopover = false + @State var showHighlightAnnotationModal = false + @State var safariWebLink: SafariWebLink? + @State private var navBarVisibilityRatio = 1.0 + @State private var showDeleteConfirmation = false + @State private var showOverlay = true + @State var increaseFontActionID: UUID? + @State var decreaseFontActionID: UUID? + + @EnvironmentObject var dataService: DataService + @EnvironmentObject var authenticator: Authenticator + @Environment(\.presentationMode) var presentationMode: Binding + @StateObject var viewModel = WebReaderViewModel() + + var fontAdjustmentPopoverView: some View { + FontSizeAdjustmentPopoverView( + increaseFontAction: { increaseFontActionID = UUID() }, + decreaseFontAction: { decreaseFontActionID = UUID() } + ) + } + + var navBariOS14: some View { + HStack(alignment: .center) { + Button( + action: { self.presentationMode.wrappedValue.dismiss() }, + label: { + Image(systemName: "chevron.backward") + .font(.appTitleTwo) + .foregroundColor(.appGrayTextContrast) + .padding(.horizontal) + } + ) + .scaleEffect(navBarVisibilityRatio) + Spacer() + Button( + action: { showFontSizePopover.toggle() }, + label: { + Image(systemName: "textformat.size") + .font(.appTitleTwo) + } + ) + .padding(.horizontal) + .scaleEffect(navBarVisibilityRatio) + } + .frame(height: readerViewNavBarHeight * navBarVisibilityRatio) + .opacity(navBarVisibilityRatio) + .background(Color.systemBackground) + .onTapGesture { + showFontSizePopover = false + } + } + + @available(macOS 12.0, *) + @available(iOS 15.0, *) + var navBar: some View { + HStack(alignment: .center) { + Button( + action: { self.presentationMode.wrappedValue.dismiss() }, + label: { + Image(systemName: "chevron.backward") + .font(.appTitleTwo) + .foregroundColor(.appGrayTextContrast) + .padding(.horizontal) + } + ) + .scaleEffect(navBarVisibilityRatio) + Spacer() + Button( + action: { showFontSizePopover.toggle() }, + label: { + Image(systemName: "textformat.size") + .font(.appTitleTwo) + } + ) + .padding(.horizontal) + .scaleEffect(navBarVisibilityRatio) + Menu( + content: { + Group { + Button( + action: { + homeFeedViewModel.setLinkArchived( + dataService: dataService, + linkId: item.id, + archived: !item.isArchived + ) + }, + label: { + Label( + item.isArchived ? "Unarchive" : "Archive", + systemImage: item.isArchived ? "tray.and.arrow.down.fill" : "archivebox" + ) + } + ) + Button( + action: { showDeleteConfirmation = true }, + label: { Label("Delete", systemImage: "trash") } + ) + } + }, + label: { + Image.profile + .padding(.horizontal) + .scaleEffect(navBarVisibilityRatio) + } + ) + } + .frame(height: readerViewNavBarHeight * navBarVisibilityRatio) + .opacity(navBarVisibilityRatio) + .background(Color.systemBackground) + .onTapGesture { + showFontSizePopover = false + } + .alert("Are you sure?", isPresented: $showDeleteConfirmation) { + Button("Remove Link", role: .destructive) { + homeFeedViewModel.removeLink(dataService: dataService, linkId: item.id) + } + Button("Cancel", role: .cancel, action: {}) + } + } + + var body: some View { + ZStack { + if let htmlContent = viewModel.htmlContent { + WebReader( + htmlContent: htmlContent, + item: item, + openLinkAction: { url in print(url) }, + webViewActionHandler: { _ in }, + navBarVisibilityRatioUpdater: { + if $0 < 1 { + showFontSizePopover = false + } + navBarVisibilityRatio = $0 + }, + authToken: authenticator.authToken ?? "", + appEnv: dataService.appEnvironment, + increaseFontActionID: $increaseFontActionID, + decreaseFontActionID: $decreaseFontActionID, + annotationSaveTransactionID: nil + ) + .overlay( + Group { + if showOverlay { + Color.systemBackground + .transition(.opacity) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250)) { + withAnimation(.linear(duration: 0.2)) { + showOverlay = false + } + } + } + } + } + ) + } else { + Color.clear + .contentShape(Rectangle()) + .onAppear { + if !viewModel.isLoading { + viewModel.loadContent(dataService: dataService, slug: item.slug) + } + } + } + if showFontSizePopover { + VStack { + Color.clear + .contentShape(Rectangle()) + .frame(height: LinkItemDetailView.navBarHeight) + HStack { + Spacer() + fontAdjustmentPopoverView + .background(Color.appButtonBackground) + .cornerRadius(8) + .padding(.trailing, 44) + } + Spacer() + } + .background( + Color.clear + .contentShape(Rectangle()) + .onTapGesture { + showFontSizePopover = false + } + ) + } + if #available(iOS 15.0, *) { + VStack(spacing: 0) { + navBar + Spacer() + } + .navigationBarHidden(true) + } else { + VStack(spacing: 0) { + navBariOS14 + Spacer() + } + .navigationBarHidden(true) + } + + }.onDisappear { + // Clear the shared webview content when exiting + WebViewManager.shared().loadHTMLString("", baseURL: nil) + } + .navigationBarHidden(true) + } +} diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift index f069e59c3..46bc48d3a 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift @@ -114,31 +114,3 @@ extension WebReaderCoordinator: WKNavigationDelegate { } } #endif - -struct WebViewConfig { - let url: URL - let themeId: String - let margin: Int - let fontSize: Int - let fontFamily: String - let rawAuthCookie: String? -} - -extension WKWebView { - func configureForOmnivoreAppEmbed(config: WebViewConfig) { - // Set cookies to pass article preferences to web view - injectCookie(cookieString: "theme=\(config.themeId); Max-Age=31536000;", url: config.url) - injectCookie(cookieString: "margin=\(config.margin); Max-Age=31536000;", url: config.url) - injectCookie(cookieString: "fontSize=\(config.fontSize); Max-Age=31536000;", url: config.url) - injectCookie(cookieString: "fontFamily=\(config.fontFamily); Max-Age=31536000;", url: config.url) - injectCookie(cookieString: config.rawAuthCookie, url: config.url) - } - - func injectCookie(cookieString: String?, url: URL) { - if let cookieString = cookieString { - for cookie in HTTPCookie.cookies(withResponseHeaderFields: ["Set-Cookie": cookieString], for: url) { - configuration.websiteDataStore.httpCookieStore.setCookie(cookie) {} - } - } - } -}