package main import ( "encoding/json" "net/http" "strconv" "strings" ) const SharedCSS = ` :root { color-scheme: dark; } body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #1e1e1e; color: #ddd; margin: 0; padding: 0; } .topbar { display: flex; align-items: center; gap: 8px; padding: 8px 16px; background: #252526; border-bottom: 1px solid #333; font-size: 13px; } .topbar a { color: #9cdcfe; text-decoration: none; padding: 4px 10px; border-radius: 3px; } .topbar a:hover { background: #2a2d2e; } .topbar a.active { background: #094771; color: #fff; } .beta-pill { margin-left: 4px; padding: 1px 4px; border: 1px solid #555; border-radius: 3px; font-size: 10px; opacity: 0.7; text-transform: uppercase; } .topbar-version { margin-left: auto; font-size: 11px; opacity: 0.45; letter-spacing: 0.4px; } .content { padding: 16px; max-width: 980px; margin: 0 auto; } .beta-tools-footer { max-width: 980px; margin: 24px auto 16px auto; padding: 12px 16px 0; border-top: 1px solid #333; } .beta-tools-footer button { width: 100%; text-align: left; background: #3a3d41; color: #ddd; } .beta-tools-footer button:hover { background: #45494e; } .beta-note { display: block; margin-top: 3px; opacity: 0.65; font-size: 11px; } h2 { margin-top: 0; font-weight: 500; } input[type=text], input[type=date], select, textarea { box-sizing: border-box; padding: 6px 8px; background: #3c3c3c; color: #ddd; border: 1px solid #3c3c3c; border-radius: 2px; font-family: inherit; font-size: 13px; } input[type=text]:focus, input[type=date]:focus, select:focus, textarea:focus { outline: 1px solid #007fd4; border-color: #007fd4; } button { background: #0e639c; color: #fff; border: none; padding: 6px 14px; border-radius: 2px; cursor: pointer; font-size: 13px; } button:hover { background: #1177bb; } button.secondary { background: #3a3d41; color: #ddd; } button.secondary:hover { background: #45494e; } button:disabled { opacity: 0.5; cursor: not-allowed; } .err { color: #f48771; white-space: pre-wrap; } .ok { color: #89d185; } .hint { font-size: 12px; opacity: 0.7; } ` type navItem struct { Path string Label string Description string Beta bool } var navItems = []navItem{ {Path: "/", Label: "Home"}, {Path: "/plec", Label: "PLEC Upload", Description: "Upload HTML to the internal PLEC server"}, {Path: "/applovin", Label: "AppLovin Upload", Description: "Upload to p.applov.in (QR preview)"}, {Path: "/base64", Label: "Base64 Scanner", Description: "Find non-base64 assets in HTML"}, {Path: "/mraid", Label: "MRAID Checker", Description: "Check MRAID requirements and best practices", Beta: true}, {Path: "/mobile", Label: "Send To Mobile", Description: "Share HTML to a phone via LAN + QR"}, {Path: "/playworks", Label: "Playworks Converter", Description: "Convert Playworks HTML to per-network variants", Beta: true}, } func visibleNavItems(betaToolsEnabled bool) []navItem { out := make([]navItem, 0, len(navItems)) for _, n := range navItems { if n.Beta && !betaToolsEnabled { continue } out = append(out, n) } return sortNavItemsForDisplay(out) } func sortNavItemsForDisplay(items []navItem) []navItem { out := append([]navItem(nil), items...) for i := 0; i < len(out); i++ { for j := i + 1; j < len(out); j++ { if out[i].Beta && !out[j].Beta { out[i], out[j] = out[j], out[i] } } } return out } func betaToolCount() int { count := 0 for _, n := range navItems { if n.Beta { count++ } } return count } func Page(activePath, title, body string) string { cfg := LoadConfig() betaToolsEnabled := cfg.BetaToolsEnabled var tabs strings.Builder for _, n := range visibleNavItems(betaToolsEnabled) { cls := "" if n.Path == activePath { cls = " class=\"active\"" } label := n.Label if n.Beta { label += `Beta` } tabs.WriteString(`` + label + ``) } betaButtonLabel := "Enable Beta Tools" betaButtonNote := "Hidden beta tools: " + strconv.Itoa(betaToolCount()) if betaToolsEnabled { betaButtonLabel = "Disable Beta Tools" betaButtonNote = "Beta tools are visible in this standalone launcher." } return ` ` + title + ` — HPL Toolbox
` + tabs.String() + `v` + AppVersion + `
` + body + `
` } func boolAttr(v bool) string { if v { return "true" } return "false" } func BetaToolsEndpoint(w http.ResponseWriter, r *http.Request) { var req struct { Enabled bool `json:"enabled"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeJSON(w, map[string]any{"ok": false, "error": err.Error()}) return } cfg := LoadConfig() cfg.BetaToolsEnabled = req.Enabled if err := SaveConfig(cfg); err != nil { writeJSON(w, map[string]any{"ok": false, "error": err.Error()}) return } writeJSON(w, map[string]any{"ok": true}) }