feat: add native macOS menu-bar application shell (#1)

This commit is contained in:
jayanezj committed 2026-10-23 07:58:49 +02:00
1 parent 730b825ada
commit 0bc6c3317b
28 files changed
+695

No files matched your search

@@ -0,0 +1,29 @@
import AppKit
import SwiftUI
@main
struct TraccarClientApp: App {
@NSApplicationDelegateAdaptor(ApplicationDelegate.self) private var delegate
var body: some Scene {
MenuBarExtra {
TrackingMenu()
} label: {
Image("MenuBarIcon")
.renderingMode(.template)
.accessibilityLabel("Traccar Client — Paused")
}
.menuBarExtraStyle(.menu)
Settings {
SettingsView()
}
}
}
@MainActor
final class ApplicationDelegate: NSObject, NSApplicationDelegate {
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
false
}
}
@@ -0,0 +1,34 @@
import SwiftUI
struct SettingsView: View {
var body: some View {
TabView {
Form {
LabeledContent("Status", value: "Paused")
Text("Server and device configuration will be available in a later build.")
}
.tabItem { Label("Connection", systemImage: "network") }
Form {
Text("Continuous tracking, manual location and SOS are not implemented yet.")
Text("This build does not request your location or send positions.")
}
.tabItem { Label("Tracking", systemImage: "location") }
Form {
Text("Login startup and tracking restoration are not enabled.")
Text("Closing Settings keeps the app in the menu bar. Use Quit to exit.")
}
.tabItem { Label("General", systemImage: "gearshape") }
Form {
LabeledContent("Status", value: "Paused")
Text("No location or network activity is started by this application shell.")
}
.tabItem { Label("Diagnostics", systemImage: "waveform.path.ecg") }
}
.formStyle(.grouped)
.padding()
.frame(width: 560, height: 320)
}
}
@@ -0,0 +1,45 @@
import AppKit
import SwiftUI
struct TrackingMenu: View {
@Environment(\.openSettings) private var openSettings
var body: some View {
Text("Paused")
Text("Tracking is not available in this build.")
Divider()
Button("Start tracking") {}
.disabled(true)
Button("Send location now") {}
.disabled(true)
Button("Send SOS") {}
.disabled(true)
Divider()
Button("Settings…") {
NSApplication.shared.activate(ignoringOtherApps: true)
openSettings()
}
.keyboardShortcut(",")
Button("About Traccar Client for macOS") {
NSApplication.shared.activate(ignoringOtherApps: true)
NSApplication.shared.orderFrontStandardAboutPanel(options: [
.applicationName: "Traccar Client for macOS",
.credits: NSAttributedString(
string: "An independent, unofficial Traccar client.\nLicensed under Apache License 2.0."
),
])
}
Divider()
Button("Quit Traccar Client macOS") {
NSApplication.shared.terminate(nil)
}
.keyboardShortcut("q")
}
}
@@ -0,0 +1,68 @@
{
"images": [
{
"filename": "icon_16x16.png",
"idiom": "mac",
"size": "16x16",
"scale": "1x"
},
{
"filename": "icon_16x16@2x.png",
"idiom": "mac",
"size": "16x16",
"scale": "2x"
},
{
"filename": "icon_32x32.png",
"idiom": "mac",
"size": "32x32",
"scale": "1x"
},
{
"filename": "icon_32x32@2x.png",
"idiom": "mac",
"size": "32x32",
"scale": "2x"
},
{
"filename": "icon_128x128.png",
"idiom": "mac",
"size": "128x128",
"scale": "1x"
},
{
"filename": "icon_128x128@2x.png",
"idiom": "mac",
"size": "128x128",
"scale": "2x"
},
{
"filename": "icon_256x256.png",
"idiom": "mac",
"size": "256x256",
"scale": "1x"
},
{
"filename": "icon_256x256@2x.png",
"idiom": "mac",
"size": "256x256",
"scale": "2x"
},
{
"filename": "icon_512x512.png",
"idiom": "mac",
"size": "512x512",
"scale": "1x"
},
{
"filename": "icon_512x512@2x.png",
"idiom": "mac",
"size": "512x512",
"scale": "2x"
}
],
"info": {
"author": "xcode",
"version": 1
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@@ -0,0 +1,6 @@
{
"info": {
"author": "xcode",
"version": 1
}
}
@@ -0,0 +1,21 @@
{
"images": [
{
"filename": "menu.png",
"idiom": "mac",
"scale": "1x"
},
{
"filename": "menu@2x.png",
"idiom": "mac",
"scale": "2x"
}
],
"info": {
"author": "xcode",
"version": 1
},
"properties": {
"template-rendering-intent": "template"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

+34
View File
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Traccar Client for macOS</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Licensed under the Apache License, Version 2.0.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>