fix: tab highlight reactivity, cleanup docs and build scripts

- Fix tab highlight not updating visually — switch from class={tabClass()}
  to Svelte's class:active directive for proper reactive class binding
- Rewrite README.md with full project structure, architecture, build guide
- Rewrite build.sh to build both GUI and server, output to build/
- Add scripts/build.sh for granular builds (gui/server/all)
- Add build/, frontend-dist/, and test vault dirs to .gitignore
- Remove stale binaries from project root
- Update AGENTS.md session summary
This commit is contained in:
mirivlad 2026-06-03 05:08:58 +08:00
parent 105657400b
commit b6a3a2238d
9 changed files with 228 additions and 43 deletions

6
.gitignore vendored
View File

@ -20,6 +20,7 @@ go.work
# Wails
frontend/dist/
frontend/frontend-dist/
frontend/node_modules/
frontend/bindings/
/verstak-gui
@ -42,3 +43,8 @@ Thumbs.db
# Vault test data
test-vault/
server-data/
Ромашка/
Тестовая папка/
# Build output
build/

View File

@ -1,3 +1,14 @@
# Session summary
## Bugs fixed (this session)
1. **webkit2_41 build tag** — binary wouldn't start without it. Added to build instructions.
2. **Sidebar refresh**`reloadTreePreservingExpanded` patches children in-place so expand/collapse state stays intact.
3. **Context menu off-screen** — changed to `position: fixed` with cursor coordinates.
4. **"Show in explorer" only for folder types** — `OpenFolder` in backend falls back to file record path for `TypeFile` nodes.
5. **Context menu not closing on action**`handleShowInFolder` calls `closeMenu()`.
6. **Wrong folder when opening file's parent folder**`OpenFolder` checks `n.FsPath == ""` for TypeFile and uses first file record path.
7. **Tab highlight not updating visually** — was using `class={tabClass(tab.id)}` which didn't trigger reactive class updates in Svelte. Switched to `class="tab" class:active={activeTab === tab.id}`.
# Build instructions
## GUI binary (Wails v2)

183
README.md
View File

