feat(ui): команды, snapshots, Fyne-окно и интеграция (--noui)
Some checks failed
CI / test (pull_request) Failing after 1m19s
CI / build-and-package (amd64, linux) (pull_request) Failing after 58s
CI / build-and-package (amd64, windows) (pull_request) Successful in 53s

Команды (спец 12.2):
- ui.Commands: действия UI → текстовые команды канала (start/cancel/skip/
  retry/continue/approve/send), единый путь через chat.Channel.
- ui.Window = chat.Channel + View; NilWindow для headless/тестов.

Snapshots (спец 12.5):
- ui.Store: чтение-модель, возвращает только копии (ListTasks/GetTask/
  GetHistory/GetTraces); ui.DBStore поверх storage.

Fyne-окно (internal/ui/desktop, build-tag cgo):
- список задач слева, сплиты рабочей области и панели «Логи»/«Состояние»,
  ввод+кнопки команд, тёмная тема, fullscreen, сохранение layout в
  Preferences, сворачивание при закрытии крестиком.
- Колбэки View через fyne.Do (спец 12.4).

Интеграция:
- app.New(..., noUI); флаг --noui; UI собирается только с cgo (ui_cgo/
  ui_noui фабрики), приложение headless без него.
- Run: окно блокирует главную горутину; «Завершить» → cancel → graceful
  shutdown (спец 12.6).
- go.mod: fyne.io/fyne/v2 v2.6.0 (direct).
This commit is contained in:
ki.sagidullin
2026-08-20 08:54:55 +05:00
parent baf2ad7147
commit c2272137b3
17 changed files with 1056 additions and 18 deletions

View File

@@ -21,7 +21,7 @@ func TestNew(t *testing.T) {
t.Setenv("RATATOSKR_DB", dbPath)
// Загружаем без config-файла (дефолты + env)
a, err := New("", "dev", "")
a, err := New("", "dev", "", true)
if err != nil {
t.Fatalf("New() err = %v", err)
}
@@ -52,7 +52,7 @@ func TestNew_MissingToken(t *testing.T) {
t.Setenv("TG_CHAT_ID", "12345")
t.Setenv("RATATOSKR_DB", dbPath)
_, err := New("", "dev", "")
_, err := New("", "dev", "", true)
if err == nil {
t.Fatal("expected error for missing token")
}
@@ -67,7 +67,7 @@ func TestNew_BadDB(t *testing.T) {
t.Setenv("TG_CHAT_ID", "12345")
t.Setenv("RATATOSKR_DB", dbPath)
_, err := New("", "dev", "")
_, err := New("", "dev", "", true)
if err == nil {
t.Fatal("expected error for invalid db path")
}
@@ -84,7 +84,7 @@ func TestNew_RunCtxCancel(t *testing.T) {
t.Setenv("TG_CHAT_ID", "12345")
t.Setenv("RATATOSKR_DB", dbPath)
a, err := New("", "dev", "")
a, err := New("", "dev", "", true)
if err != nil {
t.Fatalf("New() err = %v", err)
}
@@ -130,7 +130,7 @@ func TestNew_WorktreeCreated(t *testing.T) {
t.Fatalf("write config: %v", err)
}
a, err := New(configPath, "dev", "")
a, err := New(configPath, "dev", "", true)
if err != nil {
t.Fatalf("New() err = %v", err)
}
@@ -175,7 +175,7 @@ func TestNew_UpdateWiring(t *testing.T) {
}
// 1) base_url из update-блока, а НЕ git
a, err := New(configPath, "dev", "")
a, err := New(configPath, "dev", "", true)
if err != nil {
t.Fatalf("New() err = %v", err)
}
@@ -196,7 +196,7 @@ func TestNew_UpdateWiring(t *testing.T) {
}
// 2) вшитый updateToken перекрывает конфиг
a2, err := New(configPath, "dev", "embedded-update-token")
a2, err := New(configPath, "dev", "embedded-update-token", true)
if err != nil {
t.Fatalf("New() err = %v", err)
}
@@ -248,4 +248,4 @@ func TestVersion_Semver(t *testing.T) {
if !re.MatchString(Version) {
t.Errorf("Version = %q, ожидался формат major.minor.patch", Version)
}
}
}