diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift index bd4849c14..caed1c399 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift @@ -33,7 +33,6 @@ import Views ForEach(viewModel.items) { item in FeedCardNavigationLink( item: item, - searchQuery: searchQuery, selectedLinkItem: $selectedLinkItem, viewModel: viewModel ) @@ -96,16 +95,16 @@ import Views .onChange(of: searchQuery) { _ in // Maybe we should debounce this, but // it feels like it works ok without - viewModel.loadItems(dataService: dataService, searchQuery: searchQuery, isRefresh: true) + viewModel.loadItems(dataService: dataService, isRefresh: true) } .onSubmit(of: .search) { - viewModel.loadItems(dataService: dataService, searchQuery: searchQuery, isRefresh: true) + viewModel.loadItems(dataService: dataService, isRefresh: true) } .toolbar { ToolbarItem { Button( action: { - viewModel.loadItems(dataService: dataService, searchQuery: searchQuery, isRefresh: true) + viewModel.loadItems(dataService: dataService, isRefresh: true) }, label: { Label("Refresh Feed", systemImage: "arrow.clockwise") } ) @@ -120,7 +119,7 @@ import Views } .onAppear { if viewModel.items.isEmpty { - viewModel.loadItems(dataService: dataService, searchQuery: searchQuery, isRefresh: true) + viewModel.loadItems(dataService: dataService, isRefresh: true) } } } @@ -131,7 +130,6 @@ import Views ForEach(viewModel.items) { item in FeedCardNavigationLink( item: item, - searchQuery: searchQuery, selectedLinkItem: $selectedLinkItem, viewModel: viewModel ) @@ -148,7 +146,7 @@ import Views ToolbarItem { Button( action: { - viewModel.loadItems(dataService: dataService, searchQuery: searchQuery, isRefresh: true) + viewModel.loadItems(dataService: dataService, isRefresh: true) }, label: { Label("Refresh Feed", systemImage: "arrow.clockwise") } ) @@ -156,7 +154,7 @@ import Views } .onAppear { if viewModel.items.isEmpty { - viewModel.loadItems(dataService: dataService, searchQuery: searchQuery, isRefresh: true) + viewModel.loadItems(dataService: dataService, isRefresh: true) } } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift index 95ff997dd..1c1348c94 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/ApplyLabelsView.swift @@ -64,26 +64,28 @@ struct ApplyLabelsView: View { } } .navigationTitle("Assign Labels") - .navigationBarTitleDisplayMode(.inline) - .toolbar { - ToolbarItem(placement: .navigationBarLeading) { - Button( - action: { presentationMode.wrappedValue.dismiss() }, - label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } - ) + #if os(iOS) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button( + action: { presentationMode.wrappedValue.dismiss() }, + label: { Text("Cancel").foregroundColor(.appGrayTextContrast) } + ) + } + ToolbarItem(placement: .navigationBarTrailing) { + Button( + action: { + viewModel.saveItemLabelChanges(itemID: item.id, dataService: dataService) { labels in + commitLabelChanges(labels) + presentationMode.wrappedValue.dismiss() + } + }, + label: { Text("Save").foregroundColor(.appGrayTextContrast) } + ) + } } - ToolbarItem(placement: .navigationBarTrailing) { - Button( - action: { - viewModel.saveItemLabelChanges(itemID: item.id, dataService: dataService) { labels in - commitLabelChanges(labels) - presentationMode.wrappedValue.dismiss() - } - }, - label: { Text("Save").foregroundColor(.appGrayTextContrast) } - ) - } - } + #endif .sheet(isPresented: $viewModel.showCreateEmailModal) { CreateLabelView(viewModel: viewModel) } @@ -93,17 +95,20 @@ struct ApplyLabelsView: View { NavigationView { if viewModel.isLoading { EmptyView() - } else { - if #available(iOS 15.0, *) { + #if os(iOS) + if #available(iOS 15.0, *) { + innerBody + .searchable( + text: $labelSearchFilter, + placement: .navigationBarDrawer(displayMode: .always) + ) + } else { + innerBody + } + #else innerBody - .searchable( - text: $labelSearchFilter, - placement: .navigationBarDrawer(displayMode: .always) - ) - } else { - innerBody - } + #endif } } .onAppear { diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift index e89c6144f..627305438 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsView.swift @@ -96,8 +96,10 @@ struct CreateLabelView: View { NavigationView { VStack(spacing: 16) { TextField("Label Name", text: $newLabelName) + #if os(iOS) .keyboardType(.alphabet) - .textFieldStyle(StandardTextFieldStyle()) + #endif + .textFieldStyle(StandardTextFieldStyle()) ColorPicker( newLabelColor == .clear ? "Select Color" : newLabelColor.description, selection: $newLabelColor @@ -130,7 +132,9 @@ struct CreateLabelView: View { } } .navigationTitle("Create New Label") - .navigationBarTitleDisplayMode(.inline) + #if os(iOS) + .navigationBarTitleDisplayMode(.inline) + #endif } } } diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift index 26ee03a8d..a4544fafb 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReader.swift @@ -4,107 +4,109 @@ import Utils import Views import WebKit -struct WebReader: UIViewRepresentable { - let articleContent: ArticleContent - let item: FeedItem - let openLinkAction: (URL) -> Void - let webViewActionHandler: (WKScriptMessage, WKScriptMessageReplyHandler?) -> Void - let navBarVisibilityRatioUpdater: (Double) -> Void +#if os(iOS) + struct WebReader: UIViewRepresentable { + let articleContent: ArticleContent + let item: FeedItem + let openLinkAction: (URL) -> Void + let webViewActionHandler: (WKScriptMessage, WKScriptMessageReplyHandler?) -> Void + let navBarVisibilityRatioUpdater: (Double) -> Void - @Binding var increaseFontActionID: UUID? - @Binding var decreaseFontActionID: UUID? - @Binding var annotationSaveTransactionID: UUID? - @Binding var annotation: String + @Binding var increaseFontActionID: UUID? + @Binding var decreaseFontActionID: UUID? + @Binding var annotationSaveTransactionID: UUID? + @Binding var annotation: String - func makeCoordinator() -> WebReaderCoordinator { - WebReaderCoordinator() - } - - func fontSize() -> Int { - let storedSize = UserDefaults.standard.integer(forKey: UserDefaultKey.preferredWebFontSize.rawValue) - return storedSize <= 1 ? UITraitCollection.current.preferredWebFontSize : storedSize - } - - func makeUIView(context: Context) -> WKWebView { - let webView = WebViewManager.shared() - let contentController = WKUserContentController() - - webView.navigationDelegate = context.coordinator - webView.isOpaque = false - webView.backgroundColor = .clear - webView.configuration.userContentController = contentController - webView.scrollView.delegate = context.coordinator - webView.scrollView.contentInset.top = readerViewNavBarHeight - webView.scrollView.verticalScrollIndicatorInsets.top = readerViewNavBarHeight - - webView.configuration.userContentController.removeAllScriptMessageHandlers() - - for action in WebViewAction.allCases { - webView.configuration.userContentController.add(context.coordinator, name: action.rawValue) + func makeCoordinator() -> WebReaderCoordinator { + WebReaderCoordinator() } - webView.configuration.userContentController.add(webView, name: "viewerAction") - - webView.configuration.userContentController.addScriptMessageHandler( - context.coordinator, contentWorld: .page, name: "articleAction" - ) - - context.coordinator.linkHandler = openLinkAction - context.coordinator.webViewActionHandler = webViewActionHandler - context.coordinator.updateNavBarVisibilityRatio = navBarVisibilityRatioUpdater - loadContent(webView: webView) - - return webView - } - - func updateUIView(_ webView: WKWebView, context: Context) { - if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID { - context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID - (webView as? WebView)?.saveAnnotation(annotation: annotation) + func fontSize() -> Int { + let storedSize = UserDefaults.standard.integer(forKey: UserDefaultKey.preferredWebFontSize.rawValue) + return storedSize <= 1 ? UITraitCollection.current.preferredWebFontSize : storedSize } - if increaseFontActionID != context.coordinator.previousIncreaseFontActionID { - context.coordinator.previousIncreaseFontActionID = increaseFontActionID - (webView as? WebView)?.increaseFontSize() - } + func makeUIView(context: Context) -> WKWebView { + let webView = WebViewManager.shared() + let contentController = WKUserContentController() - if decreaseFontActionID != context.coordinator.previousDecreaseFontActionID { - context.coordinator.previousDecreaseFontActionID = decreaseFontActionID - (webView as? WebView)?.decreaseFontSize() - } + webView.navigationDelegate = context.coordinator + webView.isOpaque = false + webView.backgroundColor = .clear + webView.configuration.userContentController = contentController + webView.scrollView.delegate = context.coordinator + webView.scrollView.contentInset.top = readerViewNavBarHeight + webView.scrollView.verticalScrollIndicatorInsets.top = readerViewNavBarHeight - // If the webview had been terminated `needsReload` will have been set to true - if context.coordinator.needsReload { + webView.configuration.userContentController.removeAllScriptMessageHandlers() + + for action in WebViewAction.allCases { + webView.configuration.userContentController.add(context.coordinator, name: action.rawValue) + } + + webView.configuration.userContentController.add(webView, name: "viewerAction") + + webView.configuration.userContentController.addScriptMessageHandler( + context.coordinator, contentWorld: .page, name: "articleAction" + ) + + context.coordinator.linkHandler = openLinkAction + context.coordinator.webViewActionHandler = webViewActionHandler + context.coordinator.updateNavBarVisibilityRatio = navBarVisibilityRatioUpdater loadContent(webView: webView) - context.coordinator.needsReload = false - return + + return webView } - if webView.isLoading { return } + func updateUIView(_ webView: WKWebView, context: Context) { + if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID { + context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID + (webView as? WebView)?.saveAnnotation(annotation: annotation) + } - // If the root element is not detected then `WKWebView` may have unloaded the content - // so we need to load it again. - webView.evaluateJavaScript("document.getElementById('root') ? true : false") { hasRootElement, _ in - guard let hasRootElement = hasRootElement as? Bool else { return } + if increaseFontActionID != context.coordinator.previousIncreaseFontActionID { + context.coordinator.previousIncreaseFontActionID = increaseFontActionID + (webView as? WebView)?.increaseFontSize() + } - if !hasRootElement { - DispatchQueue.main.async { - loadContent(webView: webView) + if decreaseFontActionID != context.coordinator.previousDecreaseFontActionID { + context.coordinator.previousDecreaseFontActionID = decreaseFontActionID + (webView as? WebView)?.decreaseFontSize() + } + + // If the webview had been terminated `needsReload` will have been set to true + if context.coordinator.needsReload { + loadContent(webView: webView) + context.coordinator.needsReload = false + return + } + + if webView.isLoading { return } + + // If the root element is not detected then `WKWebView` may have unloaded the content + // so we need to load it again. + webView.evaluateJavaScript("document.getElementById('root') ? true : false") { hasRootElement, _ in + guard let hasRootElement = hasRootElement as? Bool else { return } + + if !hasRootElement { + DispatchQueue.main.async { + loadContent(webView: webView) + } } } } - } - func loadContent(webView: WKWebView) { - webView.loadHTMLString( - WebReaderContent( - articleContent: articleContent, - item: item, - isDark: UITraitCollection.current.userInterfaceStyle == .dark, - fontSize: fontSize() + func loadContent(webView: WKWebView) { + webView.loadHTMLString( + WebReaderContent( + articleContent: articleContent, + item: item, + isDark: UITraitCollection.current.userInterfaceStyle == .dark, + fontSize: fontSize() + ) + .styledContent, + baseURL: ViewsPackage.bundleURL ) - .styledContent, - baseURL: ViewsPackage.bundleURL - ) + } } -} +#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index 51bc8fca4..4759c527b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -5,278 +5,280 @@ import SwiftUI import Views import WebKit -struct WebReaderContainerView: View { - let item: FeedItem - let homeFeedViewModel: HomeFeedViewModel +#if os(iOS) + 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? - @State var annotationSaveTransactionID: UUID? - @State var annotation = String() + @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? + @State var annotationSaveTransactionID: UUID? + @State var annotation = String() - @EnvironmentObject var dataService: DataService - @Environment(\.presentationMode) var presentationMode: Binding - @StateObject var viewModel = WebReaderViewModel() + @EnvironmentObject var dataService: DataService + @Environment(\.presentationMode) var presentationMode: Binding + @StateObject var viewModel = WebReaderViewModel() - var fontAdjustmentPopoverView: some View { - FontSizeAdjustmentPopoverView( - increaseFontAction: { increaseFontActionID = UUID() }, - decreaseFontAction: { decreaseFontActionID = UUID() } - ) - } + var fontAdjustmentPopoverView: some View { + FontSizeAdjustmentPopoverView( + increaseFontAction: { increaseFontActionID = UUID() }, + decreaseFontAction: { decreaseFontActionID = UUID() } + ) + } - func webViewActionHandler(message: WKScriptMessage, replyHandler: WKScriptMessageReplyHandler?) { - if message.name == WebViewAction.readingProgressUpdate.rawValue { - let messageBody = message.body as? [String: Double] + func webViewActionHandler(message: WKScriptMessage, replyHandler: WKScriptMessageReplyHandler?) { + if message.name == WebViewAction.readingProgressUpdate.rawValue { + let messageBody = message.body as? [String: Double] - if let messageBody = messageBody, let progress = messageBody["progress"] { + if let messageBody = messageBody, let progress = messageBody["progress"] { + homeFeedViewModel.uncommittedReadingProgressUpdates[item.id] = Double(progress) + } + } + + if let replyHandler = replyHandler { + viewModel.webViewActionWithReplyHandler( + message: message, + replyHandler: replyHandler, + dataService: dataService + ) + return + } + + if message.name == WebViewAction.highlightAction.rawValue { + handleHighlightAction(message: message) + } + + if message.name == WebViewAction.readingProgressUpdate.rawValue { + guard let messageBody = message.body as? [String: Double] else { return } + guard let progress = messageBody["progress"] else { return } homeFeedViewModel.uncommittedReadingProgressUpdates[item.id] = Double(progress) } } - if let replyHandler = replyHandler { - viewModel.webViewActionWithReplyHandler( - message: message, - replyHandler: replyHandler, - dataService: dataService - ) - return - } + private func handleHighlightAction(message: WKScriptMessage) { + guard let messageBody = message.body as? [String: String] else { return } + guard let actionID = messageBody["actionID"] else { return } - if message.name == WebViewAction.highlightAction.rawValue { - handleHighlightAction(message: message) - } - - if message.name == WebViewAction.readingProgressUpdate.rawValue { - guard let messageBody = message.body as? [String: Double] else { return } - guard let progress = messageBody["progress"] else { return } - homeFeedViewModel.uncommittedReadingProgressUpdates[item.id] = Double(progress) - } - } - - private func handleHighlightAction(message: WKScriptMessage) { - guard let messageBody = message.body as? [String: String] else { return } - guard let actionID = messageBody["actionID"] else { return } - - switch actionID { - case "annotate": - annotation = messageBody["annotation"] ?? "" - showHighlightAnnotationModal = true - default: - break - } - } - - 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) + switch actionID { + case "annotate": + annotation = messageBody["annotation"] ?? "" + showHighlightAnnotationModal = true + default: + break } - Button("Cancel", role: .cancel, action: {}) } - } - var body: some View { - ZStack { - if let articleContent = viewModel.articleContent { - WebReader( - articleContent: articleContent, - item: item, - openLinkAction: { - #if os(macOS) - NSWorkspace.shared.open($0) - #elseif os(iOS) - safariWebLink = SafariWebLink(id: UUID(), url: $0) - #endif - }, - webViewActionHandler: webViewActionHandler, - navBarVisibilityRatioUpdater: { - if $0 < 1 { - showFontSizePopover = false - } - navBarVisibilityRatio = $0 - }, - increaseFontActionID: $increaseFontActionID, - decreaseFontActionID: $decreaseFontActionID, - annotationSaveTransactionID: $annotationSaveTransactionID, - annotation: $annotation + var navBariOS14: some View { + HStack(alignment: .center) { + Button( + action: { self.presentationMode.wrappedValue.dismiss() }, + label: { + Image(systemName: "chevron.backward") + .font(.appTitleTwo) + .foregroundColor(.appGrayTextContrast) + .padding(.horizontal) + } ) - .overlay( - Group { - if showOverlay { - Color.systemBackground - .transition(.opacity) - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { - withAnimation(.linear(duration: 0.2)) { - showOverlay = false + .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 articleContent = viewModel.articleContent { + WebReader( + articleContent: articleContent, + item: item, + openLinkAction: { + #if os(macOS) + NSWorkspace.shared.open($0) + #elseif os(iOS) + safariWebLink = SafariWebLink(id: UUID(), url: $0) + #endif + }, + webViewActionHandler: webViewActionHandler, + navBarVisibilityRatioUpdater: { + if $0 < 1 { + showFontSizePopover = false + } + navBarVisibilityRatio = $0 + }, + increaseFontActionID: $increaseFontActionID, + decreaseFontActionID: $decreaseFontActionID, + annotationSaveTransactionID: $annotationSaveTransactionID, + annotation: $annotation + ) + .overlay( + Group { + if showOverlay { + Color.systemBackground + .transition(.opacity) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { + withAnimation(.linear(duration: 0.2)) { + showOverlay = false + } } } - } - } - } - ) - .sheet(item: $safariWebLink) { - SafariView(url: $0.url) - } - .sheet(isPresented: $showHighlightAnnotationModal) { - HighlightAnnotationSheet( - annotation: $annotation, - onSave: { - annotationSaveTransactionID = UUID() - showHighlightAnnotationModal = false - }, - onCancel: { - showHighlightAnnotationModal = false + } } ) - } - } else { - Color.clear - .contentShape(Rectangle()) - .onAppear { - if !viewModel.isLoading { - viewModel.loadContent(dataService: dataService, slug: item.slug) - } + .sheet(item: $safariWebLink) { + SafariView(url: $0.url) } - } - if showFontSizePopover { - VStack { + .sheet(isPresented: $showHighlightAnnotationModal) { + HighlightAnnotationSheet( + annotation: $annotation, + onSave: { + annotationSaveTransactionID = UUID() + showHighlightAnnotationModal = false + }, + onCancel: { + showHighlightAnnotationModal = false + } + ) + } + } else { Color.clear .contentShape(Rectangle()) - .frame(height: LinkItemDetailView.navBarHeight) - HStack { + .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() - fontAdjustmentPopoverView - .background(Color.appButtonBackground) - .cornerRadius(8) - .padding(.trailing, 44) } - Spacer() + .background( + Color.clear + .contentShape(Rectangle()) + .onTapGesture { + showFontSizePopover = false + } + ) } - .background( - Color.clear - .contentShape(Rectangle()) - .onTapGesture { - showFontSizePopover = false - } - ) - } - if #available(iOS 15.0, *) { - VStack(spacing: 0) { - navBar - Spacer() + if #available(iOS 15.0, *) { + VStack(spacing: 0) { + navBar + Spacer() + } + .navigationBarHidden(true) + } else { + VStack(spacing: 0) { + navBariOS14 + Spacer() + } + .navigationBarHidden(true) } - .navigationBarHidden(true) - } else { - VStack(spacing: 0) { - navBariOS14 - Spacer() - } - .navigationBarHidden(true) - } - }.onDisappear { - // Clear the shared webview content when exiting - WebViewManager.shared().loadHTMLString("", baseURL: nil) + }.onDisappear { + // Clear the shared webview content when exiting + WebViewManager.shared().loadHTMLString("", baseURL: nil) + } + .navigationBarHidden(true) } - .navigationBarHidden(true) } -} +#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift index c75bca135..54f7edb5b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderCoordinator.swift @@ -2,7 +2,9 @@ import Combine import Models import Services import SwiftUI -import UIKit +#if os(iOS) + import UIKit +#endif import Utils import Views import WebKit diff --git a/apple/OmnivoreKit/Sources/Utils/ColorUtils.swift b/apple/OmnivoreKit/Sources/Utils/ColorUtils.swift index 2c20306f6..a676666c5 100644 --- a/apple/OmnivoreKit/Sources/Utils/ColorUtils.swift +++ b/apple/OmnivoreKit/Sources/Utils/ColorUtils.swift @@ -45,9 +45,17 @@ public extension Color { } private func toHex() -> String? { - guard let components = UIColor(self).cgColor.components, components.count >= 3 else { - return nil - } + #if os(iOS) + guard let components = UIColor(self).cgColor.components, components.count >= 3 else { + return nil + } + #endif + + #if os(macOS) + guard let components = NSColor(self).cgColor.components, components.count >= 3 else { + return nil + } + #endif let red = Float(components[0]) let green = Float(components[1]) let blue = Float(components[2]) @@ -61,9 +69,17 @@ public extension Color { } var isDark: Bool { - guard let components = UIColor(self).cgColor.components, components.count >= 3 else { - return false - } + #if os(iOS) + guard let components = UIColor(self).cgColor.components, components.count >= 3 else { + return false + } + #endif + + #if os(macOS) + guard let components = NSColor(self).cgColor.components, components.count >= 3 else { + return false + } + #endif let lum = 0.2126 * Float(components[0]) + 0.7152 * Float(components[1]) + 0.0722 * Float(components[2]) return lum < 0.50 diff --git a/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift b/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift index 07e458365..a78344f6e 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/WebAppView.swift @@ -10,7 +10,9 @@ enum WebViewConfigurationManager { static func create() -> WKWebViewConfiguration { let config = WKWebViewConfiguration() config.processPool = processPool - config.allowsInlineMediaPlayback = true + #if os(iOS) + config.allowsInlineMediaPlayback = true + #endif config.mediaTypesRequiringUserActionForPlayback = .audio return config } diff --git a/apple/OmnivoreKit/Sources/Views/Article/WebView.swift b/apple/OmnivoreKit/Sources/Views/Article/WebView.swift index 9744d2f9a..5a6277f00 100644 --- a/apple/OmnivoreKit/Sources/Views/Article/WebView.swift +++ b/apple/OmnivoreKit/Sources/Views/Article/WebView.swift @@ -55,7 +55,7 @@ public final class WebView: WKWebView { } #elseif os(macOS) - override func viewDidChangeEffectiveAppearance() { + override public func viewDidChangeEffectiveAppearance() { super.viewDidChangeEffectiveAppearance() switch effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) { case .some(.darkAqua):