Merge Luma launcher fork into monorepo
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:
1 parent
bc3ca0f3b9
commit
cbea5a322f
204 files changed
+25056
-65
No files matched your search
@@ -0,0 +1,100 @@
|
||||
// Embedded in the native executable and run only through Homebrew's elevated
|
||||
// exec service when jailed file reads fail. Compatible with webOS's Node 8.
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var source = JSON.parse(process.argv[1]);
|
||||
var roots = [
|
||||
'/media/developer/apps/usr/palm/applications',
|
||||
'/media/cryptofs/apps/usr/palm/applications',
|
||||
'/usr/palm/applications'
|
||||
];
|
||||
var remaining = 512 * 1024;
|
||||
var icons = [];
|
||||
var seen = Object.create(null);
|
||||
|
||||
function read(file, limit) {
|
||||
var fd;
|
||||
try {
|
||||
fd = fs.openSync(file, 'r');
|
||||
var stat = fs.fstatSync(fd);
|
||||
if (!stat.isFile() || stat.size > limit) return null;
|
||||
var bytes = Buffer.alloc(stat.size);
|
||||
var offset = 0;
|
||||
while (offset < bytes.length) {
|
||||
var count = fs.readSync(fd, bytes, offset, bytes.length - offset, offset);
|
||||
if (!count) return null;
|
||||
offset += count;
|
||||
}
|
||||
return bytes;
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT' && error.code !== 'EACCES') console.error(error.message);
|
||||
return null;
|
||||
} finally {
|
||||
if (fd !== undefined) fs.closeSync(fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
typeof source.id !== 'string' ||
|
||||
source.id.length > 128 ||
|
||||
!/^[a-zA-Z0-9]+([._-][a-zA-Z0-9]+)*$/.test(source.id)
|
||||
) {
|
||||
throw new Error('Invalid application ID');
|
||||
}
|
||||
var directories = roots.map(function (root) {
|
||||
return path.join(root, source.id);
|
||||
});
|
||||
if (
|
||||
typeof source.directory === 'string' &&
|
||||
roots.indexOf(path.dirname(source.directory)) >= 0 &&
|
||||
source.directory.split('/').indexOf('..') < 0
|
||||
) {
|
||||
if (directories.indexOf(source.directory) >= 0)
|
||||
directories.splice(directories.indexOf(source.directory), 1);
|
||||
directories.unshift(source.directory);
|
||||
}
|
||||
directories.forEach(function (directory) {
|
||||
var manifest = {};
|
||||
var bytes = read(path.join(directory, 'appinfo.json'), 64 * 1024);
|
||||
if (bytes) {
|
||||
try {
|
||||
manifest = JSON.parse(bytes.toString('utf8'));
|
||||
if (!manifest || manifest.id !== source.id) manifest = {};
|
||||
} catch (error) {
|
||||
manifest = {};
|
||||
console.error('Invalid app manifest: ' + error.message);
|
||||
}
|
||||
}
|
||||
[source.large_icon, manifest.largeIcon, source.icon, manifest.icon, 'icon.png'].forEach(
|
||||
function (icon) {
|
||||
if (
|
||||
typeof icon !== 'string' ||
|
||||
!icon ||
|
||||
icon.length > 4096 ||
|
||||
icon.split('').some(function (character) {
|
||||
var code = character.charCodeAt(0);
|
||||
return code < 32 || code === 127;
|
||||
})
|
||||
)
|
||||
return;
|
||||
icon = icon.replace(/^file:\/\//, '');
|
||||
if (icon.indexOf('://') >= 0) return;
|
||||
if (icon.split('/').indexOf('..') >= 0) return;
|
||||
var file = path.resolve(directory, icon);
|
||||
if (['.png', '.jpg', '.jpeg', '.webp'].indexOf(path.extname(file).toLowerCase()) < 0) return;
|
||||
if (
|
||||
!roots.some(function (root) {
|
||||
return file.indexOf(root + '/') === 0;
|
||||
}) ||
|
||||
seen[file]
|
||||
)
|
||||
return;
|
||||
seen[file] = true;
|
||||
var data = read(file, remaining);
|
||||
if (!data || !data.length) return;
|
||||
remaining -= data.length;
|
||||
icons.push(data.toString('hex'));
|
||||
}
|
||||
);
|
||||
});
|
||||
console.log(JSON.stringify({ returnValue: true, icons: icons }));
|
||||
Reference in new issue
Block a user