From 37362cb38c0a345ea1cb00317e712ae3805aa1e6 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Thu, 20 Oct 2022 20:00:12 +0700 Subject: [PATCH] Minor tweaks --- .swiftlint.yml | 7 ++-- Plash.xcodeproj/project.pbxproj | 10 ++--- Plash/App.swift | 8 ++-- Plash/AppState.swift | 12 ++---- Plash/Constants.swift | 37 ------------------ Plash/Menus.swift | 66 +++++++++++++++++---------------- Plash/Utilities.swift | 53 +++++++++++--------------- 7 files changed, 72 insertions(+), 121 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 53374ef..e52e414 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,5 +1,4 @@ only_rules: - - anyobject_protocol - array_init - block_based_kvo - class_delegate_protocol @@ -10,6 +9,7 @@ only_rules: - collection_alignment - colon - comma + - comma_inheritance - compiler_protocol_init - computed_accessors_order - conditional_returns_on_newline @@ -107,6 +107,7 @@ only_rules: - required_enum_case - return_arrow_whitespace - return_value_from_void_function + - self_binding - self_in_property_initialization - shorthand_operator - sorted_first_last @@ -138,9 +139,9 @@ only_rules: - unused_setter_value - valid_ibinspectable - vertical_parameter_alignment - - vertical_parameter_alignment_on_call - vertical_whitespace_closing_braces - vertical_whitespace_opening_braces + - void_function_in_ternary - void_return - xct_specific_matcher - xctfail_message @@ -174,7 +175,7 @@ identifier_name: - 'y2' - 'z2' deployment_target: - macOS_deployment_target: '11' + macOS_deployment_target: '12' custom_rules: no_nsrect: regex: '\bNSRect\b' diff --git a/Plash.xcodeproj/project.pbxproj b/Plash.xcodeproj/project.pbxproj index 71f9db0..8139d50 100644 --- a/Plash.xcodeproj/project.pbxproj +++ b/Plash.xcodeproj/project.pbxproj @@ -450,7 +450,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 12.4; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -508,7 +508,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 12.4; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -649,7 +649,7 @@ repositoryURL = "https://github.com/getsentry/sentry-cocoa"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 7.27.0; + minimumVersion = 7.28.0; }; }; E32421482384ED8300D28A91 /* XCRemoteSwiftPackageReference "Defaults" */ = { @@ -657,7 +657,7 @@ repositoryURL = "https://github.com/sindresorhus/Defaults"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 6.2.1; + minimumVersion = 6.3.0; }; }; E3805F592466ED5600489E6C /* XCRemoteSwiftPackageReference "KeyboardShortcuts" */ = { @@ -665,7 +665,7 @@ repositoryURL = "https://github.com/sindresorhus/KeyboardShortcuts"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 1.7.2; + minimumVersion = 1.8.0; }; }; E3C4E27F251540F7007A6078 /* XCRemoteSwiftPackageReference "LaunchAtLogin" */ = { diff --git a/Plash/App.swift b/Plash/App.swift index 3997d28..0d49595 100644 --- a/Plash/App.swift +++ b/Plash/App.swift @@ -4,12 +4,16 @@ import SwiftUI TODO: - Refactor the whole website handling into a controller. - Fix TODO comments in the codebase. +- Fix "Edit Website" if it's not visible in the list. Use the new `Window` type in macOS 13. TODO when targeting macOS 13: - Use SwiftUI for the websites window. We cannot do it until the window can be manually toggled. TODO when Swift 6 is out: - Convert all Combine usage to AsyncSequence. + +TODO when targeting macOS 13: += Use `MenuBarExtra`. */ @main @@ -18,10 +22,6 @@ struct AppMain: App { @StateObject private var appState = AppState.shared var body: some Scene { - // This is needed for standard keyboard shortcuts to work in text fields. (macOS 12.4) - WindowGroup { - if false {} - } Settings { SettingsScreen() .environmentObject(appState) diff --git a/Plash/AppState.swift b/Plash/AppState.swift index 7c8a545..be9dc52 100644 --- a/Plash/AppState.swift +++ b/Plash/AppState.swift @@ -1,6 +1,5 @@ import SwiftUI import Combine -import Sentry import Defaults @MainActor @@ -109,12 +108,7 @@ final class AppState: ObservableObject { "NSApplicationCrashOnExceptions": true ]) - #if !DEBUG - SentrySDK.start { - $0.dsn = "https://4ad446a4961b44ff8dc808a08379914e@o844094.ingest.sentry.io/6140750" - $0.enableSwizzling = false - } - #endif + SSApp.initSentry("https://4ad446a4961b44ff8dc808a08379914e@o844094.ingest.sentry.io/6140750") // TODO: Remove in 2023. SSApp.runOnce(identifier: "migrateToDefaultav5") { @@ -155,7 +149,9 @@ final class AppState: ObservableObject { } reloadTimer = Timer.scheduledTimer(withTimeInterval: reloadInterval, repeats: true) { [self] _ in - loadUserURL() + Task { @MainActor in + loadUserURL() + } } } diff --git a/Plash/Constants.swift b/Plash/Constants.swift index 3b0db87..52c0f3b 100644 --- a/Plash/Constants.swift +++ b/Plash/Constants.swift @@ -37,40 +37,3 @@ extension Notification.Name { static let showAddWebsiteDialog = Self("showAddWebsiteDialog") static let showEditWebsiteDialog = Self("showEditWebsiteDialog") } - - -// Swift bug workaround -extension Defaults.Serializable where Self: Codable { - public static var bridge: Defaults.TopLevelCodableBridge { Defaults.TopLevelCodableBridge() } -} - -extension Defaults.Serializable where Self: Codable & NSSecureCoding { - public static var bridge: Defaults.CodableNSSecureCodingBridge { Defaults.CodableNSSecureCodingBridge() } -} - -extension Defaults.Serializable where Self: Codable & NSSecureCoding & Defaults.PreferNSSecureCoding { - public static var bridge: Defaults.NSSecureCodingBridge { Defaults.NSSecureCodingBridge() } -} - -extension Defaults.Serializable where Self: Codable & RawRepresentable { - public static var bridge: Defaults.RawRepresentableCodableBridge { Defaults.RawRepresentableCodableBridge() } -} - -extension Defaults.Serializable where Self: Codable & RawRepresentable & Defaults.PreferRawRepresentable { - public static var bridge: Defaults.RawRepresentableBridge { Defaults.RawRepresentableBridge() } -} - -extension Defaults.Serializable where Self: RawRepresentable { - public static var bridge: Defaults.RawRepresentableBridge { Defaults.RawRepresentableBridge() } -} -extension Defaults.Serializable where Self: NSSecureCoding { - public static var bridge: Defaults.NSSecureCodingBridge { Defaults.NSSecureCodingBridge() } -} - -extension Defaults.CollectionSerializable where Element: Defaults.Serializable { - public static var bridge: Defaults.CollectionBridge { Defaults.CollectionBridge() } -} - -extension Defaults.SetAlgebraSerializable where Element: Defaults.Serializable & Hashable { - public static var bridge: Defaults.SetAlgebraBridge { Defaults.SetAlgebraBridge() } -} diff --git a/Plash/Menus.swift b/Plash/Menus.swift index 0fd427a..bf32466 100644 --- a/Plash/Menus.swift +++ b/Plash/Menus.swift @@ -53,11 +53,6 @@ extension AppState { menu.addSeparator() - menu.addLinkItem( - "Website", - destination: "https://sindresorhus.com/plash" - ) - menu.addLinkItem( "Examples", destination: "https://github.com/sindresorhus/Plash/issues/1" @@ -68,6 +63,11 @@ extension AppState { destination: "https://github.com/sindresorhus/Plash#scripting" ) + menu.addLinkItem( + "Website", + destination: "https://sindresorhus.com/plash" + ) + menu.addSeparator() menu.addLinkItem( @@ -90,40 +90,42 @@ extension AppState { menu.addSeparator() - menu.addCallbackItem( - "Reload", - isEnabled: WebsitesController.shared.current != nil - ) { [weak self] in - self?.loadUserURL() - } + if !WebsitesController.shared.all.isEmpty { + menu.addCallbackItem( + "Reload", + isEnabled: WebsitesController.shared.current != nil + ) { [weak self] in + self?.loadUserURL() + } .setShortcut(for: .reload) - menu.addCallbackItem( - "Browsing Mode", - isEnabled: WebsitesController.shared.current != nil, - isChecked: Defaults[.isBrowsingMode] - ) { - Defaults[.isBrowsingMode].toggle() - - SSApp.runOnce(identifier: "activatedBrowsingMode") { - DispatchQueue.main.async { - NSAlert.showModal( - title: "Browsing Mode lets you temporarily interact with the website. For example, to log into an account or scroll to a specific position on the website.", - message: "If you don't currently see the website, you might need to hide some windows to reveal the desktop." - ) + menu.addCallbackItem( + "Browsing Mode", + isEnabled: WebsitesController.shared.current != nil, + isChecked: Defaults[.isBrowsingMode] + ) { + Defaults[.isBrowsingMode].toggle() + + SSApp.runOnce(identifier: "activatedBrowsingMode") { + DispatchQueue.main.async { + NSAlert.showModal( + title: "Browsing Mode lets you temporarily interact with the website. For example, to log into an account or scroll to a specific position on the website.", + message: "If you don't currently see the website, you might need to hide some windows to reveal the desktop." + ) + } } } - } .setShortcut(for: .toggleBrowsingMode) - menu.addCallbackItem( - "Edit…", - isEnabled: WebsitesController.shared.current != nil - ) { - WebsitesWindowController.showWindow() + menu.addCallbackItem( + "Edit…", + isEnabled: WebsitesController.shared.current != nil + ) { + WebsitesWindowController.showWindow() - // TODO: Find a better way to do this. - NotificationCenter.default.post(name: .showEditWebsiteDialog, object: nil) + // TODO: Find a better way to do this. + NotificationCenter.default.post(name: .showEditWebsiteDialog, object: nil) + } } menu.addSeparator() diff --git a/Plash/Utilities.swift b/Plash/Utilities.swift index 279f973..495152b 100644 --- a/Plash/Utilities.swift +++ b/Plash/Utilities.swift @@ -10,6 +10,7 @@ import StoreKit import UniformTypeIdentifiers import LinkPresentation import Defaults +import Sentry /** @@ -453,6 +454,21 @@ extension SSApp { } +extension SSApp { + /** + Initialize Sentry. + */ + static func initSentry(_ dsn: String) { + #if !DEBUG && canImport(Sentry) + SentrySDK.start { + $0.dsn = dsn + $0.enableSwizzling = false + } + #endif + } +} + + extension URL { /** Convenience for opening URLs. @@ -3970,37 +3986,6 @@ extension RangeReplaceableCollection { } -extension NSImage: NSItemProviderReading { - public static var readableTypeIdentifiersForItemProvider: [String] { - NSImage.imageTypes - } - - public static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> Self { - guard let image = self.init(data: data) else { - throw NSError.appError("Unsupported or invalid image") - } - - return image - } -} - -extension NSImage: NSItemProviderWriting { - public static var writableTypeIdentifiersForItemProvider: [String] { - [UTType.tiff.identifier] - } - - public func loadData(withTypeIdentifier typeIdentifier: String, forItemProviderCompletionHandler completionHandler: @escaping (Data?, Error?) -> Void) -> Progress? { - guard let data = tiffRepresentation else { - completionHandler(nil, NSError.appError("Could not convert image to data")) - return nil - } - - completionHandler(data, nil) - return nil - } -} - - extension NSItemProvider { func loadObject(ofClass: T.Type) async throws -> T? where T: NSItemProviderReading { try await withCheckedThrowingContinuation { continuation in @@ -4042,7 +4027,11 @@ extension NSItemProvider { extension NSItemProvider { func getImage() async -> NSImage? { - try? await loadObject(ofClass: NSImage.self) + if #available(macOS 13, *) { + return try? await loadObject(ofClass: NSImage.self) + } else { + return nil + } } }