Skip to content

Commit 798a4b1

Browse files
authored
Merge pull request #2 from phendryx/auto-update
add menubar icon for macos with show log option
2 parents eafbe9b + db5f77c commit 798a4b1

7 files changed

Lines changed: 179 additions & 22 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ act.sh
1515
albiondata-client*
1616
buildall.sh
1717
run.sh
18+
*.log
19+
*.log.*
1820

1921

albiondata-client.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"os"
55
"os/exec"
6+
"runtime"
67
"strings"
78
"time"
89

@@ -27,8 +28,19 @@ func main() {
2728

2829
startUpdater()
2930

30-
go systray.Run()
31+
// On macOS, the systray requires the Cocoa event loop to run on the main thread.
32+
// So we run the client in a goroutine and systray on the main thread.
33+
// On other platforms, we do the opposite for backward compatibility.
34+
if runtime.GOOS == "darwin" {
35+
go runClient()
36+
systray.Run() // This blocks on the main thread (required for macOS)
37+
} else {
38+
go systray.Run()
39+
runClient()
40+
}
41+
}
3142

43+
func runClient() {
3244
c := client.NewClient(version)
3345
err := c.Run()
3446
if err != nil {
@@ -37,7 +49,6 @@ func main() {
3749
var b = make([]byte, 1)
3850
_, _ = os.Stdin.Read(b)
3951
}
40-
4152
}
4253

4354
func startUpdater() {

client/config.go

Lines changed: 74 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package client
22

33
import (
44
"flag"
5+
"fmt"
56
"io"
67
"os"
8+
"path/filepath"
9+
"regexp"
710
"strconv"
811
"strings"
912

@@ -14,6 +17,33 @@ import (
1417
"github.com/spf13/viper"
1518
)
1619

20+
const (
21+
logFileName = "albiondata-client.log"
22+
maxLogFiles = 10
23+
)
24+
25+
// ansiStripWriter wraps an io.Writer and strips ANSI escape codes before writing
26+
type ansiStripWriter struct {
27+
writer io.Writer
28+
regex *regexp.Regexp
29+
}
30+
31+
// newAnsiStripWriter creates a writer that strips ANSI escape codes
32+
func newAnsiStripWriter(w io.Writer) *ansiStripWriter {
33+
return &ansiStripWriter{
34+
writer: w,
35+
// Matches ANSI escape sequences like \x1b[0m, \x1b[36m, etc.
36+
regex: regexp.MustCompile(`\x1b\[[0-9;]*m`),
37+
}
38+
}
39+
40+
func (w *ansiStripWriter) Write(p []byte) (n int, err error) {
41+
stripped := w.regex.ReplaceAll(p, []byte{})
42+
_, err = w.writer.Write(stripped)
43+
// Return original length to satisfy io.Writer contract
44+
return len(p), err
45+
}
46+
1747
type config struct {
1848
AllowedWSHosts []string
1949
Debug bool
@@ -29,7 +59,6 @@ type config struct {
2959
EnableWebsockets bool
3060
ListenDevices string
3161
LogLevel string
32-
LogToFile bool
3362
Minimize bool
3463
Offline bool
3564
OfflinePath string
@@ -179,13 +208,6 @@ func (config *config) setupCommonFlags() {
179208
"Listen on this comma separated devices instead of all available. (Windows: Use MAC-Address, Linux: Use interface name)",
180209
)
181210

182-
flag.BoolVar(
183-
&config.LogToFile,
184-
"output-file",
185-
false,
186-
"Enable logging to file.",
187-
)
188-
189211
flag.StringVar(
190212
&config.OfflinePath,
191213
"o",
@@ -237,19 +259,53 @@ func (config *config) setupLogs() {
237259

238260
log.SetLevel(level)
239261

240-
if config.LogToFile {
241-
log.SetFormatter(&logrus.TextFormatter{DisableTimestamp: true, DisableSorting: true, ForceColors: false})
242-
f, err := os.OpenFile("albiondata-client-output.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0755)
243-
if err == nil {
244-
multiWriter := io.MultiWriter(os.Stdout, f)
245-
log.SetOutput(multiWriter)
246-
} else {
247-
log.SetOutput(os.Stdout)
248-
}
262+
// Rotate existing log files before creating new one
263+
rotateLogFiles()
264+
265+
// Always log to both file and terminal
266+
// Use colors for terminal, strip ANSI codes for file
267+
log.SetFormatter(&logrus.TextFormatter{FullTimestamp: true, DisableSorting: true, ForceColors: true})
268+
f, err := os.OpenFile(logFileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
269+
if err == nil {
270+
// Wrap file writer to strip ANSI codes
271+
strippedFileWriter := newAnsiStripWriter(f)
272+
multiWriter := io.MultiWriter(colorable.NewColorableStdout(), strippedFileWriter)
273+
log.SetOutput(multiWriter)
249274
} else {
250-
log.SetFormatter(&logrus.TextFormatter{FullTimestamp: true, DisableSorting: true, ForceColors: true})
251275
log.SetOutput(colorable.NewColorableStdout())
276+
log.Warnf("Could not create log file: %v", err)
277+
}
278+
}
279+
280+
// rotateLogFiles moves the current log file to a numbered backup and removes old backups
281+
func rotateLogFiles() {
282+
// Check if current log file exists
283+
if _, err := os.Stat(logFileName); os.IsNotExist(err) {
284+
return // No log file to rotate
285+
}
286+
287+
// Remove the oldest log file if we're at the limit
288+
oldestLog := fmt.Sprintf("%s.%d", logFileName, maxLogFiles)
289+
_ = os.Remove(oldestLog)
290+
291+
// Shift all existing log files up by one number
292+
for i := maxLogFiles - 1; i >= 1; i-- {
293+
oldName := fmt.Sprintf("%s.%d", logFileName, i)
294+
newName := fmt.Sprintf("%s.%d", logFileName, i+1)
295+
_ = os.Rename(oldName, newName)
296+
}
297+
298+
// Rename current log file to .1
299+
_ = os.Rename(logFileName, fmt.Sprintf("%s.1", logFileName))
300+
}
301+
302+
// GetLogFilePath returns the full path to the current log file
303+
func GetLogFilePath() string {
304+
absPath, err := filepath.Abs(logFileName)
305+
if err != nil {
306+
return logFileName
252307
}
308+
return absPath
253309
}
254310

255311
func (config *config) setupDebugEvents() {

icon/icondarwin.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//go:build darwin
2+
3+
// File generated from icon/albiondata-client.png
4+
5+
package icon
6+
7+
import (
8+
_ "embed"
9+
)
10+
11+
//go:embed albiondata-client.png
12+
var Data []byte

systray/systray_darwin.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//go:build darwin
2+
3+
package systray
4+
5+
import (
6+
"fmt"
7+
"os"
8+
"os/exec"
9+
"path/filepath"
10+
11+
"github.com/ao-data/albiondata-client/icon"
12+
"github.com/ao-data/albiondata-client/log"
13+
"github.com/getlantern/systray"
14+
)
15+
16+
var ConsoleHidden bool = false
17+
18+
const CanHideConsole = false
19+
20+
func HideConsole() {
21+
// Not supported on macOS
22+
}
23+
24+
func ShowConsole() {
25+
// Not supported on macOS
26+
}
27+
28+
func Run() {
29+
systray.Run(onReady, onExit)
30+
}
31+
32+
func onExit() {
33+
// Cleanup if needed
34+
}
35+
36+
func onReady() {
37+
systray.SetIcon(icon.Data)
38+
systray.SetTitle("") // Clear text since we have an icon now
39+
systray.SetTooltip("Albion Data Client")
40+
41+
mOpenLog := systray.AddMenuItem("Open Log File", "Open the log file in default viewer")
42+
systray.AddSeparator()
43+
mQuit := systray.AddMenuItem("Quit", "Close the Albion Data Client")
44+
45+
go func() {
46+
for {
47+
select {
48+
case <-mOpenLog.ClickedCh:
49+
openLogFile()
50+
51+
case <-mQuit.ClickedCh:
52+
fmt.Println("Requesting quit")
53+
systray.Quit()
54+
os.Exit(0)
55+
}
56+
}
57+
}()
58+
}
59+
60+
func openLogFile() {
61+
// Try to find and open the log file
62+
logFile := "albiondata-client.log"
63+
64+
// Check current directory first
65+
if _, err := os.Stat(logFile); err == nil {
66+
absPath, _ := filepath.Abs(logFile)
67+
cmd := exec.Command("open", absPath)
68+
if err := cmd.Start(); err != nil {
69+
log.Errorf("Failed to open log file: %v", err)
70+
}
71+
return
72+
}
73+
74+
// If no log file exists, show a message
75+
log.Info("No log file found yet.")
76+
}

systray/systray_others.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build linux darwin
1+
//go:build linux
22

33
package systray
44

systray/systray_win.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build windows
1+
//go:build windows
22

33
package systray
44

0 commit comments

Comments
 (0)