Merge pull request #842 from omnivore-app/fix/mac-app-updates

Mac app updates
This commit is contained in:
Satindar Dhillon
2022-06-22 14:19:50 -07:00
committed by GitHub
12 changed files with 133 additions and 118 deletions

View File

@ -159,7 +159,7 @@
"location" : "https://github.com/PSPDFKit/PSPDFKit-SP",
"state" : {
"branch" : "master",
"revision" : "0e18629c443e3f39ecfee0f600d9ef5551ecf488"
"revision" : "b7e5465ab62f5b48735145756e371502fa2a24f0"
}
},
{

View File

@ -1,10 +1,3 @@
//
// File.swift
//
//
// Created by Jackson Harper on 6/1/22.
//
import Foundation
import Models
import Services
@ -18,23 +11,25 @@ class ExtensionSaveService {
self.queue = OperationQueue()
}
private func queueSaveOperation(
_ pageScrape: PageScrapePayload,
shareExtensionViewModel: ShareExtensionChildViewModel
) {
ProcessInfo().performExpiringActivity(withReason: "app.omnivore.SaveActivity") { [self] expiring in
guard !expiring else {
self.queue.cancelAllOperations()
#if os(iOS)
private func queueSaveOperation(
_ pageScrape: PageScrapePayload,
shareExtensionViewModel: ShareExtensionChildViewModel
) {
ProcessInfo().performExpiringActivity(withReason: "app.omnivore.SaveActivity") { [self] expiring in
guard !expiring else {
self.queue.cancelAllOperations()
self.queue.waitUntilAllOperationsAreFinished()
return
}
let operation = SaveOperation(pageScrapePayload: pageScrape, shareExtensionViewModel: shareExtensionViewModel)
self.queue.addOperation(operation)
self.queue.waitUntilAllOperationsAreFinished()
return
}
let operation = SaveOperation(pageScrapePayload: pageScrape, shareExtensionViewModel: shareExtensionViewModel)
self.queue.addOperation(operation)
self.queue.waitUntilAllOperationsAreFinished()
}
}
#endif
public func save(_ extensionContext: NSExtensionContext, shareExtensionViewModel: ShareExtensionChildViewModel) {
PageScraper.scrape(extensionContext: extensionContext) { [weak self] result in
@ -71,7 +66,10 @@ class ExtensionSaveService {
}
}
}
self.queueSaveOperation(payload, shareExtensionViewModel: shareExtensionViewModel)
#if os(iOS)
// TODO: need alternative call for macos
self.queueSaveOperation(payload, shareExtensionViewModel: shareExtensionViewModel)
#endif
case .failure:
DispatchQueue.main.async {
shareExtensionViewModel.status = .failed(error: .unknown(description: "Could not retrieve content"))

View File

@ -66,24 +66,26 @@ struct LinkedItemTitleEditView: View {
NavigationView {
editForm
.navigationTitle("Edit Title and Description")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .barTrailing) {
Button(
action: {
viewModel.submit(dataService: dataService, item: item)
presentationMode.wrappedValue.dismiss()
},
label: { Text("Save").foregroundColor(.appGrayTextContrast) }
)
}
ToolbarItem(placement: .barLeading) {
Button(
action: { presentationMode.wrappedValue.dismiss() },
label: { Text("Cancel").foregroundColor(.appGrayTextContrast) }
)
}
#endif
.toolbar {
ToolbarItem(placement: .barTrailing) {
Button(
action: {
viewModel.submit(dataService: dataService, item: item)
presentationMode.wrappedValue.dismiss()
},
label: { Text("Save").foregroundColor(.appGrayTextContrast) }
)
}
ToolbarItem(placement: .barLeading) {
Button(
action: { presentationMode.wrappedValue.dismiss() },
label: { Text("Cancel").foregroundColor(.appGrayTextContrast) }
)
}
}
}
.task { viewModel.load(item: item) }
}

View File

@ -59,8 +59,7 @@ import Views
}
func handleGoogleAuth(authenticator: Authenticator) async {
guard let presentingViewController = presentingViewController() else { return }
let googleAuthResponse = await authenticator.handleGoogleAuth(presenting: presentingViewController)
let googleAuthResponse = await authenticator.handleGoogleAuth()
switch googleAuthResponse {
case let .loginError(error):
@ -72,15 +71,3 @@ import Views
}
}
}
private func presentingViewController() -> PlatformViewController? {
#if os(iOS)
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
return scene?.windows
.filter(\.isKeyWindow)
.first?
.rootViewController
#elseif os(macOS)
return nil
#endif
}

View File

@ -14,9 +14,14 @@ public class PersistentContainer: NSPersistentContainer {
// Store the sqlite file in the app group container.
// This allows shared access for app and app extensions.
let appGroupID = "group.app.omnivoreapp"
#if os(iOS)
let appGroupID = "group.app.omnivoreapp"
#else
let appGroupID = "QJF2XZ86HB.app.omnivore.app"
#endif
let appGroupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)
let appGroupContainerURL = appGroupContainer?.appendingPathComponent("store.sqlite")
container.persistentStoreDescriptions.first!.url = appGroupContainerURL
container.viewContext.automaticallyMergesChangesFromParent = true

View File

@ -10,8 +10,11 @@ public enum GoogleAuthResponse {
}
extension Authenticator {
public func handleGoogleAuth(presenting: PlatformViewController) async -> GoogleAuthResponse {
let idToken = try? await googleSignIn(presenting: presenting)
public func handleGoogleAuth() async -> GoogleAuthResponse {
let idToken = await withCheckedContinuation { continuation in
googleSignIn { continuation.resume(returning: $0) }
}
guard let idToken = idToken else { return .loginError(error: .unauthorized) }
do {
@ -47,27 +50,47 @@ extension Authenticator {
}
}
func googleSignIn(presenting: PlatformViewController) async throws -> String {
try await withCheckedThrowingContinuation { continuation in
let clientID = "\(AppKeys.sharedInstance?.iosClientGoogleId ?? "").apps.googleusercontent.com"
GIDSignIn.sharedInstance.signIn(
with: GIDConfiguration(clientID: clientID),
presenting: presenting
) { user, error in
guard let user = user, error == nil else {
continuation.resume(throwing: LoginError.unauthorized)
func googleSignIn(completion: @escaping (String?) -> Void) {
#if os(iOS)
let presenting = presentingViewController()
#else
let presenting = NSApplication.shared.windows.first
#endif
guard let presenting = presenting else {
completion(nil)
return
}
let clientID = "\(AppKeys.sharedInstance?.iosClientGoogleId ?? "").apps.googleusercontent.com"
GIDSignIn.sharedInstance.signIn(
with: GIDConfiguration(clientID: clientID),
presenting: presenting
) { user, error in
guard let user = user, error == nil else {
completion(nil)
return
}
user.authentication.do { authentication, error in
guard let idToken = authentication?.idToken, error == nil else {
completion(nil)
return
}
user.authentication.do { authentication, error in
guard let idToken = authentication?.idToken, error == nil else {
continuation.resume(throwing: LoginError.unauthorized)
return
}
continuation.resume(returning: idToken)
}
completion(idToken)
}
}
}
}
private func presentingViewController() -> PlatformViewController? {
#if os(iOS)
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
return scene?.windows
.filter(\.isKeyWindow)
.first?
.rootViewController
#elseif os(macOS)
return nil
#endif
}

View File

@ -4,9 +4,14 @@ import Foundation
import Models
import OSLog
import QuickLookThumbnailing
import UIKit
import Utils
#if os(iOS)
import UIKit
#else
import AppKit
#endif
let logger = Logger(subsystem: "app.omnivore", category: "data-service")
public final class DataService: ObservableObject {

View File

@ -1,7 +1,11 @@
import CoreImage
import Foundation
import QuickLookThumbnailing
import UIKit
#if os(iOS)
import UIKit
#else
import AppKit
#endif
public enum PDFUtils {
public static func copyToLocal(url: URL) throws -> String {
@ -64,7 +68,11 @@ public enum PDFUtils {
public static func createThumbnailFor(inputUrl: URL) async throws -> URL? {
let size = CGSize(width: 80, height: 80)
let scale = await UIScreen.main.scale
#if os(iOS)
let scale = await UIScreen.main.scale
#else
let scale = NSScreen.main?.backingScaleFactor ?? 1
#endif
let outputUrl = thumbnailUrl(localUrl: inputUrl)
// Create the thumbnail request.

View File

@ -168,14 +168,19 @@ public enum WebViewManager {
context.coordinator.needsReload = false
}
if annotationSaveTransactionID != context.coordinator.lastSavedAnnotationID {
context.coordinator.lastSavedAnnotationID = annotationSaveTransactionID
(webView as? WebView)?.dispatchEvent(.saveAnnotation(annotation: annotation))
}
if sendIncreaseFontSignal {
sendIncreaseFontSignal = false
(webView as? WebView)?.increaseFontSize()
(webView as? WebView)?.updateFontSize()
}
if sendDecreaseFontSignal {
sendDecreaseFontSignal = false
(webView as? WebView)?.decreaseFontSize()
(webView as? WebView)?.updateFontSize()
}
}
}

View File

@ -86,9 +86,9 @@ public final class WebView: WKWebView {
super.viewDidChangeEffectiveAppearance()
switch effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) {
case .some(.darkAqua):
dispatchEvent("switchToDarkMode")
dispatchEvent(.updateColorMode(isDark: true))
default:
dispatchEvent("switchToLightMode")
dispatchEvent(.updateColorMode(isDark: false))
}
}
#endif

View File

@ -81,7 +81,9 @@ public struct WebPreferencesPopoverView: View {
}
}
.listStyle(.plain)
.navigationBarTitleDisplayMode(.inline)
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.navigationTitle("Reader Font")
}
@ -148,9 +150,11 @@ public struct WebPreferencesPopoverView: View {
}
.padding()
.navigationTitle("Reader Preferences")
.navigationBarTitleDisplayMode(.inline)
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
ToolbarItem(placement: .barTrailing) {
Button(
action: dismissAction,
label: { Text("Done").foregroundColor(.appGrayTextContrast).padding() }
@ -158,7 +162,9 @@ public struct WebPreferencesPopoverView: View {
}
}
}
.navigationViewStyle(.stack)
#if os(iOS)
.navigationViewStyle(.stack)
#endif
.accentColor(.appGrayTextContrast)
}
}

View File

@ -37,36 +37,6 @@ public enum ShareExtensionStatus {
}
}
struct CornerRadiusStyle: ViewModifier {
var radius: CGFloat
var corners: UIRectCorner
struct CornerRadiusShape: Shape {
var radius = CGFloat.infinity
var corners = UIRectCorner.allCorners
func path(in rect: CGRect) -> Path {
let path = UIBezierPath(
roundedRect: rect,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius)
)
return Path(path.cgPath)
}
}
func body(content: Content) -> some View {
content
.clipShape(CornerRadiusShape(radius: radius, corners: corners))
}
}
extension View {
func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
ModifiedContent(content: self, modifier: CornerRadiusStyle(radius: radius, corners: corners))
}
}
private extension SaveArticleError {
var displayMessage: String {
switch self {
@ -197,9 +167,15 @@ public struct ShareExtensionChildView: View {
}
private func localImage(from url: URL) -> Image? {
if let data = try? Data(contentsOf: url), let img = UIImage(data: data) {
return Image(uiImage: img)
}
#if os(iOS)
if let data = try? Data(contentsOf: url), let img = UIImage(data: data) {
return Image(uiImage: img)
}
#else
if let data = try? Data(contentsOf: url), let img = NSImage(data: data) {
return Image(nsImage: img)
}
#endif
return nil
}