Команды (спец 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).
74 lines
2.4 KiB
Go
74 lines
2.4 KiB
Go
package ui
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/kamelion/ratatoskr-go/internal/storage"
|
|
)
|
|
|
|
// Store — абстракция чтения-модели для UI (спец 12.5).
|
|
//
|
|
// Возвращает только копии (value-типы), никогда — живые указатели на
|
|
// разделяемые контейнеры core/БД. UI читает снимки и реагирует на события;
|
|
// мутирует состояние только Core.
|
|
type Store interface {
|
|
// ListTasks возвращает все задачи (копии), сортировка по updated_at desc.
|
|
ListTasks(ctx context.Context) ([]storage.Task, error)
|
|
// GetTask возвращает задачу по ID (копию).
|
|
GetTask(ctx context.Context, id int64) (storage.Task, error)
|
|
// GetHistory возвращает историю диалога задачи (копии).
|
|
GetHistory(ctx context.Context, id int64) ([]storage.HistoryMsg, error)
|
|
// GetTraces возвращает трассы задачи (копии).
|
|
GetTraces(ctx context.Context, id int64) ([]storage.Trace, error)
|
|
}
|
|
|
|
// DBStore — реализация Store поверх *storage.Storage (БД).
|
|
type DBStore struct {
|
|
s *storage.Storage
|
|
}
|
|
|
|
// NewDBStore создаёт DBStore на основе БД.
|
|
func NewDBStore(s *storage.Storage) *DBStore {
|
|
return &DBStore{s: s}
|
|
}
|
|
|
|
// ListTasks реализует Store: deref-копии записей, без указателей.
|
|
func (d *DBStore) ListTasks(ctx context.Context) ([]storage.Task, error) {
|
|
rows, err := d.s.ListTasks(ctx, storage.TaskFilter{Limit: 200})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out := make([]storage.Task, 0, len(rows))
|
|
for _, r := range rows {
|
|
out = append(out, *r)
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// GetTask реализует Store.
|
|
func (d *DBStore) GetTask(ctx context.Context, id int64) (storage.Task, error) {
|
|
t, err := d.s.GetTask(ctx, id)
|
|
if err != nil {
|
|
return storage.Task{}, err
|
|
}
|
|
return *t, nil
|
|
}
|
|
|
|
// GetHistory реализует Store.
|
|
func (d *DBStore) GetHistory(ctx context.Context, id int64) ([]storage.HistoryMsg, error) {
|
|
return d.s.GetHistory(ctx, id)
|
|
}
|
|
|
|
// GetTraces реализует Store.
|
|
func (d *DBStore) GetTraces(ctx context.Context, id int64) ([]storage.Trace, error) {
|
|
rows, err := d.s.GetTraces(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out := make([]storage.Trace, 0, len(rows))
|
|
for _, r := range rows {
|
|
out = append(out, *r)
|
|
}
|
|
return out, nil
|
|
}
|