From 79dbe3686bf53bd8d7361ed197a9762a01f0320e Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 19 Sep 2023 17:21:02 +0800 Subject: [PATCH 1/5] Update safari extension, clean up the macos app --- .../xcshareddata/swiftpm/Package.resolved | 18 -- apple/OmnivoreKit/Package.swift | 15 +- .../Components/FeedCardNavigationLink.swift | 15 +- .../App/Views/Home/FilterSelectorView.swift | 9 +- .../App/Views/Home/HomeFeedViewMac.swift | 184 +++++------ .../App/Views/Home/LibraryAddLinkView.swift | 184 +++++------ .../Sources/App/Views/LibraryTabView.swift | 1 - .../App/Views/LinkItemDetailView.swift | 2 + .../App/Views/PrimaryContentView.swift | 5 +- .../Views/SlideAnimatedTransitioning.swift | 106 +++---- .../Views/SwipeRightToPopViewController.swift | 286 +++++++++--------- .../Views/WebReader/WebReaderContainer.swift | 4 +- .../Sources/App/Views/WelcomeView.swift | 1 - .../Utils/EventTracking/EventTracker.swift | 45 +-- .../Sources/Views/MacSearchBar.swift | 55 ++++ .../Sources/Views/Utils/MacOSSizeClass.swift | 8 +- .../Resources/images/extension/icon-128.png | Bin 2923 -> 14516 bytes .../Resources/images/extension/icon-16.png | Bin 348 -> 1478 bytes .../Resources/images/extension/icon-24.png | Bin 572 -> 2181 bytes .../Resources/images/extension/icon-256.png | Bin 4864 -> 29595 bytes .../Resources/images/extension/icon-32.png | Bin 716 -> 3022 bytes .../Resources/images/extension/icon-48.png | Bin 1083 -> 4712 bytes .../Resources/images/extension/icon-96.png | Bin 2108 -> 10231 bytes .../SafariExtension/Resources/manifest.json | 14 +- .../Resources/scripts/background.js | 2 +- .../scripts/content/prepare-content.js | 2 +- .../Resources/scripts/content/toast.js | 2 +- 27 files changed, 514 insertions(+), 444 deletions(-) create mode 100644 apple/OmnivoreKit/Sources/Views/MacSearchBar.swift diff --git a/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved b/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved index 4d0dfb64b..cf2e28f2c 100644 --- a/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -144,15 +144,6 @@ "version" : "2.6.0" } }, - { - "identity" : "posthog-ios", - "kind" : "remoteSourceControl", - "location" : "https://github.com/PostHog/posthog-ios.git", - "state" : { - "revision" : "3a6afc24d6bde730a19470d4e6b713f44d076ad9", - "version" : "2.0.3" - } - }, { "identity" : "promises", "kind" : "remoteSourceControl", @@ -162,15 +153,6 @@ "version" : "2.1.0" } }, - { - "identity" : "pspdfkit-sp", - "kind" : "remoteSourceControl", - "location" : "https://github.com/PSPDFKit/PSPDFKit-SP", - "state" : { - "revision" : "f4ba9790488b8f11c29cff35943e430efcdb8003", - "version" : "12.0.1" - } - }, { "identity" : "swift-argument-parser", "kind" : "remoteSourceControl", diff --git a/apple/OmnivoreKit/Package.swift b/apple/OmnivoreKit/Package.swift index cc04187a2..9122e55cc 100644 --- a/apple/OmnivoreKit/Package.swift +++ b/apple/OmnivoreKit/Package.swift @@ -46,9 +46,9 @@ let package = Package( .testTarget(name: "ModelsTests", dependencies: ["Models"]), .target( name: "Utils", - dependencies: [ - .product(name: "PostHog", package: "posthog-ios") - ], +// dependencies: [ +// .product(name: "PostHog", package: "posthog-ios") +// ], resources: [.process("Resources")] ), .testTarget(name: "UtilsTests", dependencies: ["Utils"]) @@ -58,7 +58,7 @@ let package = Package( var appPackageDependencies: [Target.Dependency] { var deps: [Target.Dependency] = ["Views", "Services", "Models", "Utils"] // Comment out following line for macOS build - deps.append(.product(name: "PSPDFKit", package: "PSPDFKit-SP")) + // deps.append(.product(name: "PSPDFKit", package: "PSPDFKit-SP")) return deps } @@ -69,10 +69,11 @@ var dependencies: [Package.Dependency] { .package(url: "https://github.com/siteline/SwiftUI-Introspect.git", from: "0.1.4"), .package(url: "https://github.com/google/GoogleSignIn-iOS", from: "6.2.2"), .package(url: "https://github.com/gonzalezreal/swift-markdown-ui", from: "2.0.0"), - .package(url: "https://github.com/exyte/PopupView.git", from: "2.6.0"), - .package(url: "https://github.com/PostHog/posthog-ios.git", from: "2.0.0") + .package(url: "https://github.com/exyte/PopupView.git", from: "2.6.0") +// , +// .package(url: "https://github.com/PostHog/posthog-ios.git", from: "2.0.0") ] // Comment out following line for macOS build - deps.append(.package(url: "https://github.com/PSPDFKit/PSPDFKit-SP", from: "12.0.1")) + // deps.append(.package(url: "https://github.com/PSPDFKit/PSPDFKit-SP", from: "12.0.1")) return deps } diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift b/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift index 8eeb2e4e6..37865d853 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/Components/FeedCardNavigationLink.swift @@ -12,18 +12,15 @@ struct MacFeedCardNavigationLink: View { @ObservedObject var viewModel: HomeFeedViewModel var body: some View { - NavigationLink( - destination: LinkItemDetailView( + ZStack { + LibraryItemCard(item: item, viewer: dataService.currentViewer) + NavigationLink(destination: LinkItemDetailView( linkedItemObjectID: item.objectID, isPDF: item.isPDF - ), - tag: item.objectID, - selection: $viewModel.selectedLinkItem - ) { - LibraryItemCard(item: item, viewer: dataService.currentViewer) + ), label: { + EmptyView() + }).opacity(0) } - .opacity(0) - .buttonStyle(PlainButtonStyle()) .onAppear { Task { await viewModel.itemAppeared(item: item, dataService: dataService) } } diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/FilterSelectorView.swift b/apple/OmnivoreKit/Sources/App/Views/Home/FilterSelectorView.swift index 04ad57902..614a714cd 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/FilterSelectorView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/FilterSelectorView.swift @@ -3,7 +3,6 @@ import Introspect import Models import Services import SwiftUI -import UIKit import Views @MainActor final class FilterSelectorViewModel: NSObject, ObservableObject { @@ -44,9 +43,11 @@ struct FilterSelectorView: View { .listStyle(.plain) #endif } - .navigationBarTitle("Library") - .navigationBarTitleDisplayMode(.inline) - .navigationBarItems(trailing: doneButton) + #if os(iOS) + .navigationBarTitle("Library") + .navigationBarTitleDisplayMode(.inline) + .navigationBarItems(trailing: doneButton) + #endif } private var innerBody: some View { diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift index 78f2e1556..b04cd20af 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewMac.swift @@ -15,6 +15,8 @@ import Views @State private var confirmationShown = false @State private var presentProfileSheet = false + @Namespace var mainNamespace + @ObservedObject var viewModel: HomeFeedViewModel func loadItems(isRefresh: Bool) { @@ -26,6 +28,95 @@ import Views } } + func menuItems(_ item: LinkedItem) -> some View { + Group { + Button( + action: { viewModel.itemUnderTitleEdit = item }, + label: { Label("Edit Info", systemImage: "info.circle") } + ) + Button( + action: { viewModel.itemUnderLabelEdit = item }, + label: { Label(item.labels?.count == 0 ? "Add Labels" : "Edit Labels", systemImage: "tag") } + ) + Button(action: { + withAnimation(.linear(duration: 0.4)) { + viewModel.setLinkArchived( + dataService: dataService, + objectID: item.objectID, + archived: !item.isArchived + ) + } + }, label: { + Label( + item.isArchived ? "Unarchive" : "Archive", + systemImage: item.isArchived ? "tray.and.arrow.down.fill" : "archivebox" + ) + }) + Button( + action: { + itemToRemove = item + confirmationShown = true + }, + label: { Label("Remove", systemImage: "trash") } + ) + } + } + + var refreshButton: some View { + Button( + action: { + loadItems(isRefresh: true) + }, + label: { Label("Refresh Feed", systemImage: "arrow.clockwise") } + ) + .disabled(viewModel.isLoading) + .opacity(viewModel.isLoading ? 0 : 1) + .overlay { + if viewModel.isLoading { + ProgressView() + .controlSize(.small) + } + } + } + + var itemsList: some View { + VStack { + MacSearchBar(searchTerm: $viewModel.searchTerm) + .padding(.leading, 10) + .padding(.trailing, 10) + .prefersDefaultFocus(false, in: mainNamespace) + + List { + ForEach(viewModel.items) { item in + MacFeedCardNavigationLink( + item: item, + viewModel: viewModel + ) + .listRowInsets(EdgeInsets()) + .contextMenu { + menuItems(item) + } + Divider().padding(5) + } + .prefersDefaultFocus(true, in: mainNamespace) + + if viewModel.isLoading { + LoadingSection() + } + } + .padding(0) + .listStyle(InsetListStyle()) + .navigationTitle("Library") + .onChange(of: viewModel.searchTerm) { _ in + loadItems(isRefresh: true) + } + .toolbar { + Spacer() + refreshButton + } + } + } + var body: some View { ZStack { if let linkRequest = viewModel.linkRequest { @@ -37,97 +128,7 @@ import Views EmptyView() } } - List { - Spacer(minLength: 10) - - ForEach(viewModel.items) { item in - MacFeedCardNavigationLink( - item: item, - viewModel: viewModel - ) - .listRowInsets(EdgeInsets()) - .contextMenu { - Button( - action: { viewModel.itemUnderTitleEdit = item }, - label: { Label("Edit Info", systemImage: "info.circle") } - ) - Button( - action: { viewModel.itemUnderLabelEdit = item }, - label: { Label(item.labels?.count == 0 ? "Add Labels" : "Edit Labels", systemImage: "tag") } - ) - Button(action: { - withAnimation(.linear(duration: 0.4)) { - viewModel.setLinkArchived( - dataService: dataService, - objectID: item.objectID, - archived: !item.isArchived - ) - } - }, label: { - Label( - item.isArchived ? "Unarchive" : "Archive", - systemImage: item.isArchived ? "tray.and.arrow.down.fill" : "archivebox" - ) - }) - Button( - action: { - itemToRemove = item - confirmationShown = true - }, - label: { Label("Remove", systemImage: "trash") } - ) - if FeatureFlag.enableSnooze { - Button { - viewModel.itemToSnoozeID = item.id - viewModel.snoozePresented = true - } label: { - Label { Text(LocalText.genericSnooze) } icon: { Image.moon } - } - } - } - Divider().padding(5) - } - - if viewModel.isLoading { - LoadingSection() - } - } - .listStyle(InsetListStyle()) - .navigationTitle("Library") - .searchable( - text: $viewModel.searchTerm, - placement: .toolbar - ) { - if viewModel.searchTerm.isEmpty { - Text(LocalText.inboxGeneric).searchCompletion("in:inbox ") - Text(LocalText.allGeneric).searchCompletion("in:all ") - Text(LocalText.archivedGeneric).searchCompletion("in:archive ") - Text(LocalText.filesGeneric).searchCompletion("type:file ") - } - } - .onChange(of: viewModel.searchTerm) { _ in - loadItems(isRefresh: true) - } - .onSubmit(of: .search) { - loadItems(isRefresh: true) - } - .toolbar { - ToolbarItem { - Button( - action: { - loadItems(isRefresh: true) - }, - label: { Label("Refresh Feed", systemImage: "arrow.clockwise") } - ) - .disabled(viewModel.isLoading) - .opacity(viewModel.isLoading ? 0 : 1) - .overlay { - if viewModel.isLoading { - ProgressView() - } - } - } - } + itemsList } .alert("Are you sure?", isPresented: $confirmationShown) { Button("Remove Link", role: .destructive) { @@ -160,6 +161,7 @@ import Views loadItems(isRefresh: true) } } + .focusScope(mainNamespace) .handlesExternalEvents(preferring: Set(["shareExtensionRequestID"]), allowing: Set(["*"])) .onOpenURL { url in viewModel.linkRequest = nil diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift b/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift index 1755f0c6d..a66d668dd 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift @@ -1,81 +1,93 @@ -#if os(iOS) - import Introspect - import Models - import Services - import SwiftUI - import UIKit - import Views - @MainActor final class LibraryAddLinkViewModel: NSObject, ObservableObject { - @Published var isLoading = false - @Published var errorMessage: String = "" - @Published var showErrorMessage: Bool = false +import Introspect +import Models +import Services +import SwiftUI +import Views - func addLink(dataService: DataService, newLinkURL: String, dismiss: DismissAction) { - isLoading = true - Task { - if URL(string: newLinkURL) == nil { - error("Invalid link") +@MainActor final class LibraryAddLinkViewModel: NSObject, ObservableObject { + @Published var isLoading = false + @Published var errorMessage: String = "" + @Published var showErrorMessage: Bool = false + + func addLink(dataService: DataService, newLinkURL: String, dismiss: DismissAction) { + isLoading = true + Task { + if URL(string: newLinkURL) == nil { + error("Invalid link") + } else { + let result = try? await dataService.saveURL(id: UUID().uuidString, url: newLinkURL) + if result == nil { + error("Error adding link") } else { - let result = try? await dataService.saveURL(id: UUID().uuidString, url: newLinkURL) - if result == nil { - error("Error adding link") - } else { - dismiss() - } + dismiss() } - isLoading = false } - } - - func error(_ msg: String) { - errorMessage = msg - showErrorMessage = true isLoading = false } } - struct LibraryAddLinkView: View { - @StateObject var viewModel = LibraryAddLinkViewModel() + func error(_ msg: String) { + errorMessage = msg + showErrorMessage = true + isLoading = false + } +} - @State var newLinkURL: String = "" - @EnvironmentObject var dataService: DataService - @Environment(\.dismiss) private var dismiss +struct LibraryAddLinkView: View { + @StateObject var viewModel = LibraryAddLinkViewModel() - enum FocusField: Hashable { - case addLinkEditor - } + @State var newLinkURL: String = "" + @EnvironmentObject var dataService: DataService + @Environment(\.dismiss) private var dismiss - @FocusState private var focusedField: FocusField? + enum FocusField: Hashable { + case addLinkEditor + } - var body: some View { - innerBody - .navigationTitle("Add Link") - .navigationBarTitleDisplayMode(.inline) - .onAppear { - focusedField = .addLinkEditor - } - } + @FocusState private var focusedField: FocusField? - var innerBody: some View { - Form { - TextField("Add Link", text: $newLinkURL) - .keyboardType(.URL) - .autocorrectionDisabled(true) - .textFieldStyle(StandardTextFieldStyle()) - .focused($focusedField, equals: .addLinkEditor) - - Button(action: { - if let url = UIPasteboard.general.url { - newLinkURL = url.absoluteString - } else { - viewModel.error("No URL on pasteboard") - } - }, label: { - Text("Get from pasteboard") - }) - } + var body: some View { + innerBody .navigationTitle("Add Link") + #if os(iOS) + .navigationBarTitleDisplayMode(.inline) + #endif + .onAppear { + focusedField = .addLinkEditor + } + } + + var pasteboardString: String? { + #if os(iOS) + UIPasteboard.general.url.absoluteString + #else + NSPasteboard.general.string(forType: NSPasteboard.PasteboardType.URL) + #endif + } + + var innerBody: some View { + Form { + TextField("Add Link", text: $newLinkURL) + #if os(iOS) + .keyboardType(.URL) + #endif + .autocorrectionDisabled(true) + .textFieldStyle(StandardTextFieldStyle()) + .focused($focusedField, equals: .addLinkEditor) + + Button(action: { + if let url = pasteboardString { + newLinkURL = url + } else { + viewModel.error("No URL on pasteboard") + } + }, label: { + Text("Get from pasteboard") + }) + } + .navigationTitle("Add Link") + #if os(iOS) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarLeading) { @@ -85,28 +97,28 @@ viewModel.isLoading ? AnyView(ProgressView()) : AnyView(addButton) } } - .alert(viewModel.errorMessage, - isPresented: $viewModel.showErrorMessage) { - Button(LocalText.genericOk, role: .cancel) { viewModel.showErrorMessage = false } - } - } - - var addButton: some View { - Button( - action: { - viewModel.addLink(dataService: dataService, newLinkURL: newLinkURL, dismiss: dismiss) - }, - label: { Text("Add").bold() } - ) - .disabled(viewModel.isLoading) - } - - var dismissButton: some View { - Button( - action: { dismiss() }, - label: { Text(LocalText.genericClose) } - ) - .disabled(viewModel.isLoading) + #endif + .alert(viewModel.errorMessage, + isPresented: $viewModel.showErrorMessage) { + Button(LocalText.genericOk, role: .cancel) { viewModel.showErrorMessage = false } } } -#endif + + var addButton: some View { + Button( + action: { + viewModel.addLink(dataService: dataService, newLinkURL: newLinkURL, dismiss: dismiss) + }, + label: { Text("Add").bold() } + ) + .disabled(viewModel.isLoading) + } + + var dismissButton: some View { + Button( + action: { dismiss() }, + label: { Text(LocalText.genericClose) } + ) + .disabled(viewModel.isLoading) + } +} diff --git a/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift b/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift index 9d3347b7a..39fa29ec8 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift @@ -46,7 +46,6 @@ struct LibraryTabView: View { if #available(iOS 16.0, *) { NavigationView { HomeView(viewModel: libraryViewModel) - .navigationBarHidden(false) } } else { // Fallback on earlier versions diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift index 83422da7f..70ef246e1 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift @@ -89,10 +89,12 @@ struct LinkItemDetailView: View { pdfContainerView } else if let item = viewModel.item { WebReaderContainerView(item: item, pop: { dismiss() }) + #if os(iOS) .navigationBarHidden(true) .lazyPop(pop: { dismiss() }, isEnabled: $isEnabled) + #endif } } .task { diff --git a/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift b/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift index 483664bd0..b8962dd4b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift @@ -9,6 +9,8 @@ import Views PrimaryContentCategory.profile ] + @State var searchTerm: String = "" + public var body: some View { innerBody } @@ -19,8 +21,6 @@ import Views return AnyView(splitView) } else { return AnyView(LibraryTabView()) - // .navigationViewStyle(.stack) - // .navigationBarTitleDisplayMode(.inline) } #else return AnyView(splitView) @@ -33,7 +33,6 @@ import Views PrimaryContentCategory.feed.destinationView Text(LocalText.navigationSelectLink) } - .accentColor(.appGrayTextContrast) } #endif diff --git a/apple/OmnivoreKit/Sources/App/Views/SlideAnimatedTransitioning.swift b/apple/OmnivoreKit/Sources/App/Views/SlideAnimatedTransitioning.swift index 164cae639..d2a9a6cfe 100644 --- a/apple/OmnivoreKit/Sources/App/Views/SlideAnimatedTransitioning.swift +++ b/apple/OmnivoreKit/Sources/App/Views/SlideAnimatedTransitioning.swift @@ -6,60 +6,64 @@ // Copyright © 2016 Warif Akhand Rishi. All rights reserved. // -import UIKit +#if os(iOS) -class SlideAnimatedTransitioning: NSObject {} + import UIKit -extension SlideAnimatedTransitioning: UIViewControllerAnimatedTransitioning { - func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { - let containerView = transitionContext.containerView - guard - let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), - let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) - else { - return + class SlideAnimatedTransitioning: NSObject {} + + extension SlideAnimatedTransitioning: UIViewControllerAnimatedTransitioning { + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + let containerView = transitionContext.containerView + guard + let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), + let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) + else { + return + } + + let width = containerView.frame.width + + var offsetLeft = fromVC.view?.frame + offsetLeft?.origin.x = width + + var offscreenRight = fromVC.view?.frame + offscreenRight?.origin.x = -width / 3.33 + + toVC.view?.frame = offscreenRight! + + fromVC.view?.layer.shadowRadius = 5.0 + fromVC.view?.layer.shadowOpacity = 1.0 + toVC.view?.layer.opacity = 0.9 + + transitionContext.containerView.addSubview(toVC.view) + transitionContext.containerView.addSubview(fromVC.view) + + UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: .curveLinear, animations: { + toVC.view?.frame = (fromVC.view?.frame)! + fromVC.view?.frame = offsetLeft! + + toVC.view?.layer.opacity = 1.0 + fromVC.view?.layer.shadowOpacity = 0.1 + + }, completion: { _ in + if !transitionContext.transitionWasCancelled { + toVC.view?.layer.opacity = 1.0 + toVC.view?.layer.shadowOpacity = 0 + fromVC.view?.layer.opacity = 1.0 + fromVC.view?.layer.shadowOpacity = 0 + + fromVC.view.removeFromSuperview() + } + // when cancelling or completing the animation, ios simulator seems to sometimes flash black backgrounds during the animation. on devices, this doesn't seem to happen though. + // containerView.backgroundColor = [UIColor whiteColor]; + transitionContext.completeTransition(!transitionContext.transitionWasCancelled) + }) } - let width = containerView.frame.width - - var offsetLeft = fromVC.view?.frame - offsetLeft?.origin.x = width - - var offscreenRight = fromVC.view?.frame - offscreenRight?.origin.x = -width / 3.33 - - toVC.view?.frame = offscreenRight! - - fromVC.view?.layer.shadowRadius = 5.0 - fromVC.view?.layer.shadowOpacity = 1.0 - toVC.view?.layer.opacity = 0.9 - - transitionContext.containerView.addSubview(toVC.view) - transitionContext.containerView.addSubview(fromVC.view) - - UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: .curveLinear, animations: { - toVC.view?.frame = (fromVC.view?.frame)! - fromVC.view?.frame = offsetLeft! - - toVC.view?.layer.opacity = 1.0 - fromVC.view?.layer.shadowOpacity = 0.1 - - }, completion: { _ in - if !transitionContext.transitionWasCancelled { - toVC.view?.layer.opacity = 1.0 - toVC.view?.layer.shadowOpacity = 0 - fromVC.view?.layer.opacity = 1.0 - fromVC.view?.layer.shadowOpacity = 0 - - fromVC.view.removeFromSuperview() - } - // when cancelling or completing the animation, ios simulator seems to sometimes flash black backgrounds during the animation. on devices, this doesn't seem to happen though. - // containerView.backgroundColor = [UIColor whiteColor]; - transitionContext.completeTransition(!transitionContext.transitionWasCancelled) - }) + func transitionDuration(using _: UIViewControllerContextTransitioning?) -> TimeInterval { + 0.3 + } } - func transitionDuration(using _: UIViewControllerContextTransitioning?) -> TimeInterval { - 0.3 - } -} +#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/SwipeRightToPopViewController.swift b/apple/OmnivoreKit/Sources/App/Views/SwipeRightToPopViewController.swift index 3a2fb967b..48e9ca2c8 100644 --- a/apple/OmnivoreKit/Sources/App/Views/SwipeRightToPopViewController.swift +++ b/apple/OmnivoreKit/Sources/App/Views/SwipeRightToPopViewController.swift @@ -10,144 +10,146 @@ // Copyright © 2019 Joseph Hinkle. All rights reserved. // -import SwiftUI -private func < (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (lll?, rrr?): - return lll < rrr - case (nil, _?): - return true - default: - return false - } -} +#if os(iOS) -private func > (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (lll?, rrr?): - return lll > rrr - default: - return rhs < lhs - } -} - -class SwipeRightToPopViewController: UIHostingController, UINavigationControllerDelegate where Content: View { - fileprivate var pop: (() -> Void)? - fileprivate var lazyPopContent: LazyPop? - private var percentDrivenInteractiveTransition: UIPercentDrivenInteractiveTransition? - private var panGestureRecognizer: UIPanGestureRecognizer! - private var parentNavigationControllerToUse: UINavigationController? - private var gestureAdded = false - - override func viewDidLayoutSubviews() { - // You need to add gesture events after every subview layout to protect against weird edge cases - // One notable edgecase is if you are in a splitview in landscape. In this case, there will be - // no nav controller with 2 vcs, so our addGesture will fail. After rotating back to portrait, - // the splitview will combine into one view with the details pushed on top. So only then would - // would the addGesture find a parent nav controller with 2 view controllers. I don't know if - // there are other edge cases, but running addGesture on every viewDidLayoutSubviews seems safe. - addGesture() + import SwiftUI + private func < (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (lll?, rrr?): + return lll < rrr + case (nil, _?): + return true + default: + return false + } } - public func addGesture() { - if !gestureAdded { - // attempt to find a parent navigationController - var currentVc: UIViewController = self - while true { - if currentVc.navigationController != nil, - currentVc.navigationController?.viewControllers.count > 1 - { - parentNavigationControllerToUse = currentVc.navigationController - break + private func > (lhs: T?, rhs: T?) -> Bool { + switch (lhs, rhs) { + case let (lll?, rrr?): + return lll > rrr + default: + return rhs < lhs + } + } + + class SwipeRightToPopViewController: UIHostingController, UINavigationControllerDelegate where Content: View { + fileprivate var pop: (() -> Void)? + fileprivate var lazyPopContent: LazyPop? + private var percentDrivenInteractiveTransition: UIPercentDrivenInteractiveTransition? + private var panGestureRecognizer: UIPanGestureRecognizer! + private var parentNavigationControllerToUse: UINavigationController? + private var gestureAdded = false + + override func viewDidLayoutSubviews() { + // You need to add gesture events after every subview layout to protect against weird edge cases + // One notable edgecase is if you are in a splitview in landscape. In this case, there will be + // no nav controller with 2 vcs, so our addGesture will fail. After rotating back to portrait, + // the splitview will combine into one view with the details pushed on top. So only then would + // would the addGesture find a parent nav controller with 2 view controllers. I don't know if + // there are other edge cases, but running addGesture on every viewDidLayoutSubviews seems safe. + addGesture() + } + + public func addGesture() { + if !gestureAdded { + // attempt to find a parent navigationController + var currentVc: UIViewController = self + while true { + if currentVc.navigationController != nil, + currentVc.navigationController?.viewControllers.count > 1 + { + parentNavigationControllerToUse = currentVc.navigationController + break + } + guard let parent = currentVc.parent else { + return + } + currentVc = parent } - guard let parent = currentVc.parent else { + guard parentNavigationControllerToUse?.viewControllers.count > 1 else { return } - currentVc = parent - } - guard parentNavigationControllerToUse?.viewControllers.count > 1 else { - return - } - panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(SwipeRightToPopViewController.handlePanGesture(_:))) - view.addGestureRecognizer(panGestureRecognizer) - gestureAdded = true + panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(SwipeRightToPopViewController.handlePanGesture(_:))) + view.addGestureRecognizer(panGestureRecognizer) + gestureAdded = true + } } - } - @objc func handlePanGesture(_ panGesture: UIPanGestureRecognizer) { - // if the parentNavigationControllerToUse has a width value, use that because it's more accurate. Otherwise use this view's width as a backup - let total = parentNavigationControllerToUse?.view.frame.width ?? view.frame.width - let percent = max(panGesture.translation(in: view).x, 0) / total + @objc func handlePanGesture(_ panGesture: UIPanGestureRecognizer) { + // if the parentNavigationControllerToUse has a width value, use that because it's more accurate. Otherwise use this view's width as a backup + let total = parentNavigationControllerToUse?.view.frame.width ?? view.frame.width + let percent = max(panGesture.translation(in: view).x, 0) / total - switch panGesture.state { - case .began: - if lazyPopContent?.isEnabled == true { - parentNavigationControllerToUse?.delegate = self - if let pop = self.pop { - pop() + switch panGesture.state { + case .began: + if lazyPopContent?.isEnabled == true { + parentNavigationControllerToUse?.delegate = self + if let pop = self.pop { + pop() + } } - } - case .changed: - if let percentDrivenInteractiveTransition = percentDrivenInteractiveTransition { - percentDrivenInteractiveTransition.update(percent) - } + case .changed: + if let percentDrivenInteractiveTransition = percentDrivenInteractiveTransition { + percentDrivenInteractiveTransition.update(percent) + } - case .ended: - let velocity = panGesture.velocity(in: view).x + case .ended: + let velocity = panGesture.velocity(in: view).x - // Continue if drag more than 50% of screen width or velocity is higher than 100 - if percent > 0.5 || velocity > 100 { - percentDrivenInteractiveTransition?.finish() - } else { + // Continue if drag more than 50% of screen width or velocity is higher than 100 + if percent > 0.5 || velocity > 100 { + percentDrivenInteractiveTransition?.finish() + } else { + percentDrivenInteractiveTransition?.cancel() + } + + case .cancelled, .failed: percentDrivenInteractiveTransition?.cancel() + + default: + break + } + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } + + func navigationController(_: UINavigationController, + animationControllerFor _: UINavigationController.Operation, + from _: UIViewController, + to _: UIViewController) -> UIViewControllerAnimatedTransitioning? + { + if #available(iOS 17.0, *) { + return nil + } else if UIDevice.isIPad { + return nil + } else { + return SlideAnimatedTransitioning() + } + } + + func navigationController(_: UINavigationController, + interactionControllerFor _: UIViewControllerAnimatedTransitioning) + -> UIViewControllerInteractiveTransitioning? + { + parentNavigationControllerToUse?.delegate = nil + // navigationController.delegate = nil + + if panGestureRecognizer.state == .began { + percentDrivenInteractiveTransition = UIPercentDrivenInteractiveTransition() + percentDrivenInteractiveTransition?.completionCurve = .easeOut + } else { + percentDrivenInteractiveTransition = nil } - case .cancelled, .failed: - percentDrivenInteractiveTransition?.cancel() - - default: - break + return percentDrivenInteractiveTransition } } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - } - - func navigationController(_: UINavigationController, - animationControllerFor _: UINavigationController.Operation, - from _: UIViewController, - to _: UIViewController) -> UIViewControllerAnimatedTransitioning? - { - if #available(iOS 17.0, *) { - return nil - } else if UIDevice.isIPad { - return nil - } else { - return SlideAnimatedTransitioning() - } - } - - func navigationController(_: UINavigationController, - interactionControllerFor _: UIViewControllerAnimatedTransitioning) - -> UIViewControllerInteractiveTransitioning? - { - parentNavigationControllerToUse?.delegate = nil - // navigationController.delegate = nil - - if panGestureRecognizer.state == .began { - percentDrivenInteractiveTransition = UIPercentDrivenInteractiveTransition() - percentDrivenInteractiveTransition?.completionCurve = .easeOut - } else { - percentDrivenInteractiveTransition = nil - } - - return percentDrivenInteractiveTransition - } -} - // // Lazy Pop SwiftUI Component // @@ -155,33 +157,35 @@ class SwipeRightToPopViewController: UIHostingController, UINa // Copyright © 2019 Joseph Hinkle. All rights reserved. // -private struct LazyPop: UIViewControllerRepresentable { - let rootView: Content - let pop: () -> Void - @Binding var isEnabled: Bool + private struct LazyPop: UIViewControllerRepresentable { + let rootView: Content + let pop: () -> Void + @Binding var isEnabled: Bool - init(_ rootView: Content, pop: @escaping () -> Void, isEnabled: (Binding)? = nil) { - self.rootView = rootView - self.pop = pop - self._isEnabled = isEnabled ?? Binding(get: { true }, set: { _ in }) - } + init(_ rootView: Content, pop: @escaping () -> Void, isEnabled: (Binding)? = nil) { + self.rootView = rootView + self.pop = pop + self._isEnabled = isEnabled ?? Binding(get: { true }, set: { _ in }) + } - func makeUIViewController(context _: Context) -> UIViewController { - let vc = SwipeRightToPopViewController(rootView: rootView) - vc.pop = pop - vc.lazyPopContent = self - return vc - } + func makeUIViewController(context _: Context) -> UIViewController { + let vc = SwipeRightToPopViewController(rootView: rootView) + vc.pop = pop + vc.lazyPopContent = self + return vc + } - func updateUIViewController(_ uiViewController: UIViewController, context _: Context) { - if let host = uiViewController as? UIHostingController { - host.rootView = rootView + func updateUIViewController(_ uiViewController: UIViewController, context _: Context) { + if let host = uiViewController as? UIHostingController { + host.rootView = rootView + } } } -} -public extension View { - func lazyPop(pop: @escaping () -> Void, isEnabled: (Binding)? = nil) -> some View { - LazyPop(self, pop: pop, isEnabled: isEnabled) + public extension View { + func lazyPop(pop: @escaping () -> Void, isEnabled: (Binding)? = nil) -> some View { + LazyPop(self, pop: pop, isEnabled: isEnabled) + } } -} + +#endif diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index d6e6528fc..f8a5ed8a2 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -427,7 +427,9 @@ struct WebReaderContainerView: View { showHighlightAnnotationModal: $showHighlightAnnotationModal ) .background(ThemeManager.currentBgColor) - .statusBar(hidden: prefersHideStatusBarInReader) + #if os(iOS) + .statusBar(hidden: prefersHideStatusBarInReader) + #endif .onAppear { if item.isUnread { dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0.1, anchorIndex: 0) diff --git a/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift b/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift index ae7fc5622..413176650 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WelcomeView.swift @@ -7,7 +7,6 @@ import Views struct WelcomeView: View { @EnvironmentObject var dataService: DataService @EnvironmentObject var authenticator: Authenticator - @Environment(\.horizontalSizeClass) var horizontalSizeClass @Environment(\.openURL) var openURL @StateObject private var viewModel = RegistrationViewModel() diff --git a/apple/OmnivoreKit/Sources/Utils/EventTracking/EventTracker.swift b/apple/OmnivoreKit/Sources/Utils/EventTracking/EventTracker.swift index 0dc18838f..245cd8094 100644 --- a/apple/OmnivoreKit/Sources/Utils/EventTracking/EventTracker.swift +++ b/apple/OmnivoreKit/Sources/Utils/EventTracking/EventTracker.swift @@ -1,24 +1,29 @@ import Foundation -import PostHog + +#if os(iOS) + import PostHog +#endif public enum EventTracker { - public static var posthog: PHGPostHog? = { - guard let writeKey = AppKeys.sharedInstance?.posthogClientKey else { - return nil - } + #if os(iOS) + public static var posthog: PHGPostHog? = { + guard let writeKey = AppKeys.sharedInstance?.posthogClientKey else { + return nil + } - guard let posthogInstanceAddress = AppKeys.sharedInstance?.posthogInstanceAddress else { - return nil - } + guard let posthogInstanceAddress = AppKeys.sharedInstance?.posthogInstanceAddress else { + return nil + } - let configuration = PHGPostHogConfiguration(apiKey: writeKey, host: posthogInstanceAddress) + let configuration = PHGPostHogConfiguration(apiKey: writeKey, host: posthogInstanceAddress) - configuration.recordScreenViews = false - configuration.captureApplicationLifecycleEvents = true + configuration.recordScreenViews = false + configuration.captureApplicationLifecycleEvents = true - PHGPostHog.setup(with: configuration) - return PHGPostHog.shared() - }() + PHGPostHog.setup(with: configuration) + return PHGPostHog.shared() + }() + #endif public static func trackForDebugging(_ message: String) { #if DEBUG @@ -27,14 +32,20 @@ public enum EventTracker { } public static func track(_ event: TrackableEvent) { - posthog?.capture(event.name, properties: event.properties) + #if os(iOS) + posthog?.capture(event.name, properties: event.properties) + #endif } public static func registerUser(userID: String) { - posthog?.identify(userID) + #if os(iOS) + posthog?.identify(userID) + #endif } public static func reset() { - posthog?.reset() + #if os(iOS) + posthog?.reset() + #endif } } diff --git a/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift b/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift new file mode 100644 index 000000000..aeea28ee3 --- /dev/null +++ b/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift @@ -0,0 +1,55 @@ +import SwiftUI + +public struct MacSearchBar: NSViewRepresentable { + @Binding var searchTerm: String + + public init( + searchTerm: Binding + ) { + self._searchTerm = searchTerm + } + + public func makeNSView(context _: Context) -> NSSearchField { + let searchField = NSSearchField(frame: .zero) + searchField.translatesAutoresizingMaskIntoConstraints = false + searchField.heightAnchor.constraint(greaterThanOrEqualToConstant: 28).isActive = true + searchField.resignFirstResponder() + + return searchField + } + + func changeSearchFieldItem(searchField: NSSearchField, sender: AnyObject) -> NSSearchField { + // Based on the Menu item selection in the search field the placeholder string is set + (searchField.cell as? NSSearchFieldCell)?.placeholderString = sender.title + return searchField + } + + public func updateNSView(_ searchField: NSSearchField, context: Context) { + searchField.font = searchField.font?.withSize(14) + searchField.stringValue = searchTerm + searchField.delegate = context.coordinator + searchField.resignFirstResponder() + } + + public func makeCoordinator() -> Coordinator { + let coordinator = Coordinator(searchTerm: $searchTerm) + return coordinator + } + + public class Coordinator: NSObject, NSSearchFieldDelegate { + var searchTerm: Binding + + init(searchTerm: Binding) { + self.searchTerm = searchTerm + super.init() + } + + public func controlTextDidChange(_ notification: Notification) { + guard let searchField = notification.object as? NSSearchField else { + // log.error("Unexpected control in update notification", source: .ui) + return + } + searchTerm.wrappedValue = searchField.stringValue + } + } +} diff --git a/apple/OmnivoreKit/Sources/Views/Utils/MacOSSizeClass.swift b/apple/OmnivoreKit/Sources/Views/Utils/MacOSSizeClass.swift index f53d08f91..b20f5d533 100644 --- a/apple/OmnivoreKit/Sources/Views/Utils/MacOSSizeClass.swift +++ b/apple/OmnivoreKit/Sources/Views/Utils/MacOSSizeClass.swift @@ -8,10 +8,10 @@ import SwiftUI // https://stackoverflow.com/questions/63526478/swiftui-userinterfacesizeclass-for-universal-macos-ios-views #if os(macOS) - public enum UserInterfaceSizeClass { - case compact - case regular - } +// public enum UserInterfaceSizeClass { +// case compact +// case regular +// } public struct HorizontalSizeClassEnvironmentKey: EnvironmentKey { public static let defaultValue: UserInterfaceSizeClass = .regular diff --git a/apple/Sources/SafariExtension/Resources/images/extension/icon-128.png b/apple/Sources/SafariExtension/Resources/images/extension/icon-128.png index 7608e31eb34043de2506bc2d6e38b7c8ba590535..d6df58ae7cf218c23a86955b5be2aa6912730426 100644 GIT binary patch literal 14516 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 literal 2923 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 diff --git a/apple/Sources/SafariExtension/Resources/images/extension/icon-16.png b/apple/Sources/SafariExtension/Resources/images/extension/icon-16.png index 26d20161834a947ac2e8e85aa234fe28801927f0..5c0b8ad309489fa4b951d73f0817f25da74d8479 100644 GIT binary patch literal 1478 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVkr05M1pgl1mAh%j*h z6I`{x0%imor0saV%ts)_S>O>_%)r1c48n{Iv*t(uO^eJ7i71Ki^|4CM&(%vz$xlkv ztH>0+>{umUo3Q%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)CuG zfu4bq9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)Btk zRH0j3nOBlnp_^B%3^4>|j!SBBa#3bMNoIbY0?6FNr2NtnTO}osMQ{LdXGvxn!lt}p zsJDO~)CbAv8|oS8!_5Y2wE>A*`4?rT0&NDFZ)a!&R*518wZ}#uWI2*!AU*|)0=;U- zWup%dHajlKxQFZv49xDHE{-7s&3!8cI{VUU{8dp zlyIb2h{~e2nJZ@crG_b)uxK9C_^+|iUP!a^Mn6&l`9A8jA5)1P^!`aX9=5$}}L z-gNb&zoxryczyKv!>P7!>VHSaNX~cB3qG)Lq5Q;->k0o?`#mCf~V@tv{!g01!f zKgQ&&gMQP!7=t|7&-6T6(;mz0zi3(8-&vnFW*t@TaLqmPNbuar4STA*Ri8y(D3SD9 zu-CLxf1lrB{WA*HS5u$M@_e!HiK&xvZg>Cq^Q7?#e;31tSsJtV^8ZdRunZ}X+U9cm z?AK>W%X)&7#W#F>nYSk5Qs;yn8+Y=(p7-j|)IU1ME=kJV*vwMu$D+Z`7`$Yq6|>V^ zw!q6P=j#W&-*njG`{l5bJJvNin%dsDgYMLrc|I4yo?Kd&+JSI?d zn0;c`{)X(M4_@70_s8_FdaLx;viof9XD^GcWleW7{qs3{W#Z-Kq31pbvPpZN*!Q2O zbP0l+XkKb4@r{ delta 332 zcmV-S0ki(b3)}*b8Gi%-006c6H|hWY0V7F7K~yMHeU7_J!eJPN4>Yvp5(?E+Lq>nY zIp60c!!f#OR4zhmNMJ)j(&SoB)ljs$*ie)$1<}wA!lZ`Z5ba82p>7SSp^(q^p7R`d zfd&DONh(i=ue{L4!~oh+gk=`FW22hWx^7rETeCfXbw(A%+kXary(`yH6j4QE=)gb7 zH>CjtJS?}bn@FttN1!zp0l*F^uLS^5OvfQN0Ps>ND6ee*P@LbYTCZ>#fm53aBMak%QnNtC4}Ql ztgNhXcvGCIsWGH5W^!X$fgIylrp`B$|M`$ZnZXH+corir7A^J-42nx+kuVr>qaW+r zJz0#fpPgcv-^YRm#EDOECRjY~hc{G86te`k1V$*-S?mv*5Wgz_!+q~V#EF~#-(|i{ z`jv%71?7miAD<1BL+u$}1pw00PGnme1(D{-h^Bd}lNN3jTAqz%rTJ3*Y%T>=)}%FL z?2rtWMQfMRN-;DgY*kMqssY!RR2cWu9`}+q>8!GfCR>?<#A9;>|f7g z!UlgKEg7v`PE43{Agm5Ng3f{(gOv`>VCWUg>KM z=id+{c@J#z#%-3K`lP&a8{2=HH`-KvL=#M@yajLkc(Q|A9)<7V16P0BCAH(>Lhc?&OY@ySKXipKF%NE-8*$ zXB2eqD3q(}MhS?5WssVx`U|a2hiS<5J1oMCJgOq$S!;2irDp%qlhYhvNBih|Ih%^_#twO5aG7BvpP!rEoV`E4 zPJLlPSh{Dt+wqfWBV(uz~+^Y+A}rn zGXtZ-e=L#t#Tmzo=IX=aRHD5oZ%q=ZCzrjuDZTZP82gsGu9qDe#YY2@B!(L=ftjtP z$_j4gvw{Bb!|r*Ai+{U=0#!XxtLNF6{^F3ytsgfq>j)5N;g*%P*H7F#$N8cK9ismv=YDUcn?J8lApQ6KfImXIB znA-u83nZSiha4aJFB+Kr(GgaZmHxJfH#Sys$g#EOvCdPP;{JZ0TM~!Am>-`S$SdpP zKRj|FaqGMBAZPvc4;ZM8n{=NHb1;&Fs-b(mqnkf=?@^pl*ld6m($7}Q#amh1T`A+% z`-GgfMhbi{=v;`boU?8ZZfSnAb8D2&?N1}BHtmt*2%a;t?)T%gf^+=rhYxJJg-0KB z`(*1Jf_0smQ8S;#cBXp@=-ZBs4P6$FFY@qBR<_rl?N49R6WiM4Iqx3tZ;@a{s_W{p z@km%#a5QpS{l)&d>`jEv?oL{1mwS|bFNhbFnY6_(JPs<{vJ<9zzb(UF)c1KDn6kI<4A+Kf@|6klU@&IwbT`kH+anCWL4kK`4WpSKhy%}POo>x2WwpON#&HuY%r!5 zRJnSpSWGo2rC&#~EHlcf7CpU*Z8hi9JzRXxy$x$kGE9B>@cvbwvdvk{mY5PS2b}?@ dGl{}UH|Jsghl(xg(7yu!IN7_BYwZFK{R`fKcW(dy delta 558 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 JPDHLkV1nKbEXe=> literal 4864 zcmZ8l2{csy`@Uv0rWt#(WzRN3wy12w7z~+=A%vo`WY3bVG{~BS##WXwWUUBE)+A(< zeTj;wWXXgS5q|gko&Rsn@BBY!&U>Htd7t-r-+RxQbLLK>CEkPsA&dY3fCFc0WCZ{$ zAY=jHQ1IgQ(9RkFpn&BmYb=k!i@(g8)3>IPicA*x1-G)&NO{)xY(B0<-sjfw{Rk*uoTpC2$<*z%aq#aNtm; z14D+vV8AMa1oi)F|4A9P;2KOoB9Tl?Oc*H`!4gA;#bTMHg@px(!5tV?FuJ+9G0d4G z3=IvL46~83Czu-ld+>NXs9`R{oW&r)ok51t%d`R+#%+Q;qmkLgP=YBqg@Kuo(av-O zof!;Mz+e~xh9MXkgBU4@8C9?m6f+x{Vg>`sz~>L%J5vBM%vm5{m@ul06x1_P#uH-* z7`C7QEHQ2e#Eg9ykpxe2EH5p5?0@ludiTaflOtR#QdZX}ujcngDx>XH_Di2nf4Tdi)c>Ta z-?#0z89cDeFFWxVICmMRn0M3GpQi^{iOmmBiA2ra!an{>fba&spHBLnDoolWBeI|_ zpM3VcnK+$TCr%%%4Lxh9r6|ddcT4l-NO~Omg=#XV<~e0 zz*&VeGO!M1`Q8os ziRwKi502Gwz=oy+8SMq!8O3g%N4c7))_4X@+NhV*cH6l=p>){NbaT zC$I|s1^H28qy6FOW^;296fNXc-(qTJCu|;Pe^IjB`*9n8_>;P3Lt%dhrx@igRdnO zBEp}ptIAShH&?mhVS1eh#Ptfa1SE!DW>syx>VEdYv`lf$Iicb9jT?ed(&qY+zj?UY zCMgw@)33^9zOe*&i0|IT=I)-wVE6te^wRd!U&~f3rZqODq%6*N9N+yU+>wVZ5U#hz z;A+vSS$r16DGh7?cm(|{8|PJdI{g>?vC^54kdX0lS2y~{oR80YKK4(~hn%Plj8xyS zN}Q1%F^QUJNTwT(|9%r^b6C@dbI7Us2C$Ec!!(-v=?RIwvkEx!apx%*}ZX6RVcq#-bAb2Jme+jZe{$utS>}I^K)clc|B6Bvi81jx^_D;LSd+LDp4Nz z**I(g4K1^U#rd#p0bFMjyrtUqVURI zdqtP!oh`%y{~UMgfZmCpmsV$sb-v;o#V~Io&coeg<@DJ2|W)2PKA-oMo z8p)+Ye}_qXNbeR10g?N_>W>mykxyQK-(Zf#12gRzb)*O)7bzj!VrYG$RxBX{q9uh8 z`dO|f!KPOyk);4lk_z}%mTn{7I`TuurmI-O>SdZCplcYrnWADFgD9L_c`lS_ zEr`5$3$uv3|3is`;DTbm-9SQk)y~}Lx0-n_sS+r2kglI1s8S|#Fh4%6JVPGol#*So zW;$Vmb-n;SxFu!mh>2ZtrqDfTGy#KTd9~!4M@P}qx2!|=s}>0y{Ed0P%1WafvWJms z)LROdRA~yQ4A{%>n@wN`*4NZ%=L}ATWz-aN4yb3>&=ZuR#^obK&!${0k+x=2os*&U zg~X;{$t_XYwOT`g={&ZC^lQATa`81< z;vJ(hKQ9)%bT0sLL1Zb z&7T;Xe$@F(tg1C!la!X#Yvs}n5uC*LH2DvvrK@9|sq}r;+q|%QI))E2g;Z)^`D^Rs zrdPU1S>EPMKNr_J7i3v4n#@Wsm0xO@_#MW3>KfLhvd{;YihmrHqe<3?DXP1a)EbvK zc5wdt5f6m`br8W$kLd+|Hy6x4%wB z@ckmiUyRe%^rCIU4KyIO9Eij{eUi}?a( z@T%YmOya`+2vpoLF5`QiKg@nSxFmUsRq$MIxql$Eqmo0tyzy{r2nu0QD@KZ$nGKbR zd&W1Y3<+y&A|ai{Br3R848yrU;gZrR8c9^Y7I^BUFkY-wfCW!f6G9L%eAj2NKxTBz zzAO2x9$BXbIqrFV3O@~5u_?Q5avI_sKjpk4nUooP`y|?4;gu4}>`H~SvG}Kmq&f7A zXVPz}ML<3C@_EPWClV35k8kU};0iB=_FJxdue10I*|-^;xrg{!Y6q_-Q`am#aD$!v z5Z1La|2f?RH-f9IBI{-@)e<4?bQd-0Dhbd{iw$$U|F&uOS`(p_F7g<6{lp&aUPJlE%I5Idsbz+$%eA(w7GDB{4f0y~(#0Y5)N zZE`vC0+#nV)*R*Otc0FaRrsRWuJ5yei9J!xPs!}FQ@KN(9fMG82fqG^k<=%+ywiwa z;a_yTCW;y4jbKqpMYN0j{n%{{$CFxsBSFT!N~o<57f1$oEM4r_fMA$qAxshW4l`(K zs)nLf3j!N%gc%3QlIgGc0XGtrZ-*Txg?;1${!p+E3*6>ZxG5I*7SKjD?oYpzgty~J zRm<8Eix~w>P$yvo1lGP<7{CsfFZpXXvG7}t2vQsQ@}7tQ;zZ(@(K`;yJ5(BXFhzdw zD(QR6$S^Du>S!?Nm{4NH=cf(eyNKQWa^7rqI07L5u6Y6CijM*SvM6kb@IEm(HtTdo&G^JWjsStsmiNL01|NS#0o zNSYEHUM~_yXaNB3*Hi^e;Ds1$){=n|IFqUgcY~K5J++ zwT3Xw|Kri0-(?k%aQ~xN`(T$@MQjme{RkGvBF<`u?vWIn&wJP!Dp`r?(ba=Ai7KiAN?E#5p+VPT(`jC4rI1l6ePx)`o<1Cqj#@vN~l4R__RoNKCgPv=F?S zb~mv8NnDU(86x?wn8xkWhpp|%pw@K*z`LXvwl1P?jJw8j9G+YFEL7(kIal(OHF7E0pOBQ+_I-~7ao8jH&7n^4jbbhDBeBv02i z*?I#5{5553FPPeyhB*ne?V?0o=S)=e52> z48NVevBM2uwbeasrJAphi?4#iMlRJ&g70OtbHA{p?@yEa0fKHf-TA%>>y%=q4OBy)0 z*kRh71A_*laQZ?nBnids9i6v3L(-ESM!S%IQ zrQau z&4jl7i04%2)oD$n!b86VCd?{^I`U$V`wgswqY!&E${^~2yjXO6fxOxrP16ueDR zJ+`c@53rG5b$+HQe1J&1DRJ9$J(nP$9+WBM1BnvU-Yalv*@W0|3xmQ1)hC~(p?ozO z0!UZ!D8r$I3xxwn%WNyVhs_ocSkXhI<8vtNif2-WPhd0J`J&wuzF8Dp2XQoWamokr zQ_1h}7=K9gA74%ZuM;IO(kjf2Th6fmSM);WcOG|s0WCd)rNY^ffukjIWjD^}HmM=v z%nJy)UYcTV5udmPsC^5tyH0;49($X&io$xgj2s=Ftckoi*6_F?Q+2cbn#$18PUAGU*0HLM=bESZJnl3ojV{&ZEp}+Eb|uOMc+-~dml18Vi?0Q)+BMwyxi(fw zlvs%~6QGZF?I|yf?pr%>=Dy0EsZ=%q;v~rhR2dN(pnwI^XpR#IGOvx-22z9l1L*+z zYp-|$WS)0}qgND282`df06vaWT%SXMj6kKyt^?@tx{Cu(jaY(yPM=2h9zffA+l|ii zghA$;>*YMdXoYMNYBhgrg=MOYEFu0qLxFFzPSlQ9McfauU*SFPTsz^ddH=23wstF2 Y-%GYu*s*pB{3{EX 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 delta 703 zcmV;w0zm!F7t95a8Gi%-007x@vVQ;o0+UHZK~#9!os>;T6;Tw&uZdA+3W?w%0~ZnG zE*D|)|KAy&W{wyjKjRD8-JaxDzg*IWfLZ`0!evZ z^JHv&ns7J5dEb2*3mD-o-s1zjk3+uc6KmzZ?74A9w?&GR-$hG!gi}6bAX*p_?i6s` z1~0PVe<^eoUs#_HPHAd(8;<*XH?37-YaY97f96)H@Wo$|ob+wxX{%x)$=8i|*)s{Z zh>I4{l8`@dYJXo_{3^sW1mA0lyi1eiHDn&H6n0@5qT9X8q#0abBFEU}Rwi5AO5KjS z0AdKjw{~ewS9M#`t25prxz+LU)q0z$88Y>;Ua`j0*#!7uzy=&1cH$iK#%S-2xlMmTT~AQ zRs&2VhZQFvyqyX-u-WEZ;*wWPD!`=RwBjg)gQ)Y+*PcVC@L{Ii*G)TNE3N%$jZK0G^+Al+}+K)b~e{N)^iBnB)-IOfKu8utCM&*72D_q9JGc*adBnb z9xYKJ$F0DeAN-T&>+^lH<^{#o+K!H9`a=mhW=Ig;h~;Jp zxUi0oEn>_m$P(dfFgpq1SA9IoQY43${2tHp95~Cfg6JyF#3%ik)4|UyQyoV+jz9k} lS$3qRNH?NG_i;R(=U+y>dmc6+vyT7(002ovPDHLkV1gL4NYnrT diff --git a/apple/Sources/SafariExtension/Resources/images/extension/icon-48.png b/apple/Sources/SafariExtension/Resources/images/extension/icon-48.png index 568703dfce3ba0feb70021c11fd0cfcb1f6aa96d..dda13bd4eb904486d334be9e4e5a6c42aa3fdf75 100644 GIT binary patch literal 4712 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 Y8gf05dS6j<_5VaoNmH?0{$a@f03*p`8~^|S delta 1073 zcmV-11kU^DB)bTZ8Gi%-008|9F$@3z1OiD!K~z}7wOD6p6hRc;7!!L<>|)0PVvX4H z-puAs6oAMt`<|X9Sa#{~!KlmbHKuxSj|<^bL@IuW zmCR)-Z!6yhlX+t{ge}73@XoZ7B3?HJ=Ye{#Kf-w#=K7nt*;XY%HeQLe=3Q!X-wLi9 z6Q1LQm^d~J&wm&YA5<3I{Ud$BtT5QXLsIiZBIV3aYJd0S=+S>?L9evnec?W>;th6n zrX}Sb-|~#w(0XhWyhR=!23k2WhoY~Y`|uduT2C<^wDF#ZS?N7Fkt3@+zLgN_NOSzV zDgJf;D=s*e)^NL^j`2_(OuP2E7v{J^oFj<5>PN@u(SL+E=%d1W!*9*old2^7pt+PZ zEVCPrX^E3@+UV9!jVW1j1)P% z5UHa%4S#J(+Dc^YrKtVoEt_LC65KLt{tRRKT=N@yjdZf|@d}$n0IC}R9)wC+34bTr zOkcI%6?obWfDa(As}#}7wOd~sSAglbjqWZ~C5ilArO1nMxhp_A&DgGp__StdCtEc@ zPD6Z1_lsc(xxXK%=MEr}B<1^%f=A^EAsT=n-hXiXYbyDlup~wUfLEGbsUprfT0Wx# z2#7)xz*;TJXaK)7yB!MdlSaYR=m5b~IAORyF88lHz^L|QS)f3%yv=SA9Y8BxCR@gq z@k}Gn`9#K!w!NHVs2j{9LP5;{wlwG>lVvM$k$mItrl=zg#(D?&D2ZPj?U1J%_sg?0K#>^FOG-%rI9%!tzlD5hmc0<(D236 zYiN-f_`u@+k>zaS?-WG2gJl+&&nh1!-c((d1gn4oK*tS5_ zg`E-m@h;5E>JWcM&9;1?-hd@6ApTBBj~j&e3t@xosuqR$8P8<(fWvl>I48@O#wzBE r4~lOI1JFNk)xko}R^t}7*X!JWVURl-0t2mc00000NkvXXu0mjfV80XW diff --git a/apple/Sources/SafariExtension/Resources/images/extension/icon-96.png b/apple/Sources/SafariExtension/Resources/images/extension/icon-96.png index 8c1aa41238cfa1c0aa98a2273ce783e3951cce00..3af64b0bef541901685467332489c0a78d5ae34a 100644 GIT binary patch literal 10231 zcmY*w};0Jei3GNcy-QC^Y-Cw?Y@4NTCp4C&k zt9R|H>NRWD{Fo4VS#czIJa_;AfFvm)qWIV9|1)7f|GjS~yKw$BP^N-1f&f5u6vC?k z^xrkHk%XcQ0N_pm0Q?F70G|K4ejNe;PD}v6u|5F6oeThA+om@w@ci8fFj1HMAtM8z z`HNuz&=BZ=Pk#}_-wObN2lz+rF9JwG;QtpZLQwsO0|@{Gn**T!!_oX}{}~d0=RYz3 zwx6;g{->A?`Cqnv_NV{hf5J53SpL=wfU}j*Z~y=hF#eekfYfxHziJxh%Ic2lG9Ydv z8!H9_V;e&g23ITFf1&_9uH1j2m5HMPv8&ZjYX@#uUf{nN+<);uZbl&SzbKBDyg+ps zd17H3dlTYs3``76Kt6b4VqzY9;~(6LB4Ymu|GVM^nmIb!ax*fzxVSL5urk=#n=&$U zad9y+u`sf*(Enx7JGfap8o1J1JCOccAKd`eCfSvo$8yU3aZ@#&9bU;sG#T< zh$RgT)Ny6Ur5-xhchcHW~9=$4->Y~_759M za4curbUy$690=v{1tQ`;j^GD5=n+5ntcCsT6*Vu3;*dA-Hg#cpa#LHx_!U#N19OqU zFMS^wGw2zILKG1Zx_lrj7}??4-6#sKOoQ z#}wF5e5KSrj9Iacc@)0}Qw&QjPl!{paQ^C=Fshq+(VHd$x_jBe!d%NLZp zxBRFZ6zyS7LRO0|M#BN_t8B}1++$_g0EA=whVC+6aQ7x-JsLu)`>G2i;Vm4*?es$b z%(N@A?|gMp!xC3TU?m@JX&l$xJh=f*1aJnbWrtnU9L0`(_d)d_)7u@3y7}E2R_f$j zF#3b2XwevQdi1=(r>`TIbaR)cs&lI(kIMriH|kBsGhsbdrV>q{(vv=e4P;-*o72>53*(uwg0Lkih=2oY$aB@=Leo)MEQt)Lz1;QQLX> zo5(v#%@P{=W^i+Vl>W3&j_8J8 zEnOjH!muhQR3Sb`GrW)$a%hx2u6l?`V4u2`^phZwM#KO=%uHxK=OWK_7baWX(^KWwqM{*K{bL>X#pOk&{-d3LVFD{I*u zADMuz0?C_Xt zr2xe6M-Fa`>K5A`CErf=+eAI4E{mP=YX>B4EQcnkoo+Fi;G`skZwm0MgMU)`7xlOaE zk=xxr7nODP2{JeoLnVobKxUiFsVJ$>+cYL^xd|{5IgoY~7BF8+y`h~4kloh;X+}{X zL~0VY#bfoc5(q4P$nE4Yg(AbMu5(;qWWkb-P}*giU8*vYgLpqFu2*kyMxh9o&cS5Ks~&>;9=udv znYe21Pfde~5gcS7V9$weD2xVTM#nKzv0oz}PGFTc1RIuCv_tg$W~ZXJ5fD_MZ(o*| zg$CuSzcCxyGC{u4Up9p9mG7j>;)zW!btX5o>}(B8JG?w)ci z|KecUkf`tgMdj@T0rXoJ6ea9I;EjI)o`lrC&Lp@V?3^`zbf|7_hvc~q1q6MDp|Siq z_?>1-&qtes1A2)ReTwlLr1_8n4oekL?29-+P?@*RkDE;cao17HjZhX#dD~bJ8hH=v z%7F`+h_=t8lq_-{j7AEa4TY^5F0nP}+2>hxIAB}#dB8-(L6v@7j6wY)E>mb?Y!Q%^ zIhVo5Negk?oiuH5KSC^!rfeynq_Vc^c#4c$mdBbd(a1YmOx%$TTUWT>=WU}FI^$R#vy+599H z5dKqBLG|IwC&Yzo$rPug2j^vnlQ0qQPcp-EmJf#SXA=g)yL6#=*k~7>75+|4&>FTA zPQtc*vj)lDcAx!>sFUzhlQ{~t_ltmrBI53ORBN|rCiJ7HsudI@Vqkvw8>y=!Y>%t4 z1~;-^5~0KVToff*AlYEJ(@De5o5{o0FfJ+T;LDL~U1nhQL@Grh5CI|GA!Yxyu{5|v zq(ryQlY(yfAU{`Nt9BJzw(R%W`@Q&z?Shw${(hYS6?KC`)3V*A0AWRPOaRfuNdFvb zEouS|vRb(eiL9Od1U&}34M~8y{5A$L8^AO&QGcxYP5rIUyY;OL4G{+?fCf@nGH8&J0Y(Ve!i~Ry#boZ?=_Z9!<>AF`4HUEvw)^iF*FU!RhLENf>+-D{l(z zo35uNyjuyp_PJyE0U`|9z7~sDUbN+@gy?v0U~c>{ow0k`OM%Vjw3XLR4#{5^Y41F^ ziiJ*+tthiaH<;}e92^3Rt0xCVwe!g!=YjJUales$onTn=JAUTYW@CXSalG_gfFqc+ zfXiFcz8WOrU!KIR;1;E8TN^RI^PEptK8lyfaGKx8Lt7GPd+UeM8hrA5oq~UYCXX0i ze!BQb_H$GFK}y4ih-}|R+@6Hfj)arpg(k#FrTbbmc~XK`eLSP{ICn8W`D{eVEnMlDfoPJtUs&EC3wWFLZ@1-VUJ`kF zk7D<*8{wq|ztRQ1c2A4NXWDH=98`8i+zgOJe`}uEmnZRe2=o;E6;2L?O}HZ$_}yN_ z$2dP|Yi?c!7s7p<`EexF35SjNYtQF9f1+{<>Oody%B<*g&a6F}$5vhlD$JGo z>*r#&yMFmIbdV7){TAIY3ONVAMhnWq+7)69KW3i^5~s{KBi~tfNdkZO>QbKB6lc?} zQy|zGHNCb{2nySGp4xqX94};Iy$!i~_Z}lKBAlIlyM{VN-El*T=G;pP(HzmBhzrj@ zx{o8&5kW=Avc+@-RbV0M^Ayvg4aKzR)t{&GHHQrEJKKRS(!OMu74c*)Cqyi3($L{F z`St9kn2C_%x}81Un7e}(Nm$`8O}$wR9YBPM_j4)br7=z&3#F=w^lty)q8MeH-BwEl1{ox-jIYlI8qZa9S zoBi2m(rq=}%1n*qw|R4B{Uck#kXRnH`JzXo~nh~)Q z@`~-uV*3NzwGwH3#dAxsDRPz3ua^lTUs1bIeW_}XbNxx5Qpdx`J|S*imi@fRyiT#P z`)T?nFu)UKPE(cacV840@S^1gNHAilJiI)Lv*O{i7QxuTRd$V@S>ifTtK0GNawl%? z<$Us@1uL*8?IEo-8}88q6@35?Uut{j_0dTl7pp#FJTR^^m&|WU-H}j4xX}AZd)@>$VNg&X5NJ zg!~j|P^J_nyV=P`%iAd$uZ&~a`jabVZoT{7UT7byyCbHz_kc0tC`kF+dm!;mOImd2 zA#t}7%kx%68YS`f@9=>p5kCT;aCu0k>!ZU4`D9R z$8ZI;#EQvNkOG#!r46a2M11Iv%%RGz^b}#HgdtRM6JD7ygw5G&I)O5M}gPp0K}=ZN zNPW%d9=A6OuUlB;NVs;o3j4~Cc(_=VHpTKBE05`6*mu#c?#s9S%5J0A>iyE5s_J{t zZ@GzYImjK=!c%<=2XrX~uc!T>AJ+obni4xMMrAxfr&>4w8+vK{5^6i@K>hLlwAOPfO+3 zcrJ-0n#8bW@#1fb)i>`Qk#v{Ui>-O?e*a9b zBWX~|3r?oDIq5eR?8~$J9fDF1MrD#Ll22RDzbkEe^J$6tCWszUCn^{H zxEkoXswCx%UNSu!)K+-)s0>fiH)eHWC==hy&XvCdC@*zpTQnjOvCz(l50Qn zq^Dbeey|~MOZ`QQJY+=mQ$W}46eKX>L*dSJK)|eoF`_YQ0{F6kI+6m$tKk6itLLfA z@Ja~IXd?)h)3+5_Kd_gfJvOgaVbeSJu zuc8}JSBKhKWtgWGqR8k-8EPB|tKg5DIIhnl!Q#|yd&TUl{=RO_L1!%VX*$LWwr3=E zN^F=%;+Hn_BNP;_r4jr~)TN>29lx9E8H2 z+kk!h6ZwJLd`yD`RkqFTD`wY&9whar_b;=P80<=1E(IW7ue0@xs05$2AaF9keG6Hc zb&Ohqma43$a~8JsxxcWelB1JU(wfn9kGJuuYRcH(8uj9u43LJTP+mgS$#kTZj90P2e0PJM#5f59M4es!J?Q5F)}t|Su5GbeIthUYP{M3k z?1|<}DW>{ZvoXNBjpEaaOFRY-Mz_Ksb{Bx}LC-7abZ=cPhiToeOUzs)%I_u{ zD^3w-yfl`qj&{m3jVYq0AnY6Oq%L9D-71s&u#j-`0T|obabKuH>B_L2mOF;3<9 zS~8)Ge6jq!^}K2cquvfYwc|5#Ypk4)u`YHEuwCT|WUDaB-`XB6Z@2Ij3&EAqy@XWX(noKO76z+$eNnm@BL zi-{13Uh=IXcv7O7@s(iMSokoWe();%n!L-##;JW^*d6K5pJmiXd926OQPZIbg+qw3 z+e*KQ`rS`%tsnA-%*lEKn9V`a6Wx_QFWd~7Z16_*(^oJ27Xk*7ymvw4(aa~j;z8(B zrzHvla@LvPx;h+gYGi076f#5F#m1|MuYdUU>f^atOsOI7+p1yWLJ9&oKa1@Jc5|XJ zXvRtPA_ax*=V@rL@=ifmQS`p2fqV7suUl!ww@b(3s!h}&jARW4ab-;p{k<%H8=D3a zQ?LLm?Hlxulw1s6580-UyV0zgPnNKQiie(J7ty6b;@SIu(T!oayNIX$|6y|Fa(i&$xRUKR9=DkH#EWi3?^T2o_HK9E`rl1 z^lt9ID#55U;|<`Ve_S*K{Usx!-R|^ zbhIG35K*26O37B8Xkd`91dKxLHm9WV{0ye{hR>b$`L#|zOo(RJ73Z&I*jPQ~D1sl) zWNtgPgXCtTo@P%{;c$v=R`9OXJ)%&*X|y=Q=Y5q?<0mB*za}(zxw&N#s}xQrt+Dio zQxq3Ex_87f{+hj?S&s2Cf!E07gUdWcLCBLZ#7aD%iJ%RoL?6Wej0P!XR~g?b&8hhc zr_kP4Ry0n~?MFX!i`$g}1HUETQYu9g*PF<;{@A+sktB0cNq_-IzMD}Y&b)K!H3!wS z{TK?4Ng|eyJ}=vTZ*(418zlD^nO2iH9q`wZ?;FJih2)L=OI;I zVCE1W4)@}ON9b;LG5Go1S%AK z@mfMrSWBsAK1hWKvHVa zQg#(0i}6sYyAWlN9_$k0ZHTZdSVeLJ%k1{^-K+JXK1|r)o@KJCr7#6v73>X38d6|t zhEeyD7ul341Ziq4x?eT2EtU??X08R~6QA zliH8%EAo%sUd6^WO30?PYZYDR^C+>NA+JuBVg`J1jKpXp42t?4J&=|ryI+&8nUFfA zrE9EW?&XN6Qk9b$+P9zEU;e&1${ZznJhBe9)==!Z6wz~IyALPS)wjB^!Zi``xdFIv z3h8;GDyqFx5L!>Y1R|lIj%!a%7i3N8Q%60F-K|HVQs?dZW2af>16s_JP>hSk$CJBy z$&B{v(C^Qw1<#-Ti}K{MdpnnGhcBcl-f$%!F-1!JA?q+o)PpO-RO0mav$M}sB~ zr2Qv8y1z_Au&AwJ+em8h~V$b%(wUi^;@JC0%OiBURz= z>d(8{#y_TDNEG@A?#pAk*k>pvLbT{tE0X9o`r)F!ty25i+1h9MxS^`8Re^qg3L80Y zN-uZ4&Y_(=quE4{KP&ycS4M3T7`UxY(+j(N5u-rT&UoXD5rg&n)H~AU(Tq9aQjF(r zHMo_Qz+e3em2j)FRr4zK#EgE3?@zZM4{OV<7DDQ;E zv{)t-66dWQHgw0D6sB`SjL`ZH)*7DF_rQaK$O#wcz|O(;WxJ&z#N+|R2a8oZGZVf) zm?!OA0k~zA@#JO3b_h*cPQ65Q@oiT%aB02D+Kdk|u-p#4?J{*LA7ey)K=g_PQiObg zlPmq<@>6cme%gR&HAt| zNo?5#x&t#E86o&z!cDt_+Wi{Obm}5mvS{aUFm-NMuWE#V!Usa9n*9|PZa@9Xhblnw zPKPjC@zZh1hx+qHvEohLZN9`@u5r9yq>Ih;{h&`nlq>kqWm51op`YRT@D z6N$8DYc>cFySZQLvqJ@QRnG7BRng0B_*P8&$d%K5l~orehPq6YX3VFXZi@V2#J9I7 zzipMPXc?GBwADD8iGO^|P>uMh`$Ny{ypmn#{;nta^-^M4t%Z1{s)vV`Hb_&$&+ASu zIt9_o%tMlM9M9%+p8SDnyK$y}qxihJ{0Es^Loj+G1$39_hjuzH>-Gl-ucGT#(-9u zr8!0PUcuW+nmmYkFxt=`xSL;0nU>C&_Q6IGHKE`3_krYWjA{(UvNC8qS_X}_I^s}7 z5M{?6)Kr3qF$xd$l5xhuOFsy!Np9G!1eHu-Ph$c0wYsgRN%49mzJT3xlL9)N_xi0a{Df&(fW{7!_Fp+9Iwd~@yx!F*`k?Dd82JCWNbu1Y;h!`?jXr|~O zC4f9ls4-?6NkG#jxNB#)`_O5b@WJxU+UClg*VXE6onGiJ6pM>4Yf+ zcH7VoZJaY=W=}ty4{o6blbMesS6D+TiS_)1sAzo<$veCnWpew1dw$J!9Zf)1p03y@ z2Bu|gTtyODn;w| zDieYzH$DJI*J}RdYtsijx7(Dhf{YW^;SJ)_!9^K)L3Tl@NwekmTCdUt*u(lm@o0h9oz;ur8A39v* znU`Do{ww^aIOc?eAH(Kov%O?e?yuGJ&QpoR0%gVhN zX_&k4%wz%ds!@v5g*58FwM*~c#R8x&34)CSE^&r$3c&3BDv-%ORzEfSBzAPxGgB)l z2Kj^Fh*6IBDs@0VJ-eg4grRUnQj@=p^_uy{%VwkzpJz>25)Apjx&w(KTk5@Cu$mwq z-YeyxqR%@h{U`=TLXYN*GB&Xm;kQ-w!+=~wG6dzsr3oe{e587v_ZpsN3Jnzp&Mzsm zFt3$pvyq108DSKUU-CV44-7}|jbN{Z8~OjVhkUU1bBsSY9*m;c@kfP*8*Nwoz3@SS|WT5!B5C~y|R{=^_nB)jQB5QS-N;Vnr-A@_;%>MRf?Wx zwfjk0FMR)exr@X}&ztmHQE+{S_aCF9w!r*_=w2o4F{DQ}T=q^TZ+1RZ ztG{bhZ9d@B-zT!Ras9|57URDXB9jK5lV_u#KPVP5`0^a%e+ukqQ zKhC_qD)mBD`~d0o%2)p3Bl!g*^fr3Ub}p+e^qy77Lv7N0oBMEzTlBCl`qLd`Q5@#^ zOY2VW_&AI4w!g|t3IGuegqL|25`NCk z6@>5SnEc?Syx+qie4dxql{6l_$0m4pf1fCKT-rI&#ek>w8pNFLU@M+F zU@8kYmE6;9zsXX7>G%ylv&xZP+u_BzbbdfA?o6T{X~U)?{&O^ES~>|a2`I)|(tOd^ zNr9=DH_4XBjGr3G z1}@oE8Z#wfwe&jP&z69^dm(Pc;VAW|h_`V2w?8KzXLEQJ?eCslsM&WSCOu$G@X-@( zt_EJ5XfF~8*5_y{=3WaHJrFD_&aPlx^k6>wB|3`TPNJ&}zcBVCC*y@tfoat2Hf#FW jYnwP!{nxWs?{_^dn58`C1LoO(erJ;ul@+NF()as60YNYu delta 2106 zcmV-A2*vmJPrMM28Gi%-002mlzq0@U00d`2O+f$vv5yPA_*lznDVS{p(xee{y5b=-`bC}&OYbtd(Phf?Q_;z-+ym?-})ZEwU!V$c;c-h zr-veHh`db3H1w^&<|&yQ-Vddq4&Lu;{}Eaw;hVx4>rw}xc&*nASbgS;M# zXs?^tj_)C?kP}t!MixERR@Pt@)u$yo*U2`_K=(!wKGX|O;&1<=GZ^p7k@4n18clC3 z%#P?uAbyj#1b+fTor!sw7>(!qBV8A7l1t%R(iHm7P?+CoBdw>kv>GevYpOE_y)krQ zuB=|tHz}9od`yt#I8C**yICrgAvqq;(|S6T!b8odXq{!@tDDhuk2ySq4{*CW)mW1! zs8KYRc6xyL4#=YT;WDi7u-m&M?R|#6OX+PlZQ!81Eq_bm%MktHGRR6bq_#M--qD2~ z#vYf+dBJXq=?^fR_B#sy84b>sh9m81rpqX6s5Gg zO=(sWGJj-WR9G5RNkT*IX(AS-;qSs_c3Z@2u@=Fli|Atyb9l%&>e|B==49&cvjIU} zVWz<8_Sp|wd}j#QZQxRs(w7jH25CGzeZ&DxmW3%3W^C3yPi33ND_UiZZVf5iI8D+0 ze(oJ-3PXBIlW1qG#G~5M%az=QEu+xZ0$*unG=IY#?L0kc$P3!0KM$$c=MtCEM_ayi z{_^}B1hz*tGkV$?fW|anOukTO@mAQzBs&o9=D_pl`F^$&=8SZ3qo#xD_W6HO`^#XF zM^AM#Y+=*8UE`2qZF%~H75PRU<66x^M)03+@;Co97|&xJzMz-oNb_{VDw5^$5xj^w zG=J9AQN){T3FZm15;+H}lE&I2?=)L&n94@0PpX!wlsiyN zNZnm!8?3V>eZNGGPfbnIKel#{8D&OiXsxbo$T+GwBQx+sAHLZr^u?QCjU$0#WU^YC zKeyqBMV#z5*%@%-a^y(Q zU%t^1bgd_|-P33luyhlTCqB+$A79TL0QT6mh(3CCtxCwtxY{!TP+N@mQ*LO#byO6806t`EX|zz6vjNs- z0ze3Kp}#!E-_<}4`ZS?c%!Eb>bp_v($_#)IG}a41GSB1_0CxyO1+L020Dn8Xk@UX> z%ouzCu!^)+7YH?k4f1{F08|I(BTv}Q%SS%|!ev^or9z(1BV^_Pgixn)OHJ%4>-mu% z0GiL-YZVD};sXslCUXEn)E2ADvH0*QuDw`HRrV^|4*(wTu~G;TYmuE)!a0ABmBdQi z2m;PB$N@%6nAMIn(iGDii0Epnm{pnXrZ3A?eKL z(ZjaLen;}^9;MAh$6x?hMS87@3%ycDy9Vy}@flt<-G3~X+{(uHS9u3@+?wwsV%J0)2lpx_&yX_WMRI^CTQL~@g@$m)Pg|od1b7FQip)@b{1|^1h^7< zIo#6wu%MQ+eP@L%Y*YOUDJIQj^mZ`J#m@^&MWa$fAF6SHU<| z46~oGN^FJ5(SHR3LiOfH9+NNU&~*jjTnDw&j`y*u0Z-7mc@Lqsm?nE3m)U@+7?|fd zQ>Yg{PEob)qxbMQZbCR*)>yYbQkCB0T`z9h-~HHuE%~>kJ7Tum(LJX(FO4aBGM+NM znx4PT^%VIa{anBR4p$DB;5Bc9Du5_a*+y2-Oxvlf!ZQKTu)L`Xlkg%wP4-lx5Fe{3 kdMr9cdZ_-gJlA9W54MkVCJ8<0egFUf07*qoM6N<$f^r}Wx&QzG diff --git a/apple/Sources/SafariExtension/Resources/manifest.json b/apple/Sources/SafariExtension/Resources/manifest.json index de9fe4d60..63789dae2 100644 --- a/apple/Sources/SafariExtension/Resources/manifest.json +++ b/apple/Sources/SafariExtension/Resources/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "Omnivore", "short_name": "Omnivore", - "version": "2.2.0", + "version": "2.4.2", "description": "Save PDFs and Articles to your Omnivore library", "author": "Omnivore Media, Inc", "default_locale": "en", @@ -75,12 +75,12 @@ ], "browser_action": { "default_icon": { - "16": "/images/toolbar/icon-16.png", - "19": "/images/toolbar/icon-19.png", - "24": "/images/toolbar/icon-24.png", - "32": "/images/toolbar/icon-32.png", - "38": "/images/toolbar/icon-38.png", - "48": "/images/toolbar/icon-48.png" + "16": "/images/extension/icon-16.png", + "19": "/images/extension/icon-19.png", + "24": "/images/extension/icon-24.png", + "32": "/images/extension/icon-32.png", + "38": "/images/extension/icon-38.png", + "48": "/images/extension/icon-48.png" }, "default_title": "Omnivore Save Article" }, diff --git a/apple/Sources/SafariExtension/Resources/scripts/background.js b/apple/Sources/SafariExtension/Resources/scripts/background.js index 2622ae52e..0db7c28e2 100644 --- a/apple/Sources/SafariExtension/Resources/scripts/background.js +++ b/apple/Sources/SafariExtension/Resources/scripts/background.js @@ -1 +1 @@ -(()=>{"use strict";var e,t=new Uint8Array(16);function a(){if(!e&&!(e="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return e(t)}const n=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;for(var s=[],o=0;o<256;++o)s.push((o+256).toString(16).substr(1));const r=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,a=(s[e[t+0]]+s[e[t+1]]+s[e[t+2]]+s[e[t+3]]+"-"+s[e[t+4]]+s[e[t+5]]+"-"+s[e[t+6]]+s[e[t+7]]+"-"+s[e[t+8]]+s[e[t+9]]+"-"+s[e[t+10]]+s[e[t+11]]+s[e[t+12]]+s[e[t+13]]+s[e[t+14]]+s[e[t+15]]).toLowerCase();if(!function(e){return"string"==typeof e&&n.test(e)}(a))throw TypeError("Stringified UUID is invalid");return a},i=function(e,t,n){var s=(e=e||{}).random||(e.rng||a)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=s[o];return t}return r(s)};let d=(e=21)=>crypto.getRandomValues(new Uint8Array(e)).reduce(((e,t)=>e+((t&=63)<36?t.toString(36):t<62?(t-26).toString(36).toUpperCase():t>62?"-":"_")),"");const c="https://omnivore.app",u="https://api-prod.omnivore.app/api/";let l=[],p={};async function g(e,t){const a=JSON.stringify({query:"mutation UploadFileRequest($input: UploadFileRequestInput!) {\n uploadFileRequest(input:$input) {\n ... on UploadFileRequestError {\n errorCodes\n }\n ... on UploadFileRequestSuccess {\n id\n createdPageId\n uploadSignedUrl\n }\n }\n }",variables:{input:{url:e,contentType:t,createPageEntry:!0}}}),n="uploadFileRequest",s=await gqlRequest(u+"graphql",a);if(!s[n].errorCodes)return s.uploadFileRequest;"UNAUTHORIZED"===s[n].errorCodes[0]?(browserApi.tabs.sendMessage(currentTab.id,{action:ACTIONS.UpdateStatus,payload:{target:"logged_out",status:"logged_out",message:"You are not logged in.",ctx:toolbarCtx}}),b()):browserApi.tabs.sendMessage(currentTab.id,{action:ACTIONS.UpdateStatus,payload:{status:"failure",message:"Unable to save page.",ctx:toolbarCtx}})}function b(){getStorageItem("postInstallClickComplete").then((e=>{e&&removeStorage("postInstallClickComplete")}))}async function I(e,t){const a=i();await f(e,SAVE_URL_QUERY,"saveUrl",{source:"extension",clientRequestId:a,url:encodeURI(t)})}async function f(e,t,a,n){const s={omnivoreURL:c,originalURL:n.url,requestId:n.clientRequestId};p[s.requestId]=void 0;const o=JSON.stringify({query:t,variables:{input:n}});browserApi.tabs.sendMessage(e.id,{action:ACTIONS.ShowToolbar,payload:{type:"loading",ctx:s}});try{const t=await gqlRequest(u+"graphql",o);if(t[a].errorCodes)return void("UNAUTHORIZED"===t[a].errorCodes[0]?(browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{target:"logged_out",status:"logged_out",message:"You are not logged in.",ctx:s}}),b()):browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{status:"failure",message:"Unable to save page.",ctx:s}}));const n=t[a]?t[a].url:void 0,r=t[a]?t[a].clientRequestId:void 0;browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{status:"success",target:"page",ctx:{readerURL:n,responseId:r,requestId:s.requestId}}}),p[s.requestId]={readerURL:n,responseId:r,requestId:s.requestId}}catch(e){console.log("error saving: ",e)}h(e.id)}function y(e,t,a,n){browserApi.tabs.sendMessage(e,{action:ACTIONS.UpdateStatus,payload:{target:t,status:a,message:n}})}async function h(e){l.filter((t=>t.tabId===e)).forEach((async t=>{let a=!1;const n=p[t.clientRequestId];if(n)switch(t.type){case"EDIT_TITLE":a=await async function(e,t,a){return updatePageTitle(u+"graphql",a.responseId,t.title).then((()=>(y(e,"title","success","Title updated."),!0))).catch((t=>(console.log("caught error updating title: ",t),y(e,"title","failure","Error updating title."),!0)))}(e,t,n);break;case"ADD_NOTE":a=await async function(e,t,a){const n=i(),s=d(8);return addNote(u+"graphql",a.responseId,n,s,t.note).then((()=>(y(e,"note","success","Note updated."),!0))).catch((t=>(console.log("caught error updating title: ",t),y(e,"note","failure","Error adding note."),!0)))}(e,t,n);break;case"SET_LABELS":a=await async function(e,t,a){return setLabels(u+"graphql",a.responseId,t.labelIds).then((()=>(y(e,"labels","success","Labels updated."),!0))).catch((()=>(y(e,"labels","failure","Error updating labels."),!0)))}(e,t,n);break;case"ARCHIVE":a=await async function(e,t,a){return archive(u+"graphql",a.responseId).then((()=>(y(e,"extra","success","Archived"),!0))).catch((()=>(y(e,"extra","failure","Error archiving"),!0)))}(e,0,n);break;case"DELETE":a=await async function(e,t,a){return deleteItem(u+"graphql",a.responseId).then((()=>(y(e,"extra","success","Deleted"),!0))).catch((()=>(y(e,"extra","failure","Error deleting"),!0)))}(e,0,n)}if(a){const e=l.findIndex((e=>t.id===e.id));e>-1&&l.splice(e,1)}}))}async function A(e){browserApi.tabs.sendMessage(e.id,{action:ACTIONS.GetContent},(async t=>{if(!t||"object"!=typeof t)return void await I(e,e.url);const a=i();var{type:n}=t;const{pageInfo:s,doc:o,uploadContentObjUrl:r}=t;switch("html"==n&&handleBackendUrl(e.url)&&(n="url"),n){case"html":await f(e,SAVE_PAGE_QUERY,"savePage",{source:"extension",clientRequestId:a,originalContent:o,title:s.title,url:encodeURI(e.url)});break;case"url":await f(e,SAVE_URL_QUERY,"saveUrl",{source:"extension",clientRequestId:a,url:encodeURI(e.url)});break;case"pdf":{const t=await async function(e,t,a,n,s){const o={omnivoreURL:c,originalURL:t,requestId:a};p[o.requestId]=void 0,browserApi.tabs.sendMessage(e.id,{action:ACTIONS.ShowToolbar,payload:{type:"loading",ctx:o}});const r=await g(t,n);console.log("done uploading pdf",r);const i=await function({id:e,uploadSignedUrl:t},a,n){return fetch(n).then((e=>e.blob())).then((e=>fetch(t,{method:"PUT",headers:{"Content-Type":a},body:e}))).catch((e=>{console.error("error uploading file",e)}))}(r,n,s);return console.log(" uploadFileResult: ",i),URL.revokeObjectURL(s),i&&r.createdPageId&&(p[o.requestId]={requestId:o.requestId,responseId:r.createdPageId},browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{status:"success",target:"page",ctx:{requestId:o.requestId,responseId:r.createdPageId}}})),i}(e,encodeURI(e.url),a,s.contentType,r);if(!t||!t.id)return void await f(e,SAVE_URL_QUERY,"saveUrl",{source:"extension",clientRequestId:a,url:encodeURI(e.url)});break}}}))}async function w(e){const t=await getStorageItem(e+"_saveInProgress");if(!t)return;clearInterval(t);const a=await getStorageItem(e+"_saveInProgressTimeoutId_"+t);a&&clearTimeout(a)}function S(e){return Promise.resolve(!0)}function v(e){new Promise((e=>{browserApi.tabs.query({active:!0,currentWindow:!0},(function(t){e(t[0]||null)}))})).then((t=>{browserApi.tabs.sendMessage(t.id,{action:ACTIONS.Ping},(async function(a){if(a&&a.pong)await S(t.id)&&e(t);else{const a=browserApi.runtime.getManifest().content_scripts,n=[...a[0].js,...a[1].js];!function(a,n,s){function o(e,t,a){return function(){browserScriptingApi.executeScript(e,t,a)}}let r=async function(){await S(t.id)&&e(t)};for(let e=n.length-1;e>=0;--e)r=o(a,{file:n[e]},r);null!==r&&r()}(t.id,n)}}))}))}function R(e,t){let a="/images/toolbar/icon";if(ENV_IS_FIREFOX?a+="_firefox":ENV_IS_EDGE&&(a+="_edge"),e||(a+="_inactive"),("boolean"==typeof t?t:window.matchMedia("(prefers-color-scheme: dark)").matches)&&(a+="_dark"),ENV_IS_FIREFOX)return a+".svg";const n=["16","24","32","48"];ENV_IS_EDGE||n.push("19","38");const s={};for(let e=0;e{!function t(){browserApi.tabs.get(e,(function(e){browserApi.runtime.lastError&&setTimeout(t,150),q(e)}))}()})),browserApi.tabs.onUpdated.addListener(((e,t,a)=>{t.status&&a&&a.active&&q(a)})),browserApi.tabs.onRemoved.addListener((e=>{!function(e){getStorage().then((function(t){const a=[],n=Object.keys(t),s=e+"_saveInProgress";for(let e=0;e{if("complete"!==e.status)browserApi.tabs.sendMessage(e.id,{action:ACTIONS.ShowMessage,payload:{type:"loading",text:"Page loading..."}}),a&&"function"==typeof a&&a();else{t&&"function"==typeof t&&t(),await A(e);try{await updateLabelsCache(u+"graphql",e),browserApi.tabs.sendMessage(e.id,{action:ACTIONS.LabelCacheUpdated,payload:{}})}catch(e){return void console.error("error fetching labels",e,u)}}}))}w(e),t(null,(()=>{!function(e,t,a,n=1e3,s=10500){const o=setInterval(e,n),r=setTimeout((()=>{clearInterval(o),t()}),s);a&&"function"==typeof a&&a(o,r)}((()=>{t((()=>{w(e)}))}),(()=>{w(e),browserApi.tabs.get(e,(async e=>{await A(e)}))}),((t,a)=>{const n={};n[e+"_saveInProgress"]=t,n[e+"_saveInProgressTimeoutId_"+t]=a,setStorage(n)}))}))}(e.id)}))})),browserApi.runtime.onMessage.addListener(((e,t,a)=>{if(e.forwardToTab)return delete e.forwardToTab,void browserApi.tabs.sendRequest(t.tab.id,e);e.action===ACTIONS.RefreshDarkMode&&m(t.tab.id,e.payload.value),e.action===ACTIONS.EditTitle&&(l.push({id:i(),type:"EDIT_TITLE",tabId:t.tab.id,title:e.payload.title,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.Archive&&(l.push({id:i(),type:"ARCHIVE",tabId:t.tab.id,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.Delete&&(l.push({type:"DELETE",tabId:t.tab.id,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.AddNote&&(l.push({id:i(),type:"ADD_NOTE",tabId:t.tab.id,note:e.payload.note,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.SetLabels&&(l.push({id:i(),type:"SET_LABELS",tabId:t.tab.id,labelIds:e.payload.labelIds,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id))})),browserActionApi.setIcon({path:R(!0)}),browserApi.contextMenus.create({id:"save-selection",title:"Save to Omnivore",contexts:["link"],onclick:async function(e){v((async function(t){await I(t,e.linkUrl)}))}})})(); \ No newline at end of file +(()=>{"use strict";var e,t=new Uint8Array(16);function a(){if(!e&&!(e="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return e(t)}const n=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;for(var s=[],o=0;o<256;++o)s.push((o+256).toString(16).substr(1));const r=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,a=(s[e[t+0]]+s[e[t+1]]+s[e[t+2]]+s[e[t+3]]+"-"+s[e[t+4]]+s[e[t+5]]+"-"+s[e[t+6]]+s[e[t+7]]+"-"+s[e[t+8]]+s[e[t+9]]+"-"+s[e[t+10]]+s[e[t+11]]+s[e[t+12]]+s[e[t+13]]+s[e[t+14]]+s[e[t+15]]).toLowerCase();if(!function(e){return"string"==typeof e&&n.test(e)}(a))throw TypeError("Stringified UUID is invalid");return a},i=function(e,t,n){var s=(e=e||{}).random||(e.rng||a)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=s[o];return t}return r(s)};let d=(e=21)=>crypto.getRandomValues(new Uint8Array(e)).reduce(((e,t)=>e+((t&=63)<36?t.toString(36):t<62?(t-26).toString(36).toUpperCase():t>62?"-":"_")),"");const c="https://omnivore.app",u="https://api-prod.omnivore.app/api/";let l=[],p={};async function g(e,t){const a=JSON.stringify({query:"mutation UploadFileRequest($input: UploadFileRequestInput!) {\n uploadFileRequest(input:$input) {\n ... on UploadFileRequestError {\n errorCodes\n }\n ... on UploadFileRequestSuccess {\n id\n createdPageId\n uploadSignedUrl\n }\n }\n }",variables:{input:{url:e,contentType:t,createPageEntry:!0}}}),n="uploadFileRequest",s=await gqlRequest(u+"graphql",a);if(!s[n].errorCodes)return s.uploadFileRequest;"UNAUTHORIZED"===s[n].errorCodes[0]?(browserApi.tabs.sendMessage(currentTab.id,{action:ACTIONS.UpdateStatus,payload:{target:"logged_out",status:"logged_out",message:"You are not logged in.",ctx:toolbarCtx}}),b()):browserApi.tabs.sendMessage(currentTab.id,{action:ACTIONS.UpdateStatus,payload:{status:"failure",message:"Unable to save page.",ctx:toolbarCtx}})}function b(){getStorageItem("postInstallClickComplete").then((e=>{e&&removeStorage("postInstallClickComplete")}))}async function I(e,t){const a=i();await f(e,SAVE_URL_QUERY,"saveUrl",{source:"extension",clientRequestId:a,url:encodeURI(t)})}async function f(e,t,a,n){const s={omnivoreURL:c,originalURL:n.url,requestId:n.clientRequestId};p[s.requestId]=void 0;const o=JSON.stringify({query:t,variables:{input:n}});browserApi.tabs.sendMessage(e.id,{action:ACTIONS.ShowToolbar,payload:{type:"loading",ctx:s}});try{const t=await gqlRequest(u+"graphql",o);if(t[a].errorCodes)return void("UNAUTHORIZED"===t[a].errorCodes[0]?(browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{target:"logged_out",status:"logged_out",message:"You are not logged in.",ctx:s}}),b()):browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{status:"failure",message:"Unable to save page.",ctx:s}}));const n=t[a]?t[a].url:void 0,r=t[a]?t[a].clientRequestId:void 0;browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{status:"success",target:"page",ctx:{readerURL:n,responseId:r,requestId:s.requestId}}}),p[s.requestId]={readerURL:n,responseId:r,requestId:s.requestId}}catch(e){console.log("error saving: ",e)}h(e.id)}function y(e,t,a,n){browserApi.tabs.sendMessage(e,{action:ACTIONS.UpdateStatus,payload:{target:t,status:a,message:n}})}async function h(e){l.filter((t=>t.tabId===e)).forEach((async t=>{let a=!1;const n=p[t.clientRequestId];if(n)switch(t.type){case"EDIT_TITLE":a=await async function(e,t,a){return updatePageTitle(u+"graphql",a.responseId,t.title).then((()=>(y(e,"title","success","Title updated."),!0))).catch((t=>(console.log("caught error updating title: ",t),y(e,"title","failure","Error updating title."),!0)))}(e,t,n);break;case"ADD_NOTE":a=await async function(e,t,a){const n=i(),s=d(8);return addNote(u+"graphql",a.responseId,n,s,t.note).then((()=>(y(e,"note","success","Note updated."),!0))).catch((t=>(console.log("caught error updating title: ",t),y(e,"note","failure","Error adding note."),!0)))}(e,t,n);break;case"SET_LABELS":a=await async function(e,t,a){return setLabels(u+"graphql",a.responseId,t.labelIds).then((()=>(y(e,"labels","success","Labels updated."),!0))).catch((()=>(y(e,"labels","failure","Error updating labels."),!0)))}(e,t,n);break;case"ARCHIVE":a=await async function(e,t,a){return archive(u+"graphql",a.responseId).then((()=>(y(e,"extra","success","Archived"),!0))).catch((()=>(y(e,"extra","failure","Error archiving"),!0)))}(e,0,n);break;case"DELETE":a=await async function(e,t,a){return deleteItem(u+"graphql",a.responseId).then((()=>(y(e,"extra","success","Deleted"),!0))).catch((()=>(y(e,"extra","failure","Error deleting"),!0)))}(e,0,n)}if(a){const e=l.findIndex((e=>t.id===e.id));e>-1&&l.splice(e,1)}}))}async function w(e){browserApi.tabs.sendMessage(e.id,{action:ACTIONS.GetContent},(async t=>{if(!t||"object"!=typeof t)return void await I(e,e.url);const a=i();var{type:n}=t;const{pageInfo:s,doc:o,uploadContentObjUrl:r}=t;switch("html"==n&&handleBackendUrl(e.url)&&(n="url"),n){case"html":await f(e,SAVE_PAGE_QUERY,"savePage",{source:"extension",clientRequestId:a,originalContent:o,title:s.title,url:encodeURI(e.url)});break;case"url":await f(e,SAVE_URL_QUERY,"saveUrl",{source:"extension",clientRequestId:a,url:encodeURI(e.url)});break;case"pdf":{const t=await async function(e,t,a,n,s){const o={omnivoreURL:c,originalURL:t,requestId:a};p[o.requestId]=void 0,browserApi.tabs.sendMessage(e.id,{action:ACTIONS.ShowToolbar,payload:{type:"loading",ctx:o}});const r=await g(t,n);console.log("done uploading pdf",r);const i=await function({id:e,uploadSignedUrl:t},a,n){return fetch(n).then((e=>e.blob())).then((e=>fetch(t,{method:"PUT",headers:{"Content-Type":a},body:e}))).catch((e=>{console.error("error uploading file",e)}))}(r,n,s);return console.log(" uploadFileResult: ",i),URL.revokeObjectURL(s),i&&r.createdPageId&&(p[o.requestId]={requestId:o.requestId,responseId:r.createdPageId},browserApi.tabs.sendMessage(e.id,{action:ACTIONS.UpdateStatus,payload:{status:"success",target:"page",ctx:{requestId:o.requestId,responseId:r.createdPageId}}})),i}(e,encodeURI(e.url),a,s.contentType,r);if(!t||!t.id)return void await f(e,SAVE_URL_QUERY,"saveUrl",{source:"extension",clientRequestId:a,url:encodeURI(e.url)});break}}}))}async function A(e){const t=await getStorageItem(e+"_saveInProgress");if(!t)return;clearInterval(t);const a=await getStorageItem(e+"_saveInProgressTimeoutId_"+t);a&&clearTimeout(a)}function S(e){return Promise.resolve(!0)}function q(e){new Promise((e=>{browserApi.tabs.query({active:!0,currentWindow:!0},(function(t){e(t[0]||null)}))})).then((t=>{console.log("currentTab: ",t),browserApi.tabs.sendMessage(t.id,{action:ACTIONS.Ping},(async function(a){if(a&&a.pong)await S(t.id)&&e(t);else{const a=browserApi.runtime.getManifest().content_scripts,n=[...a[0].js,...a[1].js];!function(a,n,s){function o(e,t,a){return function(){browserScriptingApi.executeScript(e,t,a)}}let r=async function(){await S(t.id)&&e(t)};for(let e=n.length-1;e>=0;--e)r=o(a,{file:n[e]},r);null!==r&&r()}(t.id,n)}}))}))}browserApi.tabs.onActivated.addListener((({tabId:e})=>{!function t(){browserApi.tabs.get(e,(function(e){browserApi.runtime.lastError&&setTimeout(t,150)}))}()})),browserApi.tabs.onRemoved.addListener((e=>{!function(e){getStorage().then((function(t){const a=[],n=Object.keys(t),s=e+"_saveInProgress";for(let e=0;e{if("complete"!==e.status)browserApi.tabs.sendMessage(e.id,{action:ACTIONS.ShowMessage,payload:{type:"loading",text:"Page loading..."}}),a&&"function"==typeof a&&a();else{t&&"function"==typeof t&&t(),await w(e);try{await updateLabelsCache(u+"graphql",e),browserApi.tabs.sendMessage(e.id,{action:ACTIONS.LabelCacheUpdated,payload:{}})}catch(e){return void console.error("error fetching labels",e,u)}}}))}A(e),t(null,(()=>{!function(e,t,a,n=1e3,s=10500){const o=setInterval(e,n),r=setTimeout((()=>{clearInterval(o),t()}),s);a&&"function"==typeof a&&a(o,r)}((()=>{t((()=>{A(e)}))}),(()=>{A(e),browserApi.tabs.get(e,(async e=>{await w(e)}))}),((t,a)=>{const n={};n[e+"_saveInProgress"]=t,n[e+"_saveInProgressTimeoutId_"+t]=a,setStorage(n)}))}))}(e.id)}))})),browserApi.runtime.onMessage.addListener(((e,t,a)=>{if(e.forwardToTab)return delete e.forwardToTab,void browserApi.tabs.sendRequest(t.tab.id,e);e.action===ACTIONS.EditTitle&&(l.push({id:i(),type:"EDIT_TITLE",tabId:t.tab.id,title:e.payload.title,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.Archive&&(l.push({id:i(),type:"ARCHIVE",tabId:t.tab.id,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.Delete&&(l.push({type:"DELETE",tabId:t.tab.id,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.AddNote&&(l.push({id:i(),type:"ADD_NOTE",tabId:t.tab.id,note:e.payload.note,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id)),e.action===ACTIONS.SetLabels&&(l.push({id:i(),type:"SET_LABELS",tabId:t.tab.id,labelIds:e.payload.labelIds,clientRequestId:e.payload.ctx.requestId}),h(t.tab.id))})),browserApi.contextMenus.create({id:"save-selection",title:"Save this link to Omnivore",contexts:["link"],onclick:async function(e){q((async function(t){await I(t,e.linkUrl)}))}})})(); \ No newline at end of file diff --git a/apple/Sources/SafariExtension/Resources/scripts/content/prepare-content.js b/apple/Sources/SafariExtension/Resources/scripts/content/prepare-content.js index a2eb658ee..31fdcc15d 100644 --- a/apple/Sources/SafariExtension/Resources/scripts/content/prepare-content.js +++ b/apple/Sources/SafariExtension/Resources/scripts/content/prepare-content.js @@ -1 +1 @@ -"use strict";!function(){const e={};function t(t){const n=t.tagName.toLowerCase();if("iframe"===n){const n=e[t.src];if(!n)return;const o=document.createElement("div");o.className="omnivore-instagram-embed",o.innerHTML=n;const r=t.parentNode;if(!r)return;return void r.replaceChild(o,t)}if("img"===n||"image"===n){if(-1===window.getComputedStyle(t).getPropertyValue("filter").indexOf("blur("))return;return void t.remove()}const o=window.getComputedStyle(t),r=o.getPropertyValue("background-image");if(r&&"none"!==r)return;const i=o.getPropertyValue("filter");if(i&&-1!==i.indexOf("blur("))return void t.remove();if(t.src)return;if(t.innerHTML.length>24)return;const c=/url\("(.+?)"\)/gi,a=c.exec(r);c.lastIndex=0;const l=a&&a[1];if(!l)return;const s=document.createElement("img");s.src=l;const d=t.parentNode;d&&d.replaceChild(s,t)}function n(){const e=document.createElement("div");e.style.position="absolute",e.style.left="-2000px",e.style.zIndex="-2000",e.innerHTML=document.body.innerHTML,document.documentElement.appendChild(e),Array.from(e.getElementsByTagName("*")).forEach(t);try{if("undefined"!=typeof create_time&&create_time){const t=new Date(1e3*create_time),n=document.createElement("div");n.className="omnivore-published-date",n.innerHTML=t.toLocaleString(),e.appendChild(n)}}catch(e){console.log("Error while trying to add published date to WeChat post",e)}const n=`${document.head.innerHTML}${e.innerHTML}`;return e.remove(),n}function o(){const e=document.querySelectorAll(".webext-omnivore-backdrop");for(let t=0;t{for(let t=0;t{if(t!==ACTIONS.AddIframeContent)return;const{url:i,content:c}=n;e[i]=c,r({})})),window.prepareContent=async function(){const e=await async function(){const e=".pdf"===window.location.pathname.slice(-4).toLowerCase(),t=-1!==["application/acrobat","application/pdf","application/x-pdf","applications/vnd.pdf","text/pdf","text/x-pdf"].indexOf(document.contentType);if(!e&&!t)return Promise.resolve(null);const n=document.querySelector("embed");return n&&"application/pdf"!==n.type?Promise.resolve(null):ENV_DOES_NOT_SUPPORT_BLOB_URL_ACCESS&&n.src?Promise.resolve({type:"url",uploadContentObjUrl:n.src}):new Promise(((e,t)=>{const n=new XMLHttpRequest;n.open("GET","",!0),n.responseType="blob",n.onload=function(n){200===this.status?e({type:"pdf",uploadContentObjUrl:URL.createObjectURL(this.response)}):t(n)},n.send()}))}();if(e)return e;const t=window.location.href;try{if(handleBackendUrl(t))return{type:"url"}}catch{console.log("error checking url")}return await async function(e){const t=document.scrollingElement||document.body,n=t.scrollTop,r=t.scrollHeight;o();const i=function(){const e=document.createElement("div");return e.className="webext-omnivore-backdrop",e.style.cssText="all: initial !important;\n position: fixed !important;\n top: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n left: 0 !important;\n z-index: 99999 !important;\n background: #fff !important;\n opacity: 0.8 !important;\n transition: opacity 0.3s !important;\n -webkit-backdrop-filter: blur(4px) !important;\n backdrop-filter: blur(4px) !important;\n ",e}();for(document.body.appendChild(i);t.scrollTop<=r-500&&window.location.href===e;){const e=t.scrollTop;if(t.scrollTop+=500,await new Promise((e=>{setTimeout(e,10)})),t.scrollTop===e)break}t.scrollTop=n,await new Promise((e=>{setTimeout(e,10)}))}(t),o(),{type:"html",content:n()}}}(); \ No newline at end of file +"use strict";!function(){const e={};function t(t){const n=t.tagName.toLowerCase();if("iframe"===n){const n=e[t.src];if(!n)return;const o=document.createElement("div");o.className="omnivore-instagram-embed",o.innerHTML=n;const r=t.parentNode;if(!r)return;return void r.replaceChild(o,t)}if("img"===n||"image"===n){if(-1===window.getComputedStyle(t).getPropertyValue("filter").indexOf("blur("))return;return void t.remove()}const o=window.getComputedStyle(t),r=o.getPropertyValue("background-image");if(r&&"none"!==r)return;const i=o.getPropertyValue("filter");if(i&&-1!==i.indexOf("blur("))return void t.remove();if(t.src)return;if(t.innerHTML.length>24)return;const c=/url\("(.+?)"\)/gi,a=c.exec(r);c.lastIndex=0;const l=a&&a[1];if(!l)return;const s=document.createElement("img");s.src=l;const p=t.parentNode;p&&p.replaceChild(s,t)}function n(){const e=document.createElement("div");e.style.position="absolute",e.style.left="-2000px",e.style.zIndex="-2000",e.innerHTML=document.body.innerHTML,document.documentElement.appendChild(e),Array.from(e.getElementsByTagName("*")).forEach(t);const n=`${document.head.innerHTML}${e.innerHTML}`;return e.remove(),n}function o(){const e=document.querySelectorAll(".webext-omnivore-backdrop");for(let t=0;t{for(let t=0;t{if(t!==ACTIONS.AddIframeContent)return;const{url:i,content:c}=n;e[i]=c,r({})})),window.prepareContent=async function(){const e=await async function(){const e=".pdf"===window.location.pathname.slice(-4).toLowerCase(),t=-1!==["application/acrobat","application/pdf","application/x-pdf","applications/vnd.pdf","text/pdf","text/x-pdf"].indexOf(document.contentType);if(!e&&!t)return Promise.resolve(null);const n=document.querySelector("embed");return n&&"application/pdf"!==n.type?Promise.resolve(null):ENV_DOES_NOT_SUPPORT_BLOB_URL_ACCESS&&n.src?Promise.resolve({type:"url",uploadContentObjUrl:n.src}):new Promise(((e,t)=>{const n=new XMLHttpRequest;n.open("GET","",!0),n.responseType="blob",n.onload=function(n){200===this.status?e({type:"pdf",uploadContentObjUrl:URL.createObjectURL(this.response)}):t(n)},n.send()}))}();if(e)return e;const t=window.location.href;try{if(handleBackendUrl(t))return{type:"url"}}catch{console.log("error checking url")}return await async function(e){const t=document.scrollingElement||document.body,n=t.scrollTop,r=t.scrollHeight;o();const i=function(){const e=document.createElement("div");return e.className="webext-omnivore-backdrop",e.style.cssText="all: initial !important;\n position: fixed !important;\n top: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n left: 0 !important;\n z-index: 99999 !important;\n background: #fff !important;\n opacity: 0.8 !important;\n transition: opacity 0.3s !important;\n -webkit-backdrop-filter: blur(4px) !important;\n backdrop-filter: blur(4px) !important;\n ",e}();for(document.body.appendChild(i);t.scrollTop<=r-500&&window.location.href===e;){const e=t.scrollTop;if(t.scrollTop+=500,await new Promise((e=>{setTimeout(e,10)})),t.scrollTop===e)break}t.scrollTop=n,await new Promise((e=>{setTimeout(e,10)}))}(t),o(),{type:"html",content:n()}}}(); \ No newline at end of file diff --git a/apple/Sources/SafariExtension/Resources/scripts/content/toast.js b/apple/Sources/SafariExtension/Resources/scripts/content/toast.js index 000920040..72178c056 100644 --- a/apple/Sources/SafariExtension/Resources/scripts/content/toast.js +++ b/apple/Sources/SafariExtension/Resources/scripts/content/toast.js @@ -1 +1 @@ -!function(){let e,t,o,n=[],a=!1;const r={spinner:'\n \n \n \n \n \n \n \n \n \n ',success:'\n \n \n \n ',failure:'\n \n \n \n ',close:'',animatedLoader:'\n \n
\n '};function s(){a=!0,o&&clearTimeout(o)}function i(o){if(e)switch(o.ctx&&(t={...t,...o.ctx}),o.target){case"logged_out":s(),l("failure"),c("#omnivore-logged-out-row"),d("#omnivore-logged-out-status","empty","You are not logged in."),["#omnivore-toast-edit-title-btn","#omnivore-toast-edit-labels-btn","#omnivore-toast-read-now-btn","#omnivore-toast-add-note-btn","#omnivore-open-menu-btn"].forEach((t=>{e.shadowRoot.querySelector(t).disabled=!0}));break;case"page":l(o.status);break;case"note":d("#omnivore-add-note-status",o.status,o.message,"success"==o.status?2500:void 0),"success"==o.status&&setTimeout((()=>{c("#omnivore-add-note-status")}),3e3);break;case"title":d("#omnivore-edit-title-status",o.status,o.message,"success"==o.status?2500:void 0),"success"==o.status&&setTimeout((()=>{c("#omnivore-edit-title-status")}),3e3);break;case"labels":d("#omnivore-edit-labels-status",o.status,o.message,"success"==o.status?2500:void 0);break;case"extra":d("#omnivore-extra-status",o.status,o.message,"success"==o.status?2500:void 0),"success"==o.status&&setTimeout((()=>{e.remove()}),3e3)}else console.log("no statusBox to update")}function l(t){const n=e.shadowRoot.querySelector(".omnivore-toast-statusBox");switch(t){case"loading":n.innerHTML=r.animatedLoader;break;case"success":o=setTimeout((function(){console.log("hiding: ",e,a),a||(e.remove(),e=void 0)}),2500),n.innerHTML=r.success;break;case"failure":n.innerHTML=r.failure}}function d(t,o,n,a){const s=e.shadowRoot.querySelector(t),i=(()=>{switch(o){case"loading":return r.animatedLoader;case"success":return r.success;case"failure":return r.failure;case"none":return"";default:return}})();s.innerHTML=i?`${i}${n}`:n,a&&setTimeout((()=>{s.innerHTML=""}),a)}function c(t){console.log("currentToastEl: ",e);const o=e.shadowRoot.querySelector(t),n=o?.getAttribute("data-state");if(e.shadowRoot.querySelectorAll(".omnivore-toast-func-row").forEach((e=>{e.setAttribute("data-state","closed")})),o&&n){const e="open"===n?"closed":"open";o.setAttribute("data-state",e)}}function u(e,t){const o=document.createElement("button"),n=document.createElement("span");n.style="width:10px;height:10px;border-radius:1000px;",n.style.setProperty("background-color",e.color);const a=document.createElement("span");a.style="margin-left: 10px;pointer-events: none;",a.innerText=e.name;const r=document.createElement("span");return r.style="margin-left: auto;pointer-events: none;",r.className="checkbox",r.innerHTML='\n \n \n \n ',o.appendChild(n),o.appendChild(a),o.appendChild(r),o.onclick=m,o.onkeydown=p,o.setAttribute("data-label-id",e.id),o.setAttribute("data-label-idx",t),o.setAttribute("data-label-selected",e.selected?"on":"off"),o.setAttribute("tabIndex","-1"),o}function m(e){e.preventDefault();const t=e.target.getAttribute("data-label-id");f(e,t)}function f(e,t){const o=e.target.getAttribute("data-label-selected");if(!t||!o)return;const a="on"!=o;e.target.setAttribute("data-label-selected",a?"on":"off");const r=n.find((e=>e.id===t));r&&(r.selected=a)}function p(e){switch(e.key.toLowerCase()){case"arrowup":{if(e.target==e.target.form.querySelector("#omnivore-edit-label-text"))return;const t=e.target.getAttribute("data-label-idx");let o=t&&NaN!=Number(t)?Number(t)-1:0;if(e.target==e.target.form.querySelector("#omnivore-save-button")){const t=Math.max(...Array.from(e.target.form.querySelectorAll("button[data-label-idx]")).map((e=>Number(e.getAttribute("data-label-idx")))));NaN!=t&&(o=t)}const n=e.target.form.querySelector(`button[data-label-idx='${o}']`);n?n.focus():e.target.form.querySelector("#omnivore-edit-label-text")?.focus(),e.preventDefault();break}case"arrowdown":{const t=e.target.getAttribute("data-label-idx"),o=t&&NaN!=Number(t)?Number(t)+1:0,n=e.target.form.querySelector(`button[data-label-idx='${o}']`);n?n.focus():e.target.form.querySelector(".omnivore-save-button")?.focus(),e.preventDefault();break}case"enter":{const t=e.target.getAttribute("data-label-id");f(e,t),e.preventDefault();break}}}function b(){s(),c("#omnivore-add-note-row"),e.shadowRoot.querySelector("#omnivore-add-note-textarea")?.focus(),e.shadowRoot.querySelector("#omnivore-add-note-form").onsubmit=e=>{console.log("submitting form: ",e),d("#omnivore-add-note-status","loading","Adding note..."),browserApi.runtime.sendMessage({action:ACTIONS.AddNote,payload:{ctx:t,note:e.target.elements.title.value}}),e.preventDefault()}}function g(){console.log("editing title"),s(),c("#omnivore-edit-title-row"),e.shadowRoot.querySelector("#omnivore-edit-title-textarea")?.focus(),e.shadowRoot.querySelector("#omnivore-edit-title-form").onsubmit=e=>{d("#omnivore-edit-title-status","loading","Updating title..."),browserApi.runtime.sendMessage({action:ACTIONS.EditTitle,payload:{ctx:t,title:e.target.elements.title.value}}),e.preventDefault()}}async function v(){s(),await getStorageItem("labels").then((e=>{n=e})),c("#omnivore-edit-labels-row"),e.shadowRoot.querySelector("#omnivore-edit-label-text")?.focus();const o=e.shadowRoot.querySelector("#omnivore-edit-labels-list");e.shadowRoot.querySelector("#omnivore-edit-label-text").addEventListener("input",(function(){!async function(t){const o=e.shadowRoot.querySelector("#omnivore-edit-labels-list");o&&(o.innerHTML="",t?n.filter((e=>e.name.toLowerCase().indexOf(t.toLowerCase())>-1)).forEach((function(e,t){const n=u(e,t);o.appendChild(n)})):n.forEach((function(e,t){const n=u(e,t);o.appendChild(n)})))}(this.value)})),e.shadowRoot.querySelector("#omnivore-edit-label-text").onkeydown=p,o&&(o.innerHTML="",n.forEach((function(e,t){const n=u(e,t);o.appendChild(n)}))),e.shadowRoot.querySelector("#omnivore-edit-labels-form").onsubmit=o=>{o.preventDefault(),e.shadowRoot.querySelector("#omnivore-edit-labels-status").innerText="Updating labels...";const a=n.filter((e=>e.selected)).map((e=>e.id));browserApi.runtime.sendMessage({action:ACTIONS.SetLabels,payload:{ctx:t,labelIds:a}})}}function w(){s(),e.shadowRoot.querySelector("#omnivore-toast-container").setAttribute("data-state","open"),t&&t.readerURL?window.open(t.readerURL,"_blank"):t?window.open(new URL(`/article?url=${encodeURI(t.originalURL)}`,t.omnivoreURL),"_blank"):alert("Error no URL found."),setTimeout((()=>{L()}),1e3)}function h(e){browserApi.runtime.sendMessage({action:ACTIONS.Archive,payload:{ctx:t}}),e.preventDefault()}function C(e){browserApi.runtime.sendMessage({action:ACTIONS.Delete,payload:{ctx:t}}),e.preventDefault()}function y(){s(),c("#omnivore-extra-buttons-row")}function L(){e.remove(),e=void 0}function x(){window.open(new URL("/login",t.omnivoreURL),"_blank"),setTimeout(L,2e3)}window.showToolbar=function(o){t=o.ctx,async function(t){document.body&&(e||(e=await async function(){const e=await fetch(browserApi.runtime.getURL("views/toast.html")),t=await e.text(),o=document.createElement("div");o.attachShadow({mode:"open"}),o.shadowRoot&&(o.shadowRoot.innerHTML="");const n=document.createElement("div");return n.id="#omnivore-toast",n.innerHTML=t,o.shadowRoot.appendChild(n),document.body.appendChild(o),function(e){const t=[{id:"#omnivore-toast-add-note-btn",func:b},{id:"#omnivore-toast-edit-title-btn",func:g},{id:"#omnivore-toast-edit-labels-btn",func:v},{id:"#omnivore-toast-read-now-btn",func:w},{id:"#omnivore-open-menu-btn",func:y},{id:"#omnivore-toast-close-btn",func:L},{id:"#omnivore-toast-login-btn",func:x},{id:"#omnivore-toast-archive-btn",func:h},{id:"#omnivore-toast-delete-btn",func:C}];for(const o of t){const t=e.shadowRoot.querySelector(o.id);t&&t.addEventListener("click",o.func)}if(window.matchMedia("(max-width: 500px)").matches){e.shadowRoot.querySelectorAll(".omnivore-top-button-label").forEach((e=>{e.style.display="none"}));const t=e.shadowRoot.querySelector("#omnivore-toast-container");t.style.width="280px",t.style.top="unset",t.style.bottom="20px"}}(o),o}()),"loading"===t.type&&i({status:"loading",target:"page"}),document.querySelectorAll("#omnivore-toast").forEach((t=>{t!==e&&(console.log("removing current toast el: ",e),t.remove())})))}(o).catch((e=>console.log("error showing toast",e)))},window.updateStatus=i,window.updateLabelsFromCache=function(e){(async()=>{await getStorageItem("labels").then((e=>{n=e,console.log(" == updated labels",e)}))})()}}(); \ No newline at end of file +!function(){let e,t,o,n=[],a=!1;const r={spinner:'\n \n \n \n \n \n \n \n \n \n ',success:'\n \n \n \n ',failure:'\n \n \n \n ',close:'',animatedLoader:'\n \n
\n '};function s(){a=!0,o&&clearTimeout(o)}function i(o){if(e)switch(o.ctx&&(t={...t,...o.ctx}),o.target){case"logged_out":s(),l("failure"),c("#omnivore-logged-out-row"),d("#omnivore-logged-out-status","empty","You are not logged in."),["#omnivore-toast-edit-title-btn","#omnivore-toast-edit-labels-btn","#omnivore-toast-read-now-btn","#omnivore-toast-add-note-btn","#omnivore-open-menu-btn"].forEach((t=>{e.shadowRoot.querySelector(t).disabled=!0}));break;case"page":l(o.status);break;case"note":d("#omnivore-add-note-status",o.status,o.message,"success"==o.status?2500:void 0),"success"==o.status&&setTimeout((()=>{c("#omnivore-add-note-status")}),3e3);break;case"title":d("#omnivore-edit-title-status",o.status,o.message,"success"==o.status?2500:void 0),"success"==o.status&&setTimeout((()=>{c("#omnivore-edit-title-status")}),3e3);break;case"labels":d("#omnivore-edit-labels-status",o.status,o.message,"success"==o.status?2500:void 0);break;case"extra":d("#omnivore-extra-status",o.status,o.message,"success"==o.status?2500:void 0),"success"==o.status&&setTimeout((()=>{e.remove()}),3e3)}else console.log("no statusBox to update")}function l(t){const n=e.shadowRoot.querySelector(".omnivore-toast-statusBox");switch(t){case"loading":n.innerHTML=r.animatedLoader;break;case"success":o=setTimeout((function(){console.log("hiding: ",e,a),a||(e.remove(),e=void 0)}),2500),n.innerHTML=r.success;break;case"failure":n.innerHTML=r.failure}}function d(t,o,n,a){const s=e.shadowRoot.querySelector(t),i=(()=>{switch(o){case"loading":return r.animatedLoader;case"success":return r.success;case"failure":return r.failure;case"none":return"";default:return}})();s.innerHTML=i?`${i}${n}`:n,a&&setTimeout((()=>{s.innerHTML=""}),a)}function c(t){console.log("currentToastEl: ",e);const o=e.shadowRoot.querySelector(t),n=o?.getAttribute("data-state");if(e.shadowRoot.querySelectorAll(".omnivore-toast-func-row").forEach((e=>{e.setAttribute("data-state","closed")})),o&&n){const e="open"===n?"closed":"open";o.setAttribute("data-state",e)}}function u(e,t){const o=document.createElement("button"),n=document.createElement("span");n.style="width:10px;height:10px;border-radius:1000px;",n.style.setProperty("background-color",e.color);const a=document.createElement("span");a.style="margin-left: 10px;pointer-events: none;",a.innerText=e.name;const r=document.createElement("span");return r.style="margin-left: auto;pointer-events: none;",r.className="checkbox",r.innerHTML='\n \n \n \n ',o.appendChild(n),o.appendChild(a),o.appendChild(r),o.onclick=m,o.onkeydown=f,o.setAttribute("data-label-id",e.id),o.setAttribute("data-label-idx",t),o.setAttribute("data-label-selected",e.selected?"on":"off"),o.setAttribute("tabIndex","-1"),o}function m(e){e.preventDefault();const t=e.target.getAttribute("data-label-id");p(e,t)}function p(e,t){const o=e.target.getAttribute("data-label-selected");if(!t||!o)return;const a="on"!=o;e.target.setAttribute("data-label-selected",a?"on":"off");const r=n.find((e=>e.id===t));r&&(r.selected=a)}function f(e){switch(e.cancelBubble=!0,e.stopPropogation&&e.stopPropogation(),e.key.toLowerCase()){case"arrowup":{if(e.target==e.target.form.querySelector("#omnivore-edit-label-text"))return;const t=e.target.getAttribute("data-label-idx");let o=t&&NaN!=Number(t)?Number(t)-1:0;if(e.target==e.target.form.querySelector("#omnivore-save-button")){const t=Math.max(...Array.from(e.target.form.querySelectorAll("button[data-label-idx]")).map((e=>Number(e.getAttribute("data-label-idx")))));NaN!=t&&(o=t)}const n=e.target.form.querySelector(`button[data-label-idx='${o}']`);n?n.focus():e.target.form.querySelector("#omnivore-edit-label-text")?.focus(),e.preventDefault();break}case"arrowdown":{const t=e.target.getAttribute("data-label-idx"),o=t&&NaN!=Number(t)?Number(t)+1:0,n=e.target.form.querySelector(`button[data-label-idx='${o}']`);n?n.focus():e.target.form.querySelector(".omnivore-save-button")?.focus(),e.preventDefault();break}case"enter":{const t=e.target.getAttribute("data-label-id");p(e,t),e.preventDefault();break}}}function b(){s(),c("#omnivore-add-note-row");const o=e.shadowRoot.querySelector("#omnivore-add-note-textarea");o&&(o.focus(),o.onkeydown=e=>{e.cancelBubble=!0,e.stopPropogation&&e.stopPropogation(),13==e.keyCode&&(e.metaKey||e.ctrlKey)&&(d("#omnivore-add-note-status","loading","Adding note..."),browserApi.runtime.sendMessage({action:ACTIONS.AddNote,payload:{ctx:t,note:o.value}}))}),e.shadowRoot.querySelector("#omnivore-add-note-form").onsubmit=e=>{console.log("submitting form: ",e),d("#omnivore-add-note-status","loading","Adding note..."),browserApi.runtime.sendMessage({action:ACTIONS.AddNote,payload:{ctx:t,note:e.target.elements.title.value}}),e.preventDefault(),e.stopPropogation()}}function g(){s(),c("#omnivore-edit-title-row");const o=e.shadowRoot.querySelector("#omnivore-edit-title-textarea");o&&(o.focus(),o.onkeydown=e=>{e.cancelBubble=!0,e.stopPropogation&&e.stopPropogation()}),e.shadowRoot.querySelector("#omnivore-edit-title-form").onsubmit=e=>{d("#omnivore-edit-title-status","loading","Updating title..."),browserApi.runtime.sendMessage({action:ACTIONS.EditTitle,payload:{ctx:t,title:e.target.elements.title.value}}),e.preventDefault()}}async function v(){s(),await getStorageItem("labels").then((e=>{n=e})),c("#omnivore-edit-labels-row"),e.shadowRoot.querySelector("#omnivore-edit-label-text")?.focus();const o=e.shadowRoot.querySelector("#omnivore-edit-labels-list");e.shadowRoot.querySelector("#omnivore-edit-label-text").addEventListener("input",(function(){!async function(t){const o=e.shadowRoot.querySelector("#omnivore-edit-labels-list");o&&(o.innerHTML="",t?n.filter((e=>e.name.toLowerCase().indexOf(t.toLowerCase())>-1)).forEach((function(e,t){const n=u(e,t);o.appendChild(n)})):n.forEach((function(e,t){const n=u(e,t);o.appendChild(n)})))}(this.value)})),e.shadowRoot.querySelector("#omnivore-edit-label-text").onkeydown=f,o&&(o.innerHTML="",n.forEach((function(e,t){const n=u(e,t);o.appendChild(n)}))),e.shadowRoot.querySelector("#omnivore-edit-labels-form").onsubmit=o=>{o.preventDefault(),e.shadowRoot.querySelector("#omnivore-edit-labels-status").innerText="Updating labels...";const a=n.filter((e=>e.selected)).map((e=>e.id));browserApi.runtime.sendMessage({action:ACTIONS.SetLabels,payload:{ctx:t,labelIds:a}})}}function w(){s(),e.shadowRoot.querySelector("#omnivore-toast-container").setAttribute("data-state","open"),t&&t.readerURL?window.open(t.readerURL,"_blank"):t?window.open(new URL(`/article?url=${encodeURI(t.originalURL)}`,t.omnivoreURL),"_blank"):alert("Error no URL found."),setTimeout((()=>{x()}),1e3)}function h(e){browserApi.runtime.sendMessage({action:ACTIONS.Archive,payload:{ctx:t}}),e.preventDefault()}function y(e){browserApi.runtime.sendMessage({action:ACTIONS.Delete,payload:{ctx:t}}),e.preventDefault()}function C(){s(),c("#omnivore-extra-buttons-row")}function x(){e.remove(),e=void 0}function L(){window.open(new URL("/login",t.omnivoreURL),"_blank"),setTimeout(x,2e3)}window.showToolbar=function(o){t=o.ctx,async function(t){document.body&&(e||(e=await async function(){const e=await fetch(browserApi.runtime.getURL("views/toast.html")),t=await e.text(),o=document.createElement("div");o.tabIndex=0,o.attachShadow({mode:"open"}),o.shadowRoot&&(o.shadowRoot.innerHTML="");const n=document.createElement("div");return n.id="#omnivore-toast",n.innerHTML=t,n.tabIndex=0,o.shadowRoot.appendChild(n),document.body.appendChild(o),function(e){const t=[{id:"#omnivore-toast-add-note-btn",func:b},{id:"#omnivore-toast-edit-title-btn",func:g},{id:"#omnivore-toast-edit-labels-btn",func:v},{id:"#omnivore-toast-read-now-btn",func:w},{id:"#omnivore-open-menu-btn",func:C},{id:"#omnivore-toast-close-btn",func:x},{id:"#omnivore-toast-login-btn",func:L},{id:"#omnivore-toast-archive-btn",func:h},{id:"#omnivore-toast-delete-btn",func:y}];for(const o of t){const t=e.shadowRoot.querySelector(o.id);t&&t.addEventListener("click",o.func)}if(window.matchMedia("(max-width: 500px)").matches){e.shadowRoot.querySelectorAll(".omnivore-top-button-label").forEach((e=>{e.style.display="none"}));const t=e.shadowRoot.querySelector("#omnivore-toast-container");t.style.width="280px",t.style.top="unset",t.style.bottom="20px"}}(o),function(e){e.addEventListener("keydown",(e=>{switch(e.key){case"r":w();break;case"l":v();break;case"m":C();break;case"t":g();break;case"n":e.preventDefault(),b()}e.cancelBubble=!0,e.stopPropogation&&e.stopPropogation()}))}(o),o}()),"loading"===t.type&&i({status:"loading",target:"page"}),document.querySelectorAll("#omnivore-toast").forEach((t=>{t!==e&&(console.log("removing current toast el: ",e),t.remove())})),e.focus())}(o).catch((e=>console.log("error showing toast",e)))},window.updateStatus=i,window.updateLabelsFromCache=function(e){(async()=>{await getStorageItem("labels").then((e=>{n=e,console.log(" == updated labels",e)}))})()}}(); \ No newline at end of file From 8a5372fd639c5a61f75fa5bc047578ba12adf637 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 19 Sep 2023 17:47:34 +0800 Subject: [PATCH 2/5] iOS build fixes --- .../App/Views/Home/LibraryAddLinkView.swift | 2 +- .../Sources/Views/MacSearchBar.swift | 96 ++++++++++--------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift b/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift index a66d668dd..7fb03a786 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/LibraryAddLinkView.swift @@ -60,7 +60,7 @@ struct LibraryAddLinkView: View { var pasteboardString: String? { #if os(iOS) - UIPasteboard.general.url.absoluteString + UIPasteboard.general.url?.absoluteString #else NSPasteboard.general.string(forType: NSPasteboard.PasteboardType.URL) #endif diff --git a/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift b/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift index aeea28ee3..1dc915a9b 100644 --- a/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift +++ b/apple/OmnivoreKit/Sources/Views/MacSearchBar.swift @@ -1,55 +1,57 @@ import SwiftUI -public struct MacSearchBar: NSViewRepresentable { - @Binding var searchTerm: String +#if os(macOS) + public struct MacSearchBar: NSViewRepresentable { + @Binding var searchTerm: String - public init( - searchTerm: Binding - ) { - self._searchTerm = searchTerm - } - - public func makeNSView(context _: Context) -> NSSearchField { - let searchField = NSSearchField(frame: .zero) - searchField.translatesAutoresizingMaskIntoConstraints = false - searchField.heightAnchor.constraint(greaterThanOrEqualToConstant: 28).isActive = true - searchField.resignFirstResponder() - - return searchField - } - - func changeSearchFieldItem(searchField: NSSearchField, sender: AnyObject) -> NSSearchField { - // Based on the Menu item selection in the search field the placeholder string is set - (searchField.cell as? NSSearchFieldCell)?.placeholderString = sender.title - return searchField - } - - public func updateNSView(_ searchField: NSSearchField, context: Context) { - searchField.font = searchField.font?.withSize(14) - searchField.stringValue = searchTerm - searchField.delegate = context.coordinator - searchField.resignFirstResponder() - } - - public func makeCoordinator() -> Coordinator { - let coordinator = Coordinator(searchTerm: $searchTerm) - return coordinator - } - - public class Coordinator: NSObject, NSSearchFieldDelegate { - var searchTerm: Binding - - init(searchTerm: Binding) { - self.searchTerm = searchTerm - super.init() + public init( + searchTerm: Binding + ) { + self._searchTerm = searchTerm } - public func controlTextDidChange(_ notification: Notification) { - guard let searchField = notification.object as? NSSearchField else { - // log.error("Unexpected control in update notification", source: .ui) - return + public func makeNSView(context _: Context) -> NSSearchField { + let searchField = NSSearchField(frame: .zero) + searchField.translatesAutoresizingMaskIntoConstraints = false + searchField.heightAnchor.constraint(greaterThanOrEqualToConstant: 28).isActive = true + searchField.resignFirstResponder() + + return searchField + } + + func changeSearchFieldItem(searchField: NSSearchField, sender: AnyObject) -> NSSearchField { + // Based on the Menu item selection in the search field the placeholder string is set + (searchField.cell as? NSSearchFieldCell)?.placeholderString = sender.title + return searchField + } + + public func updateNSView(_ searchField: NSSearchField, context: Context) { + searchField.font = searchField.font?.withSize(14) + searchField.stringValue = searchTerm + searchField.delegate = context.coordinator + searchField.resignFirstResponder() + } + + public func makeCoordinator() -> Coordinator { + let coordinator = Coordinator(searchTerm: $searchTerm) + return coordinator + } + + public class Coordinator: NSObject, NSSearchFieldDelegate { + var searchTerm: Binding + + init(searchTerm: Binding) { + self.searchTerm = searchTerm + super.init() + } + + public func controlTextDidChange(_ notification: Notification) { + guard let searchField = notification.object as? NSSearchField else { + // log.error("Unexpected control in update notification", source: .ui) + return + } + searchTerm.wrappedValue = searchField.stringValue } - searchTerm.wrappedValue = searchField.stringValue } } -} +#endif From b714fe1f9468d56ef12f93f56cac947609f8c09e Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 19 Sep 2023 18:09:12 +0800 Subject: [PATCH 3/5] Revert Package changes, try the when conditional that doesnt seem to do what we need --- .../xcshareddata/swiftpm/Package.resolved | 18 ++++++++++++++++++ apple/OmnivoreKit/Package.swift | 15 +++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved b/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved index cf2e28f2c..4d0dfb64b 100644 --- a/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/apple/Omnivore.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -144,6 +144,15 @@ "version" : "2.6.0" } }, + { + "identity" : "posthog-ios", + "kind" : "remoteSourceControl", + "location" : "https://github.com/PostHog/posthog-ios.git", + "state" : { + "revision" : "3a6afc24d6bde730a19470d4e6b713f44d076ad9", + "version" : "2.0.3" + } + }, { "identity" : "promises", "kind" : "remoteSourceControl", @@ -153,6 +162,15 @@ "version" : "2.1.0" } }, + { + "identity" : "pspdfkit-sp", + "kind" : "remoteSourceControl", + "location" : "https://github.com/PSPDFKit/PSPDFKit-SP", + "state" : { + "revision" : "f4ba9790488b8f11c29cff35943e430efcdb8003", + "version" : "12.0.1" + } + }, { "identity" : "swift-argument-parser", "kind" : "remoteSourceControl", diff --git a/apple/OmnivoreKit/Package.swift b/apple/OmnivoreKit/Package.swift index 9122e55cc..afe997291 100644 --- a/apple/OmnivoreKit/Package.swift +++ b/apple/OmnivoreKit/Package.swift @@ -46,9 +46,9 @@ let package = Package( .testTarget(name: "ModelsTests", dependencies: ["Models"]), .target( name: "Utils", -// dependencies: [ -// .product(name: "PostHog", package: "posthog-ios") -// ], + dependencies: [ + .product(name: "PostHog", package: "posthog-ios", condition: .when(platforms: [.iOS])) + ], resources: [.process("Resources")] ), .testTarget(name: "UtilsTests", dependencies: ["Utils"]) @@ -58,7 +58,7 @@ let package = Package( var appPackageDependencies: [Target.Dependency] { var deps: [Target.Dependency] = ["Views", "Services", "Models", "Utils"] // Comment out following line for macOS build - // deps.append(.product(name: "PSPDFKit", package: "PSPDFKit-SP")) + deps.append(.product(name: "PSPDFKit", package: "PSPDFKit-SP", condition: .when(platforms: [.iOS]))) return deps } @@ -69,11 +69,10 @@ var dependencies: [Package.Dependency] { .package(url: "https://github.com/siteline/SwiftUI-Introspect.git", from: "0.1.4"), .package(url: "https://github.com/google/GoogleSignIn-iOS", from: "6.2.2"), .package(url: "https://github.com/gonzalezreal/swift-markdown-ui", from: "2.0.0"), - .package(url: "https://github.com/exyte/PopupView.git", from: "2.6.0") -// , -// .package(url: "https://github.com/PostHog/posthog-ios.git", from: "2.0.0") + .package(url: "https://github.com/exyte/PopupView.git", from: "2.6.0"), + .package(url: "https://github.com/PostHog/posthog-ios.git", from: "2.0.0") ] // Comment out following line for macOS build - // deps.append(.package(url: "https://github.com/PSPDFKit/PSPDFKit-SP", from: "12.0.1")) + deps.append(.package(url: "https://github.com/PSPDFKit/PSPDFKit-SP", from: "12.0.1")) return deps } From b8e033f7366918a78f57d3295348953fdaef0ad2 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 19 Sep 2023 18:26:31 +0800 Subject: [PATCH 4/5] Fixes for iOS15 --- .../OmnivoreKit/Sources/App/Views/LibraryTabView.swift | 10 +++------- .../Sources/App/Views/PrimaryContentView.swift | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift b/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift index 39fa29ec8..90e5f9c2c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LibraryTabView.swift @@ -43,13 +43,9 @@ struct LibraryTabView: View { ) var body: some View { - if #available(iOS 16.0, *) { - NavigationView { - HomeView(viewModel: libraryViewModel) - } - } else { - // Fallback on earlier versions - EmptyView() + NavigationView { + HomeView(viewModel: libraryViewModel) + .navigationBarTitleDisplayMode(.inline) } } } diff --git a/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift b/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift index b8962dd4b..d4efcf18c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift @@ -89,6 +89,7 @@ import Views .sheet(isPresented: $addLinkPresented) { NavigationView { LibraryAddLinkView() + .navigationBarTitleDisplayMode(.inline) } } } From 99df19631754412bb4bc128644baf5e836306dc1 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 19 Sep 2023 19:05:15 +0800 Subject: [PATCH 5/5] Bump marketing version, set stack navigation style for iOS15 --- apple/Omnivore.xcodeproj/project.pbxproj | 8 ++++---- .../Sources/App/Views/PrimaryContentView.swift | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apple/Omnivore.xcodeproj/project.pbxproj b/apple/Omnivore.xcodeproj/project.pbxproj index b852d8c5e..8186a649d 100644 --- a/apple/Omnivore.xcodeproj/project.pbxproj +++ b/apple/Omnivore.xcodeproj/project.pbxproj @@ -1400,7 +1400,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 1.30.0; + MARKETING_VERSION = 1.31.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; @@ -1435,7 +1435,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 12.0; - MARKETING_VERSION = 1.30.0; + MARKETING_VERSION = 1.31.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1490,7 +1490,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.30.0; + MARKETING_VERSION = 1.31.0; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; PRODUCT_NAME = Omnivore; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1831,7 +1831,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.30.0; + MARKETING_VERSION = 1.31.0; PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.app; PRODUCT_NAME = Omnivore; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift b/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift index d4efcf18c..e6ba752d3 100644 --- a/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/PrimaryContentView.swift @@ -20,7 +20,10 @@ import Views if UIDevice.isIPad { return AnyView(splitView) } else { - return AnyView(LibraryTabView()) + return AnyView( + LibraryTabView() + .navigationViewStyle(.stack) + ) } #else return AnyView(splitView)