badge.go

 1package macos
 2
 3import (
 4	_ "embed"
 5	"fmt"
 6	"os"
 7	"os/exec"
 8	"path/filepath"
 9	"runtime"
10	"strconv"
11)
12
13//go:embed badge.swift
14var badgeSwift string
15
16// SetBadge updates the macOS Dock badge count.
17func SetBadge(count int) error {
18	if runtime.GOOS != "darwin" {
19		return nil
20	}
21
22	tmpDir, err := os.MkdirTemp("", "matcha-badge")
23	if err != nil {
24		return err
25	}
26	defer os.RemoveAll(tmpDir) //nolint:errcheck
27
28	swiftFile := filepath.Join(tmpDir, "badge.swift")
29	if err := os.WriteFile(swiftFile, []byte(badgeSwift), 0644); err != nil {
30		return err
31	}
32
33	binFile := filepath.Join(tmpDir, "badge")
34
35	// Compile
36	cmd := exec.Command("swiftc", swiftFile, "-o", binFile) //nolint:noctx
37	if out, err := cmd.CombinedOutput(); err != nil {
38		return fmt.Errorf("failed to compile badge helper: %w\n%s", err, string(out))
39	}
40
41	// Run
42	// If we want to target our specific app, we might need a different approach,
43	// but for now, this will set the badge for the process that runs it.
44	// To set it for the 'MatchaMail.app', we'd need that app to be running and
45	// listen for a notification, OR we run this compiled tool *inside* the app bundle context.
46
47	err = exec.Command(binFile, strconv.Itoa(count)).Run() //nolint:noctx
48	if err != nil {
49		return fmt.Errorf("failed to set badge: %w", err)
50	}
51
52	return nil
53}