Updates.
authorScott Gasch <[email protected]>
Tue, 7 Apr 2026 17:03:12 +0000 (10:03 -0700)
committerScott Gasch <[email protected]>
Tue, 7 Apr 2026 17:03:12 +0000 (10:03 -0700)
immich_photo_renderer.py
kiosk.py

index be6e5dba669c10d4e12c2ea9d11026ea16eb895e..55901545fdbb6f01c29e86cb13e3a7cb8b8ac4c7 100644 (file)
@@ -4,6 +4,7 @@ import datetime
 import os
 import random
 import re
+import time
 from typing import Any, Dict, List, Optional, Set
 
 from scottutilz import immich
@@ -84,8 +85,9 @@ def get_layout_class(asset: dict[str, Any]) -> str:
         orientation = int(orientation)
         if orientation in [6, 8]:
             aspect_ratio = float(1) / aspect_ratio
+            (width, height) = (height, width)
 
-    if aspect_ratio > 1.5:
+    if aspect_ratio > 1.6 and width > height:
         return 'panorama_mode'
     return 'standard_mode'
 
@@ -154,6 +156,8 @@ class immich_photo_renderer(renderer.abstaining_renderer):
             jpeg = self.immich_cli.get_asset_thumbnail(selected_uuid, size="fullsize")
             with open("/var/www/kiosk/pages/mfs/current.jpeg", "wb") as f:
                 f.write(jpeg)
+                f.flush()
+                os.fsync(f.fileno())
         except Exception:
             print("Failed to get image!")
             return False
@@ -222,6 +226,7 @@ class immich_photo_renderer(renderer.abstaining_renderer):
    <span class="album-name">{album_name}</span>
 </div>
 """
+        cache_buster = int(time.time())
         with file_writer.file_writer("photo_33_3600.html") as f:
             f.write(
                 f"""
@@ -263,20 +268,19 @@ class immich_photo_renderer(renderer.abstaining_renderer):
   }}
   .standard_mode .photo-pane {{
         flex: 1;
-        max-width: 80vw; /* Limit width to 80% */
+        max-width: 80vw;
   }}
   .panorama_mode .photo-pane {{
-        flex: 1;
-        height: 70vh; /* Limit height to 70% */
-        width: 100vw;
+        flex: 1 1 auto;
+        max-height: 75vh;
         min-height: 0;
+        width: 100vw;
   }}
   .photo-pane img {{
         max-width: 100%;
         max-height: 100%;
         object-fit: contain;
         box-shadow: 0 0 50px rgba(0,0,0,0.5);
-        border-radius: 4px;
   }}
 
   /* --- Info Pane Logic --- */
@@ -301,12 +305,12 @@ class immich_photo_renderer(renderer.abstaining_renderer):
         flex-direction: column;
   }}
   .panorama_mode .info-pane {{
-        flex: 0 0 var(--bottom-h);
-        flex-direction: row;
+        flex: 0 1 auto;
+        min-height: 20vh;
+        display: flex;
+        /* flex-direction: row; */
         align-items: center;
-        border-top: 2px solid #333;
-        gap: 2vw; /* Use relative gap */
-        padding: 0 3vw;
+        padding: 2vh 3vw;
   }}
 
   /* --- Typography & Elements --- */
@@ -321,10 +325,10 @@ class immich_photo_renderer(renderer.abstaining_renderer):
         margin-bottom: 2vh;
   }}
   .panorama_mode .description {{
-        flex: 1;
-        font-size: 1.8rem;
+        flex: 1.5;
+        font-size: clamp(1.2rem, 2.8vh, 2.5rem);
+        overflow: visible;
         margin: 0;
-        font-size: clamp(1.2rem, 2.5vh, 2.2rem);
         padding-right: 2vw;
         min-width: 0; /* Allows text to truncate/wrap properly */
   }}
