feat(settings): add home content customization and config injection
- Add home_content setting for custom homepage (HTML or iframe URL) - Inject public settings into index.html to eliminate page flash - Support ETag caching with automatic invalidation on settings update - Add Vite plugin for dev mode settings injection - Refactor HomeView to use appStore instead of local API calls
This commit is contained in:
77
backend/internal/web/html_cache.go
Normal file
77
backend/internal/web/html_cache.go
Normal file
@@ -0,0 +1,77 @@
|
||||
//go:build embed
|
||||
|
||||
package web
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HTMLCache manages the cached index.html with injected settings
|
||||
type HTMLCache struct {
|
||||
mu sync.RWMutex
|
||||
cachedHTML []byte
|
||||
etag string
|
||||
baseHTMLHash string // Hash of the original index.html (immutable after build)
|
||||
settingsVersion uint64 // Incremented when settings change
|
||||
}
|
||||
|
||||
// CachedHTML represents the cache state
|
||||
type CachedHTML struct {
|
||||
Content []byte
|
||||
ETag string
|
||||
}
|
||||
|
||||
// NewHTMLCache creates a new HTML cache instance
|
||||
func NewHTMLCache() *HTMLCache {
|
||||
return &HTMLCache{}
|
||||
}
|
||||
|
||||
// SetBaseHTML initializes the cache with the base HTML template
|
||||
func (c *HTMLCache) SetBaseHTML(baseHTML []byte) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
hash := sha256.Sum256(baseHTML)
|
||||
c.baseHTMLHash = hex.EncodeToString(hash[:8]) // First 8 bytes for brevity
|
||||
}
|
||||
|
||||
// Invalidate marks the cache as stale
|
||||
func (c *HTMLCache) Invalidate() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.settingsVersion++
|
||||
c.cachedHTML = nil
|
||||
c.etag = ""
|
||||
}
|
||||
|
||||
// Get returns the cached HTML or nil if cache is stale
|
||||
func (c *HTMLCache) Get() *CachedHTML {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
if c.cachedHTML == nil {
|
||||
return nil
|
||||
}
|
||||
return &CachedHTML{
|
||||
Content: c.cachedHTML,
|
||||
ETag: c.etag,
|
||||
}
|
||||
}
|
||||
|
||||
// Set updates the cache with new rendered HTML
|
||||
func (c *HTMLCache) Set(html []byte, settingsJSON []byte) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.cachedHTML = html
|
||||
c.etag = c.generateETag(settingsJSON)
|
||||
}
|
||||
|
||||
// generateETag creates an ETag from base HTML hash + settings hash
|
||||
func (c *HTMLCache) generateETag(settingsJSON []byte) string {
|
||||
settingsHash := sha256.Sum256(settingsJSON)
|
||||
return `"` + c.baseHTMLHash + "-" + hex.EncodeToString(settingsHash[:8]) + `"`
|
||||
}
|
||||
Reference in New Issue
Block a user