Initial commit
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
// PreferencesView.swift
|
||||
// GreenshotMac
|
||||
//
|
||||
// Port of Greenshot's SettingsForm.
|
||||
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
|
||||
struct PreferencesView: View {
|
||||
var body: some View {
|
||||
TabView {
|
||||
GeneralPreferences()
|
||||
.tabItem { Label("General", systemImage: "gearshape") }
|
||||
OutputPreferences()
|
||||
.tabItem { Label("Output", systemImage: "square.and.arrow.down") }
|
||||
HotkeyPreferences()
|
||||
.tabItem { Label("Hotkeys", systemImage: "keyboard") }
|
||||
EditorPreferences()
|
||||
.tabItem { Label("Editor", systemImage: "pencil.tip.crop.circle") }
|
||||
}
|
||||
.padding(16)
|
||||
.frame(width: 520, height: 380)
|
||||
}
|
||||
}
|
||||
|
||||
private struct GeneralPreferences: View {
|
||||
@AppStorage(Configuration.Keys.defaultDestination) private var destination = DestinationID.editor.rawValue
|
||||
@AppStorage(Configuration.Keys.captureMousepointer) private var captureMousePointer = false
|
||||
@AppStorage(Configuration.Keys.captureDelayMillis) private var captureDelay = 0
|
||||
@AppStorage(Configuration.Keys.playCameraSound) private var cameraSound = true
|
||||
@AppStorage(Configuration.Keys.showFlashAnimation) private var flash = true
|
||||
@AppStorage(Configuration.Keys.showMagnifier) private var magnifier = true
|
||||
@AppStorage(Configuration.Keys.showSelectionSize) private var selectionSize = true
|
||||
@AppStorage(Configuration.Keys.windowCaptureMode) private var windowMode = WindowCaptureMode.window.rawValue
|
||||
@State private var launchAtLogin = LaunchAtLogin.isEnabled
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Picker("After capture:", selection: $destination) {
|
||||
ForEach(DestinationID.allCases.filter { $0 != .openWith }, id: \.rawValue) { item in
|
||||
Text(item.title).tag(item.rawValue)
|
||||
}
|
||||
}
|
||||
Picker("Window capture:", selection: $windowMode) {
|
||||
Text("Window only").tag(WindowCaptureMode.window.rawValue)
|
||||
Text("Window with shadow").tag(WindowCaptureMode.windowWithShadow.rawValue)
|
||||
Text("Crop from screen").tag(WindowCaptureMode.screen.rawValue)
|
||||
}
|
||||
Toggle("Capture the mouse pointer", isOn: $captureMousePointer)
|
||||
Toggle("Play a shutter sound", isOn: $cameraSound)
|
||||
Toggle("Flash the captured area", isOn: $flash)
|
||||
Toggle("Show magnifier while selecting", isOn: $magnifier)
|
||||
Toggle("Show selection size while selecting", isOn: $selectionSize)
|
||||
Toggle("Launch at login", isOn: $launchAtLogin)
|
||||
.onChange(of: launchAtLogin) { _, newValue in
|
||||
LaunchAtLogin.isEnabled = newValue
|
||||
}
|
||||
HStack {
|
||||
Text("Capture delay:")
|
||||
Slider(value: Binding(get: { Double(captureDelay) },
|
||||
set: { captureDelay = Int($0) }),
|
||||
in: 0...5000, step: 250)
|
||||
Text("\(captureDelay) ms").frame(width: 70, alignment: .trailing)
|
||||
}
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
}
|
||||
}
|
||||
|
||||
private struct OutputPreferences: View {
|
||||
@AppStorage(Configuration.Keys.outputFilePath) private var outputPath = ""
|
||||
@AppStorage(Configuration.Keys.outputFileFilenamePattern) private var pattern = ""
|
||||
@AppStorage(Configuration.Keys.outputFileFormat) private var format = OutputFormat.png.rawValue
|
||||
@AppStorage(Configuration.Keys.outputFileJpegQuality) private var jpegQuality = 80
|
||||
@AppStorage(Configuration.Keys.copyPathToClipboard) private var copyPath = false
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
HStack {
|
||||
Text("Save to:")
|
||||
Text(outputPath).lineLimit(1).truncationMode(.middle)
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button("Choose…", action: chooseFolder)
|
||||
}
|
||||
TextField("Filename pattern:", text: $pattern)
|
||||
Text("Variables: ${capturetime}, ${title}, ${appname}, ${user}, ${hostname}, ${mode}, ${NUM}. "
|
||||
+ "Example: ${capturetime:d\"yyyy-MM-dd HH_mm_ss\"}-${title}")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
Picker("Format:", selection: $format) {
|
||||
ForEach(OutputFormat.allCases, id: \.rawValue) { item in
|
||||
Text(item.displayName).tag(item.rawValue)
|
||||
}
|
||||
}
|
||||
if format == OutputFormat.jpg.rawValue {
|
||||
HStack {
|
||||
Text("JPEG quality:")
|
||||
Slider(value: Binding(get: { Double(jpegQuality) },
|
||||
set: { jpegQuality = Int($0) }),
|
||||
in: 10...100, step: 5)
|
||||
Text("\(jpegQuality)%").frame(width: 50, alignment: .trailing)
|
||||
}
|
||||
}
|
||||
Toggle("Copy the file path to the clipboard after saving", isOn: $copyPath)
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
}
|
||||
|
||||
private func chooseFolder() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.canChooseDirectories = true
|
||||
panel.canChooseFiles = false
|
||||
panel.allowsMultipleSelection = false
|
||||
panel.directoryURL = URL(fileURLWithPath: outputPath, isDirectory: true)
|
||||
if panel.runModal() == .OK, let url = panel.url {
|
||||
outputPath = url.path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct HotkeyPreferences: View {
|
||||
var body: some View {
|
||||
Form {
|
||||
ForEach(HotkeyAction.allCases, id: \.rawValue) { action in
|
||||
HStack {
|
||||
Text(action.title)
|
||||
Spacer()
|
||||
HotkeyRecorder(action: action)
|
||||
.frame(width: 150, height: 24)
|
||||
}
|
||||
}
|
||||
Text("Click a shortcut, then press the new combination. Backspace clears it, Esc cancels. "
|
||||
+ "A modifier key is required.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
}
|
||||
}
|
||||
|
||||
private struct EditorPreferences: View {
|
||||
@AppStorage(Configuration.Keys.editorLineThickness) private var lineThickness = 2
|
||||
@AppStorage(Configuration.Keys.editorFontFamily) private var fontFamily = "Helvetica"
|
||||
@AppStorage(Configuration.Keys.editorFontSize) private var fontSize = 14
|
||||
@AppStorage(Configuration.Keys.editorPixelSize) private var pixelSize = 8
|
||||
@AppStorage(Configuration.Keys.editorBlurRadius) private var blurRadius = 12
|
||||
@AppStorage(Configuration.Keys.editorDropShadow) private var dropShadow = false
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Stepper("Default line thickness: \(lineThickness) px", value: $lineThickness, in: 0...20)
|
||||
Picker("Default font:", selection: $fontFamily) {
|
||||
ForEach(["Helvetica", "Helvetica Neue", "Menlo", "Times New Roman", "Arial", "Georgia"], id: \.self) {
|
||||
Text($0).tag($0)
|
||||
}
|
||||
}
|
||||
Stepper("Default font size: \(fontSize) pt", value: $fontSize, in: 6...96)
|
||||
Stepper("Pixelation size: \(pixelSize) px", value: $pixelSize, in: 2...40)
|
||||
Stepper("Blur radius: \(blurRadius) px", value: $blurRadius, in: 1...40)
|
||||
Toggle("Drop shadow on new elements", isOn: $dropShadow)
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user