@@ -383,7 +387,7 @@ class immich_photo_renderer(renderer.abstaining_renderer):
   .panorama_mode .album-section-title {{
         writing-mode: vertical-lr;
         transform: rotate(180deg);
-        margin: 0;
+        margin: 10px;
   }}
 
   .album-grid {{
@@ -393,11 +397,12 @@ class immich_photo_renderer(renderer.abstaining_renderer):
   .standard_mode .album-grid {{
         display: grid;
         grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
+        justify-content: flex-end;
   }}
   .panorama_mode .album-grid {{
-        flex: 1;
+        flex: 1.3;
         flex-direction: row;
-        justify-content: flex-start;
+        justify-content: center;
   }}
   .album-card {{
         display: flex;
@@ -421,12 +426,22 @@ class immich_photo_renderer(renderer.abstaining_renderer):
 /*        white-space: nowrap;
         overflow: hidden;
         text-overflow: ellipsis; */
+
+        /* Fix #1: Force long words like 'AdobeLightroom' to break */
+        word-break: break-word;
+        overflow-wrap: break-word;
+
+        /* Fix #2: Multi-line truncation (The "Best of Both Worlds") */
+        display: -webkit-box;
+        -webkit-line-clamp: 2; /* Show exactly 3 lines, then dots */
+        -webkit-box-orient: vertical;
+        overflow: hidden;
   }}
 </style>
 <div class="kiosk-container {layout_class}">
     <!-- Photo Section -->
     <div class="photo-pane">
-        <img src="/kiosk/mfs/current.jpeg" alt="Current kiosk photo">
+        <img src="/kiosk/mfs/current.jpeg?v={cache_buster}" alt="Current kiosk photo">
     </div>
 
     <!-- Metadata Section -->
@@ -443,6 +458,7 @@ class immich_photo_renderer(renderer.abstaining_renderer):
                 {date.strftime("%B %-d, %Y")}
             </div>
         </div>
+     <!--   <div class="divider"></div> -->
         <div class="album-section-title">Appears In</div>
         <div class="album-grid">
             {album_html}
index 55b14920c723caaea8cd5610ee56cc47ca04d60b..308c649e717b80f1b47bfc1b4f47630d4f95c7ea 100755 (executable)
--- a/kiosk.py
+++ b/kiosk.py
@@ -395,7 +395,7 @@ def emit_wrapped(
         """
 <HEAD>
   <TITLE>Kitchen Kiosk</TITLE>
-  <LINK rel="stylesheet" type="text/css" href="style.css">
+  <LINK rel="stylesheet" type="text/css" href="style_new.css">
   <meta name="google" content="notranslate">
   <SCRIPT TYPE="text/javascript">
 
@@ -441,21 +441,42 @@ def emit_wrapped(
     f.write(
         """
   // Operate the clock at the top of the page.
+  function runClock() {
+    var today = new Date();
+    var h = today.getHours() %% 12 || 12;
+    var m = maybeAddZero(today.getMinutes());
+    var ampm = today.getHours() >= 12 ? 'pm' : 'am';
+
+    // We wrap the colon in a span that stays there forever.
+    // We just toggle the opacity to make it "blink".
+    var style = (today.getSeconds() %% 2 == 0) ? "opacity: 0;" : "opacity: 1;";
+    var colon = "<span style='" + style + " font-size: 6vmin;'>:</span>";
+
+    document.getElementById("time").innerHTML = h + colon + m + ampm;
+    document.getElementById("date").innerHTML = today.toDateString();
+    setTimeout(runClock, 1000);
+  }
+/*
   function runClock() {
     var today = new Date();
     var h = today.getHours();
     var ampm = h >= 12 ? 'pm' : 'am';
     h = h %% 12;
-    h = h ? h : 12; // the hour '0' should be '12'
+    h = h ? h : 12;
     var m = maybeAddZero(today.getMinutes());
+
+    // Default colon
     var colon = ":";
+
+    // "Blink" logic: Hide the colon by matching the background color (#E6B8B8)
+    // We use 6vmin here to match your new larger clock size
     if (today.getSeconds() %% 2 == 0) {
-      colon = "<FONT STYLE='color: #%s; font-size: 4vmin; font-weight: bold'>:</FONT>";
+      colon = "<span style='color: #%s; font-size: 6vmin;'>:</span>";
     }
     document.getElementById("time").innerHTML = h + colon + m + ampm;
     document.getElementById("date").innerHTML = today.toDateString();
     var t = setTimeout(function(){runClock()}, 1000);
-  }
+  }*/
 """
         % bgcolor
     )
@@ -553,48 +574,39 @@ def emit_wrapped(
     f.write(f'<BODY BGCOLOR="#{bgcolor}">')
     f.write(
         """
-    <TABLE style="width:100%" BORDER=0>
-    <TR HEIGHT=30>
-        <TD ALIGN="left">
-            <DIV id="date">&nbsp;</DIV>
-        </TD>
-        <TD ALIGN="center"><FONT COLOR=#bbbbbb>
-            <DIV id="info"></DIV></FONT>
-        </TD>
-        <TD ALIGN="right">
-            <DIV id="time">&nbsp;</DIV>
-        </TD>
-    </TR>
-    </TABLE>
-    <DIV ID="content" STYLE="flex: 1; width: 100%; visibility: hidden;">
-        <!-- BEGIN main page contents. -->
+<DIV class="header-wrapper">
+    <DIV id="date">&nbsp;</DIV>
+    <DIV id="info-container"><DIV id="info"></DIV></DIV>
+    <DIV id="time">&nbsp;</DIV>
+</DIV>
+<DIV ID="content" STYLE="width: 100%; visibility: hidden; position: relative;">
+<!-- BEGIN main page contents. -->
 """
     )
     f.write(f'<!--#include virtual="{filename}"-->')
     f.write(
         """
-        <!-- END main page contents. -->
-    </DIV>
-    <DIV STYLE="position: absolute; bottom: 0; width: 100%; left: 0;">
-    <!--    <DIV STYLE="position: absolute; top:1030px; width:99%"> -->
-        <P ALIGN="right" STYLE="margin: 0 10px 2px 0;">
+<!-- END main page contents. -->
+</DIV>
+<DIV STYLE="position: absolute; bottom: 0; width: 100%; left: 0;">
+    <P ALIGN="right" STYLE="margin: 0 10px 2px 0;">
 """
     )
     f.write(
-        '<span style="font-size: 0.6rem; color: #888888; font-family: monospace;">'
+        '    <span style="font-size: 1vh; color: #888888; font-family: monospace;">'
         f'{pageid} @ {age} ago.</span>'
     )
     f.write(
         """
-        </P>
-        <HR id="countdown" STYLE="width: 0px;
-                                  text-align: left;
-                                  margin: 0;
-                                  border: none;
-                                  height: 5px;
-                                  visibility: hidden;
-                                  background-color: maroon;">
-    </DIV>
+    </P>
+    <HR id="countdown" STYLE="width: 0px;
+                              text-align: left;
+                              margin: 0;
+                              border: none;
+                              height: 5px;
+                              visibility: hidden;
+                              background-color: maroon;">
+</DIV>
 </BODY>"""
     )