Skip to content

Commit 0831ae9

Browse files
committed
Defer heavy dashboard work in mobile app
1 parent bc30da5 commit 0831ae9

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

custom_components/oig_cloud/www/js/core/core.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,18 @@ function runWhenIdle(task, timeoutMs = 2000, fallbackDelayMs = 600) {
3636
function detectHaApp() {
3737
try {
3838
const ua = window.navigator?.userAgent || '';
39-
return /Home Assistant/i.test(ua);
39+
return /Home Assistant|HomeAssistant/i.test(ua);
40+
} catch (e) {
41+
return false;
42+
}
43+
}
44+
45+
function detectMobile() {
46+
try {
47+
const ua = window.navigator?.userAgent || '';
48+
const mobileUA = /Android|iPhone|iPad|iPod|Mobile/i.test(ua);
49+
const smallViewport = window.innerWidth <= 768 || window.matchMedia?.('(max-width: 768px)')?.matches;
50+
return mobileUA || !!smallViewport;
4051
} catch (e) {
4152
return false;
4253
}
@@ -46,6 +57,9 @@ window.OIG_RUNTIME = window.OIG_RUNTIME || {};
4657
if (window.OIG_RUNTIME.isHaApp === undefined) {
4758
window.OIG_RUNTIME.isHaApp = detectHaApp();
4859
}
60+
if (window.OIG_RUNTIME.isMobile === undefined) {
61+
window.OIG_RUNTIME.isMobile = detectMobile();
62+
}
4963
if (window.OIG_RUNTIME.initialLoadComplete === undefined) {
5064
window.OIG_RUNTIME.initialLoadComplete = false;
5165
}
@@ -321,6 +335,7 @@ var closeGridChargingDialog = window.DashboardGridCharging?.closeGridChargingDia
321335
// === INITIALIZATION ===
322336
function init() {
323337
console.log('[Dashboard] Initializing...');
338+
const isConstrainedRuntime = !!(window.OIG_RUNTIME?.isHaApp || window.OIG_RUNTIME?.isMobile);
324339

325340
// Detekovat a aplikovat téma z Home Assistantu
326341
detectAndApplyTheme();
@@ -369,16 +384,16 @@ function init() {
369384
const startHeavyLoad = () => {
370385
forceFullRefresh();
371386
};
372-
if (window.OIG_RUNTIME?.isHaApp) {
373-
setTimeout(() => runWhenIdle(startHeavyLoad, 2500, 900), 200);
387+
if (isConstrainedRuntime) {
388+
setTimeout(() => runWhenIdle(startHeavyLoad, 3500, 1200), 200);
374389
} else {
375390
startHeavyLoad();
376391
}
377392

378393
updateTime();
379394

380395
// NOVÉ: Load extended timeline for Today Plan Tile
381-
runWhenIdle(buildExtendedTimeline, 2500, 900);
396+
runWhenIdle(buildExtendedTimeline, isConstrainedRuntime ? 3500 : 2500, isConstrainedRuntime ? 1200 : 900);
382397

383398
// OPRAVA: Načíst pricing data pokud je pricing tab aktivní při načtení stránky
384399
const pricingTab = document.getElementById('pricing-tab');
@@ -566,10 +581,18 @@ function init() {
566581
// Problém: Po restartu HA se někdy načítají CSS/HTML v jiném pořadí
567582
// Řešení: Opakované překreslení po různých intervalech
568583
// OPRAVA BUG #3: Inicializovat cache před prvním kreslením
569-
setTimeout(() => { getNodeCenters(); drawConnections(); }, 100); // První pokus po 100ms
570-
setTimeout(() => { getNodeCenters(); drawConnections(); }, 500); // Druhý pokus po 500ms
571-
setTimeout(() => { getNodeCenters(); drawConnections(); }, 1000); // Třetí pokus po 1s
572-
setTimeout(() => { getNodeCenters(); drawConnections(); }, 2000); // Finální po 2s
584+
const scheduleConnectionsDraw = (delay) => {
585+
setTimeout(() => { getNodeCenters(); drawConnections(); }, delay);
586+
};
587+
if (isConstrainedRuntime) {
588+
scheduleConnectionsDraw(200); // První pokus po 200ms (mobile/HA app)
589+
scheduleConnectionsDraw(1200); // Finální po 1.2s
590+
} else {
591+
scheduleConnectionsDraw(100); // První pokus po 100ms
592+
scheduleConnectionsDraw(500); // Druhý pokus po 500ms
593+
scheduleConnectionsDraw(1000); // Třetí pokus po 1s
594+
scheduleConnectionsDraw(2000); // Finální po 2s
595+
}
573596

574597
// Mobile: Toggle node details on click (collapsed by default)
575598
if (window.innerWidth <= 768) {

custom_components/oig_cloud/www/js/features/flow.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,9 +1150,10 @@ async function loadData() {
11501150
return;
11511151
}
11521152
loadDataInProgress = true;
1153-
try {
11541153
const runtime = window.OIG_RUNTIME || {};
1155-
const shouldYield = !!runtime.isHaApp && !runtime.initialLoadComplete;
1154+
try {
1155+
const isConstrainedRuntime = !!runtime.isHaApp || !!runtime.isMobile || window.innerWidth <= 768;
1156+
const shouldYield = isConstrainedRuntime && !runtime.initialLoadComplete;
11561157
const yieldIfNeeded = async () => {
11571158
if (!shouldYield) return;
11581159
await new Promise(resolve => {
@@ -1415,6 +1416,7 @@ async function loadData() {
14151416
}
14161417

14171418
await updatePlannerModeBadge();
1419+
await yieldIfNeeded();
14181420

14191421
// Aktualizovat boiler mode (ve flow diagramu), ale zachovat třídu mode-changing pokud existuje
14201422
const boilerModeFlowData = await getSensorStringSafe(getSensorId('boiler_manual_mode'));
@@ -1562,7 +1564,11 @@ async function loadData() {
15621564
const flowTab = document.querySelector('#flow-tab');
15631565
const isFlowTabActive = flowTab && flowTab.classList.contains('active');
15641566
if (isFlowTabActive) {
1565-
animateFlow(currentPowerValues);
1567+
if (isConstrainedRuntime && !runtime.initialLoadComplete) {
1568+
runtime.pendingFlowValues = currentPowerValues;
1569+
} else {
1570+
animateFlow(currentPowerValues);
1571+
}
15661572
}
15671573
}
15681574

@@ -1575,7 +1581,7 @@ async function loadData() {
15751581
// Load details for all nodes (only on first load or explicit refresh)
15761582
if (!previousValues['node-details-loaded']) {
15771583
// Do not await heavy details on first render; it can freeze iOS WebView.
1578-
if (runtime.isHaApp && !runtime.initialLoadComplete) {
1584+
if ((runtime.isHaApp || runtime.isMobile || window.innerWidth <= 768) && !runtime.initialLoadComplete) {
15791585
if (!runtime.nodeDetailsScheduled) {
15801586
runtime.nodeDetailsScheduled = true;
15811587
setTimeout(() => {
@@ -1618,6 +1624,16 @@ async function loadData() {
16181624
if (window.OIG_RUNTIME) {
16191625
window.OIG_RUNTIME.initialLoadComplete = true;
16201626
}
1627+
if (runtime.pendingFlowValues && (runtime.isHaApp || runtime.isMobile || window.innerWidth <= 768)) {
1628+
const pendingValues = runtime.pendingFlowValues;
1629+
runtime.pendingFlowValues = null;
1630+
setTimeout(() => {
1631+
const flowTab = document.querySelector('#flow-tab');
1632+
if (flowTab && flowTab.classList.contains('active')) {
1633+
animateFlow(pendingValues);
1634+
}
1635+
}, 400);
1636+
}
16211637
if (loadDataPending) {
16221638
loadDataPending = false;
16231639
setTimeout(() => loadData(), 0);

0 commit comments

Comments
 (0)