Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ Loopback, AirDrop's `awdl`/`llw`, bridges and the like are never shown.
* `AppIcon.swift` — the icon, drawn in CoreGraphics: a blue ↑ and a green ↓ over a glowing
throughput trace. `build.sh` renders it to an `.iconset` → `.icns` when it bundles the app.
* `LoginItem.swift` — `SMAppService.mainApp`. The app registers *itself*, so `build.sh
install` launches the installed copy with `--enable-login-item`, and `uninstall` runs it
with `--disable-login-item` before deleting it. A copy dragged in from the disk image
install` runs the installed copy with `--enable-login-item` (register, print the state,
exit) before launching it, and `uninstall` runs it with `--disable-login-item` before
deleting it. A copy dragged in from the disk image
registers on its first launch from `/Applications` instead; either way a
`loginItemRegistered` default is set so it happens once and a later "off" is respected.
* `DMGBackground.swift` — the disk image's background picture, drawn in code like the icon
Expand Down
25 changes: 16 additions & 9 deletions Sources/NimbusNetBar/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import NimbusUpdater
//
// Flags (all optional; build.sh uses most of them):
// --hz N sample rate for this run (default: saved setting, else 2)
// --enable-login-item register this bundle as a Login Item, then keep running
// --enable-login-item register this bundle as a Login Item and exit
// --disable-login-item unregister the Login Item and exit
// --login-item-status print the Login Item state and exit
// --render-icon PATH [--size PX] write the app icon as a PNG and exit
Expand All @@ -21,7 +21,6 @@ import NimbusUpdater

struct Options {
var hz: Double?
var enableLoginItem = false
var dumpBarPath: String?
}

Expand Down Expand Up @@ -53,7 +52,12 @@ while !args.isEmpty {
case "--hz":
guard let v = Double(takeValue(a)), v > 0, v <= 30 else { fputs("--hz must be 0–30\n", stderr); usage() }
options.hz = v
case "--enable-login-item": options.enableLoginItem = true
case "--enable-login-item":
do { try LoginItem.setEnabled(true); print("login item: \(LoginItem.statusDescription)") }
catch { fputs("could not register login item: \(error)\n", stderr); exit(1) }
UserDefaults.standard.set(true, forKey: LoginItem.registeredDefaultsKey)
UserDefaults.standard.synchronize() // about to exit; do not leave the write pending
exit(0)
case "--disable-login-item":
do { try LoginItem.setEnabled(false); print("login item: \(LoginItem.statusDescription)") }
catch { fputs("could not unregister login item: \(error)\n", stderr); exit(1) }
Expand All @@ -75,7 +79,10 @@ while !args.isEmpty {
NSApplication.shared.appearance = NSAppearance(named: .darkAqua)
let v = ChartView(frame: NSRect(x: 0, y: 0, width: 448, height: ChartView.chartHeight))
let fake: [NetworkMonitor.Rate] = (0..<52).map { i in
NetworkMonitor.Rate(down: Double(i % 9) * 1_400_000 + (i % 4 == 0 ? 6_000_000 : 0), up: Double(i % 5) * 400_000)
let burst: Double = i % 4 == 0 ? 6_000_000 : 0
let down: Double = Double(i % 9) * 1_400_000 + burst
let up: Double = Double(i % 5) * 400_000
return NetworkMonitor.Rate(down: down, up: up)
}
v.history = { fake }
v.simulateHover(at: 40)
Expand Down Expand Up @@ -243,13 +250,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
updater?.start()
monitor.start()

// Login Item. `build.sh install` passes --enable-login-item; a drag-install from the
// disk image has nobody to pass it, so the first launch from /Applications registers
// too. Once only — the flag is then set, so turning it off later (menu, System
// Settings) sticks across relaunches and updates.
// Login Item. `build.sh install` registers with --enable-login-item before launching;
// a drag-install from the disk image has nobody to do that, so the first launch from
// /Applications registers instead. Once only — the flag is then set, so turning it
// off later (menu, System Settings) sticks across relaunches and updates.
let installed = Bundle.main.bundlePath.hasPrefix("/Applications/")
let registered = UserDefaults.standard.bool(forKey: LoginItem.registeredDefaultsKey)
if options.enableLoginItem || (installed && !registered) {
if installed && !registered {
do { try LoginItem.setEnabled(true); NSLog("login item: \(LoginItem.statusDescription)") }
catch { NSLog("could not register login item: \(error)") }
UserDefaults.standard.set(true, forKey: LoginItem.registeredDefaultsKey)
Expand Down
7 changes: 3 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,10 @@ case "$cmd" in
fi
ditto "$REL_APP" "$INSTALLED"
# SMAppService registration is done by the app itself, for the bundle it runs from —
# so launch the installed copy and have it register.
open -n "$INSTALLED" --args --enable-login-item
sleep 1.5
# so run the installed copy to register (it prints the state and exits), then launch it.
"$INSTALLED/Contents/MacOS/$NAME" --enable-login-item || warn "could not register the login item"
open "$INSTALLED"
say "installed $INSTALLED"
note "login item: $("$INSTALLED/Contents/MacOS/$NAME" --login-item-status)"
note "It is running now and will start at login. Toggle that in the menu or in System Settings › General › Login Items."
;;

Expand Down
Loading