Use lowercase puter branding

This commit is contained in:
2026-08-15 00:05:24 -04:00
parent 053bb71da2
commit a67bb5fdf3
23 changed files with 41 additions and 41 deletions
+7 -7
View File
@@ -2,20 +2,20 @@
import PackageDescription import PackageDescription
let package = Package( let package = Package(
name: "Puter", name: "puter",
platforms: [.macOS(.v14)], platforms: [.macOS(.v14)],
products: [ products: [
.executable(name: "Puter", targets: ["Puter"]) .executable(name: "puter", targets: ["puter"])
], ],
targets: [ targets: [
.executableTarget( .executableTarget(
name: "Puter", name: "puter",
path: "Sources/Puter" path: "Sources/puter"
), ),
.testTarget( .testTarget(
name: "PuterTests", name: "puterTests",
dependencies: ["Puter"], dependencies: ["puter"],
path: "Tests/PuterTests" path: "Tests/puterTests"
) )
] ]
) )
+2 -2
View File
@@ -1,4 +1,4 @@
# Puter # puter
A native macOS system monitor written in SwiftUI and inspired by Windows 11 Task Manager. A native macOS system monitor written in SwiftUI and inspired by Windows 11 Task Manager.
@@ -57,7 +57,7 @@ To create a standard double-clickable app bundle:
```sh ```sh
./scripts/build-app.sh ./scripts/build-app.sh
open "dist/Puter.app" open "dist/puter.app"
``` ```
To create a drag-to-install disk image containing the app and an Applications shortcut: To create a drag-to-install disk image containing the app and an Applications shortcut:
+5 -5
View File
@@ -5,17 +5,17 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Puter</string> <string>puter</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Puter</string> <string>puter</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>local.mactaskmanager.app</string> <string>dev.soconnor.puter</string>
<key>CFBundleIconName</key> <key>CFBundleIconName</key>
<string>Puter</string> <string>puter</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Puter</string> <string>puter</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
@@ -83,7 +83,7 @@ struct SettingsView: View {
var body: some View { var body: some View {
@Bindable var monitor = monitor @Bindable var monitor = monitor
VStack(spacing: 0) { VStack(spacing: 0) {
PageHeader(title: "Settings", subtitle: "Customize Puter") PageHeader(title: "Settings", subtitle: "Customize puter")
Form { Form {
Section("General") { Section("General") {
Picker("Default start page", selection: $defaultStartPage) { Picker("Default start page", selection: $defaultStartPage) {
@@ -125,7 +125,7 @@ struct SettingsView: View {
} }
Section("About") { Section("About") {
LabeledContent("Application", value: "Puter") LabeledContent("Application", value: "puter")
LabeledContent("Version", value: appVersion) LabeledContent("Version", value: appVersion)
LabeledContent("Framework", value: "Native SwiftUI") LabeledContent("Framework", value: "Native SwiftUI")
} }
@@ -2,7 +2,7 @@ import AppKit
import SwiftUI import SwiftUI
extension Notification.Name { extension Notification.Name {
static let runNewTask = Notification.Name("Puter.runNewTask") static let runNewTask = Notification.Name("puter.runNewTask")
} }
struct ContentView: View { struct ContentView: View {
@@ -70,14 +70,14 @@ struct ContentView: View {
TaskToolbarContent(showingNewTask: $showingNewTask) TaskToolbarContent(showingNewTask: $showingNewTask)
} }
} }
.navigationTitle("Puter") .navigationTitle("puter")
.animation(.snappy(duration: 0.22), value: sidebarCompact) .animation(.snappy(duration: 0.22), value: sidebarCompact)
.onChange(of: selection) { _, _ in searchText = "" } .onChange(of: selection) { _, _ in searchText = "" }
.onReceive(NotificationCenter.default.publisher(for: .runNewTask)) { _ in showingNewTask = true } .onReceive(NotificationCenter.default.publisher(for: .runNewTask)) { _ in showingNewTask = true }
.sheet(isPresented: $showingNewTask) { .sheet(isPresented: $showingNewTask) {
NewTaskView(isPresented: $showingNewTask) NewTaskView(isPresented: $showingNewTask)
} }
.alert("Puter", isPresented: Binding( .alert("puter", isPresented: Binding(
get: { monitor.errorMessage != nil }, get: { monitor.errorMessage != nil },
set: { if !$0 { monitor.errorMessage = nil } } set: { if !$0 { monitor.errorMessage = nil } }
)) { )) {
@@ -294,7 +294,7 @@ struct HardwareView: View {
metric("Control backend", FanControlService.isAvailable ? "Ready" : "Unavailable") metric("Control backend", FanControlService.isAvailable ? "Ready" : "Unavailable")
Spacer() Spacer()
} }
Text("Puter reads fan sensors directly through the Mac's SMC interface. Manual targets are clamped to each fan's reported safe range; Automatic returns control to macOS.") Text("puter reads fan sensors directly through the Mac's SMC interface. Manual targets are clamped to each fan's reported safe range; Automatic returns control to macOS.")
.font(.caption).foregroundStyle(.secondary) .font(.caption).foregroundStyle(.secondary)
HStack { HStack {
Button("Apply targets", systemImage: "speedometer") { Button("Apply targets", systemImage: "speedometer") {
@@ -126,7 +126,7 @@ enum ProcessDiagnosticReporter {
let panel = NSSavePanel() let panel = NSSavePanel()
panel.title = "Create diagnostic report" panel.title = "Create diagnostic report"
panel.message = "Puter will sample \(process.displayName) for \(duration) seconds and save a text report." panel.message = "puter will sample \(process.displayName) for \(duration) seconds and save a text report."
panel.prompt = "Create Report" panel.prompt = "Create Report"
panel.nameFieldStringValue = safeFilename("\(process.displayName)-\(process.pid)-sample.txt") panel.nameFieldStringValue = safeFilename("\(process.displayName)-\(process.pid)-sample.txt")
panel.allowedContentTypes = [.plainText] panel.allowedContentTypes = [.plainText]
@@ -6,7 +6,7 @@ struct PuterApp: App {
@AppStorage("sidebarCompact") private var sidebarCompact = false @AppStorage("sidebarCompact") private var sidebarCompact = false
var body: some Scene { var body: some Scene {
WindowGroup("Puter") { WindowGroup("puter") {
ContentView() ContentView()
.environment(monitor) .environment(monitor)
.frame(minWidth: 820, minHeight: 560) .frame(minWidth: 820, minHeight: 560)
@@ -66,7 +66,7 @@ struct AppHistoryView: View {
Button("Cancel", role: .cancel) {} Button("Cancel", role: .cancel) {}
Button("Reset", role: .destructive) { monitor.resetAppHistory() } Button("Reset", role: .destructive) { monitor.resetAppHistory() }
} message: { } message: {
Text("CPU time and network totals collected by Puter will be permanently cleared.") Text("CPU time and network totals collected by puter will be permanently cleared.")
} }
.sheet(item: $inspectedUsage) { AppUsagePropertiesView(usage: $0) } .sheet(item: $inspectedUsage) { AppUsagePropertiesView(usage: $0) }
} }
@@ -147,7 +147,7 @@ final class SystemMonitor {
func terminate(_ process: ProcessRecord, force: Bool = false) { func terminate(_ process: ProcessRecord, force: Bool = false) {
guard process.pid != getpid() else { guard process.pid != getpid() else {
errorMessage = "Puter cannot end itself." errorMessage = "puter cannot end itself."
return return
} }
let signal = force ? SIGKILL : SIGTERM let signal = force ? SIGKILL : SIGTERM
@@ -170,7 +170,7 @@ final class SystemMonitor {
func terminateGroup(_ group: [ProcessRecord]) { func terminateGroup(_ group: [ProcessRecord]) {
guard !group.contains(where: { $0.pid == getpid() }) else { guard !group.contains(where: { $0.pid == getpid() }) else {
errorMessage = "Puter cannot end an application group that contains itself." errorMessage = "puter cannot end an application group that contains itself."
return return
} }
let pids = Set(group.map(\.pid)) let pids = Set(group.map(\.pid))
@@ -188,7 +188,7 @@ final class SystemMonitor {
func sendSignal(_ signal: Int32, to process: ProcessRecord, successMessage: String? = nil) { func sendSignal(_ signal: Int32, to process: ProcessRecord, successMessage: String? = nil) {
guard process.pid != getpid() else { guard process.pid != getpid() else {
errorMessage = "Puter cannot control itself." errorMessage = "puter cannot control itself."
return return
} }
if kill(process.pid, signal) != 0 { if kill(process.pid, signal) != 0 {
@@ -415,7 +415,7 @@ private enum AppHistoryPersistence {
} }
static let directory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0] static let directory = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0]
.appendingPathComponent("MacTaskManager", isDirectory: true) .appendingPathComponent("puter", isDirectory: true)
static let url = directory.appendingPathComponent("app-history.json") static let url = directory.appendingPathComponent("app-history.json")
} }
@@ -1,5 +1,5 @@
import XCTest import XCTest
@testable import Puter @testable import puter
final class ModelTests: XCTestCase { final class ModelTests: XCTestCase {
func testAppleSystemServicePublisherAndDomainIdentity() { func testAppleSystemServicePublisherAndDomainIdentity() {

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

+7 -7
View File
@@ -2,10 +2,10 @@
set -euo pipefail set -euo pipefail
PROJECT_DIR="${0:A:h:h}" PROJECT_DIR="${0:A:h:h}"
APP_DIR="$PROJECT_DIR/dist/Puter.app" APP_DIR="$PROJECT_DIR/dist/puter.app"
ICON_SOURCE="${PUTER_ICON_SOURCE:-$PROJECT_DIR/Puter.icon}" ICON_SOURCE="${PUTER_ICON_SOURCE:-$PROJECT_DIR/puter.icon}"
STAGING_ROOT="$(mktemp -d /tmp/puter-build.XXXXXX)" STAGING_ROOT="$(mktemp -d /tmp/puter-build.XXXXXX)"
STAGED_APP="$STAGING_ROOT/Puter.app" STAGED_APP="$STAGING_ROOT/puter.app"
CONTENTS_DIR="$STAGED_APP/Contents" CONTENTS_DIR="$STAGED_APP/Contents"
trap '/bin/rm -rf -- "$STAGING_ROOT"' EXIT trap '/bin/rm -rf -- "$STAGING_ROOT"' EXIT
@@ -14,9 +14,9 @@ cd "$PROJECT_DIR"
swift build -c release swift build -c release
mkdir -p "$CONTENTS_DIR/MacOS" "$CONTENTS_DIR/Resources" mkdir -p "$CONTENTS_DIR/MacOS" "$CONTENTS_DIR/Resources"
cp "$PROJECT_DIR/.build/release/Puter" "$CONTENTS_DIR/MacOS/Puter" cp "$PROJECT_DIR/.build/release/puter" "$CONTENTS_DIR/MacOS/puter"
cp "$PROJECT_DIR/Resources/Info.plist" "$CONTENTS_DIR/Info.plist" cp "$PROJECT_DIR/Resources/Info.plist" "$CONTENTS_DIR/Info.plist"
chmod +x "$CONTENTS_DIR/MacOS/Puter" chmod +x "$CONTENTS_DIR/MacOS/puter"
SMC_SOURCE="/Applications/Stats.app/Contents/Resources/smc" SMC_SOURCE="/Applications/Stats.app/Contents/Resources/smc"
if [[ -x "$SMC_SOURCE" ]]; then if [[ -x "$SMC_SOURCE" ]]; then
@@ -31,14 +31,14 @@ if [[ -d "$ICON_SOURCE" ]]; then
--compile "$CONTENTS_DIR/Resources" \ --compile "$CONTENTS_DIR/Resources" \
--platform macosx \ --platform macosx \
--minimum-deployment-target 14.0 \ --minimum-deployment-target 14.0 \
--app-icon Puter \ --app-icon puter \
--output-partial-info-plist "$CONTENTS_DIR/Resources/IconInfo.plist" >/dev/null --output-partial-info-plist "$CONTENTS_DIR/Resources/IconInfo.plist" >/dev/null
[[ -s "$CONTENTS_DIR/Resources/Assets.car" ]] || { [[ -s "$CONTENTS_DIR/Resources/Assets.car" ]] || {
print -u2 "Icon Composer did not produce an Assets.car file" print -u2 "Icon Composer did not produce an Assets.car file"
exit 1 exit 1
} }
[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconName' "$CONTENTS_DIR/Info.plist")" == "Puter" ]] || { [[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconName' "$CONTENTS_DIR/Info.plist")" == "puter" ]] || {
print -u2 "CFBundleIconName must reference the Icon Composer asset" print -u2 "CFBundleIconName must reference the Icon Composer asset"
exit 1 exit 1
} }
+6 -6
View File
@@ -2,8 +2,8 @@
set -euo pipefail set -euo pipefail
PROJECT_DIR="${0:A:h:h}" PROJECT_DIR="${0:A:h:h}"
APP_PATH="$PROJECT_DIR/dist/Puter.app" APP_PATH="$PROJECT_DIR/dist/puter.app"
DMG_PATH="$PROJECT_DIR/dist/Puter-macOS.dmg" DMG_PATH="$PROJECT_DIR/dist/puter-macOS.dmg"
STAGING_DIR="$(mktemp -d /tmp/puter-dmg.XXXXXX)" STAGING_DIR="$(mktemp -d /tmp/puter-dmg.XXXXXX)"
cleanup() { cleanup() {
@@ -15,13 +15,13 @@ if [[ ! -d "$APP_PATH" ]]; then
"$PROJECT_DIR/scripts/build-app.sh" "$PROJECT_DIR/scripts/build-app.sh"
fi fi
ditto --norsrc "$APP_PATH" "$STAGING_DIR/Puter.app" ditto --norsrc "$APP_PATH" "$STAGING_DIR/puter.app"
xattr -cr "$STAGING_DIR/Puter.app" xattr -cr "$STAGING_DIR/puter.app"
codesign --verify --deep --strict "$STAGING_DIR/Puter.app" codesign --verify --deep --strict "$STAGING_DIR/puter.app"
ln -s /Applications "$STAGING_DIR/Applications" ln -s /Applications "$STAGING_DIR/Applications"
hdiutil create \ hdiutil create \
-volname "Puter" \ -volname "puter" \
-srcfolder "$STAGING_DIR" \ -srcfolder "$STAGING_DIR" \
-format UDZO \ -format UDZO \
-imagekey zlib-level=9 \ -imagekey zlib-level=9 \