Skip to content

Commit 04ac08d

Browse files
committed
Add version checking and update notification feature
- Introduced version management with a new version package. - Implemented update check functionality in the model. - Updated import paths to reflect the new module structure. - Enhanced README with build and run instructions for different platforms.
1 parent f86b3f2 commit 04ac08d

File tree

5 files changed

+133
-17
lines changed

5 files changed

+133
-17
lines changed

README.md

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Golter
22

3+
![Logo](https://golter.sametcc.me/opengraph-image)
4+
35
Terminal-based file converter built with Go. It provides a modern, user-friendly Terminal User Interface (TUI) for batch converting images, videos, audio, and documents between various formats.
46

57
## Features
@@ -128,6 +130,8 @@ sudo pacman -S ffmpeg
128130

129131
# Build
130132
go build -o golter main.go
133+
134+
# Run
131135
./golter
132136
```
133137

@@ -137,8 +141,13 @@ go build -o golter main.go
137141
<summary><b>macOS</b></summary>
138142

139143
```bash
144+
# Install ffmpeg
140145
brew install ffmpeg
146+
147+
# Build
141148
go build -o golter main.go
149+
150+
# Run
142151
./golter
143152
```
144153

@@ -156,6 +165,8 @@ choco install ffmpeg
156165
157166
# Build
158167
go build -o golter.exe main.go
168+
169+
# Run
159170
.\golter.exe
160171
```
161172

@@ -194,19 +205,6 @@ Start in a specific directory:
194205
| `Esc` | Go back / Cancel |
195206
| `q` | Quit application |
196207

197-
### Workflow
198-
199-
1. **Navigate:** Browse your file system using arrow keys or Vim bindings
200-
2. **Select:** Press `Space` to mark files (files must be of the same type)
201-
3. **Confirm:** Press `c` when done selecting files
202-
4. **Choose Action:**
203-
- **Convert Format:** Change file format (e.g., JPG → PNG)
204-
- **Compress Files:** Reduce size while keeping format
205-
5. **Configure:**
206-
- **Convert:** Select target format
207-
- **Compress:** Choose quality level
208-
6. **Process:** Watch the progress as files are converted concurrently
209-
210208
## License
211209

212210
[GPL-3.0](LICENSE)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module golter
1+
module github.com/sametcn99/golter
22

33
go 1.24.4
44

internal/tui/model.go

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import (
99
"sync/atomic"
1010
"time"
1111

12-
"golter/internal/converter"
12+
"github.com/sametcn99/golter/internal/converter"
13+
"github.com/sametcn99/golter/internal/version"
1314

1415
"github.com/charmbracelet/bubbles/progress"
1516
"github.com/charmbracelet/bubbles/spinner"
@@ -72,6 +73,13 @@ type progressMsg struct {
7273

7374
type tickMsg time.Time
7475

76+
type checkUpdateMsg struct {
77+
latest string
78+
url string
79+
available bool
80+
err error
81+
}
82+
7583
// Model represents the main application model
7684
type Model struct {
7785
state State
@@ -96,6 +104,9 @@ type Model struct {
96104
width int
97105
height int
98106
startTime time.Time
107+
latestVersion string
108+
updateUrl string
109+
updateAvailable bool
99110
}
100111

101112
// NewModel creates a new Model with initial configuration
@@ -165,9 +176,15 @@ func statFile(path string) (os.FileInfo, error) {
165176
func (m Model) Init() tea.Cmd {
166177
return tea.Batch(
167178
m.spinner.Tick,
179+
checkUpdatesCmd,
168180
)
169181
}
170182

183+
func checkUpdatesCmd() tea.Msg {
184+
latest, url, available, err := version.CheckForUpdates()
185+
return checkUpdateMsg{latest, url, available, err}
186+
}
187+
171188
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
172189
switch msg := msg.(type) {
173190
case tea.WindowSizeMsg:
@@ -304,6 +321,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
304321
var cmd tea.Cmd
305322
m.spinner, cmd = m.spinner.Update(msg)
306323
return m, cmd
324+
325+
case checkUpdateMsg:
326+
if msg.err == nil && msg.available {
327+
m.latestVersion = msg.latest
328+
m.updateUrl = msg.url
329+
m.updateAvailable = true
330+
}
331+
return m, nil
307332
}
308333

309334
// State-specific handling
@@ -511,7 +536,13 @@ func (m Model) View() string {
511536
var s strings.Builder
512537

513538
// Header with branding
514-
header := headerStyle.Render(" " + iconConvert + " Golter - File Converter ")
539+
versionInfo := fmt.Sprintf(" v%s", version.Current)
540+
if m.updateAvailable {
541+
linkText := fmt.Sprintf("(Update available: v%s)", m.latestVersion)
542+
link := fmt.Sprintf("\x1b]8;;%s\x1b\\%s\x1b]8;;\x1b\\", m.updateUrl, linkText)
543+
versionInfo += " " + link
544+
}
545+
header := headerStyle.Render(" " + iconConvert + " Golter - File Converter" + versionInfo + " ")
515546
s.WriteString("\n" + header + "\n\n")
516547

517548
switch m.state {

internal/version/version.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package version
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"strconv"
8+
"strings"
9+
"time"
10+
)
11+
12+
// Current represents the current version of the application
13+
const (
14+
Current = "0.1.1"
15+
Repo = "sametcn99/golter"
16+
)
17+
18+
type Release struct {
19+
TagName string `json:"tag_name"`
20+
HTMLURL string `json:"html_url"`
21+
}
22+
23+
// CheckForUpdates checks GitHub for the latest release
24+
// Returns latest version string, release URL, true if update available, and error if any
25+
func CheckForUpdates() (string, string, bool, error) {
26+
url := fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", Repo)
27+
client := http.Client{
28+
Timeout: 2 * time.Second,
29+
}
30+
31+
resp, err := client.Get(url)
32+
if err != nil {
33+
return "", "", false, err
34+
}
35+
defer resp.Body.Close()
36+
37+
if resp.StatusCode != http.StatusOK {
38+
return "", "", false, fmt.Errorf("API responded with status %d", resp.StatusCode)
39+
}
40+
41+
var release Release
42+
if err := json.NewDecoder(resp.Body).Decode(&release); err != nil {
43+
return "", "", false, err
44+
}
45+
46+
latest := strings.TrimPrefix(release.TagName, "v")
47+
current := strings.TrimPrefix(Current, "v")
48+
49+
if isNewer(current, latest) {
50+
return latest, release.HTMLURL, true, nil
51+
}
52+
53+
return latest, "", false, nil
54+
}
55+
56+
// isNewer returns true if v2 is newer than v1
57+
// Assumes semantic versioning (x.y.z)
58+
func isNewer(v1, v2 string) bool {
59+
p1 := strings.Split(v1, ".")
60+
p2 := strings.Split(v2, ".")
61+
62+
len1 := len(p1)
63+
len2 := len(p2)
64+
maxLen := len1
65+
if len2 > maxLen {
66+
maxLen = len2
67+
}
68+
69+
for i := 0; i < maxLen; i++ {
70+
var n1, n2 int
71+
if i < len1 {
72+
n1, _ = strconv.Atoi(p1[i])
73+
}
74+
if i < len2 {
75+
n2, _ = strconv.Atoi(p2[i])
76+
}
77+
78+
if n2 > n1 {
79+
return true
80+
}
81+
if n1 > n2 {
82+
return false
83+
}
84+
}
85+
86+
return false
87+
}

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"fmt"
55
"os"
66

7-
"golter/internal/tui"
7+
"github.com/sametcn99/golter/internal/tui"
88

99
tea "github.com/charmbracelet/bubbletea"
1010
)

0 commit comments

Comments
 (0)