Skip to content

Commit

Permalink
Require macOS 12
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed May 23, 2022
1 parent 50ddb4b commit 99466c3
Show file tree
Hide file tree
Showing 19 changed files with 556 additions and 668 deletions.
3 changes: 3 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,3 +204,6 @@ custom_rules:
final_class:
regex: '^class [a-zA-Z\d]+[^{]+\{'
message: 'Classes should be marked as final whenever possible. If you actually need it to be subclassable, just add `// swiftlint:disable:next final_class`.'
no_alignment_center:
regex: '\b\(alignment: .center\b'
message: 'This alignment is the default.'
8 changes: 2 additions & 6 deletions Plash.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
E3369A9A265E344300BAC78B /* URLCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3369A99265E344300BAC78B /* URLCommands.swift */; };
E34FCBCE264D32150022BDD3 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = E34FCBCD264D32150022BDD3 /* App.swift */; };
E354442626061C9100CA060F /* Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E354442526061C9100CA060F /* Migration.swift */; };
E354442C26062D2A00CA060F /* WebsitesWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E354442B26062D2A00CA060F /* WebsitesWindowController.swift */; };
E354442F26062D6300CA060F /* WebsitesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E354442E26062D6300CA060F /* WebsitesScreen.swift */; };
E354443C2607505100CA060F /* WebsitesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E354443B2607505100CA060F /* WebsitesController.swift */; };
E3805F5B2466ED5600489E6C /* KeyboardShortcuts in Frameworks */ = {isa = PBXBuildFile; productRef = E3805F5A2466ED5600489E6C /* KeyboardShortcuts */; };
Expand Down Expand Up @@ -86,7 +85,6 @@
E3369A99265E344300BAC78B /* URLCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLCommands.swift; sourceTree = "<group>"; };
E34FCBCD264D32150022BDD3 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
E354442526061C9100CA060F /* Migration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Migration.swift; sourceTree = "<group>"; };
E354442B26062D2A00CA060F /* WebsitesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebsitesWindowController.swift; sourceTree = "<group>"; };
E354442E26062D6300CA060F /* WebsitesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebsitesScreen.swift; sourceTree = "<group>"; };
E354443B2607505100CA060F /* WebsitesController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebsitesController.swift; sourceTree = "<group>"; };
E384F27F24C3B37E002FD21B /* Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Events.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -154,7 +152,6 @@
E32421462384EB4E00D28A91 /* DesktopWindow.swift */,
E30FD88823C4515200C716E9 /* SSWebView.swift */,
E32421592384FBE500D28A91 /* WebViewController.swift */,
E354442B26062D2A00CA060F /* WebsitesWindowController.swift */,
E354442E26062D6300CA060F /* WebsitesScreen.swift */,
E32421352384E9D700D28A91 /* AddWebsiteScreen.swift */,
E333EB1A2385244E005FCE44 /* SettingsScreen.swift */,
Expand Down Expand Up @@ -370,7 +367,6 @@
E34FCBCE264D32150022BDD3 /* App.swift in Sources */,
E32421562384F09D00D28A91 /* Constants.swift in Sources */,
E3FAF815264333D300CF7963 /* Website.swift in Sources */,
E354442C26062D2A00CA060F /* WebsitesWindowController.swift in Sources */,
E333EB1B2385244E005FCE44 /* SettingsScreen.swift in Sources */,
E354442F26062D6300CA060F /* WebsitesScreen.swift in Sources */,
E354443C2607505100CA060F /* WebsitesController.swift in Sources */,
Expand Down Expand Up @@ -451,7 +447,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MACOSX_DEPLOYMENT_TARGET = 12.3;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -508,7 +504,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MACOSX_DEPLOYMENT_TARGET = 12.3;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
Expand Down
187 changes: 91 additions & 96 deletions Plash/AddWebsiteScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import LinkPresentation
import Defaults

