Merge Luma launcher fork into monorepo
CI / Identify a merged version PR (push) Canceled after 0s
CI / Rust checks, rendering, and native package (push) Canceled after 0s
CI / Publish release and Homebrew feed (push) Canceled after 0s
Release PR / Maintain Version Packages PR (push) Canceled after 0s

Move trampoline files (boot-hook, watcher, overlay) into trampoline/
subdirectory. Add upstream Luma v2.3.1 source at repo root with our
additions:

- Page::Ha (4th nav tab) with placeholder empty state
- HA tab config schema and default entity mapping (ha-home/)
- Nav keys renamed: "home" → "start", new "ha" tab between Apps and Settings
- All state.rs/view.rs/main.rs/tests.rs updated for 4-tab navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Kaloyan DanchevandClaude Opus 4.6 committed 2026-10-24 11:52:55 +03:00
1 parent bc3ca0f3b9
commit cbea5a322f
204 files changed
+25056 -65

No files matched your search

+224
View File
@@ -0,0 +1,224 @@
// Optional host-only source refresh. Normal builds use the checked-in SVGs and
// never contact these hosts. Hashes cover the original bytes before adaptation.
import fs from 'node:fs/promises';
import path from 'node:path';
import { createHash } from 'node:crypto';
const root = path.resolve(import.meta.dirname, '..');
const simple =
'https://raw.githubusercontent.com/simple-icons/simple-icons/90bd1f3e7b77851fd0c56474f6fa43b816babdab';
const commons = (file) => {
file = decodeURIComponent(file);
const hash = createHash('md5').update(file).digest('hex');
return `https://upload.wikimedia.org/wikipedia/commons/${hash[0]}/${hash.slice(0, 2)}/${encodeURIComponent(file)}`;
};
export const sources = [
[
'spotify',
commons('Spotify_logo_with_text.svg'),
'c0e57c534e7fce5e66fb419c269b97d436385a2c69b9f508edf480ef60dedf91',
],
[
'plex',
`${simple}/icons/plex.svg`,
'129500c2bda2175c95402d12e0a96642de61a2561d45a4d9719edc8abd43c8ea',
],
[
'hbo-max',
commons('HBO_Max_%282025%29.svg'),
'c8728242f74e388ef3a507745875335528a4980123f2c4cae9f08d666fbda63b',
],
[
'paramount-plus',
`${simple}/icons/paramountplus.svg`,
'6b8a777222266eefdb08b9737cef97cdecf10143f5402d06634f615b127851f9',
],
[
'peacock',
commons('NBCUniversal_Peacock_Logo_%282026%29.svg'),
'bf53d69c5deda4de4db1997d0616cfc43ede490f5634003bfcc5094477595f2c',
],
[
'hulu',
commons('Hulu_logo_%282018%29.svg'),
'6bf705502216ffd2ad58721bcb1b76b93d3a2a31995dfa919ef34a847d038e1f',
],
[
'crunchyroll',
`${simple}/icons/crunchyroll.svg`,
'3b9c3d87339e18ec09f25e0c3eaffdc5ad4630df3d108fcd907e1b64c4cd13ea',
],
[
'twitch',
`${simple}/icons/twitch.svg`,
'dbe27bc02a01b8d89b6259cacef328c9fa70bb13c29f38c36eb1421863f6f0b6',
],
[
'dazn',
`${simple}/icons/dazn.svg`,
'19d9da58d96ee8bd05bf7253f706203dd0c1762469523b8960eb8efc3b1017ef',
],
[
'rakuten-tv',
commons('Rakuten_TV_logo.svg'),
'43b83db4948b04a3072ce264265452e59a65a4ccc4e32c710c73044ebf49ae86',
],
[
'apple-music',
commons('Apple_Music_Logo_%282026%29.svg'),
'974eab4dbecce108dcfc5299bce64a5461eb57a56a259d59d9e52bc4d9b29556',
],
[
'amazon-music',
commons('Amazon_Music_logo.svg'),
'71b407417a0a20e42c79e6e0a643c76fbd56e4aaacc0b7335178e13fd458ef60',
],
[
'bbc-iplayer',
commons('BBC_iPlayer_2021_%28Alt%29.svg'),
'05325387e1af09f7f177eb4dbb20225793949f92f6295bfd8604a01c2c98f63e',
],
[
'itvx',
`${simple}/icons/itvx.svg`,
'eafc08ffdda9c16ec292c03ed795a1111945240670f50ef6515b896efc8b4153',
],
[
'channel-4',
`${simple}/icons/channel4.svg`,
'cb7205ad42186cf48bb30e350753d0323e1f4efd03a33749c7e17e7868d4978a',
],
[
'now-tv',
`${simple}/icons/now.svg`,
'bcffe72bc6cc06123c6e2b736fb7c2d2ff432025ebd014118702b5b670d17a85',
],
[
'rtl-plus',
commons('RTL%2B_Logo_2021.svg'),
'4f28b89be7c76acec5b467e66df51fb332ea0c46a9cde4f3be6fb5270c105884',
],
[
'joyn',
commons('Joyn_logo.svg'),
'a5b387fbb02c2be6c1408e0d56d4c4ee32fd19eaf86a776fa05de38d6afb0570',
],
[
'waipu-tv',
commons('Waipu_TV_Logo_2016.svg'),
'1013fbb5274899a386f57b34413165b9a66933a1614855c5acaa2553a942be97',
],
[
'zattoo',
commons('Logo_Zattoo.svg'),
'2df3c7eaf5e953f2aef43353c622f6c6c06688a9649995b88effb2d1fc0fce5d',
],
[
'skyshowtime',
commons('SkyShowtime_Logo.svg'),
'da31ab32038e050cb759335057243054034556117552fa88d4e14457503daa92',
],
[
'coupang-play',
'https://raw.githubusercontent.com/SinJungho/Damoa_Team-Project/db1955f0f6f09d9329518120afe42af375632de0/src/svg/CoupangPlayLogo.jsx',
'0069daf83ee2b3389d6082d8dd09ed2007872752beab3191ba7922935ac99c36',
],
[
'tving',
commons('TVING_logo.svg'),
'4dd2952a96b1b0b4d879d1b6444e137806cddee3cd8352145d7266f4f726964c',
],
[
'wavve',
'https://www.wavve.com/static/element-icons-tag-ic-brand-wavve-b343dcb2.svg',
'b343dcb207257023fe27845d230699d6320134b780e8571f1e71095f8c71f0a8',
],
[
'watcha',
commons('Watcha_logo.svg'),
'6d1239c5fd4d9ad9e8dd54d07e13c65bf970552195ee6243ace814d3c5aff18a',
],
[
'movistar-plus',
commons('Movistar_Plus%2B_2022_logo.svg'),
'f8b775c43d273a9e1d97b539c22356392146271c89a9f2a9fb851863ea0600a8',
],
[
'filmin',
'https://raw.githubusercontent.com/DCueto/filmin-svelte-clone/36c977e31ec76abb42473b243584acbaed23579f/src/assets/filmin_logo.svg',
'f9fbaec75b29bedec27236bf3717701b8871344e5bcb0ac8bc2e8c9a0c127b4d',
],
];
async function download(url) {
const response = await fetch(url, { signal: AbortSignal.timeout(60000) });
if (!response.ok) throw new Error(`${response.status}: ${url}`);
const text = await response.text();
if (!text.includes('<svg') || text.includes('data:image/'))
throw new Error(`Not standalone vector artwork: ${url}`);
return text;
}
// The Coupang SVG was distributed as a component. Keep only its static SVG
// paths, resolving numeric JSX attributes and removing its redundant bounds clip.
export function prepareSvg(name, original, url) {
let svg = original.replace(/<\?xml[^?]*\?>/, '');
if (name === 'crunchyroll') {
svg = svg.replace('<svg ', '<svg fill="#FF5E00" ');
}
if (name === 'coupang-play') {
svg = svg
.slice(svg.indexOf('<svg'), svg.lastIndexOf('</svg>') + 6)
.replace(/style=\{\{[\s\S]*?\}\}/g, '')
.replace(/=\{([\d.]+)\}/g, '="$1"')
.replace(/<defs>[\s\S]*?<\/defs>/g, '')
.replace(/\sclip-path="[^"]*"/g, '');
}
if (['peacock', 'watcha'].includes(name)) {
// These clips only repeat the artwork's rectangular outer bounds. Keep
// gradient definitions while removing the redundant clipping wrapper.
svg = svg
.replace(/<clipPath\b[^>]*>[\s\S]*?<\/clipPath>/g, '')
.replace(/\sclip-path="[^"]*"/g, '');
}
// Source provenance stays beside the original paths. Display-only white
// treatments and tight bounds are applied by the host mesh compiler.
return `<!-- Source: ${url} -->\n${svg.trim()}\n`;
}
if (process.argv[1] && path.resolve(process.argv[1]) === import.meta.filename) {
const checksums = process.argv.includes('--checksums');
const only = process.argv.includes('--only')
? process.argv[process.argv.indexOf('--only') + 1]
: undefined;
if (process.argv.includes('--only') && !sources.some(([name]) => name === only)) {
throw new Error('Pass a known brand name after --only');
}
for (const [name, url, expected] of sources) {
if (only && name !== only) continue;
let original;
try {
original = await download(url);
} catch (error) {
if (!checksums) throw error;
console.error(`${name}: ${error.message}`);
continue;
}
const digest = createHash('sha256').update(original).digest('hex');
if (checksums) {
console.log(`${name} ${digest} ${Buffer.byteLength(original)}`);
continue;
}
if (digest !== expected) throw new Error(`Source checksum mismatch: ${name}`);
await fs.writeFile(
path.join(root, 'assets/logos', `${name}.svg`),
prepareSvg(name, original, url),
);
console.log(`Restored vector source: ${name}`);
}
if (!checksums && !only) {
const response = await fetch(`${simple}/LICENSE.md`, { signal: AbortSignal.timeout(60000) });
if (!response.ok) throw new Error('Could not restore the Simple Icons CC0 notice');
await fs.writeFile(path.join(root, 'assets/licenses/simple-icons.txt'), await response.text());
}
}