foxygit / infodisplay Log in
commits tags

/kiosk/templates/display.html · 9.87 KB

raw
<!DOCTYPE html>
<html lang="sv">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Kiosk Display</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    html, body { width: 100%; height: 100%; overflow: hidden; background: #000; cursor: none; }
    * { cursor: none !important; }
    .layer { position: fixed; inset: 0; display: none; }
    #layer-iframe iframe { width: 100%; height: 100%; border: none; }
    #layer-video { background: #000; display: flex; align-items: center; justify-content: center; }
    #layer-video video { width: 100%; height: 100%; object-fit: contain; }
    #layer-image { background: #000; display: flex; align-items: center; justify-content: center; }
    #layer-image img { width: 100%; height: 100%; object-fit: contain; }
    #layer-idle { background: #111; display: flex; align-items: center; justify-content: center; }
    #layer-idle .ip { color: #fff; font-family: monospace; font-size: 4vw; opacity: 0.6; }

    /* Ticker overlay */
    #ticker {
      display: none;
      position: fixed;
      left: 0; right: 0;
      z-index: 9999;
      overflow: hidden;
      pointer-events: none;
    }
    #ticker.top    { top: 0; }
    #ticker.bottom { bottom: 0; }
    #ticker-text {
      display: inline-block;
      white-space: nowrap;
    }
    @keyframes ticker-scroll {
      from { transform: translateX(100vw); }
      to   { transform: translateX(-100%); }
    }
    /* === Kiosk chat overlay === */
    #kiosk-chat-overlay {
      font-family: 'Segoe UI', system-ui, sans-serif;
    }
    #kc-msgs {
      position: absolute;
      bottom: 0; left: 0; right: 0;
      display: flex;
      flex-direction: column;
      gap: .55rem;
      padding: .75rem;
    }
    .kc-msg {
      display: flex;
      align-items: flex-start;
      gap: .55rem;
      animation: kc-in .25s ease;
    }
    .kc-avatar {
      width: 2rem; height: 2rem;
      border-radius: 50%;
      display: flex; align-items: center; justify-content: center;
      font-size: 1rem;
      flex-shrink: 0;
      margin-top: .1rem;
      overflow: hidden;
    }
    .kc-body { flex: 1; min-width: 0; }
    .kc-name {
      font-size: .78rem;
      font-weight: 700;
      margin-bottom: .15rem;
    }
    .kc-text {
      font-size: 1.05rem;
      line-height: 1.45;
      word-break: break-word;
      color: #e8e8e8;
      text-shadow: 0 1px 4px #000c;
    }
    .kc-system {
      font-size: .8rem;
      color: #aaa;
      font-style: italic;
      padding: .05rem .25rem;
      text-shadow: 0 1px 3px #000c;
    }
    @keyframes kc-in {
      from { opacity: 0; transform: translateY(8px); }
      to   { opacity: 1; transform: translateY(0);   }
    }
    @keyframes ticker-scroll-seamless {
      from { transform: translateX(0); }
      to   { transform: translateX(-50%); }
    }
    /* kiosk chat overlay header */
    #kc-header {
      display: flex;
      align-items: center;
      gap: .5rem;
      padding: .55rem .75rem .45rem;
      border-bottom: 1px solid #ffffff14;
      flex-shrink: 0;
    }
    #kc-title {
      font-size: .9rem;
      font-weight: 700;
      color: #fff;
      letter-spacing: .02em;
    }
    #kc-count {
      font-size: .72rem;
      color: #888;
      background: #1a1a1a;
      padding: .15rem .5rem;
      border-radius: 99px;
      margin-right: auto;
    }
    #kc-qr {
      width: 48px; height: 48px;
      border-radius: 5px;
      background: #fff;
      padding: 2px;
      flex-shrink: 0;
    }
    #kc-msgs-wrap {
      flex: 1;
      overflow: hidden;
      position: relative;
    }
    .dot-live {
      width: .5rem; height: .5rem;
      background: #ef4444;
      border-radius: 50%;
      display: inline-block;
      flex-shrink: 0;
      animation: kc-pulse 1.4s infinite;
    }
    @keyframes kc-pulse {
      0%,100% { opacity: 1; }
      50%      { opacity: .3; }
    }

    /* === Layer transitions === */
    .layer { will-change: transform, opacity; }

    /* Fade */
    @keyframes tx-fade-in  { from { opacity: 0; } to { opacity: 1; } }
    @keyframes tx-fade-out { from { opacity: 1; } to { opacity: 0; } }

    /* Slide left — ny layer kommer från höger */
    @keyframes tx-slide-left-in  { from { transform: translateX(100%); } to { transform: translateX(0); } }
    @keyframes tx-slide-left-out { from { transform: translateX(0);    } to { transform: translateX(-100%); } }

    /* Slide right — ny layer kommer från vänster */
    @keyframes tx-slide-right-in  { from { transform: translateX(-100%); } to { transform: translateX(0); } }
    @keyframes tx-slide-right-out { from { transform: translateX(0);     } to { transform: translateX(100%); } }

    /* Slide up — ny layer kommer underifrån */
    @keyframes tx-slide-up-in  { from { transform: translateY(100%); } to { transform: translateY(0); } }
    @keyframes tx-slide-up-out { from { transform: translateY(0);    } to { transform: translateY(-100%); } }

    /* Slide down — ny layer kommer uppifrån */
    @keyframes tx-slide-down-in  { from { transform: translateY(-100%); } to { transform: translateY(0); } }
    @keyframes tx-slide-down-out { from { transform: translateY(0);     } to { transform: translateY(100%); } }

    /* Zoom */
    @keyframes tx-zoom-in  { from { transform: scale(0.85); opacity: 0; } to { transform: scale(1);    opacity: 1; } }
    @keyframes tx-zoom-out { from { transform: scale(1);    opacity: 1; } to { transform: scale(1.15); opacity: 0; } }

    /* Wipe — vänster till höger via clip-path */
    @keyframes tx-wipe-in  { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0% 0 0); } }
    @keyframes tx-wipe-out { from { opacity: 1; } to { opacity: 0; } }

    /* Blur dissolve (pixel-liknande) */
    @keyframes tx-blur-in  { from { filter: blur(24px) brightness(1.3); opacity: 0; } to { filter: blur(0) brightness(1); opacity: 1; } }
    @keyframes tx-blur-out { from { filter: blur(0) brightness(1);      opacity: 1; } to { filter: blur(24px) brightness(0.5); opacity: 0; } }

    /* Pixel canvas overlay */
    #tx-pixel-canvas {
      position: fixed; inset: 0; z-index: 99998;
      pointer-events: none;
      display: none;
    }
  </style>
