diff --git a/battery.go b/battery.go new file mode 100644 index 0000000..1751bb7 --- /dev/null +++ b/battery.go @@ -0,0 +1,79 @@ +package main + +import ( + "fmt" + "os" + "strconv" + "strings" + "time" + + "github.com/mattn/go-gtk/glib" +) + +func initBattery(a *App) { + base := "/sys/class/power_supply" + entries, err := os.ReadDir(base) + if err != nil { + fmt.Println("battery init:", err) + return + } + + var folder string + for _, e := range entries { + if strings.Contains(strings.ToLower(e.Name()), "bat") { + folder = e.Name() + break + } + } + if folder == "" { + fmt.Println("no battery folder found") + return + } + rootPath := base + "/" + folder + + info, err := readBattery(rootPath) + if err != nil { + fmt.Println("read battery:", err) + return + } + a.battery = info + a.updateBatteryLabel(info) + + go func() { + last := info + for { + cur, err := readBattery(rootPath) + if err == nil && + (cur.Percent != last.Percent || cur.Charging != last.Charging) { + last = cur + a.battery = cur + glib.IdleAdd(func() { + a.updateBatteryLabel(cur) + }) + } + time.Sleep(30 * time.Second) + } + }() + +} + +func readBattery(rootPath string) (BatteryInfo, error) { + val, err := os.ReadFile(rootPath + "/capacity") + if err != nil { + return BatteryInfo{}, err + } + status, err := os.ReadFile(rootPath + "/status") + if err != nil { + return BatteryInfo{}, err + } + + p, err := strconv.Atoi(strings.TrimSpace(string(val))) + if err != nil { + return BatteryInfo{}, err + } + + s := strings.ToLower(strings.TrimSpace(string(status))) + charging := !strings.Contains(s, "dis") + + return BatteryInfo{Percent: p, Charging: charging, Path: rootPath}, nil +} diff --git a/go.mod b/go.mod index 4c7c392..4462240 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module main go 1.25.2 -require github.com/mattn/go-gtk v0.0.0-20240119050609-48574e312fac +require ( + github.com/mattn/go-gtk v0.0.0-20240119050609-48574e312fac + golang.org/x/sys v0.37.0 +) require ( github.com/mattn/go-pointer v0.0.1 // indirect diff --git a/go.sum b/go.sum index 4b89484..d3e1c0e 100644 --- a/go.sum +++ b/go.sum @@ -8,5 +8,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 31e4e20..9ba0c34 100644 --- a/main.go +++ b/main.go @@ -4,45 +4,128 @@ package main import "C" import ( + "fmt" + "runtime" + "time" + + "github.com/mattn/go-gtk/gdk" + "github.com/mattn/go-gtk/glib" "github.com/mattn/go-gtk/gtk" ) +func screenSizeWithFallback() (int, int) { + w, h := gdk.ScreenWidth(), gdk.ScreenHeight() + if w <= 0 || h <= 0 { + // Kindle Paperwhite 4 portrait as a safe fallback + return 1072, 1448 + } + return w, h +} + +type App struct { + battery BatteryInfo + batteryLabel *gtk.Label +} + +type BatteryInfo struct { + Percent int + Charging bool + Path string +} + +func startMinuteClock(onTick func(now time.Time)) (stop func()) { + quit := make(chan struct{}) + go func() { + for { + now := time.Now() + next := now.Truncate(time.Minute).Add(time.Minute) + wait := time.Until(next) + select { + case <-time.After(wait): + n := time.Now() + glib.IdleAdd(func() { onTick(n) }) + case <-quit: + return + } + } + }() + return func() { close(quit) } +} + func main() { + app := App{} + runtime.LockOSThread() gtk.Init(nil) - // Main window + w, h := screenSizeWithFallback() + fmt.Printf("Using screen size: %dx%d\n", w, h) + win := gtk.NewWindow(gtk.WINDOW_TOPLEVEL) win.SetTitle("L:A_N:application_PC:TS_ID:com.lab126.store") - win.SetDefaultSize(400, 200) + win.SetDefaultSize(w, h) win.Connect("destroy", gtk.MainQuit) - // Vertical layout container - vbox := gtk.NewVBox(false, 10) - win.Add(vbox) + bg := gtk.NewEventBox() + bg.ModifyBG(gtk.STATE_NORMAL, gdk.NewColor("#ffffff")) + win.Add(bg) - // Label - label := gtk.NewLabel("Hello Kindle!") - vbox.PackStart(label, false, false, 10) + // main container + root := gtk.NewVBox(false, 0) + bg.Add(root) - // Horizontal box for buttons - hbox := gtk.NewHBox(true, 5) - vbox.PackStart(hbox, false, false, 10) + // top bar + topBar := gtk.NewHBox(false, 8) + topBar.SetBorderWidth(6) + root.PackStart(topBar, false, false, 0) - // Show button - btnShow := gtk.NewButtonWithLabel("Show Text") - btnShow.Clicked(func() { - label.Show() + leftStatus := gtk.NewLabel("random info here") + topBar.PackStart(leftStatus, false, false, 8) + + app.batteryLabel = gtk.NewLabel("Batt --%") + netLabel := gtk.NewLabel("Wi-Fi") + timeLabel := gtk.NewLabel(time.Now().Format("15:04")) + + topBar.PackEnd(timeLabel, false, false, 8) + topBar.PackEnd(netLabel, false, false, 8) + topBar.PackEnd(app.batteryLabel, false, false, 8) + + //Scrollable content + scroll := gtk.NewScrolledWindow(nil, nil) + scroll.SetShadowType(gtk.SHADOW_NONE) + scroll.SetPolicy(gtk.POLICY_NEVER, gtk.POLICY_NEVER) + scroll.ModifyBG(gtk.STATE_NORMAL, gdk.NewColor("#ffffff")) + root.PackStart(scroll, true, true, 0) + + vp := gtk.NewViewport(nil, nil) + vp.ModifyBG(gtk.STATE_NORMAL, gdk.NewColor("#ffffff")) + scroll.Add(vp) + + content := gtk.NewVBox(false, 14) + content.ModifyBG(gtk.STATE_NORMAL, gdk.NewColor("#ffffff")) + vp.Add(content) + + title := gtk.NewLabel("") + title.SetMarkup("some cool text") + content.PackStart(title, false, false, 0) + + body := gtk.NewLabel("aaaa") + body.SetLineWrap(true) + content.PackStart(body, false, false, 0) + + _ = startMinuteClock(func(now time.Time) { + timeLabel.SetText(now.Format("15:04")) }) - - // Hide button - btnHide := gtk.NewButtonWithLabel("Hide Text") - btnHide.Clicked(func() { - label.Hide() - }) - - hbox.PackStart(btnShow, true, true, 5) - hbox.PackStart(btnHide, true, true, 5) + initBattery(&app) win.ShowAll() gtk.Main() } + +func (a *App) updateBatteryLabel(b BatteryInfo) { + txt := fmt.Sprintf("%d%%", b.Percent) + fmt.Println("changed battery label") + if b.Charging { + txt += " (charging)" + } + a.batteryLabel.SetText(txt) +}