1
0

fix: load FA locally instead of CDN; Alpine color input error via x-init+

This commit is contained in:
Maksim Totmin 2026-06-17 13:53:48 +07:00
parent 44ad064488
commit fe8ca312c4
15 changed files with 71 additions and 16 deletions

View File

@ -101,7 +101,7 @@ func Run(ctx context.Context, cfg *config.Config, opts RunOptions) error {
ssCtrl := NewScreensaver(&cfg.Screensaver)
ge := NewGestureEngine(cfg.Timing.LongPressMs, cfg.Timing.DoubleTapMs, func(a *config.Action) {
ge := NewGestureEngine(cfg.Timing.LongPressMs, cfg.Timing.DoubleTapMs, func(idx int, a *config.Action) {
if a == nil {
return
}
@ -119,6 +119,8 @@ func Run(ctx context.Context, cfg *config.Config, opts RunOptions) error {
pm.startPeriodicKeys()
}
web.BroadcastPageChange(newPage)
} else {
primaryPM.RefreshDisplayKey(idx)
}
})

View File

@ -7,7 +7,7 @@ import (
"streamdeck-lets-go/internal/config"
)
type ActionCallback func(a *config.Action)
type ActionCallback func(idx int, a *config.Action)
type gestureKeyState struct {
mu sync.Mutex
@ -122,9 +122,9 @@ func (ge *GestureEngine) handleKeyPress(state *gestureKeyState, evt Event, actio
state.mu.Unlock()
if a := findAction(actions, "hold_start"); a != nil {
ge.onAction(a)
ge.onAction(evt.Index, a)
} else if a := findAction(actions, "long_press"); a != nil {
ge.onAction(a)
ge.onAction(evt.Index, a)
}
})
state.mu.Unlock()
@ -138,7 +138,7 @@ func (ge *GestureEngine) handleKeyRelease(state *gestureKeyState, evt Event, act
state.holdActive = false
state.mu.Unlock()
if a := findAction(actions, "hold_end"); a != nil {
ge.onAction(a)
ge.onAction(evt.Index, a)
}
return
}
@ -147,7 +147,7 @@ func (ge *GestureEngine) handleKeyRelease(state *gestureKeyState, evt Event, act
state.lastTapAt = time.Time{}
state.mu.Unlock()
if a := findAction(actions, "double_tap"); a != nil {
ge.onAction(a)
ge.onAction(evt.Index, a)
}
return
}
@ -162,7 +162,7 @@ func (ge *GestureEngine) handleKeyRelease(state *gestureKeyState, evt Event, act
state.pendingTap = nil
state.mu.Unlock()
if a := findAction(actions, "tap"); a != nil {
ge.onAction(a)
ge.onAction(evt.Index, a)
}
return
}

22
page.go
View File

@ -490,6 +490,28 @@ func (pm *PageManager) renderKeyOutput(idx int, d *config.DisplayCfg, output str
}
}
func (pm *PageManager) RefreshDisplayKey(idx int) {
pm.mu.RLock()
page := pm.pages[pm.active]
pm.mu.RUnlock()
if page == nil {
return
}
for _, k := range page.Keys {
if k.Index == idx && k.Display != nil {
timeout := 30 * time.Second
if k.Display.Timeout != "" {
if t, err := time.ParseDuration(k.Display.Timeout); err == nil && t > 0 {
timeout = t
}
}
output, err := execDisplayCapture(k.Display, timeout)
pm.renderKeyOutput(idx, k.Display, output, err)
return
}
}
}
var (
unicodeFontOnce sync.Once
unicodeFontData []byte

View File

@ -15,6 +15,7 @@ document.addEventListener('alpine:init', () => {
// ── Edit state ──
editing: null,
editForm: {
bg_color: '',
actions: {
tap: {},
long_press: {},

9
static/fontawesome/css/all.min.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -6,7 +6,7 @@
<title>StreamDeck</title>
<script src="/static/app.js"></script>
<script defer src="/static/alpine.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
<link rel="stylesheet" href="/static/fontawesome/css/all.min.css">
<link rel="stylesheet" href="/static/styles.css">
</head>
<body>
@ -505,8 +505,8 @@
<div class="form-group">
<label>Background</label>
<div style="display:flex;gap:8px;align-items:center;">
<input type="color" :value="editForm.bg_color || '#000000'"
@input="editForm.bg_color = $event.target.value"
<input type="color"
x-init="$el.value = editForm.bg_color || '#000000'; $el.addEventListener('input', () => editForm.bg_color = $el.value); $watch('editForm.bg_color', v => $el.value = v || '#000000')"
style="width:40px;height:40px;padding:2px;border-radius:var(--radius-xs);cursor:pointer;">
<input type="text" x-model="editForm.bg_color"
placeholder="#rrggbb or #rrggbbaa" maxlength="9"

31
web.go
View File

@ -459,6 +459,16 @@ func backupOldConfig(path string) {
}
}
func collectIcons(cfg *config.Config, used map[string]bool) {
for _, p := range cfg.Pages {
for _, k := range p.Keys {
if k.Icon != "" {
used[k.Icon] = true
}
}
}
}
func gcImages(cfg *config.Config) {
imgDir := filepath.Join(configDir(), "images")
entries, err := os.ReadDir(imgDir)
@ -466,13 +476,24 @@ func gcImages(cfg *config.Config) {
return
}
used := make(map[string]bool, len(entries))
for _, p := range cfg.Pages {
for _, k := range p.Keys {
if k.Icon != "" {
used[k.Icon] = true
used := make(map[string]bool)
collectIcons(cfg, used)
backupDir := filepath.Join(configDir(), "backups")
backupEntries, _ := os.ReadDir(backupDir)
for _, be := range backupEntries {
if be.IsDir() {
continue
}
data, err := os.ReadFile(filepath.Join(backupDir, be.Name()))
if err != nil {
continue
}
var backupCfg config.Config
if err := json.Unmarshal(data, &backupCfg); err != nil {
continue
}
collectIcons(&backupCfg, used)
}
for _, e := range entries {