release: 5.0.14 — Command Palette Localization + Klarere Hints
Aus dem 2. Screenshot-Pass (scripts/ui-screenshot2.js — Modals, Hover, responsive): - Command Palette war teilweise hardcoded Deutsch: Input-Placeholder 'Suche Befehl...' + Hint-Zeile 'Up/Down zum Navigieren, Enter zum Ausfuehren, Esc zum Schliessen'. Im EN-Mode zeigte das trotzdem Deutsch. Jetzt ueber Locale-Keys (commandPaletteSearchPlaceholder + commandPaletteHint) verdrahtet — zeigt 'Search command...' / 'Up/Down to navigate, Enter to run, Esc to close' im EN-Mode. - Command-Hint von 'Tab' auf 'Open' geaendert — 'Tab' las sich wie eine Tastatur-Taste statt 'oeffnet diesen Tab'. Verifiziert: Trim-Modal, Merge/Clips/Archive/Stats Tabs, alle 5 Themes, Light-Theme Inputs — alles sauber. minWidth:1200 -> sub-1200px responsive ist kein realer Fall. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
951158fe5a
commit
7ef1ce1a6f
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "twitch-vod-manager",
|
"name": "twitch-vod-manager",
|
||||||
"version": "5.0.13",
|
"version": "5.0.14",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "twitch-vod-manager",
|
"name": "twitch-vod-manager",
|
||||||
"version": "5.0.13",
|
"version": "5.0.14",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.16.1",
|
"axios": "^1.16.1",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "twitch-vod-manager",
|
"name": "twitch-vod-manager",
|
||||||
"version": "5.0.13",
|
"version": "5.0.14",
|
||||||
"description": "Twitch VOD Manager - Download Twitch VODs easily",
|
"description": "Twitch VOD Manager - Download Twitch VODs easily",
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
"author": "xRangerDE",
|
"author": "xRangerDE",
|
||||||
|
|||||||
90
scripts/ui-screenshot2.js
Normal file
90
scripts/ui-screenshot2.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// UI-Screenshot Teil 2 — Modals, Hover-States, schmales Fenster, Queue mit
|
||||||
|
// aktivem Download. Ergaenzt ui-screenshot.js fuer die selteneren UI-Pfade.
|
||||||
|
const { _electron: electron } = require('playwright');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const OUT_DIR = path.join(process.cwd(), 'tmp_ui_shots');
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
fs.mkdirSync(OUT_DIR, { recursive: true });
|
||||||
|
const electronPath = require('electron');
|
||||||
|
const app = await electron.launch({ executablePath: electronPath, args: ['.'], cwd: process.cwd() });
|
||||||
|
const win = await app.firstWindow();
|
||||||
|
await win.setViewportSize({ width: 1280, height: 900 });
|
||||||
|
await win.waitForTimeout(2500);
|
||||||
|
|
||||||
|
const shot = async (name) => {
|
||||||
|
try { await win.screenshot({ path: path.join(OUT_DIR, `${name}.png`), animations: 'disabled', timeout: 8000 }); process.stdout.write(`shot: ${name}\n`); }
|
||||||
|
catch (e) { process.stdout.write(`shot FAILED: ${name} — ${String(e).split('\n')[0]}\n`); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// VODs mit xqc laden fuer Modal-Kontext
|
||||||
|
await win.evaluate(() => window.showTab('vods'));
|
||||||
|
await win.evaluate(async () => { await window.selectStreamer('xqc'); });
|
||||||
|
await win.waitForTimeout(4000);
|
||||||
|
|
||||||
|
// 1. Clip/Trim-Dialog Modal (Trim VOD auf erster Card)
|
||||||
|
const trimBtn = win.locator('.vod-card .vod-btn.secondary').first();
|
||||||
|
if (await trimBtn.count()) {
|
||||||
|
await trimBtn.click().catch(() => {});
|
||||||
|
await win.waitForTimeout(800);
|
||||||
|
await shot('07-modal-trim');
|
||||||
|
await win.keyboard.press('Escape');
|
||||||
|
await win.waitForTimeout(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Command Palette (Ctrl+K)
|
||||||
|
await win.keyboard.press('Control+K');
|
||||||
|
await win.waitForTimeout(500);
|
||||||
|
await shot('08-command-palette');
|
||||||
|
// Tippe etwas zum Filtern
|
||||||
|
await win.keyboard.type('set');
|
||||||
|
await win.waitForTimeout(300);
|
||||||
|
await shot('08-command-palette-filtered');
|
||||||
|
await win.keyboard.press('Escape');
|
||||||
|
await win.waitForTimeout(300);
|
||||||
|
|
||||||
|
// 3. Template Guide Modal (Settings -> Template-Guide oeffnen falls Button da)
|
||||||
|
await win.evaluate(() => window.showTab('settings'));
|
||||||
|
await win.waitForTimeout(500);
|
||||||
|
const tgOpened = await win.evaluate(() => {
|
||||||
|
if (typeof window.openTemplateGuide === 'function') { window.openTemplateGuide(); return true; }
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (tgOpened) {
|
||||||
|
await win.waitForTimeout(700);
|
||||||
|
await shot('09-template-guide');
|
||||||
|
await win.keyboard.press('Escape');
|
||||||
|
await win.waitForTimeout(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. VOD-Card Hover (Storyboard-Preview)
|
||||||
|
await win.evaluate(() => window.showTab('vods'));
|
||||||
|
await win.waitForTimeout(800);
|
||||||
|
const firstCard = win.locator('.vod-card').first();
|
||||||
|
if (await firstCard.count()) {
|
||||||
|
await firstCard.hover();
|
||||||
|
await win.waitForTimeout(1200); // debounce + storyboard fetch
|
||||||
|
await shot('10-vod-hover');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Schmales Fenster (responsive) — 760px
|
||||||
|
await win.setViewportSize({ width: 760, height: 900 });
|
||||||
|
await win.waitForTimeout(800);
|
||||||
|
await shot('11-narrow-vods');
|
||||||
|
await win.evaluate(() => window.showTab('settings'));
|
||||||
|
await win.waitForTimeout(500);
|
||||||
|
await shot('11-narrow-settings');
|
||||||
|
|
||||||
|
// 6. Sehr schmal — 520px
|
||||||
|
await win.setViewportSize({ width: 520, height: 800 });
|
||||||
|
await win.evaluate(() => window.showTab('vods'));
|
||||||
|
await win.waitForTimeout(800);
|
||||||
|
await shot('12-tiny-vods');
|
||||||
|
|
||||||
|
await app.close();
|
||||||
|
process.stdout.write(`\nDone part 2.\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((e) => { process.stderr.write(String(e) + '\n'); process.exit(1); });
|
||||||
@ -821,10 +821,10 @@
|
|||||||
placeholder="Suche Befehl..."
|
placeholder="Suche Befehl..."
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
aria-label="Command Palette Suche"
|
aria-label="Command Palette"
|
||||||
/>
|
/>
|
||||||
<ul id="commandPaletteList" class="cp-list" role="listbox" aria-label="Command results"></ul>
|
<ul id="commandPaletteList" class="cp-list" role="listbox" aria-label="Command results"></ul>
|
||||||
<p class="cp-hint">Up/Down zum Navigieren, Enter zum Ausfuhren, Esc zum Schliessen</p>
|
<p class="cp-hint" id="commandPaletteHint">Up/Down zum Navigieren, Enter zum Ausfuehren, Esc zum Schliessen</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -28,13 +28,15 @@ interface PaletteCommand {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hint 'Open' statt 'Tab' — 'Tab' las sich wie eine Tastatur-Taste
|
||||||
|
// ('druecke Tab') statt 'oeffnet diesen Tab'.
|
||||||
const tabs: Array<{ id: string; labels: string[]; hint: string }> = [
|
const tabs: Array<{ id: string; labels: string[]; hint: string }> = [
|
||||||
{ id: 'vods', labels: ['VODs', 'videos', 'streams'], hint: 'Tab' },
|
{ id: 'vods', labels: ['VODs', 'videos', 'streams'], hint: 'Open' },
|
||||||
{ id: 'queue', labels: ['Queue', 'downloads', 'warteschlange'], hint: 'Tab' },
|
{ id: 'queue', labels: ['Queue', 'downloads', 'warteschlange'], hint: 'Open' },
|
||||||
{ id: 'streamers', labels: ['Streamers', 'channels'], hint: 'Tab' },
|
{ id: 'streamers', labels: ['Streamers', 'channels'], hint: 'Open' },
|
||||||
{ id: 'stats', labels: ['Stats', 'statistiken', 'dashboard'], hint: 'Tab' },
|
{ id: 'stats', labels: ['Stats', 'statistiken', 'dashboard'], hint: 'Open' },
|
||||||
{ id: 'archive', labels: ['Archive', 'archiv'], hint: 'Tab' },
|
{ id: 'archive', labels: ['Archive', 'archiv'], hint: 'Open' },
|
||||||
{ id: 'settings', labels: ['Settings', 'einstellungen', 'config'], hint: 'Tab' },
|
{ id: 'settings', labels: ['Settings', 'einstellungen', 'config'], hint: 'Open' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const tabCommands: PaletteCommand[] = tabs.map(t => ({
|
const tabCommands: PaletteCommand[] = tabs.map(t => ({
|
||||||
|
|||||||
@ -22,6 +22,8 @@ const UI_TEXT_DE = {
|
|||||||
cutterSelectTitle: 'Video auswahlen',
|
cutterSelectTitle: 'Video auswahlen',
|
||||||
cutterPreviewPlaceholder: 'Video auswahlen um Vorschau zu sehen',
|
cutterPreviewPlaceholder: 'Video auswahlen um Vorschau zu sehen',
|
||||||
cutterBrowse: 'Durchsuchen',
|
cutterBrowse: 'Durchsuchen',
|
||||||
|
commandPaletteSearchPlaceholder: 'Befehl suchen...',
|
||||||
|
commandPaletteHint: 'Up/Down zum Navigieren, Enter zum Ausfuehren, Esc zum Schliessen',
|
||||||
mergeTitle: 'Videos zusammenfugen',
|
mergeTitle: 'Videos zusammenfugen',
|
||||||
mergeDesc: 'Wahle mehrere Videos aus, um sie zu einem Video zusammenzufugen. Die Reihenfolge kann geandert werden.',
|
mergeDesc: 'Wahle mehrere Videos aus, um sie zu einem Video zusammenzufugen. Die Reihenfolge kann geandert werden.',
|
||||||
mergeAdd: '+ Videos hinzufugen',
|
mergeAdd: '+ Videos hinzufugen',
|
||||||
|
|||||||
@ -22,6 +22,8 @@ const UI_TEXT_EN = {
|
|||||||
cutterSelectTitle: 'Select video',
|
cutterSelectTitle: 'Select video',
|
||||||
cutterPreviewPlaceholder: 'Select a video to see a preview',
|
cutterPreviewPlaceholder: 'Select a video to see a preview',
|
||||||
cutterBrowse: 'Browse',
|
cutterBrowse: 'Browse',
|
||||||
|
commandPaletteSearchPlaceholder: 'Search command...',
|
||||||
|
commandPaletteHint: 'Up/Down to navigate, Enter to run, Esc to close',
|
||||||
mergeTitle: 'Merge videos',
|
mergeTitle: 'Merge videos',
|
||||||
mergeDesc: 'Select multiple videos to merge into one file. You can change the order before merging.',
|
mergeDesc: 'Select multiple videos to merge into one file. You can change the order before merging.',
|
||||||
mergeAdd: '+ Add videos',
|
mergeAdd: '+ Add videos',
|
||||||
|
|||||||
@ -120,6 +120,8 @@ function applyLanguageToStaticUI(): void {
|
|||||||
setText('cutterSelectTitle', UI_TEXT.static.cutterSelectTitle);
|
setText('cutterSelectTitle', UI_TEXT.static.cutterSelectTitle);
|
||||||
setText('cutterPreviewPlaceholder', UI_TEXT.static.cutterPreviewPlaceholder);
|
setText('cutterPreviewPlaceholder', UI_TEXT.static.cutterPreviewPlaceholder);
|
||||||
setText('cutterBrowseBtn', UI_TEXT.static.cutterBrowse);
|
setText('cutterBrowseBtn', UI_TEXT.static.cutterBrowse);
|
||||||
|
setPlaceholder('commandPaletteInput', UI_TEXT.static.commandPaletteSearchPlaceholder);
|
||||||
|
setText('commandPaletteHint', UI_TEXT.static.commandPaletteHint);
|
||||||
setText('cutterInfoDurationLabel', UI_TEXT.cutter.infoDuration);
|
setText('cutterInfoDurationLabel', UI_TEXT.cutter.infoDuration);
|
||||||
setText('cutterInfoResolutionLabel', UI_TEXT.cutter.infoResolution);
|
setText('cutterInfoResolutionLabel', UI_TEXT.cutter.infoResolution);
|
||||||
setText('cutterInfoFpsLabel', UI_TEXT.cutter.infoFps);
|
setText('cutterInfoFpsLabel', UI_TEXT.cutter.infoFps);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user