Skip to content

Commit

Permalink
feat: online version checker and indicators #23
Browse files Browse the repository at this point in the history
  • Loading branch information
leukipp committed Oct 10, 2023
1 parent 12db32d commit ac37679
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 25 deletions.
40 changes: 37 additions & 3 deletions common/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"flag"
"fmt"
"os"
"path"
"strings"

"net/http"
"path/filepath"
)

Expand All @@ -18,6 +21,8 @@ type BuildInfo struct {
Version string // Build version
Commit string // Build commit
Date string // Build date
Source string // Build summary
Latest string // Build latest
Summary string // Build summary
}

Expand All @@ -32,14 +37,16 @@ type Arguments struct {
V bool // Argument for verbose mode
}

func InitArgs(name, version, commit, date string) {
func InitArgs(name, version, commit, date, source string) {

// Build information
Build = BuildInfo{
Name: name,
Version: version,
Commit: Truncate(commit, 7),
Date: date,
Source: source,
Latest: version,
}
Build.Summary = fmt.Sprintf("%s v%s-%s, built on %s", Build.Name, Build.Version, Build.Commit, Build.Date)

Expand All @@ -58,7 +65,34 @@ func InitArgs(name, version, commit, date string) {
fmt.Fprintf(flag.CommandLine.Output(), "%s\n\nUsage:\n", Build.Summary)
flag.PrintDefaults()
}

// Parse arguments
flag.Parse()

// Version checker
suspended := false
if _, err := os.Stat(filepath.Join(Args.Cache, "no-version-check")); !os.IsNotExist(err) {
suspended = true
}
if !suspended && VersionToInt(Build.Version) > 0 {
Build.Latest = Latest(source)
if VersionToInt(Build.Latest) > VersionToInt(Build.Version) {
Build.Summary = fmt.Sprintf("%s, >>> %s v%s available <<<", Build.Summary, Build.Name, Build.Latest)
}
}
}

func Latest(source string) string {

// Request latest version from github
res, err := http.Get(strings.Trim(source, "/") + "/releases/latest")
if err != nil {
return Build.Version
}

// Parse latest version from redirect url
version := path.Base(res.Request.URL.Path)
if !strings.HasPrefix(version, "v") {
return Build.Version
}

return version[1:]
}
18 changes: 18 additions & 0 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"crypto/sha1"
"encoding/hex"
"reflect"
"regexp"
"strconv"
"strings"

"github.com/BurntSushi/xgbutil/xrect"
)
Expand Down Expand Up @@ -49,3 +52,18 @@ func IsInsideRect(p *Pointer, r xrect.Rect) bool {

return xInRect && yInRect
}

