This commit is contained in:
Mateusz Gruszczyński
2026-09-07 11:38:55 +02:00
parent 749172e527
commit 0cb09769fd
17 changed files with 83 additions and 44 deletions
+1
View File
@@ -10,6 +10,7 @@
<link rel="icon" href="__GREE_BASE_PATH__/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="__GREE_STYLES_ASSET__">
<script src="__GREE_THEME_INIT_ASSET__"></script>
<script src="__GREE_LANG_INIT_ASSET__"></script>
<title>GREE Controller</title>
</head>
+2 -7
View File
@@ -265,19 +265,14 @@ function renderLanguageOptions() {
async function loadLanguages() {
try {
const languageNonce = Date.now().toString(36);
const languageUrl = path => {
const separator = String(path).includes('?') ? '&' : '?';
return `${withBase(path)}${separator}v=${languageNonce}`;
};
const response = await fetch(languageUrl('/lang/index.json'), { cache: 'no-store' });
const response = await fetch(withBase('/lang/index.json'));
if (!response.ok) throw new Error(`Language index HTTP ${response.status}`);
const manifest = await response.json();
const languages = Array.isArray(manifest.languages) ? manifest.languages : [];
if (!languages.some(item => item.code === DEFAULT_LANGUAGE)) throw new Error('Default English language pack is missing');
const loaded = await Promise.all(languages.map(async item => {
const packResponse = await fetch(languageUrl(item.path || `/lang/${encodeURIComponent(item.code)}.json`), { cache: 'no-store' });
const packResponse = await fetch(withBase(item.path || `/lang/${encodeURIComponent(item.code)}.json`));
if (!packResponse.ok) throw new Error(`Language ${item.code} HTTP ${packResponse.status}`);
const pack = await packResponse.json();
return { item, pack };
+8 -4
View File
@@ -4,10 +4,14 @@ window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', ()
if ('serviceWorker' in navigator) window.addEventListener('load', () => navigator.serviceWorker.register(withBase('/sw.js')).catch(() => { }));
async function startApplication() {
observeTopbarHeight();
applyTheme();
await loadLanguages();
applyTranslations();
try {
observeTopbarHeight();
applyTheme();
await loadLanguages();
applyTranslations();
} finally {
document.documentElement.classList.remove('i18n-loading');
}
setupFormUx();
updateZoneSensorFields();
updateSchedulePresetField();
+7
View File
@@ -0,0 +1,7 @@
'use strict';
(() => {
const row = document.cookie.split('; ').find(item => item.startsWith('gree_controller_language='));
const language = row ? decodeURIComponent(row.split('=').slice(1).join('=')) : 'en';
document.documentElement.lang = language || 'en';
document.documentElement.classList.add('i18n-loading');
})();
+4
View File
@@ -95,6 +95,10 @@ body {
color: var(--text);
}
html.i18n-loading body {
visibility: hidden;
}
button,
input,
select {
+1 -1
View File
@@ -1,7 +1,7 @@
const CACHE = 'gree-controller-__GREE_ASSET_CACHE__';
const SCOPE = new URL(self.registration.scope).pathname.replace(/\/$/, '');
const path = value => `${SCOPE}${value.startsWith('/') ? value : `/${value}`}` || '/';
const ASSETS = [path('__GREE_STYLES_ASSET__'), path('__GREE_APP_ASSET__'), path('__GREE_THEME_INIT_ASSET__'), path('/favicon.svg'), path('/manifest.webmanifest')];
const ASSETS = [path('__GREE_STYLES_ASSET__'), path('__GREE_APP_ASSET__'), path('__GREE_THEME_INIT_ASSET__'), path('__GREE_LANG_INIT_ASSET__'), path('/favicon.svg'), path('/manifest.webmanifest')];
self.addEventListener('install', event => event.waitUntil(caches.open(CACHE).then(cache => cache.addAll(ASSETS)).then(() => self.skipWaiting())));
self.addEventListener('activate', event => event.waitUntil(caches.keys().then(keys => Promise.all(keys.filter(key => key !== CACHE).map(key => caches.delete(key)))).then(() => self.clients.claim())));
self.addEventListener('fetch', event => {