@ -1,46 +1,155 @@
# Верстак
**Верстак** — локальная программа, где по каждому клиенту или проекту
лежат все его файлы, заметки, документы, ссылки, действия и история работ.
**Верстак** — local-first рабочий vault. Всё организовано вокруг **дел**, а не задач.
Это не замечатель, не CRM, не таск-трекер. **Нишевая аудитория** — люди,
у которых работа организована через дела, а не через задачи:
```
дело → файлы → заметки → документы → действия → история → вернуться через месяц
```
## Для кого
Один продукт — разные входные двери:
| Кто | Как видит Верстак |
|-----|-------------------|
| Фрилансер / дизайнер | клиентские проекты, файлы, правки, история работ |
| Мастер по ПК | клиенты, устройства, серийники, фото, журнал |
| Разработчик | локальный workspace: заметки, репы, команды, файлы |
| Писатель / мейкер | мастерская проектов: материалы, заметки, версии, история |
## Универсальные сущности
Базовая модель предельно проста — плагины добавляют функционал:
- **Дело** — контекст для всего остального
- **Заметка** — Markdown внутри vault
- **Файл / Документ** — любой файл, привязанный к делу
- **Действие** — кнопка запуска: URL, файл, папка, команда
- **Журнал** — записи о затраченном времени
Плагины (шаблоны дел, календарь, канбан, импортёры) расширяют
эти сущности без перекомпиляции программы.
Дело может быть: клиентом, проектом, набором документов, рецептом, архивом, разовой работой.
Внутри дела: вложенные папки, Markdown-заметки, файлы, действия (URL/файл/папка/команда), журнал работ, история активности.
## Стек
Go + SQLite + Lua (плагины) + Wails + Bubble Tea.
| Слой | Технология |
|------|------------|
| GUI | Wails v2 + Svelte 4 |
| CLI/TUI | Go (bubbletea-like) |
| Backend | Go |
| Хранилище | SQLite (индекс) + файловая система (vault) |
| Плагины | Lua |
| Синхронизация | HTTP API (опциональный сервер) |
## Архитектура
```
┌────────────────────┐
│ GUI (Wails v2) │
└─────────┬──────────┘
┌─────────▼────────┐ ┌─────────────┐
│ Core Library │◄──│ CLI Commands │
└─────────┬────────┘ └─────────────┘
┌─────────▼──────────┐
│ Local Vault+SQLite │
└─────────┬──────────┘
┌─────────▼──────────┐
│ Sync Client │
└─────────┬──────────┘
┌─────────▼──────────┐
│ Sync Server │
└────────────────────┘
```
## Быстрый старт
### Требования
- Go 1.25+
- Node.js 20+
- libwebkit2gtk-4.1-dev, libgtk-3-dev и другие Wails-зависимости (см. [wails.io/docs/desktop/linux](https://wails.io/docs/desktop/linux))
- npm
### Сборка
```bash
# Всё сразу (GUI + сервер)
./build.sh
# Или по отдельности
./scripts/build.sh gui # только GUI
./scripts/build.sh server # только сервер
```
Бинарники попадают в `build/`:
- `verstak-gui-linux-amd64` — GUI-приложение
- `verstak-server-linux-amd64` — опциональный сервер синхронизации
### Запуск
```bash
# GUI (после сборки)
./build/verstak-gui-linux-amd64
# Сервер (после сборки)
./build/verstak-server-linux-amd64 --help
# CLI
go run ./cmd/verstak/ --help
```
## Структура проекта
```
.
├── cmd/ # Точки входа
│ ├── verstak/ # CLI/TUI
│ ├── verstak-gui/ # Wails GUI
│ └── verstak-server/ # Sync server
├── internal/
│ ├── core/ # Бизнес-логика
│ │ ├── actions/ # Действия (URL, папка, команда)
│ │ ├── config/ # Конфигурация
│ │ ├── files/ # Файлы и импорт
│ │ ├── i18n/ # Интернационализация (Go)
│ │ ├── nodes/ # Дела/узлы дерева
│ │ ├── plugins/ # Lua-плагины
│ │ ├── search/ # Поиск
│ │ ├── storage/ # SQLite + миграции
│ │ ├── sync/ # Синхронизация
│ │ ├── templates/ # Шаблоны дел
│ │ ├── vault/ # Vault layout
│ │ └── worklog/ # Журнал работ
│ └── gui/ # Wails bridge (embedded HTML)
├── frontend/ # Svelte-приложение
│ └── src/
│ ├── lib/
│ │ └── i18n/ # Локали (JS)
│ └── ...svelte # Компоненты
├── migrations/ # SQL-миграции
├── docs/ # Документация
├── build.sh # Скрипт полной сборки
└── scripts/ # Вспомогательные скрипты
```
## CLI команды
```bash
go run ./cmd/verstak/ sync # Синхронизация с сервером
go run ./cmd/verstak/ sync configure # Настройка сервера
go run ./cmd/verstak/ sync status # Статус синхронизации
```
## Vault layout
Данные хранятся в локальной папке (vault). Структура на диске:
```
vault/
.verstak/ # Служебные данные (БД, кеш, бэкапы)
Проекты/ # Пользовательские папки-дела
Клиенты/
Рабочие/
Archive/
```
Внутри папок-дел: `Notes/`, `Files/`, `Documents/`, `Overview.md`.
Vault открывается в любом файловом менеджере без специальных инструментов.
## Документация
- Описание продукта: [docs/01_Product_Spec.md](docs/01_Product_Spec.md)
- Архитектура: [docs/02_Architecture.md](docs/02_Architecture.md)
- Плагины: [docs/09_Extensibility.md](docs/09_Extensibility.md)
- План разработки: [docs/PLAN.md](docs/PLAN.md)
| Раздел | Описание |
|--------|----------|
| [Описание продукта](docs/01_Product_Spec.md) | Аудитория, сценарии, фичи |
| [Архитектура](docs/02_Architecture.md) | Компоненты, плагины, sync |
| [Модель данных](docs/03_Data_Model_Storage.md) | SQLite, vault, файлы |
| [Синхронизация](docs/04_Sync_Backup_Activity.md) | Sync, backup, activity |
| [UI/UX](docs/05_UI_UX.md) | Экраны GUI/TUI |
| [Плагины](docs/09_Extensibility.md) | Lua-плагины, шаблоны |
| [Сервер синхронизации](docs/10_Sync_Server_Guide.md) | Установка и настройка сервера |
| [Vault layout](docs/VAULT_LAYOUT.md) | Структура папок на диске |
| [План](docs/PLAN.md) | Дорожная карта |
| [Шаблоны](docs/TEMPLATES.md) | Шаблоны дел |
## Лицензия
MIT

View File

@ -9,6 +9,18 @@ elif [ -s "$HOME/.nvm/nvm.sh" ]; then
. "$HOME/.nvm/nvm.sh"
fi
BUILD_DIR="build"
mkdir -p "$BUILD_DIR"
echo "==> Building frontend..."
cd frontend && npm run build && cd ..
rm -rf cmd/verstak-gui/frontend-dist && cp -r frontend/dist cmd/verstak-gui/frontend-dist
go build -tags "gui production webkit2_41" -o verstak-gui ./cmd/verstak-gui
cp -r frontend/dist/* cmd/verstak-gui/frontend-dist/
echo "==> Building GUI binary..."
go build -tags "webkit2_41 desktop production" -ldflags="-s -w" -o "$BUILD_DIR/verstak-gui-linux-amd64" ./cmd/verstak-gui/
echo "==> Building server binary..."
go build -ldflags="-s -w" -o "$BUILD_DIR/verstak-server-linux-amd64" ./cmd/verstak-server/
echo "==> Done. Binaries in $BUILD_DIR/:"
ls -lh "$BUILD_DIR/"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -16,8 +16,8 @@
background: #13131f;
}
</style>
<script type="module" crossorigin src="/assets/main-CuGUigdf.js"></script>
<link rel="stylesheet" crossorigin href="/assets/main-D-hpY-IS.css">
<script type="module" crossorigin src="/assets/main-C54_blTe.js"></script>
<link rel="stylesheet" crossorigin href="/assets/main-CtXutc3Z.css">
</head>
<body>
<div id="app"></div>

View File

@ -972,7 +972,6 @@
}
// ===== Helpers =====
function tabClass(id) { return activeTab === id ? 'tab active' : 'tab' }
function eventLabel(type) {
const labels = {
'note_created': t('event.noteCreated'),
@ -1257,7 +1256,7 @@
<!-- Tabs -->
<div class="tabs">
{#each tabs as tab}
<button class={tabClass(tab.id)} on:click={() => { activeTab = tab.id; if (tab.id === 'files' && selectedNode && fileItems.length === 0 && !currentFolderId) loadFolder(selectedNode.id) }}>{tab.label}</button>
<button class="tab" class:active={activeTab === tab.id} on:click={() => { activeTab = tab.id; if (tab.id === 'files' && selectedNode && fileItems.length === 0 && !currentFolderId) loadFolder(selectedNode.id) }}>{tab.label}</button>
{/each}
</div>
<div class="tab-content">

44
scripts/build.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
set -e
# Individual build scripts
build_gui() {
echo "==> Building GUI binary..."
# Build frontend
cd frontend && npm run build && cd ..
# Copy frontend dist to Wails embed directory
cp -r frontend/dist/* cmd/verstak-gui/frontend-dist/
# Build Go binary with Wails v2
# Tags: webkit2_41 required for WebKitGTK 2.41+, desktop/production for Wails
go build -tags "webkit2_41 desktop production" -ldflags="-s -w" -o build/verstak-gui-linux-amd64 ./cmd/verstak-gui/
echo "==> GUI binary: build/verstak-gui-linux-amd64"
}
build_server() {
echo "==> Building server binary..."
go build -ldflags="-s -w" -o build/verstak-server-linux-amd64 ./cmd/verstak-server/
echo "==> Server binary: build/verstak-server-linux-amd64"
}
build_all() {
mkdir -p build
build_gui
build_server
echo "==> All binaries built."
ls -lh build/
}
case "${1:-all}" in
gui) build_gui ;;
server) build_server ;;
all) build_all ;;
*)
echo "Usage: $0 [gui|server|all]"
exit 1
;;
esac