Skip to content

Commit

Permalink
Target macOS 12
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Dec 9, 2022
1 parent 11fbbb9 commit 55f4425
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 140 deletions.
12 changes: 6 additions & 6 deletions Gifski.xcodeproj/project.pbxproj
Expand Up @@ -637,7 +637,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.4;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
Expand Down Expand Up @@ -694,7 +694,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.4;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
Expand Down Expand Up @@ -808,31 +808,31 @@
repositoryURL = "https://github.com/sindresorhus/Defaults";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.2.1;
minimumVersion = 7.0.0;
};
};
E3339E982395768F00303839 /* XCRemoteSwiftPackageReference "CircularProgress" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sindresorhus/CircularProgress";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.2.0;
minimumVersion = 3.0.1;
};
};
E3339E9B2395789500303839 /* XCRemoteSwiftPackageReference "DockProgress" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sindresorhus/DockProgress";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 3.2.0;
minimumVersion = 4.0.1;
};
};
E3C874A8252CFE5B00AB1099 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 9.4.1;
minimumVersion = 10.2.0;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down
2 changes: 1 addition & 1 deletion Gifski.xcodeproj/xcshareddata/xcschemes/Gifski.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
LastUpgradeVersion = "1410"
version = "1.8">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
22 changes: 1 addition & 21 deletions Gifski/App.swift
Expand Up @@ -5,9 +5,6 @@ import FirebaseCrashlytics
import DockProgress

/**
TODO when targeting macOS 12:
- Upload non-App Store version.
TODO when targeting macOS 13:
- Rewrite everything to use async/await, AsyncSequence, and actors.
- Rewrite `CheckerboardView` to use `SwiftUI.Canvas`.
Expand Down Expand Up @@ -38,24 +35,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
NSApp.servicesProvider = self

// We have to include `.badge` otherwise system preferences does not show the checkbox to turn off sounds. (macOS 12.4)
notificationCenter.requestAuthorization(options: [.sound, .badge]) { success, _ in
guard
!SSApp.isFirstLaunch,
success
else {
return
}

DispatchQueue.main.async {
// TODO: Remove this in 2023.
SSApp.runOnce(identifier: "notificationSoundNotice") {
NSAlert.showModal(
title: "The conversion completed notification now plays a sound.",
message: "If you don't want this, you can turn it off in “System Preferences › Notifications & Focus › Gifski”."
)
}
}
}
notificationCenter.requestAuthorization(options: [.sound, .badge]) { _, _ in }

mainWindowController.showWindow(self)

Expand Down
4 changes: 2 additions & 2 deletions Gifski/Base.lproj/MainMenu.xib
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
Expand Down
4 changes: 2 additions & 2 deletions Gifski/EditVideoViewController.swift
Expand Up @@ -10,8 +10,8 @@ struct SpeedView: View {
HStack(alignment: .firstTextBaseline) {
Text("Speed:")
Slider(value: $outputSpeed, in: 0.5...5, step: 0.5)
Text("\(outputSpeed.formatted)×")
.font(.system().monospacedDigit()) // TODO: Use `.monospacedDigit()` view modifier when targeting macOS 12.
Text("\(outputSpeed.formatted())×")
.monospacedDigit()
.frame(width: 30, alignment: .leading)
}
.padding(.leading, 52)
Expand Down
45 changes: 21 additions & 24 deletions Gifski/EstimatedFileSize.swift
Expand Up @@ -2,20 +2,14 @@ import SwiftUI
import FirebaseCrashlytics

final class EstimatedFileSizeModel: ObservableObject {
static let formatter: ByteCountFormatter = {
let formatter = ByteCountFormatter()
formatter.zeroPadsFractionDigits = true
return formatter
}()

@Published var estimatedFileSize: String?
@Published var error: Error?

// This is outside the scope of "file estimate", but it was easier to add this here than doing a separate SwiftUI view. This should be refactored out into a separate view when all of Gifski is SwiftUI.
@Published var duration: TimeInterval = 0

var estimatedFileSizeNaive: String {
Self.formatter.string(fromByteCount: Int64(getNaiveEstimate()))
Int(getNaiveEstimate()).formatted(.byteCount(style: .file))
}

private let getConversionSettings: () -> GIFGenerator.Conversion
Expand Down Expand Up @@ -56,8 +50,7 @@ final class EstimatedFileSizeModel: ObservableObject {
// We add 10% extra because it's better to estimate slightly too much than too little.
let fileSize = (Double(data.count) * gifski.sizeMultiplierForEstimation) * 1.1

// TODO: Use the new formatter API when targeting macOS 12.
self.estimatedFileSize = Self.formatter.string(fromByteCount: Int64(fileSize))
self.estimatedFileSize = Int(fileSize).formatted(.byteCount(style: .file))
case .failure(let error):
switch error {
case .cancelled:
Expand Down Expand Up @@ -100,31 +93,35 @@ struct EstimatedFileSizeView: View {
HStack(spacing: 0) {
Text("Estimated size: ")
Text(model.estimatedFileSize ?? model.estimatedFileSizeNaive)
// TODO: Use `View#monospacedDigit()` when targeting macOS 12.
.font(.system(size: 13).monospacedDigit())
.foregroundColor(model.estimatedFileSize == nil ? .secondary : .primary)
.monospacedDigit()
.foregroundStyle(model.estimatedFileSize == nil ? .secondary : .primary)
}
.foregroundColor(.secondary)
HStack {
if model.estimatedFileSize == nil {
ProgressView()
.controlSize(.mini)
.padding(.leading, -4)
.help("Calculating file size estimate")
}
.foregroundStyle(.secondary)
if model.estimatedFileSize == nil {
ProgressView()
.controlSize(.mini)
.padding(.leading, -4)
.help("Calculating file size estimate")
}
// This causes SwiftUI to crash internally on macOS 12.0 when changing the trim size many times so the estimation indicator keeps changing.
// .animation(.easeInOut, value: model.estimatedFileSize)
}
}
// It's important to set a width here as otherwise it can cause internal SwiftUI crashes on macOS 11 and 12.
.frame(width: 500, height: 22, alignment: .leading)
.overlay2 {
.overlay {
if model.error == nil {
HStack {
// TODO: Use the below instead when targeting macOS 13.
/*
Duration.seconds(duration)
.formatted(
.time(pattern: .minuteSecond(padMinuteToLength: 2, fractionalSecondsLength: 2))
.locale(locale)
)
*/
Text(DateComponentsFormatter.localizedStringPositionalWithFractionalSeconds(model.duration))
// TODO: Use `View#monospacedDigit()` when targeting macOS 12.
.font(.system(size: 13).monospacedDigit())
.monospacedDigit()
.padding(.horizontal, 6)
.padding(.vertical, 3)
.background(Color.primary.opacity(0.04))
Expand All @@ -133,7 +130,7 @@ struct EstimatedFileSizeView: View {
.padding(.leading, 220)
}
}
.onAppear {
.task {
if model.estimatedFileSize == nil {
model.updateEstimate()
}
Expand Down
89 changes: 8 additions & 81 deletions Gifski/Utilities.swift
Expand Up @@ -542,35 +542,11 @@ extension String.StringInterpolation {
}
}


extension Double {
/**
Converts the number to a string and strips fractional trailing zeros.
```
let x = 1.0
print(1.0)
//=> "1.0"
print(1.0.formatted)
//=> "1"
print(0.0100.formatted)
//=> "0.01"
```
*/
var formatted: String {
truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
}
}


extension CGSize {
/**
Example: `140×100`
*/
var formatted: String { "\(width.double.formatted)×\(height.double.formatted)" }
var formatted: String { "\(width.formatted())×\(height.formatted())" }
}


Expand Down Expand Up @@ -2005,10 +1981,10 @@ extension URL {
extension String {
/*
```
"https://sindresorhus.com".openUrl()
"https://sindresorhus.com".openURL()
```
*/
func openUrl() {
func openURL() {
URL(string: self)?.open()
}
}
Expand Down Expand Up @@ -2220,8 +2196,7 @@ extension URL {
var fileSize: Int { resourceValue(forKey: .fileSizeKey) ?? 0 }

var fileSizeFormatted: String {
// TODO: Use `.formatted(.byteCount(style: .file))` when targeting macOS 12.
ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
fileSize.formatted(.byteCount(style: .file))
}

var exists: Bool { FileManager.default.fileExists(atPath: path) }
Expand Down Expand Up @@ -2493,7 +2468,6 @@ extension Result {
}


// TODO: Find a way to reduce the number of overloads for `wrap()`.
final class Once {
private var lock = os_unfair_lock()
private var hasRun = false
Expand Down Expand Up @@ -3929,17 +3903,6 @@ extension Sequence where Element: Sequence {
}


extension NSFont {
/**
Returns a new version of the font with the existing font descriptor replaced by the given font descriptor.
*/
func withDescriptor(_ descriptor: NSFontDescriptor) -> NSFont {
// It's important that the size is `0` and not `pointSize` as otherwise the descriptor is not able to change the font size.
Self(descriptor: descriptor, size: 0) ?? self
}
}


extension String {
var attributedString: NSAttributedString { NSAttributedString(string: self) }
}
Expand Down Expand Up @@ -4037,15 +4000,6 @@ extension String {
}


extension NSExtensionContext {
var inputItemsTyped: [NSExtensionItem] { inputItems as! [NSExtensionItem] }

var attachments: [NSItemProvider] {
inputItemsTyped.compactMap(\.attachments).flatten()
}
}


extension UnsafeMutableRawPointer {
/**
Convert an unsafe mutable raw pointer to an array.
Expand All @@ -4069,14 +4023,6 @@ extension Data {
}


extension [UInt8] {
/**
Convert the array to data.
*/
var data: Data { Data(self) }
}


extension CGImage {
static let empty = NSImage(size: CGSize(widthHeight: 1), flipped: false) { _ in true }
.cgImage(forProposedRect: nil, context: nil, hints: nil)!
Expand Down Expand Up @@ -4559,7 +4505,6 @@ extension AVPlayerItem {
return duration / totalDuration
}

// TODO: Make it async when targeting macOS 12.
/**
Seek to the given percentage (`0...1`) of the total duration.
*/
Expand Down Expand Up @@ -4634,9 +4579,9 @@ extension OperatingSystem {
/**
- Note: Only use this when you cannot use an `if #available` check. For example, inline in function calls.
*/
static let isMacOS13OrLater: Bool = {
static let isMacOS14OrLater: Bool = {
#if os(macOS)
if #available(macOS 13, *) {
if #available(macOS 14, *) {
return true
} else {
return false
Expand All @@ -4649,9 +4594,9 @@ extension OperatingSystem {
/**
- Note: Only use this when you cannot use an `if #available` check. For example, inline in function calls.
*/
static let isMacOS12OrLater: Bool = {
static let isMacOS13OrLater: Bool = {
#if os(macOS)
if #available(macOS 12, *) {
if #available(macOS 13, *) {
return true
} else {
return false
Expand Down Expand Up @@ -4742,21 +4687,3 @@ extension ClosedRange {
bound1 <= bound2 ? bound1...bound2 : bound2...bound1
}
}


// TODO: Remove when targeting macOS 12.
extension View {
func overlay2(
alignment: Alignment = .center,
@ViewBuilder content: () -> some View
) -> some View {
overlay(ZStack(content: content), alignment: alignment)
}

func background2(
alignment: Alignment = .center,
@ViewBuilder content: () -> some View
) -> some View {
background(ZStack(content: content), alignment: alignment)
}
}

0 comments on commit 55f4425

Please sign in to comment.