Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func Init(e *gin.Engine) {
})
g.GET("/favicon.ico", handles.Favicon)
g.GET("/robots.txt", handles.Robots)
g.GET("/manifest.json", static.ManifestJSON)
g.GET("/i/:link_name", handles.Plist)
common.SecretKey = []byte(conf.Conf.JwtSecret)
g.Use(middlewares.StoragesLoaded)
Expand Down
7 changes: 7 additions & 0 deletions server/static/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ func getSiteConfig() SiteConfig {
}
if siteConfig.BasePath != "" {
siteConfig.BasePath = utils.FixAndCleanPath(siteConfig.BasePath)
// Keep consistent with frontend: trim trailing slash unless it's root
if siteConfig.BasePath != "/" && strings.HasSuffix(siteConfig.BasePath, "/") {
siteConfig.BasePath = strings.TrimSuffix(siteConfig.BasePath, "/")
}
}
if siteConfig.BasePath == "" {
siteConfig.BasePath = "/"
}
if siteConfig.Cdn == "" {
siteConfig.Cdn = strings.TrimSuffix(siteConfig.BasePath, "/")
Expand Down
70 changes: 68 additions & 2 deletions server/static/static.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package static

import (
"encoding/json"
"errors"
"fmt"
"io"
Expand All @@ -17,6 +18,20 @@ import (
"github.com/gin-gonic/gin"
)

type ManifestIcon struct {
Src string `json:"src"`
Sizes string `json:"sizes"`
Type string `json:"type"`
}

type Manifest struct {
Display string `json:"display"`
Scope string `json:"scope"`
StartURL string `json:"start_url"`
Name string `json:"name"`
Icons []ManifestIcon `json:"icons"`
}

var static fs.FS

func initStatic() {
Expand Down Expand Up @@ -77,9 +92,15 @@ func initIndex(siteConfig SiteConfig) {
utils.Log.Debug("Successfully read index.html from static files system")
}
utils.Log.Debug("Replacing placeholders in index.html...")
// Construct the correct manifest path based on basePath
manifestPath := "/manifest.json"
if siteConfig.BasePath != "/" {
manifestPath = siteConfig.BasePath + "/manifest.json"
}
replaceMap := map[string]string{
"cdn: undefined": fmt.Sprintf("cdn: '%s'", siteConfig.Cdn),
"base_path: undefined": fmt.Sprintf("base_path: '%s'", siteConfig.BasePath),
"cdn: undefined": fmt.Sprintf("cdn: '%s'", siteConfig.Cdn),
"base_path: undefined": fmt.Sprintf("base_path: '%s'", siteConfig.BasePath),
`href="/manifest.json"`: fmt.Sprintf(`href="%s"`, manifestPath),
}
conf.RawIndexHtml = replaceStrings(conf.RawIndexHtml, replaceMap)
UpdateIndex()
Expand Down Expand Up @@ -110,12 +131,57 @@ func UpdateIndex() {
utils.Log.Debug("Index.html update completed")
}

func ManifestJSON(c *gin.Context) {
// Get site configuration to ensure consistent base path handling
siteConfig := getSiteConfig()

// Get site title from settings
siteTitle := setting.GetStr(conf.SiteTitle)

// Get logo from settings, use the first line (light theme logo)
logoSetting := setting.GetStr(conf.Logo)
logoUrl := strings.Split(logoSetting, "\n")[0]

// Use base path from site config for consistency
basePath := siteConfig.BasePath

// Determine scope and start_url
// PWA scope and start_url should always point to our application's base path
// regardless of whether static resources come from CDN or local server
scope := basePath
startURL := basePath

manifest := Manifest{
Display: "standalone",
Scope: scope,
StartURL: startURL,
Name: siteTitle,
Icons: []ManifestIcon{
{
Src: logoUrl,
Sizes: "512x512",
Type: "image/png",
},
},
}

c.Header("Content-Type", "application/json")
c.Header("Cache-Control", "public, max-age=3600") // cache for 1 hour

if err := json.NewEncoder(c.Writer).Encode(manifest); err != nil {
utils.Log.Errorf("Failed to encode manifest.json: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate manifest"})
return
}
}

func Static(r *gin.RouterGroup, noRoute func(handlers ...gin.HandlerFunc)) {
utils.Log.Debug("Setting up static routes...")
siteConfig := getSiteConfig()
initStatic()
initIndex(siteConfig)
folders := []string{"assets", "images", "streamer", "static"}

if conf.Conf.Cdn == "" {
utils.Log.Debug("Setting up static file serving...")
r.Use(func(c *gin.Context) {
Expand Down