feat: Playtube Stream Dock Plugin 1.0.0 (Ajazz AKP153E) mit Icon-Pack

This commit is contained in:
2026-09-26 21:00:36 +02:00
commit 179a785adb
221 changed files with 10254 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
// Erzeugt das Playtube-Icon-Pack (PNG, 288x288) in zwei Varianten und packt es als Zip.
// Aufruf: npm run iconpack
import { execFileSync } from 'node:child_process';
import { copyFileSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { Canvas } from './raster.mjs';
import { drawGlyph, GLYPHS } from './glyphs.mjs';
import { drawExtra, EXTRA_GLYPHS } from './glyphs-extra.mjs';
import { drawApp, APP_GLYPHS } from './glyphs-apps.mjs';
import { DARK_BG, WHITE, brandGradient } from './brand.mjs';
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const PACK_NAME = 'Playtube-Icons';
const PACK_DIR = path.join(ROOT, 'iconpack', PACK_NAME);
const ZIP = path.join(ROOT, 'dist', `${PACK_NAME}.zip`);
const SIZE = 288;
const GLYPH_RADIUS = SIZE * 0.31;
const README = `Playtube Icon Pack
==================
Ordner:
gradient/ Playtube-Look: Verlauf violett -> pink, weisses Symbol
dark/ dunkler Hintergrund, Symbol im Playtube-Verlauf
Alle Bilder: PNG, 288 x 288 Pixel (das Geraet nutzt 144 x 144, die doppelte Groesse bleibt beim
Verkleinern scharf).
Benutzen in der Stream-Dock-Software:
Taste anklicken -> das Vorschaubild der Taste (oben links im Einstellungsbereich) anklicken ->
"Bild waehlen" / Ordner-Symbol -> eine PNG-Datei aus diesem Pack auswaehlen.
`;
function render(variant, drawer, name) {
const canvas = new Canvas(SIZE);
const gradient = brandGradient(SIZE);
const background = variant === 'gradient' ? gradient : DARK_BG;
canvas.roundRect(0, 0, SIZE, SIZE, 0, background);
drawer(canvas, name, SIZE / 2, SIZE / 2, GLYPH_RADIUS, variant === 'gradient' ? WHITE : gradient, background);
return canvas.png();
}
const SD_PACK_DIR = path.join(ROOT, 'iconpack', 'com.fojadrachi.playtube.sdIconPack');
// Deutsche Suchbegriffe zusaetzlich zu den englischen Symbolnamen.
const GERMAN_TAGS = {
folder: ['ordner'], file: ['datei'], home: ['start', 'zuhause'], gear: ['einstellungen', 'zahnrad'],
plus: ['hinzufuegen'], minus: ['entfernen'], close: ['schliessen'], check: ['haken', 'ok'], star: ['stern', 'favorit'],
search: ['suche', 'lupe'], power: ['ein', 'aus'], mic: ['mikrofon'], headphones: ['kopfhoerer'], lock: ['schloss'],
bell: ['glocke', 'benachrichtigung'], clock: ['uhr', 'zeit'], calendar: ['kalender'], mail: ['post', 'email'],
globe: ['welt', 'internet'], download: ['herunterladen'], upload: ['hochladen'], trash: ['papierkorb', 'loeschen'],
eye: ['auge', 'anzeigen'], stop: ['stopp'], refresh: ['aktualisieren', 'neu laden'], wifi: ['wlan'], grid: ['raster'],
menu: ['menue'], more: ['mehr'], info: ['information'], warning: ['warnung'], monitor: ['bildschirm'],
sun: ['sonne', 'hell'], moon: ['mond', 'dunkel'], play: ['abspielen'], pause: ['pause'], next: ['weiter', 'naechster'],
previous: ['zurueck', 'vorheriger'], volup: ['lauter'], voldown: ['leiser'], vol: ['lautstaerke'], mute: ['stumm'],
heart: ['herz', 'gefaellt mir'], shuffle: ['zufall'], repeat: ['wiederholen'], playlist: ['liste'],
'eye-off': ['auge', 'ausblenden', 'verstecken'], lightbulb: ['gluehbirne', 'licht', 'lampe'],
'pc-monitor': ['pc', 'computer', 'system', 'monitor', 'leistung'], chrome: ['browser', 'google'],
discord: ['chat', 'voice'], steam: ['spiele', 'games'], twitch: ['stream', 'live'], netflix: ['serien', 'filme'],
youtube: ['video'], medal: ['clips', 'aufnahme'], nvidia: ['grafikkarte', 'gpu'], steelseries: ['sonar', 'audio'],
aniworld: ['anime'], prismlens: ['filter', 'kamera'],
};
/** Stream-Dock-Icon-Pack (.sdIconPack): manifest.json, icons.json, icon.png und icons/*.png. */
function buildStreamDockPack(jobs) {
rmSync(SD_PACK_DIR, { recursive: true, force: true });
mkdirSync(path.join(SD_PACK_DIR, 'icons'), { recursive: true });
mkdirSync(path.join(SD_PACK_DIR, 'previews'), { recursive: true });
const entries = [];
for (const variant of ['gradient', 'dark']) {
for (const { name } of jobs) {
const file = `${variant}_${name}.png`;
copyFileSync(path.join(PACK_DIR, variant, `${name}.png`), path.join(SD_PACK_DIR, 'icons', file));
const base = name.split('-')[0];
entries.push({
path: file,
name: `${name.replace(/-/g, ' ')} (${variant})`,
tags: ['playtube', variant, ...name.split('-'), ...(GERMAN_TAGS[name] || GERMAN_TAGS[base] || [])],
});
}
}
writeFileSync(path.join(SD_PACK_DIR, 'icons.json'), `${JSON.stringify(entries, null, 2)}\n`);
writeFileSync(path.join(SD_PACK_DIR, 'manifest.json'), `${JSON.stringify({
Name: 'Playtube Icons',
Version: '1.0.0',
Description: 'Icons im Playtube-Look (Verlauf violett/pink): Ordner, Pfeile, Player-Symbole und mehr.',
Author: 'Playtube',
Icon: 'icon.png',
}, null, 2)}\n`);
const logo = render('gradient', drawGlyph, 'play');
writeFileSync(path.join(SD_PACK_DIR, 'icon.png'), logo);
writeFileSync(path.join(SD_PACK_DIR, 'previews', 'preview1.png'), logo);
}
function main() {
rmSync(PACK_DIR, { recursive: true, force: true });
const jobs = [
...GLYPHS.map((name) => ({ name, drawer: drawGlyph })),
...EXTRA_GLYPHS.map((name) => ({ name, drawer: drawExtra })),
...APP_GLYPHS.map((name) => ({ name, drawer: drawApp })),
];
for (const variant of ['gradient', 'dark']) {
mkdirSync(path.join(PACK_DIR, variant), { recursive: true });
for (const { name, drawer } of jobs) {
writeFileSync(path.join(PACK_DIR, variant, `${name}.png`), render(variant, drawer, name));
}
}
writeFileSync(path.join(PACK_DIR, 'LIESMICH.txt'), README);
buildStreamDockPack(jobs);
mkdirSync(path.dirname(ZIP), { recursive: true });
rmSync(ZIP, { force: true });
// Unter Windows das mitgelieferte bsdtar (Git-Bash-GNU-tar liest "C:" als Netzwerk-Host).
const tar = process.platform === 'win32' ? path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'tar.exe') : 'tar';
execFileSync(tar, ['-a', '-c', '-f', ZIP, '-C', path.dirname(PACK_DIR), PACK_NAME], { stdio: 'inherit' });
process.stdout.write(`${jobs.length} Symbole x 2 Varianten -> ${PACK_DIR}\nZip: ${ZIP}\n`);
}
main();