Rename app and repository to Puter

This commit is contained in:
2026-08-14 23:55:16 -04:00
parent b7faf0ac70
commit 053bb71da2
28 changed files with 1804 additions and 302 deletions
+170
View File
@@ -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
}
}
}