feat: настройки Browser Bridge в Verstak и extension

Verstak (GUI):
- SettingsBrowserBridge.svelte — новая секция в Settings:
  toggle вкл/выкл сервера, поле порта (default 9786),
  статус (Запущен/Остановлен), кнопки Сохранить/Перезапустить
- SettingsWindow + SettingsSidebar — подключена секция browserBridge
- BridgeConfig: добавлено поле Enabled (default true)
- RestartBridge() — новый биндинг для перезапуска сервера
- initVault: проверяет bc.Enabled перед запуском bridge

Extension (Chrome + Firefox):
- popup: панель настроек с полем порта (default 9786)
- кнопка «Проверить» — fetch /api/ping с таймаутом 3с
- кнопка «Сохранить» — сохраняет port в chrome.storage.local
- статус соединения: ✓ Сервер отвечает / ✗ Недоступен / ✗ Таймаут
- оба расширения работают только с 127.0.0.1
This commit is contained in:
2026-06-07 01:03:35 +08:00
parent 1cc0c407b1
commit 8cbc87cdad
12 changed files with 840 additions and 101 deletions
+57
View File
@@ -1,6 +1,7 @@
package main
import (
"fmt"
"log"
"verstak/internal/core/bridge"
@@ -112,3 +113,59 @@ func bridgeToBrowser(ev bridge.Event) browser.Event {
Note: ev.Note,
}
}
// RestartBridge stops and restarts the bridge server with current config.
func (a *App) RestartBridge() error {
a.mu.Lock()
defer a.mu.Unlock()
// Stop existing server
if a.bridge != nil {
a.bridge.Stop()
a.bridge = nil
}
// Load config
appCfg, err := config.LoadAppConfig()
if err != nil || appCfg == nil {
appCfg = config.DefaultAppConfig()
}
bc := a.bridgeConfig(appCfg)
if !bc.Enabled {
return nil
}
handler := func(events []bridge.Event) {
be := make([]browser.Event, 0, len(events))
for _, ev := range events {
be = append(be, bridgeToBrowser(ev))
}
n, err := a.browser.InsertEvents(be)
if err != nil {
log.Printf("[bridge] store events: %v", err)
return
}
if n > 0 {
log.Printf("[bridge] stored %d/%d events", n, len(be))
}
}
srv := bridge.NewServer(bridge.Config{
Port: bc.Port,
Secret: bc.Secret,
}, handler)
port, err := srv.Start(bridge.Config{
Port: bc.Port,
AutoGenPort: bc.AutoGenPort,
Secret: bc.Secret,
})
if err != nil {
return fmt.Errorf("bridge restart: %w", err)
}
a.bridge = srv
log.Printf("[bridge] restarted on port %d", port)
return nil
}
+6 -2
View File
@@ -284,8 +284,12 @@ func (a *App) initVault(vaultPath string) error {
// Start auto-sync loop
go a.autoSyncLoop()
// Start bridge server for browser extension integration.
a.startBridge(appCfg)
// Start bridge server for browser extension integration (if enabled).
if appCfg == nil || appCfg.Vault.Bridge.Enabled {
a.startBridge(appCfg)
} else {
log.Println("[bridge] disabled by config")
}
return nil
}