func VersionToInt(version string) int {

// Remove non-numeric characters
reg := regexp.MustCompile("[^0-9]+")
numeric := reg.ReplaceAllString(strings.Split(version, "-")[0], "")

// Convert version string to integer
integer, err := strconv.Atoi(numeric)
if err != nil {
return -1
}

return integer
}
25 changes: 21 additions & 4 deletions input/traybinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package input
import (
"fmt"
"os"
"os/exec"
"strings"
"time"

Expand Down Expand Up @@ -56,13 +57,29 @@ func items(tr *desktop.Tracker) {
systray.SetTooltip(fmt.Sprintf("%s - tiling manager", common.Build.Name))
systray.SetTitle(common.Build.Name)

// Version section
// Version checker
latest := common.VersionToInt(common.Build.Latest)
current := common.VersionToInt(common.Build.Version)
title := fmt.Sprintf("%s v%s", common.Build.Name, common.Build.Version)
if latest > current {
title = fmt.Sprintf("%s (v%s available)", title, common.Build.Latest)
}
version := systray.AddMenuItem(title, title)
version.SetIcon(common.File.Icon)
version.Disable()

// Menu section
// Menu item hyperlink
if latest > current {
go func() {
for {
<-version.ClickedCh
exec.Command("xdg-open", common.Build.Source).Start()
}
}()
} else {
version.Disable()
}

// Menu items
menu = &Menu{}
systray.AddSeparator()
for _, m := range common.Config.TilingIcon {
Expand Down Expand Up @@ -91,7 +108,7 @@ func items(tr *desktop.Tracker) {
menu.Toggle = item
}

// Menu item clicked
// Menu item action
go func() {
for {
<-item.ClickedCh
Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ var (

// Build date
date = "unknown"

// Build source
source = "https://github.com/leukipp/cortile"
)

var (
Expand All @@ -46,7 +49,7 @@ var (
func main() {

// Init command line arguments
common.InitArgs(name, version, commit, date)
common.InitArgs(name, version, commit, date, source)

// Init embedded files
common.InitFiles(toml, icon)
Expand Down
48 changes: 31 additions & 17 deletions ui/icon.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func UpdateIcon(ws *desktop.Workspace) {
}

// Initialize image
color := image.Uniform{rgba("icon_foreground")}
col := image.Uniform{rgba("icon_foreground")}
icon := image.NewRGBA(image.Rect(0, 0, iconSize, iconSize))

// Draw background rectangle
Expand All @@ -45,27 +45,41 @@ func UpdateIcon(ws *desktop.Workspace) {
// Draw layout rectangles
switch name {
case "fullscreen":
draw.Draw(icon, image.Rect(x0, y0, x1, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x1, y1), &col, image.Point{}, draw.Src)
case "vertical-left":
draw.Draw(icon, image.Rect(x0, y0, x0+(x1-x0)/2-layoutMargin, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0, x1, y0+(y1-y0)/2-layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0+(y1-y0)/2+layoutMargin, x1, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x0+(x1-x0)/2-layoutMargin, y1), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0, x1, y0+(y1-y0)/2-layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0+(y1-y0)/2+layoutMargin, x1, y1), &col, image.Point{}, draw.Src)
case "vertical-right":
draw.Draw(icon, image.Rect(x0, y0, x0+(x1-x0)/2-layoutMargin, y0+(y1-y0)/2-layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0+(y1-y0)/2+layoutMargin, x0+(x1-x0)/2-layoutMargin, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0, x1, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x0+(x1-x0)/2-layoutMargin, y0+(y1-y0)/2-layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0+(y1-y0)/2+layoutMargin, x0+(x1-x0)/2-layoutMargin, y1), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0, x1, y1), &col, image.Point{}, draw.Src)
case "horizontal-top":
draw.Draw(icon, image.Rect(x0, y0, x1, y0+(y1-y0)/2-layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0+(y1-y0)/2+layoutMargin, x0+(x1-x0)/2-layoutMargin, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0+(y1-y0)/2+layoutMargin, x1, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x1, y0+(y1-y0)/2-layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0+(y1-y0)/2+layoutMargin, x0+(x1-x0)/2-layoutMargin, y1), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0+(y1-y0)/2+layoutMargin, x1, y1), &col, image.Point{}, draw.Src)
case "horizontal-bottom":
draw.Draw(icon, image.Rect(x0, y0, x0+(x1-x0)/2-layoutMargin, y0+(y1-y0)/2-layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0, x1, y0+(y1-y0)/2-layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0+(y1-y0)/2+layoutMargin, x1, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x0+(x1-x0)/2-layoutMargin, y0+(y1-y0)/2-layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+(x1-x0)/2+layoutMargin, y0, x1, y0+(y1-y0)/2-layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0+(y1-y0)/2+layoutMargin, x1, y1), &col, image.Point{}, draw.Src)
case "disabled":
draw.Draw(icon, image.Rect(x0, y0, x0+2*layoutMargin, y1-2*layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x1-2*layoutMargin, y0+2*layoutMargin), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+2*layoutMargin+20, y0+2*layoutMargin+20, x1, y1), &color, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x0+2*layoutMargin, y1-2*layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0, y0, x1-2*layoutMargin, y0+2*layoutMargin), &col, image.Point{}, draw.Src)
draw.Draw(icon, image.Rect(x0+2*layoutMargin+20, y0+2*layoutMargin+20, x1, y1), &col, image.Point{}, draw.Src)
}

// Draw version checker
latest := common.VersionToInt(common.Build.Latest)
current := common.VersionToInt(common.Build.Version)
if latest > current {
col := image.Uniform{color.RGBA{
R: uint8(250),
G: uint8(80),
B: uint8(30),
A: uint8(255),
}}
dx, dy := iconSize/10, iconSize/10
draw.Draw(icon, image.Rect(x1-dx, y1-dy, x1+dx, y1+dy), &col, image.Point{}, draw.Src)
}

// Encode image bytes
Expand Down

0 comments on commit ac37679

Please sign in to comment.