struct AddWebsiteScreen: View {
@Environment(\.presentationMode) private var presentationMode
@State private var nativeWindow: NSWindow?
@Environment(\.dismiss) private var dismiss
@State private var hostingWindow: NSWindow?
@State private var isFetchingTitle = false
@State private var isApplyConfirmationPresented = false
@State private var originalWebsite: Website?
@State private var urlString = ""
@State private var isShowingApplyConfirmation = false
@Namespace private var mainNamespace

@State private var newWebsite = Website(
id: UUID(),
Expand Down Expand Up @@ -45,6 +46,71 @@ struct AddWebsiteScreen: View {
}
}

var body: some View {
VStack(alignment: .leading) {
if SSApp.isFirstLaunch {
firstLaunchView
}
VStack(alignment: .leading) {
topView
if isEditing {
editingView
}
}
}
.frame(width: 500)
.bindNativeWindow($hostingWindow)
// Note: Current only works when a text field is focused. (macOS 11.3)
.onExitCommand {
guard isEditing, hasChanges else {
dismiss()
return
}

isApplyConfirmationPresented = true
}
.onSubmit {
submit()
}
.confirmationDialog2(
"Keep changes?",
isPresented: $isApplyConfirmationPresented
) {
Button("Keep") {
dismiss()
}
Button("Don't Keep", role: .destructive) {
revert()
dismiss()
}
Button("Cancel", role: .cancel) {}
}
.toolbar {
// TODO: This can be simplified when `.toolbar` supports conditionals.
ToolbarItem {
if isEditing {
Button("Revert") {
revert()
}
.disabled(!hasChanges)
}
}
ToolbarItem(placement: .cancellationAction) {
if !isEditing {
Button("Cancel") {
dismiss()
}
}
}
ToolbarItem(placement: .confirmationAction) {
Button(isEditing ? "Done" : "Add") {
submit()
}
.disabled(!isURLValid)
}
}
}

private var firstLaunchView: some View {
HStack {
HStack(spacing: 3) {
Expand All @@ -64,21 +130,15 @@ struct AddWebsiteScreen: View {
private var topView: some View {
VStack(alignment: .leading) {
HStack {
// TextField(
// "twitter.com",
// // `removingNewlines` is a workaround for a SwiftUI bug where it doesn't respect the line limit when pasting in multiple lines. (macOS 12.0)
// // TODO: Report to Apple. Still an issue on macOS 12.
// text: $urlString.setMap(\.removingNewlines)
// )
NativeTextField(
text: $urlString.setMap(\.removingNewlines),
placeholder: "twitter.com",
isFirstResponder: !isEditing,
roundedStyle: true,
isSingleLine: true
TextField(
"twitter.com",
// `removingNewlines` is a workaround for a SwiftUI bug where it doesn't respect the line limit when pasting in multiple lines. (macOS 12.0)
// TODO: Report to Apple. Still an issue on macOS 13.
text: $urlString.setMap(\.removingNewlines)
)
.textFieldStyle(.roundedBorder)
.lineLimit(1)
.prefersDefaultFocus(!isEditing, in: mainNamespace)
.padding(.vertical)
// This change listener is used to respond to URL changes from the outside, like the "Revert" button or the Shortcuts actions.
.onChange(of: website.wrappedValue.url) {
Expand Down Expand Up @@ -132,7 +192,7 @@ struct AddWebsiteScreen: View {
.textFieldStyle(.roundedBorder)
.lineLimit(1)
.disabled(isFetchingTitle)
.overlay2(alignment: .trailing) {
.overlay(alignment: .trailing) {
if isFetchingTitle {
ProgressView()
.controlSize(.small)
Expand All @@ -155,7 +215,7 @@ struct AddWebsiteScreen: View {
.help("Creates a fake dark mode for websites without a native dark mode by inverting all the colors on the website.")
Toggle("Use print styles", isOn: website.usePrintStyles)
.help("Forces the website to use its print styles (“@media print”) if any. Some websites have a simpler presentation for printing, for example, Google Calendar.")
// TODO: Put these inside a `DisclosureGroup` called `Advanced` when macOS 12 is out. It's too buggy on macOS 11.
// TODO: Put these inside a `DisclosureGroup` called `Advanced` when macOS 13 is out. It's too buggy on macOS 12.
VStack(alignment: .leading) {
HStack {
Text("CSS:")
Expand Down Expand Up @@ -196,74 +256,12 @@ struct AddWebsiteScreen: View {
.padding()
}

var body: some View {
VStack(alignment: .leading) {
if SSApp.isFirstLaunch {
firstLaunchView
}
VStack(alignment: .leading) {
topView
if isEditing {
editingView
}
}
private func submit() {
if isEditing {
dismiss()
} else {
add()
}
.frame(width: 500)
.bindNativeWindow($nativeWindow)
// Note: Current only works when a text field is focused. (macOS 11.3)
.onExitCommand {
guard isEditing, hasChanges else {
presentationMode.wrappedValue.dismiss()
return
}

isShowingApplyConfirmation = true
}
.alert(isPresented: $isShowingApplyConfirmation) {
// TODO: Add a "Cancel" button when SwiftUI supports more than 2 buttons.
Alert(
title: Text("Keep changes?"),
primaryButton: .default(Text("Keep")) {
presentationMode.wrappedValue.dismiss()
},
secondaryButton: .destructive(Text("Don't Keep")) {
revert()
presentationMode.wrappedValue.dismiss()
}
)
}
.toolbar {
// TODO: This can be simplified when `.toolbar` supports conditionals.
ToolbarItem {
if isEditing {
Button("Revert") {
revert()
}
.disabled(!hasChanges)
}
}
ToolbarItem(placement: .cancellationAction) {
if !isEditing {
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}
}
}
ToolbarItem(placement: .confirmationAction) {
Group {
if isEditing {
Button("Done") {
presentationMode.wrappedValue.dismiss()
}
} else {
Button("Add") {
add()
}
}
}
.disabled(!isURLValid)
}
}
}

private func revert() {
Expand All @@ -276,12 +274,12 @@ struct AddWebsiteScreen: View {

private func add() {
WebsitesController.shared.add(website.wrappedValue)
presentationMode.wrappedValue.dismiss()
dismiss()

SSApp.runOnce(identifier: "editWebsiteTip") {
// TODO: Find a better way to inform the user about this.
DispatchQueue.main.async { // Works around crash. (macOS 12.1)
NSAlert.showModal(
Task {
await NSAlert.show(
title: "Right-click a website in the list to edit it, toggle dark mode, add custom CSS/JavaScript, and more."
)
}
Expand All @@ -290,8 +288,8 @@ struct AddWebsiteScreen: View {

@MainActor
private func chooseLocalWebsite() async -> URL? {
// guard let window = nativeWindow else {
// return
// guard let window = hostingWIndow else {
// return nil
// }

let panel = NSOpenPanel()
Expand All @@ -314,8 +312,8 @@ struct AddWebsiteScreen: View {
panel.directoryURL = url
}

// TODO: Make it a sheet instead when targeting macOS 12. On macOS 11, it doesn't work to open a sheet inside another sheet.
// panel.beginSheet(window) {
// TODO: Make it a sheet instead when targeting macOS 13. On macOS 12.4, it doesn't work to open a sheet inside another sheet.
// let result = await panel.beginSheet(window)
let result = await panel.begin()

guard
Expand All @@ -326,17 +324,14 @@ struct AddWebsiteScreen: View {
}

guard url.appendingPathComponent("index.html", isDirectory: false).exists else {
// This prevents a crash. (macOS 12.1)
DispatchQueue.main.async {
NSAlert.showModal(title: "Please choose a directory that contains a “index.html” file.")
}
await NSAlert.show(title: "Please choose a directory that contains a “index.html” file.")
return await chooseLocalWebsite()
}

do {
try SecurityScopedBookmarkManager.saveBookmark(for: url)
} catch {
error.presentAsModal()
await error.present()
return nil
}

Expand Down
3 changes: 2 additions & 1 deletion Plash/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ TODO:
TODO when targeting macOS 13:
- Use SwiftUI for the websites window. We cannot do it until the window can be manually toggled.
- Convert all Combine usage to AsyncSequence.
*/

@main
Expand All @@ -15,7 +16,7 @@ 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.1)
// This is needed for standard keyboard shortcuts to work in text fields. (macOS 12.4)
WindowGroup {
if false {}
}
Expand Down
2 changes: 1 addition & 1 deletion Plash/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ final class AppState: ObservableObject {
_ = desktopWindow
setUpEvents()
showWelcomeScreenIfNeeded()
SSApp.requestReviewAfterBeingCalledThisManyTimes([5, 50, 500])
SSApp.requestReviewAfterBeingCalledThisManyTimes([8, 50, 500])

#if DEBUG
// SSApp.showSettingsWindow()
Expand Down
5 changes: 0 additions & 5 deletions Plash/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ extension Defaults.Keys {
static let bringBrowsingModeToFront = Key<Bool>("bringBrowsingModeToFront", default: false)
static let openExternalLinksInBrowser = Key<Bool>("openExternalLinksInBrowser", default: false)
static let muteAudio = Key<Bool>("muteAudio", default: true)

// TODO: Remove at some point in the future. Not before 2023.
// Deprecated
static let url = Key<URL?>("url")
static let customCSS = Key<String>("customCSS", default: "")
}

extension Website: Defaults.Serializable {}
Expand Down
8 changes: 3 additions & 5 deletions Plash/Events.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import KeyboardShortcuts

extension AppState {
func setUpEvents() {
menu.needsUpdatePublisher
.sink { [self] _ in
updateMenu()
}
.store(in: &cancellables)
menu.onUpdate = { [self] in
updateMenu()
}

webViewController.didLoadPublisher
.convertToResult()
Expand Down
Loading

0 comments on commit 99466c3

Please sign in to comment.