mirror of
https://github.com/myronblair/jarvis
synced 2026-06-30 17:50:23 -05:00
Fire HD 8 tablet mode: auto-detect Silk UA, optimised layout + touch targets
This commit is contained in:
@@ -1208,3 +1208,159 @@ body::after{
|
|||||||
/* ── AGENT TOPOLOGY ────────────────────────────────────────────────── */
|
/* ── AGENT TOPOLOGY ────────────────────────────────────────────────── */
|
||||||
#agentTopoCanvas{background:transparent;border-top:1px solid rgba(0,212,255,0.08);display:block}
|
#agentTopoCanvas{background:transparent;border-top:1px solid rgba(0,212,255,0.08);display:block}
|
||||||
#agent-topo-btn.active{background:rgba(0,212,255,0.15);border-color:rgba(0,212,255,0.5)}
|
#agent-topo-btn.active{background:rgba(0,212,255,0.15);border-color:rgba(0,212,255,0.5)}
|
||||||
|
|
||||||
|
/* ════════════════════════════════════════════════════════════════════════
|
||||||
|
FIRE HD 8 (12th Gen) TABLET MODE
|
||||||
|
Applied via body.tablet-mode — set automatically on Silk UA detection
|
||||||
|
Target: 1280×800 landscape, 189 PPI, touch-only input
|
||||||
|
════════════════════════════════════════════════════════════════════════ */
|
||||||
|
|
||||||
|
/* Prevent accidental text selection on touch; restore for inputs */
|
||||||
|
body.tablet-mode { -webkit-user-select:none; user-select:none; }
|
||||||
|
body.tablet-mode input,
|
||||||
|
body.tablet-mode textarea { -webkit-user-select:auto; user-select:auto; }
|
||||||
|
|
||||||
|
/* ── TOPBAR — taller row, bigger tap zones ─────────────────────── */
|
||||||
|
body.tablet-mode #topBar {
|
||||||
|
height:54px;
|
||||||
|
padding:0 12px;
|
||||||
|
}
|
||||||
|
body.tablet-mode #clock { font-size:1.1rem; letter-spacing:3px; }
|
||||||
|
body.tablet-mode .tb-logo { font-size:0.95rem; }
|
||||||
|
|
||||||
|
/* Toolbar buttons — min 40px touch target */
|
||||||
|
body.tablet-mode .btn-panels,
|
||||||
|
body.tablet-mode .btn-camera {
|
||||||
|
font-size:0.62rem;
|
||||||
|
letter-spacing:1.5px;
|
||||||
|
padding:9px 13px;
|
||||||
|
min-height:40px;
|
||||||
|
margin-right:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Theme color dots — bigger tap area */
|
||||||
|
body.tablet-mode #themeBar { gap:6px; }
|
||||||
|
body.tablet-mode .theme-btn {
|
||||||
|
width:20px; height:20px;
|
||||||
|
font-size:0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap + logout */
|
||||||
|
body.tablet-mode #btn-swap-panels {
|
||||||
|
font-size:0.65rem;
|
||||||
|
padding:7px 11px;
|
||||||
|
}
|
||||||
|
body.tablet-mode .btn-logout {
|
||||||
|
font-size:0.72rem;
|
||||||
|
padding:7px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── MAIN LAYOUT — narrower side panels → wider center ──────────── */
|
||||||
|
/* 220+220 side cols → center gets ~808px instead of ~660px */
|
||||||
|
body.tablet-mode #mainLayout {
|
||||||
|
grid-template-columns:220px 1fr 220px;
|
||||||
|
padding:8px;
|
||||||
|
gap:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── PANELS — tighter padding, larger text ──────────────────────── */
|
||||||
|
body.tablet-mode .panel { padding:11px; }
|
||||||
|
body.tablet-mode .panel-title {
|
||||||
|
font-size:0.67rem;
|
||||||
|
letter-spacing:2.5px;
|
||||||
|
margin-bottom:9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Metric rows */
|
||||||
|
body.tablet-mode .metric-label { font-size:0.75rem; }
|
||||||
|
body.tablet-mode .service-row { font-size:0.75rem; padding:6px 0; }
|
||||||
|
body.tablet-mode .val-row { font-size:0.75rem; padding:4px 0; }
|
||||||
|
body.tablet-mode .device-item { font-size:0.75rem; padding:7px 0; }
|
||||||
|
body.tablet-mode .device-name { font-size:0.75rem; }
|
||||||
|
body.tablet-mode .device-ip { font-size:0.68rem; }
|
||||||
|
body.tablet-mode .vm-card { font-size:0.75rem; padding:9px 10px; }
|
||||||
|
|
||||||
|
/* Scrollable side panels — smooth touch inertia */
|
||||||
|
body.tablet-mode #leftPanel,
|
||||||
|
body.tablet-mode #rightPanel {
|
||||||
|
-webkit-overflow-scrolling:touch;
|
||||||
|
overscroll-behavior:contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── CENTER — arc reactor + chat ────────────────────────────────── */
|
||||||
|
/* Scale reactor down so chat gets more vertical room */
|
||||||
|
body.tablet-mode #arcReactor { width:180px; height:180px; }
|
||||||
|
body.tablet-mode .arc-ring.r1 { width:180px; height:180px; }
|
||||||
|
body.tablet-mode .arc-ring.r2 { width:159px; height:159px; }
|
||||||
|
body.tablet-mode .arc-ring.r3 { width:139px; height:139px; }
|
||||||
|
body.tablet-mode .arc-ring.r4 { width:118px; height:118px; }
|
||||||
|
body.tablet-mode .arc-ring.r5 { width:94px; height:94px; }
|
||||||
|
body.tablet-mode .arc-ring.r6 { width:72px; height:72px; }
|
||||||
|
body.tablet-mode .arc-ring.r7 { width:51px; height:51px; }
|
||||||
|
body.tablet-mode .arc-core { width:30px; height:30px; }
|
||||||
|
|
||||||
|
/* Chat messages — comfortable reading size */
|
||||||
|
body.tablet-mode .msg {
|
||||||
|
font-size:0.95rem;
|
||||||
|
line-height:1.55;
|
||||||
|
padding:11px 14px;
|
||||||
|
}
|
||||||
|
body.tablet-mode .msg.user { font-size:0.88rem; }
|
||||||
|
body.tablet-mode .msg.system { font-size:0.78rem; }
|
||||||
|
|
||||||
|
/* Touch-scroll chat log */
|
||||||
|
body.tablet-mode #chatLog {
|
||||||
|
-webkit-overflow-scrolling:touch;
|
||||||
|
overscroll-behavior:contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input row — 16px prevents Silk from zooming on focus */
|
||||||
|
body.tablet-mode #textInput {
|
||||||
|
font-size:1rem;
|
||||||
|
min-height:46px;
|
||||||
|
padding:12px 14px;
|
||||||
|
}
|
||||||
|
body.tablet-mode #sendBtn {
|
||||||
|
font-size:0.68rem;
|
||||||
|
min-height:46px;
|
||||||
|
padding:0 18px;
|
||||||
|
}
|
||||||
|
body.tablet-mode #micBtn {
|
||||||
|
width:52px; height:52px;
|
||||||
|
flex-shrink:0;
|
||||||
|
}
|
||||||
|
body.tablet-mode #searchBtn {
|
||||||
|
min-height:46px !important;
|
||||||
|
padding:0 13px !important;
|
||||||
|
font-size:1.1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── TABS — bigger tap targets ──────────────────────────────────── */
|
||||||
|
body.tablet-mode .tab {
|
||||||
|
font-size:0.58rem;
|
||||||
|
letter-spacing:1.5px;
|
||||||
|
padding:9px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── HA TABLE — more readable on 8" ────────────────────────────── */
|
||||||
|
body.tablet-mode .ha-thead th { font-size:0.55rem; padding:6px 3px 8px; }
|
||||||
|
body.tablet-mode .ha-row td { font-size:0.74rem; padding:6px 3px; }
|
||||||
|
|
||||||
|
/* Toggle slider — bigger for fat fingers */
|
||||||
|
body.tablet-mode .ha-toggle { width:36px; height:18px; }
|
||||||
|
body.tablet-mode .ha-slider::before { width:12px; height:12px; left:2px; top:2px; }
|
||||||
|
body.tablet-mode .ha-toggle input:checked + .ha-slider::before { transform:translateX(18px); }
|
||||||
|
|
||||||
|
/* ── DISABLE HOVER-RISE — not meaningful on touch ───────────────── */
|
||||||
|
body.tablet-mode .panel:hover {
|
||||||
|
transform:translateY(var(--pty,0px)) !important;
|
||||||
|
border-color:var(--panel-border) !important;
|
||||||
|
box-shadow:none !important;
|
||||||
|
transition:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── ALERTS ──────────────────────────────────────────────────────── */
|
||||||
|
body.tablet-mode .alert-item { font-size:0.75rem; padding:9px 11px; }
|
||||||
|
|
||||||
|
/* ── BOTTOM BAR ─────────────────────────────────────────────────── */
|
||||||
|
body.tablet-mode #bottomBar { font-size:0.7rem; height:34px; }
|
||||||
|
|||||||
@@ -1755,7 +1755,20 @@ document.addEventListener('keydown', function(e) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── KIOSK MODE ───────────────────────────────────────────────────────────────────────
|
|
||||||
|
// ── FIRE HD 8 TABLET DETECTION ────────────────────────────────────────────────────────
|
||||||
|
const IS_SILK = /Silk\//i.test(navigator.userAgent);
|
||||||
|
const IS_FIRE = /KFTT|KFOT|KFJWI|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFMEWI|KFFOWI|KFSAWA|KFMAWI|KFGIWI|KFDOWI|KFTBWI|KFTRWI|KFKAWI/i.test(navigator.userAgent);
|
||||||
|
function isTablet() { return IS_SILK || IS_FIRE; }
|
||||||
|
|
||||||
|
function applyTabletMode() {
|
||||||
|
document.body.classList.add("tablet-mode");
|
||||||
|
const kb = document.getElementById("kioskBtn");
|
||||||
|
if (kb) kb.title = "Full-screen kiosk (Fire HD 8 layout active)";
|
||||||
|
}
|
||||||
|
if (isTablet()) applyTabletMode();
|
||||||
|
|
||||||
|
// ── KIOSK MODE ────────────────────────────────────────────────────────────────────────
|
||||||
let _wakeLock = null;
|
let _wakeLock = null;
|
||||||
|
|
||||||
async function toggleKiosk() {
|
async function toggleKiosk() {
|
||||||
@@ -1763,41 +1776,36 @@ async function toggleKiosk() {
|
|||||||
const isFs = !!(document.fullscreenElement || document.webkitFullscreenElement);
|
const isFs = !!(document.fullscreenElement || document.webkitFullscreenElement);
|
||||||
|
|
||||||
if (!isFs) {
|
if (!isFs) {
|
||||||
|
applyTabletMode();
|
||||||
const el = document.documentElement;
|
const el = document.documentElement;
|
||||||
const req = el.requestFullscreen || el.webkitRequestFullscreen || el.mozRequestFullScreen || el.msRequestFullscreen;
|
const req = el.requestFullscreen || el.webkitRequestFullscreen || el.mozRequestFullScreen || el.msRequestFullscreen;
|
||||||
if (req) req.call(el).catch(() => {});
|
if (req) req.call(el).catch(() => {});
|
||||||
// Screen Wake Lock — keeps tablet display on
|
|
||||||
if ("wakeLock" in navigator) {
|
if ("wakeLock" in navigator) {
|
||||||
try { _wakeLock = await navigator.wakeLock.request("screen"); } catch(e) {}
|
try { _wakeLock = await navigator.wakeLock.request("screen"); } catch(e) {}
|
||||||
}
|
}
|
||||||
if (btn) { btn.textContent = "⛶ EXIT"; btn.style.color = "var(--cyan)"; }
|
if (btn) { btn.textContent = "⧞ EXIT"; btn.style.color = "var(--cyan)"; }
|
||||||
} else {
|
} else {
|
||||||
const ex = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
|
const ex = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
|
||||||
if (ex) ex.call(document).catch(() => {});
|
if (ex) ex.call(document).catch(() => {});
|
||||||
if (_wakeLock) { _wakeLock.release().catch(() => {}); _wakeLock = null; }
|
if (_wakeLock) { _wakeLock.release().catch(() => {}); _wakeLock = null; }
|
||||||
if (btn) { btn.textContent = "⛶ KIOSK"; btn.style.color = ""; }
|
if (btn) { btn.textContent = "⧞ KIOSK"; btn.style.color = ""; }
|
||||||
|
if (!isTablet()) document.body.classList.remove("tablet-mode");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-acquire wake lock if released by system (e.g. tab switch)
|
|
||||||
document.addEventListener("visibilitychange", async () => {
|
document.addEventListener("visibilitychange", async () => {
|
||||||
if (_wakeLock && document.visibilityState === "visible") {
|
if (_wakeLock && document.visibilityState === "visible") {
|
||||||
try { _wakeLock = await navigator.wakeLock.request("screen"); } catch(e) {}
|
try { _wakeLock = await navigator.wakeLock.request("screen"); } catch(e) {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sync button label when fullscreen is exited via Esc key
|
function _onFsChange() {
|
||||||
document.addEventListener("fullscreenchange", () => {
|
|
||||||
const btn = document.getElementById("kioskBtn");
|
const btn = document.getElementById("kioskBtn");
|
||||||
if (!document.fullscreenElement && !document.webkitFullscreenElement) {
|
if (!document.fullscreenElement && !document.webkitFullscreenElement) {
|
||||||
if (_wakeLock) { _wakeLock.release().catch(() => {}); _wakeLock = null; }
|
if (_wakeLock) { _wakeLock.release().catch(() => {}); _wakeLock = null; }
|
||||||
if (btn) { btn.textContent = "⛶ KIOSK"; btn.style.color = ""; }
|
if (btn) { btn.textContent = "⧞ KIOSK"; btn.style.color = ""; }
|
||||||
|
if (!isTablet()) document.body.classList.remove("tablet-mode");
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
document.addEventListener("webkitfullscreenchange", () => {
|
document.addEventListener("fullscreenchange", _onFsChange);
|
||||||
const btn = document.getElementById("kioskBtn");
|
document.addEventListener("webkitfullscreenchange", _onFsChange);
|
||||||
if (!document.webkitFullscreenElement && !document.fullscreenElement) {
|
|
||||||
if (_wakeLock) { _wakeLock.release().catch(() => {}); _wakeLock = null; }
|
|
||||||
if (btn) { btn.textContent = "⛶ KIOSK"; btn.style.color = ""; }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user