Rename app and repository to Puter
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
struct NewTaskView: View {
|
||||
@Binding var isPresented: Bool
|
||||
@State private var path = ""
|
||||
@State private var errorMessage: String?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 18) {
|
||||
HStack(spacing: 14) {
|
||||
Image(systemName: "plus.square.dashed")
|
||||
.font(.system(size: 32))
|
||||
.foregroundStyle(.tint)
|
||||
VStack(alignment: .leading, spacing: 3) {
|
||||
Text("Run new task").font(.title2.weight(.semibold))
|
||||
Text("Open an application, document, or executable.").foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
TextField("Application or executable path", text: $path)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.onSubmit { launch() }
|
||||
Button("Browse…") { browse() }
|
||||
}
|
||||
|
||||
if let errorMessage {
|
||||
Label(errorMessage, systemImage: "exclamationmark.triangle.fill")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("Tip: drag an app or file from Finder into the path field.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button("Cancel") { isPresented = false }
|
||||
.keyboardShortcut(.cancelAction)
|
||||
Button("Run") { launch() }
|
||||
.keyboardShortcut(.defaultAction)
|
||||
.buttonStyle(.borderedProminent)
|
||||
.disabled(path.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
|
||||
}
|
||||
}
|
||||
.padding(24)
|
||||
.frame(width: 560)
|
||||
}
|
||||
|
||||
private func browse() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.title = "Choose an application, executable, or document"
|
||||
panel.canChooseDirectories = false
|
||||
panel.canChooseFiles = true
|
||||
panel.allowsMultipleSelection = false
|
||||
if panel.runModal() == .OK, let url = panel.url { path = url.path }
|
||||
}
|
||||
|
||||
private func launch() {
|
||||
let cleaned = (path as NSString).expandingTildeInPath.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let url = URL(fileURLWithPath: cleaned)
|
||||
guard FileManager.default.fileExists(atPath: cleaned) else {
|
||||
errorMessage = "That file could not be found."
|
||||
return
|
||||
}
|
||||
if NSWorkspace.shared.open(url) {
|
||||
isPresented = false
|
||||
} else {
|
||||
errorMessage = "macOS could not open this item."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsView: View {
|
||||
@Environment(SystemMonitor.self) private var monitor
|
||||
@AppStorage("alwaysOnTop") private var alwaysOnTop = false
|
||||
@AppStorage("defaultStartPage") private var defaultStartPage: TaskSection = .processes
|
||||
@AppStorage("diagnosticReportDuration") private var diagnosticDuration = 5
|
||||
@AppStorage("diagnosticAskEveryTime") private var diagnosticAskEveryTime = true
|
||||
@AppStorage("diagnosticReportDirectory") private var diagnosticDirectory = ""
|
||||
|
||||
var body: some View {
|
||||
@Bindable var monitor = monitor
|
||||
VStack(spacing: 0) {
|
||||
PageHeader(title: "Settings", subtitle: "Customize Puter")
|
||||
Form {
|
||||
Section("General") {
|
||||
Picker("Default start page", selection: $defaultStartPage) {
|
||||
ForEach(TaskSection.allCases.filter { $0 != .settings }) { section in
|
||||
Text(section.rawValue).tag(section)
|
||||
}
|
||||
}
|
||||
Picker("Real-time update speed", selection: $monitor.updateSpeed) {
|
||||
ForEach(UpdateSpeed.allCases) { speed in
|
||||
Text(speed.rawValue).tag(speed)
|
||||
}
|
||||
}
|
||||
Toggle("Always on top", isOn: $alwaysOnTop)
|
||||
.onChange(of: alwaysOnTop) { _, enabled in
|
||||
NSApp.keyWindow?.level = enabled ? .floating : .normal
|
||||
}
|
||||
}
|
||||
|
||||
Section("Process data") {
|
||||
LabeledContent("Refresh interval", value: intervalLabel)
|
||||
LabeledContent("Process source", value: "macOS process table")
|
||||
LabeledContent("Memory units", value: "Automatic")
|
||||
}
|
||||
|
||||
Section("Diagnostic reports") {
|
||||
Picker("Sample duration", selection: $diagnosticDuration) {
|
||||
Text("1 second").tag(1)
|
||||
Text("5 seconds").tag(5)
|
||||
Text("10 seconds").tag(10)
|
||||
}
|
||||
Toggle("Ask where to save each report", isOn: $diagnosticAskEveryTime)
|
||||
LabeledContent("Output folder") {
|
||||
HStack(spacing: 10) {
|
||||
Text(diagnosticDirectory.isEmpty ? "Not selected" : URL(fileURLWithPath: diagnosticDirectory).lastPathComponent)
|
||||
.foregroundStyle(.secondary)
|
||||
Button("Choose…") { chooseDiagnosticDirectory() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Section("About") {
|
||||
LabeledContent("Application", value: "Puter")
|
||||
LabeledContent("Version", value: appVersion)
|
||||
LabeledContent("Framework", value: "Native SwiftUI")
|
||||
}
|
||||
}
|
||||
.formStyle(.grouped)
|
||||
.scrollContentBackground(.hidden)
|
||||
.frame(maxWidth: 720)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
.task {
|
||||
NSApp.keyWindow?.level = alwaysOnTop ? .floating : .normal
|
||||
}
|
||||
}
|
||||
|
||||
private var intervalLabel: String {
|
||||
switch monitor.updateSpeed {
|
||||
case .high: "Every second"
|
||||
case .normal: "Every 2 seconds"
|
||||
case .low: "Every 5 seconds"
|
||||
case .paused: "Paused"
|
||||
}
|
||||
}
|
||||
|
||||
private var appVersion: String {
|
||||
Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String ?? "Development"
|
||||
}
|
||||
|
||||
private func chooseDiagnosticDirectory() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.title = "Choose diagnostic report folder"
|
||||
panel.prompt = "Choose"
|
||||
panel.canChooseFiles = false
|
||||
panel.canChooseDirectories = true
|
||||
panel.allowsMultipleSelection = false
|
||||
if !diagnosticDirectory.isEmpty {
|
||||
panel.directoryURL = URL(fileURLWithPath: diagnosticDirectory, isDirectory: true)
|
||||
}
|
||||
if panel.runModal() == .OK, let url = panel.url {
|
||||
diagnosticDirectory = url.path
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user