</head>
<body>
  <div id="layer-iframe" class="layer">
    <iframe id="frame" src="" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
  </div>

  <div id="layer-video" class="layer">
    <video id="video" autoplay></video>
  </div>

  <div id="layer-local" class="layer"></div>

  <div id="layer-image" class="layer">
    <img id="image" src="" alt="">
  </div>

  <!-- YouTube Livechat overlay -->
  <div id="chat-overlay" style="display:none; position:fixed; top:0; z-index:9998; pointer-events:auto; transition:opacity .3s;">
    <iframe id="chat-frame" src="" frameborder="0" style="width:100%;height:100%;border:none;"></iframe>
  </div>

  <!-- Kiosk Livechat overlay (inbyggd, ingen iframe) -->
  <div id="kiosk-chat-overlay" style="display:none; position:fixed; top:0; z-index:9997; pointer-events:none; overflow:hidden; font-family:'Segoe UI',system-ui,sans-serif; flex-direction:column; background:#0f0f0fd0;">
    <div id="kc-header">
      <span class="dot-live"></span>
      <span id="kc-title">Livechat</span>
      <span id="kc-count">0 aktiva</span>
      <img id="kc-qr" src="/api/chat-qr" alt="QR">
    </div>
    <div id="kc-msgs-wrap">
      <div id="kc-msgs" style="position:absolute;bottom:0;left:0;right:0;display:flex;flex-direction:column;gap:.45rem;padding:.6rem .75rem;"></div>
    </div>
  </div>

  <!-- Ticker overlay -->
  <div id="ticker" class="bottom">
    <span id="ticker-text"></span>
  </div>

  <div id="layer-idle" class="layer" style="display: block;">
    <span class="ip">{{ local_ip }}:5000</span>
  </div>

  <!-- Clock overlay -->
  <div id="clock-overlay" style="display:none; position:fixed; z-index:9990; pointer-events:none; flex-direction:column; align-items:center;">
    <div id="clock-digital"></div>
    <canvas id="clock-analog"></canvas>
    <div id="clock-date"></div>
  </div>

  <!-- Transition: pixel canvas overlay -->
  <canvas id="tx-pixel-canvas"></canvas>

  <!-- Söv-overlay — täcker allt -->
  <div id="layer-sleep" style="display:none; position:fixed; inset:0; background:#000; z-index:99999;"></div>

  <!-- Musik: bakgrundsaudio (lokal MP3) -->
  <audio id="music-player" preload="auto" style="display:none"></audio>

  <!-- Musik: dold iframe för YouTube-spellista -->
  <iframe id="music-yt-frame" src="" allow="autoplay; encrypted-media" style="position:fixed;width:320px;height:180px;left:-400px;top:0;pointer-events:none;border:none;"></iframe>

  <!-- Now Playing-overlay -->
  <div id="now-playing-overlay" style="display:none; position:fixed; z-index:9985; pointer-events:none; max-width:320px;">
    <div id="now-playing-inner" style="
      background: rgba(0,0,0,0.72);
      backdrop-filter: blur(8px);
      border-radius: 10px;
      padding: .55rem .85rem;
      display: flex;
      align-items: center;
      gap: .6rem;
      animation: np-fadein .4s ease;
    ">
      <span id="now-playing-icon" style="font-size:1.3rem;flex-shrink:0;">♪</span>
      <div style="min-width:0;">
        <div id="now-playing-title" style="color:#fff;font-size:.88rem;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 4px #000c;"></div>
        <div id="now-playing-artist" style="color:#bbb;font-size:.75rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 4px #000c;"></div>
      </div>
    </div>
  </div>

  <style>
    @keyframes np-fadein {
      from { opacity:0; transform:translateY(6px); }
      to   { opacity:1; transform:translateY(0); }
    }
  </style>

  <script src="/static/socket.io.min.js"></script>
  <script src="/static/display.js"></script>
  {% for name in active_overlays %}
    <script src="/static/addons/{{ name }}/overlay.js"></script>
  {% endfor %}
</body>
</html>