From 619ee199bdf3887dcec5c9bdecb37a05ffe80571 Mon Sep 17 00:00:00 2001 From: Robert Ison Date: Sat, 14 Feb 2026 22:49:40 -0500 Subject: [PATCH 1/3] Add a "TV" Mode. --- internal/server/handlers_device.go | 25 ++++ internal/server/server.go | 4 + web/templates/manager/device_tv.html | 146 ++++++++++++++++++++++++ web/templates/partials/device_card.html | 7 ++ 4 files changed, 182 insertions(+) create mode 100644 web/templates/manager/device_tv.html diff --git a/internal/server/handlers_device.go b/internal/server/handlers_device.go index 9ef3147d..daa1368e 100644 --- a/internal/server/handlers_device.go +++ b/internal/server/handlers_device.go @@ -224,6 +224,31 @@ func (s *Server) handleCreateDevicePost(w http.ResponseWriter, r *http.Request) http.Redirect(w, r, "/", http.StatusSeeOther) } +func (s *Server) handleDeviceTV(w http.ResponseWriter, r *http.Request) { + user := GetUser(r) + localizer := s.getLocalizer(r) + device := GetDevice(r) // Middleware provides this + + if device == nil { + slog.Error("Device not found in context") + http.Error(w, "Device not found", http.StatusNotFound) + return + } + + // Load the apps for the grid + if err := s.DB.Preload("Apps").First(device, "id = ?", device.ID).Error; err != nil { + slog.Error("Failed to preload apps", "error", err) + } + + // Double check the template name "device_tv" matches + // the key in the map in server.go + s.renderTemplate(w, r, "device_tv", TemplateData{ + User: user, + Localizer: localizer, + Device: device, + }) +} + func (s *Server) handleUpdateDeviceGet(w http.ResponseWriter, r *http.Request) { user := GetUser(r) device := GetDevice(r) diff --git a/internal/server/server.go b/internal/server/server.go index 6f5ea7bc..53a4791c 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -66,6 +66,7 @@ var templateFiles = map[string]string{ "uploadapp": "manager/uploadapp.html", "firmware": "manager/firmware.html", "update": "manager/update.html", + "device_tv": "manager/device_tv.html", } func NewServer(db *gorm.DB, cfg *config.Settings) *Server { @@ -281,6 +282,9 @@ func (s *Server) routes() { s.Router.HandleFunc("POST /devices/{id}/update_firmware_settings", s.RequireLogin(s.RequireDevice(s.handleUpdateFirmwareSettings))) + // Add this line for the TV View endpoint + s.Router.HandleFunc("GET /devices/{id}/tv", s.RequireLogin(s.RequireDevice(s.handleDeviceTV))) + // Websocket routes s.SetupWebsocketRoutes() diff --git a/web/templates/manager/device_tv.html b/web/templates/manager/device_tv.html new file mode 100644 index 00000000..3f2b1b29 --- /dev/null +++ b/web/templates/manager/device_tv.html @@ -0,0 +1,146 @@ +{{define "device_tv"}} + + + + + + {{ .Device.Name }} - TV Mode + + + + +
+
+ {{ range .Device.Apps }} + {{ if .Enabled }}
+ +
+ {{ end }} + {{ end }} +
+ +
+
+ {{ .Device.Name }} Live Monitor +
+ +
+
+ + +{{end}} \ No newline at end of file diff --git a/web/templates/partials/device_card.html b/web/templates/partials/device_card.html index 8a400d09..06487138 100644 --- a/web/templates/partials/device_card.html +++ b/web/templates/partials/device_card.html @@ -172,6 +172,13 @@

style="min-width: 100px" href="/devices/{{ .Item.ID }}/firmware"> {{ t .Localizer "Firmware" }} {{ end }} + + + {{ t .Localizer "TV Mode" }} + {{ end }} From da9d7ad2011006aa8de75df42d6066e1bd38633c Mon Sep 17 00:00:00 2001 From: Robert Ison Date: Sat, 14 Feb 2026 23:08:04 -0500 Subject: [PATCH 2/3] Gemini Fixes --- internal/server/handlers_device.go | 13 ------------- web/templates/manager/device_tv.html | 9 --------- 2 files changed, 22 deletions(-) diff --git a/internal/server/handlers_device.go b/internal/server/handlers_device.go index daa1368e..be9ac932 100644 --- a/internal/server/handlers_device.go +++ b/internal/server/handlers_device.go @@ -229,19 +229,6 @@ func (s *Server) handleDeviceTV(w http.ResponseWriter, r *http.Request) { localizer := s.getLocalizer(r) device := GetDevice(r) // Middleware provides this - if device == nil { - slog.Error("Device not found in context") - http.Error(w, "Device not found", http.StatusNotFound) - return - } - - // Load the apps for the grid - if err := s.DB.Preload("Apps").First(device, "id = ?", device.ID).Error; err != nil { - slog.Error("Failed to preload apps", "error", err) - } - - // Double check the template name "device_tv" matches - // the key in the map in server.go s.renderTemplate(w, r, "device_tv", TemplateData{ User: user, Localizer: localizer, diff --git a/web/templates/manager/device_tv.html b/web/templates/manager/device_tv.html index 3f2b1b29..c265aca3 100644 --- a/web/templates/manager/device_tv.html +++ b/web/templates/manager/device_tv.html @@ -85,15 +85,6 @@ align-content: center; } - .app-grid { - display: grid; - /* This line is the 'brain' that fills the screen smartly */ - grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); - gap: 30px; - flex-grow: 1; - align-content: center; /* Keeps things centered if there's only one row */ - } - .app-card img { width: 100%; height: auto; From 4595f007be54a9d1c4c890fa674c2d9a60db1700 Mon Sep 17 00:00:00 2001 From: Robert Ison Date: Sun, 15 Feb 2026 23:36:01 -0500 Subject: [PATCH 3/3] Lint fixes --- web/templates/manager/device_tv.html | 66 ++++++++++++++----------- web/templates/partials/device_card.html | 7 ++- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/web/templates/manager/device_tv.html b/web/templates/manager/device_tv.html index c265aca3..7bc19fc5 100644 --- a/web/templates/manager/device_tv.html +++ b/web/templates/manager/device_tv.html @@ -1,11 +1,11 @@ {{define "device_tv"}} - - - - {{ .Device.Name }} - TV Mode - - - - -
-
- {{ range .Device.Apps }} - {{ if .Enabled }}
- + + + +
+
+ {{ range .Device.Apps }} + {{ if .Enabled }} +
+
- {{ end }} - {{ end }} -
- -
-
- {{ .Device.Name }} Live Monitor + {{ end }} + {{ end }} +
+
+
+ {{ .Device.Name }} Live Monitor +
+
-
-
- + -{{end}} \ No newline at end of file +{{end}} diff --git a/web/templates/partials/device_card.html b/web/templates/partials/device_card.html index 06487138..93af0d1b 100644 --- a/web/templates/partials/device_card.html +++ b/web/templates/partials/device_card.html @@ -172,11 +172,10 @@

style="min-width: 100px" href="/devices/{{ .Item.ID }}/firmware"> {{ t .Localizer "Firmware" }} {{ end }} - + style="min-width: 100px" + href="/devices/{{ .Item.ID }}/tv" + target="_blank"> {{ t .Localizer "TV Mode" }}