Release version 0.2.3
Improve the History tab by keeping records in chronological order, rendering them as a compact table, and allowing the Time column to toggle ascending or descending order. Use the native Fyne table header so users can resize columns, including Detail and Log, and show only the log file name instead of the full log path. Bump the application version to 0.2.3 and update README artifact examples plus docs/CHANGELOG.md.
This commit is contained in:
@@ -86,7 +86,7 @@ The binary is written to:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
# GUI executable produced by scripts\build-windows.bat.
|
# GUI executable produced by scripts\build-windows.bat.
|
||||||
dist\windows\pysentry-0.2.2-windows-amd64.exe
|
dist\windows\pysentry-0.2.3-windows-amd64.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
@@ -101,7 +101,7 @@ The binary is written to:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
# Linux executable produced by scripts/build-linux.sh.
|
# Linux executable produced by scripts/build-linux.sh.
|
||||||
dist/linux/pysentry-0.2.2-linux-amd64
|
dist/linux/pysentry-0.2.3-linux-amd64
|
||||||
```
|
```
|
||||||
|
|
||||||
Linux using Docker:
|
Linux using Docker:
|
||||||
@@ -118,7 +118,7 @@ The binary is copied to:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
# Linux executable copied out of the Docker build image.
|
# Linux executable copied out of the Docker build image.
|
||||||
dist\linux\pysentry-0.2.2-linux-amd64
|
dist\linux\pysentry-0.2.3-linux-amd64
|
||||||
```
|
```
|
||||||
|
|
||||||
Release build from Linux:
|
Release build from Linux:
|
||||||
@@ -143,13 +143,13 @@ The binaries are copied to:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
# Linux artifact.
|
# Linux artifact.
|
||||||
dist/linux/pysentry-0.2.2-linux-amd64
|
dist/linux/pysentry-0.2.3-linux-amd64
|
||||||
|
|
||||||
# Linux arm64 artifact.
|
# Linux arm64 artifact.
|
||||||
dist/linux/pysentry-0.2.2-linux-arm64
|
dist/linux/pysentry-0.2.3-linux-arm64
|
||||||
|
|
||||||
# Windows artifact cross-compiled from Linux.
|
# Windows artifact cross-compiled from Linux.
|
||||||
dist/windows/pysentry-0.2.2-windows-amd64.exe
|
dist/windows/pysentry-0.2.3-windows-amd64.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run From Source
|
## Run From Source
|
||||||
@@ -292,7 +292,7 @@ Linux:
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
Type=Application
|
Type=Application
|
||||||
Name=PySentry
|
Name=PySentry
|
||||||
Exec=/opt/pysentry/pysentry-0.2.2-linux-amd64
|
Exec=/opt/pysentry/pysentry-0.2.3-linux-amd64
|
||||||
Terminal=false
|
Terminal=false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
All notable PySentry changes are recorded in this file.
|
All notable PySentry changes are recorded in this file.
|
||||||
|
|
||||||
|
## 0.2.3 - 2026-06-15
|
||||||
|
|
||||||
|
- Changed History to use chronological ordering with new records appended at the bottom.
|
||||||
|
- Replaced the History list with a compact table.
|
||||||
|
- Added Time column sorting in both ascending and descending directions.
|
||||||
|
- Made History table columns user-resizable through the native Fyne table header.
|
||||||
|
- Shortened the Log column display to file names instead of full paths.
|
||||||
|
- Unified UI event timestamps with command run timestamps.
|
||||||
|
|
||||||
## 0.2.2 - 2026-06-15
|
## 0.2.2 - 2026-06-15
|
||||||
|
|
||||||
- Added Linux desktop integration that installs a user-level `.desktop` file and icon so taskbars can match the running window to the PySentry icon.
|
- Added Linux desktop integration that installs a user-level `.desktop` file and icon so taskbars can match the running window to the PySentry icon.
|
||||||
|
|||||||
+1
-1
@@ -3,4 +3,4 @@ package core
|
|||||||
// Version is the application version shown in the GUI and used by build
|
// Version is the application version shown in the GUI and used by build
|
||||||
// scripts in artifact names. It is a var rather than a const so release builds
|
// scripts in artifact names. It is a var rather than a const so release builds
|
||||||
// can override it with Go ldflags when CI tags a build.
|
// can override it with Go ldflags when CI tags a build.
|
||||||
var Version = "0.2.2"
|
var Version = "0.2.3"
|
||||||
|
|||||||
+64
-13
@@ -620,9 +620,34 @@ func showJobDialog(w fyne.Window, title string, current job, onSave func(job)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newHistoryView(events *[]event) *fyne.Container {
|
func newHistoryView(events *[]event) *fyne.Container {
|
||||||
|
descending := false
|
||||||
|
headerText := func(id widget.TableCellID) string {
|
||||||
|
headers := []string{"Time", "Trigger", "Job", "State", "Detail", "Log"}
|
||||||
|
if id.Row < 0 && id.Col == 0 {
|
||||||
|
if descending {
|
||||||
|
return "Time desc"
|
||||||
|
}
|
||||||
|
return "Time asc"
|
||||||
|
}
|
||||||
|
if id.Row < 0 && id.Col >= 0 && id.Col < len(headers) {
|
||||||
|
return headers[id.Col]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
sortedEvents := func() []event {
|
||||||
|
result := append([]event(nil), (*events)...)
|
||||||
|
sort.SliceStable(result, func(left int, right int) bool {
|
||||||
|
if descending {
|
||||||
|
return result[left].Time > result[right].Time
|
||||||
|
}
|
||||||
|
return result[left].Time < result[right].Time
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
table := widget.NewTable(
|
table := widget.NewTable(
|
||||||
func() (int, int) {
|
func() (int, int) {
|
||||||
return len(*events) + 1, 6
|
return len(*events), 6
|
||||||
},
|
},
|
||||||
func() fyne.CanvasObject {
|
func() fyne.CanvasObject {
|
||||||
label := widget.NewLabel("")
|
label := widget.NewLabel("")
|
||||||
@@ -631,30 +656,44 @@ func newHistoryView(events *[]event) *fyne.Container {
|
|||||||
},
|
},
|
||||||
func(id widget.TableCellID, item fyne.CanvasObject) {
|
func(id widget.TableCellID, item fyne.CanvasObject) {
|
||||||
label := item.(*widget.Label)
|
label := item.(*widget.Label)
|
||||||
label.SetText(historyCellText(id, *events))
|
label.SetText(historyCellText(id, sortedEvents()))
|
||||||
label.TextStyle = fyne.TextStyle{Bold: id.Row == 0}
|
label.TextStyle = fyne.TextStyle{}
|
||||||
label.Refresh()
|
label.Refresh()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
table.ShowHeaderRow = true
|
||||||
|
table.CreateHeader = func() fyne.CanvasObject {
|
||||||
|
label := widget.NewLabel("")
|
||||||
|
label.Wrapping = fyne.TextTruncate
|
||||||
|
return label
|
||||||
|
}
|
||||||
|
table.UpdateHeader = func(id widget.TableCellID, item fyne.CanvasObject) {
|
||||||
|
label := item.(*widget.Label)
|
||||||
|
label.SetText(headerText(id))
|
||||||
|
label.TextStyle = fyne.TextStyle{Bold: true}
|
||||||
|
label.Refresh()
|
||||||
|
}
|
||||||
|
table.OnSelected = func(id widget.TableCellID) {
|
||||||
|
if id.Row < 0 && id.Col == 0 {
|
||||||
|
descending = !descending
|
||||||
|
table.Refresh()
|
||||||
|
}
|
||||||
|
table.Unselect(id)
|
||||||
|
}
|
||||||
table.SetColumnWidth(0, 150)
|
table.SetColumnWidth(0, 150)
|
||||||
table.SetColumnWidth(1, 90)
|
table.SetColumnWidth(1, 90)
|
||||||
table.SetColumnWidth(2, 170)
|
table.SetColumnWidth(2, 170)
|
||||||
table.SetColumnWidth(3, 90)
|
table.SetColumnWidth(3, 90)
|
||||||
table.SetColumnWidth(4, 360)
|
table.SetColumnWidth(4, 260)
|
||||||
table.SetColumnWidth(5, 320)
|
table.SetColumnWidth(5, 240)
|
||||||
return container.NewPadded(table)
|
return container.NewPadded(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
func historyCellText(id widget.TableCellID, events []event) string {
|
func historyCellText(id widget.TableCellID, events []event) string {
|
||||||
headers := []string{"Time", "Trigger", "Job", "State", "Detail", "Log"}
|
if id.Row < 0 || id.Row >= len(events) {
|
||||||
if id.Row == 0 {
|
|
||||||
return headers[id.Col]
|
|
||||||
}
|
|
||||||
eventIndex := id.Row - 1
|
|
||||||
if eventIndex < 0 || eventIndex >= len(events) {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
current := events[eventIndex]
|
current := events[id.Row]
|
||||||
trigger := current.Trigger
|
trigger := current.Trigger
|
||||||
if trigger == "" {
|
if trigger == "" {
|
||||||
trigger = "Unknown"
|
trigger = "Unknown"
|
||||||
@@ -671,12 +710,24 @@ func historyCellText(id widget.TableCellID, events []event) string {
|
|||||||
case 4:
|
case 4:
|
||||||
return current.Detail
|
return current.Detail
|
||||||
case 5:
|
case 5:
|
||||||
return current.LogFile
|
return logFileName(current.LogFile)
|
||||||
default:
|
default:
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logFileName(path string) string {
|
||||||
|
path = strings.TrimSpace(path)
|
||||||
|
if path == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
path = strings.ReplaceAll(path, "\\", "/")
|
||||||
|
if slash := strings.LastIndex(path, "/"); slash >= 0 {
|
||||||
|
return path[slash+1:]
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
func settingsView(w fyne.Window, store *core.Store, jobs *[]job) fyne.CanvasObject {
|
func settingsView(w fyne.Window, store *core.Store, jobs *[]job) fyne.CanvasObject {
|
||||||
startOnLogin := widget.NewCheck("Start PySentry when I sign in", nil)
|
startOnLogin := widget.NewCheck("Start PySentry when I sign in", nil)
|
||||||
startOnLogin.SetChecked(store.Config.StartOnLogin)
|
startOnLogin.SetChecked(store.Config.StartOnLogin)
|
||||||
|
|||||||
Reference in New Issue
Block a user