Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ per Windows (portatile e installabile), Mac e Android, e va online su [GitHub Pa
- **Clear** (licenza source-available, non permissiva) si può spegnere dal Centro AI.
- **Nota onesta**: i modelli veri non sono stati scaricati né eseguiti; prove con motori finti (`test/unit/funzioni-ai.test.mjs`, `test/unit/motore_ai_server*.py`).

## [1.8.5] — 2026-10-30 · Revisione finale: tutto in ordine

- **Montaggio più pulito**: barra del contenitore con le sole voci principali, lettere dei tasti leggibili (la S non sembra più un 5), Esc chiude il menu del tasto destro, velocità scritte ×0,25 / ×0,5.
- **Mixer e Strumenti** stanno nella colonna senza tagli; la colonna destra si allarga sugli schermi grandi.
- **Modifica clip**: tessere degli effetti più piccole (sei per riga), niente doppioni, etichette intere.
- **Finale** senza titoli ripetuti; **LIVE** con REGISTRA unico pulsante oro; **Montage** con tutti i 28 stili a schermo.
- **Guida, Novità, Cerca, Centro AI e finestre di sicurezza** rifinite; testi lunghi con i puntini e il testo intero al passaggio.
- **README nuovo** come pagina prodotto, con i download in alto.

## [1.8.2] — 2026-10-30 · Meno scritte, tutto leggibile e a schermo

- **Scritte leggibili**: il carattere a 7 segmenti resta solo sui numeri (timecode); pesi, VRAM e dati usano un carattere mono pulito.
Expand Down
315 changes: 117 additions & 198 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "daprod-video",
"productName": "DaProd Video",
"version": "1.8.2",
"version": "1.8.5",
"description": "DaProd Video: il montaggio video vecchio stile, moderno dentro. Timeline, due monitor, pulsantiera e VU a lancetta.",
"author": "DaProd",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "daprod-video"
version = "1.8.2"
version = "1.8.5"
description = "DaProd Video: il montaggio vecchio stile, moderno dentro"
authors = ["DaProd"]
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { attivaSuggerimenti } from './ui/suggerimento';
// il sistema «Banco» sulle altre schermate: va DOPO tutti gli altri stili (anche quelli che arrivano con ui/app)
import './stile/schermate.css';
import './stile/montage.css';
import './stile/montaggioRev.css';
import { h } from './ui/dom';
import { isTauri } from './platform';
import { preparaRiserva } from './media/riserva';
Expand Down
1 change: 1 addition & 0 deletions src/stile/finale.css
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ html #app[data-pagina='finale']:not(.stretto) {
.fin-schede-nav button { min-height: var(--riga, clamp(34px, 3.15vh, 36px)); font: 600 15px/1.3 var(--ui); }
.fin-schede-nav button[aria-pressed='true'] { border-color: var(--cia, #35e8ff); color: var(--cia, #35e8ff); }
.fin-schede-corpo { min-width: 0; min-height: 0; }
.finale .fin-doppio { display: none; }
.fin-schede-corpo > [hidden] { display: none !important; }
.finale :is(button, summary, input, select, textarea):focus-visible { outline: 2px solid var(--cia); outline-offset: 2px; }
.fin-misure { gap: 8px; padding: 8px 12px; }
Expand Down
4 changes: 4 additions & 0 deletions src/stile/live.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
border: 1px solid var(--bordo-forte); background: var(--metallo-chiaro); color: var(--testo);
font: 700 17px var(--ui); letter-spacing: 1px; box-shadow: none;
}
/* l'unico oro della pagina è REGISTRA (fermo); «Esporta» della testata diventa di metallo */
#app .live:not(.in-onda):not(.in-pausa) .live-btn.reg:not(:disabled) { background: var(--oro); color: #14110a; border-color: rgba(255, 213, 74, 0.5); box-shadow: 0 0 0 1px rgba(255, 213, 74, 0.35), 0 6px 18px rgba(255, 171, 0, 0.22); }
#app .live:not(.in-onda):not(.in-pausa) .live-btn.reg:not(:disabled) .live-punto { background: var(--rosso); }
#app[data-pagina='live'] .testata .btn.primario { background: linear-gradient(180deg, #2c2b34, #1d1c23); color: var(--testo); border-color: var(--bordo-forte); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07); }
#app .live .live-btn.reg .live-punto { width: 14px; height: 14px; border-radius: 50%; flex: none; background: #4d4650; box-shadow: none; transition: background 0.15s, border-radius 0.15s; }
#app .live.in-onda .live-btn.reg { border-color: var(--rosso); background: rgba(255, 77, 109, 0.15); }
#app .live.in-onda .live-btn.reg .live-punto { border-radius: 2px; background: var(--rosso); box-shadow: 0 0 12px var(--rosso); animation: live-pulsa 1s ease-in-out infinite; }
Expand Down
14 changes: 8 additions & 6 deletions src/stile/montage.css
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,17 @@

/* ——— 2 · gli stili ——— */
.montage .mt-filtri { flex: none; }
.montage .mt-feste { flex: 1; min-height: 0; overflow: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: minmax(196px, 1fr); gap: 14px; align-content: start; padding: 2px; }
.montage .mt-festa { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; min-height: 196px; padding: 0 0 12px; overflow: hidden; text-align: left; border: 2px solid transparent; border-radius: 8px; color: var(--testo); cursor: pointer; }
.montage .mt-festa canvas { position: absolute; left: 0; top: 0; width: 100%; height: calc(100% - 96px); object-fit: cover; }
.montage .mt-feste { flex: 1; min-height: 0; overflow: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: minmax(150px, 1fr); gap: 12px; align-content: stretch; padding: 2px; }
.montage .mt-festa { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; min-height: 150px; padding: 0 0 10px; overflow: hidden; text-align: left; border: 2px solid transparent; border-radius: 8px; color: var(--testo); cursor: pointer; }
.montage .mt-festa canvas { position: absolute; left: 0; top: 0; width: 100%; height: calc(100% - 84px); object-fit: cover; }
.montage .mt-velo { position: absolute; left: 0; right: 0; bottom: 84px; height: 40px; background: linear-gradient(180deg, rgba(11, 10, 15, 0), rgba(11, 10, 15, 0.78)); pointer-events: none; }
.montage .mt-festa b, .montage .mt-festa small, .montage .mt-festa em { position: relative; font-style: normal; padding: 0 14px; }
.montage .mt-festa b { font: 700 22px/1.15 var(--ui); }
.montage .mt-festa small { font: 500 14px/1.3 var(--ui); color: #cfcadb; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.montage .mt-festa b { font: 700 20px/1.15 var(--ui); }
.montage .mt-festa small { font: 500 14px/1.3 var(--ui); color: #cfcadb; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
/* ritmo e musica stanno nel suggerimento e al passo 3: sulla scheda sono una scritta in più */
.montage .mt-festa em { display: none; }
.montage .mt-festa em { font: 600 12.5px var(--ui); color: var(--etichetta); letter-spacing: 0.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.montage .mt-festa::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 96px; background: rgba(11, 10, 15, 0.82); z-index: 0; }
.montage .mt-festa::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 84px; background: rgba(11, 10, 15, 0.82); z-index: 0; }
.montage .mt-festa b, .montage .mt-festa small, .montage .mt-festa em { z-index: 1; }
.montage .mt-festa:hover { border-color: var(--bordo-forte); }
.montage .mt-festa.scelta { border-color: var(--cia); box-shadow: 0 0 0 1px var(--cia); }
Expand Down
55 changes: 55 additions & 0 deletions src/stile/montaggioRev.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Revisione 1.8.5 — Montaggio, colonna destra, Modifica clip, Cerca, Centro AI, finestre.
Solo correzioni di ordine (cose tagliate, schiacciate, duplicate): le regole grandi stanno nei file «Banco».
Va DOPO tutti gli altri stili. */

/* ——— la colonna destra cresce con lo schermo (a 2560 era sempre stretta e il resto restava vuoto) ——— */
@media (min-width: 1800px) { :root { --lato: clamp(300px, 15.6vw, 420px); } }

/* ——— contenitore stretto (barretta di icone): solo le voci principali, senza il solco di puntini delle sottovoci ——— */
@container (max-width: 430px) {
.bin-cat.sotto { display: none; }
.bin-albero-titolo { display: block; font-size: 0; height: 1px; padding: 0; margin: 6px 6px; background: var(--bordo); }
}

/* ——— Mixer: le strisce dividono la colonna (cinque non stavano e «ASCOLTO» usciva dal bordo) ——— */
.strisce { gap: 4px; }
.striscia { flex: 1 1 0; width: auto; min-width: 0; }
.striscia-nome, .striscia-tipo { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.striscia.master .striscia-nome { font-size: 9px; letter-spacing: 0; }

/* ——— Strumenti: forma d'onda e vettorscopio stanno tutti e due nella colonna, senza scorrere ——— */
.lato-corpo:has(> .scopi) { overflow: hidden; }
.scopi { display: flex; flex-direction: column; height: 100%; min-height: 0; box-sizing: border-box; gap: 6px; }
.scopi figure { margin: 0; display: flex; flex-direction: column; min-height: 0; }
.scopi figure:first-of-type { flex: 0 0 34%; }
.scopi figure:nth-of-type(2) { flex: 1 1 0; }
.scopi canvas, .scopi figure:nth-child(2) canvas { flex: 1 1 0; min-height: 0; width: 100%; height: 100%; object-fit: contain; margin: 0; }
.scopi figcaption { flex: none; padding-top: 2px; }
.scopi .nota { flex: none; margin: 0; font-size: 12px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* ——— Cerca (Ctrl+K): le righe non escono dal riquadro, il testo lungo ha i puntini ——— */
.cerca-voce { grid-template-columns: 118px minmax(0, 1fr) auto; }
.cerca-testo { min-width: 0; }
.cerca-testo b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cerca-cat { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ——— Tasti della centralina: i tasti restano piccoli (si allungavano quanto la riga della spiegazione) ——— */
.tasto-riga { align-items: start; }
.tasto-riga .tasti { align-self: start; align-items: flex-start; }
.tasto-riga kbd { align-self: flex-start; height: auto; line-height: 1.5; }

/* ——— Centro AI: titoli e frasi lunghe con i puntini, niente tagli a metà parola ——— */
.centro-ai .sch-funzione p { min-width: 0; }

/* ——— Modifica clip ——— */
.editor-clip .tessere { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 8px; }
.editor-clip .ec-campi { min-width: 0; }
.scopi figure:first-of-type canvas { object-fit: fill; }

/* ——— pulsantiera: la «S» nel carattere a spaziatura fissa sembrava un 5 (SEPARA e MIX avevano lo stesso numero): le lettere vanno nel carattere normale ——— */
.tasto-num .tasto-numero.lettera { font: 800 12px var(--ui); }
.menu-contesto .voce .tasto.lettera, .voce .tasto.lettera { font: 700 13px var(--ui); }

/* Modifica clip: la sezione principale non ha più il filo giallo (vecchio stile) che toccava i campi */
.editor-clip .isp-gruppo.principale { box-shadow: none; border: 0; }
.editor-clip .isp-riga { grid-template-columns: minmax(96px, 150px) minmax(0, 1fr) auto; }
7 changes: 7 additions & 0 deletions src/stile/schermate.css
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,10 @@ body.pip-live { background: var(--fondo, #0b0a0f); }
.home .hm-quando { font-family: var(--mono) !important; font-size: 12px !important; }
.home .hm-targa .hm-seg { font-family: var(--mono); }
.dialogo.centro-ai { width: min(1120px, calc(100vw - 48px)); max-height: calc(100dvh - 80px); }

/* guida: l'icona dell'argomento sta staccata dal titolo e l'elenco usa l'altezza che c'è */
.dialogo.guida .guida-corpo h3 { display: flex; gap: 10px; align-items: center; }
.dialogo.guida .guida-elenco { max-height: 70vh; }

/* novità: il titolo della versione è testo, non oro (l'oro è dell'azione) */
.novita-titolo { color: var(--testo, #ebe7f4); font-size: 18px; }
1 change: 1 addition & 0 deletions src/stile/solido.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

/* comandi alti almeno 44 px */
.btn.sol-alto { min-height: 44px; padding: 0 18px; border-radius: 6px; font-size: 14px; font-weight: 700; }
.dialogo.solido .btn.sol-alto { font: 700 15px var(--ui); } /* tutti i tasti del piede della stessa misura */
.btn.sol-leggero { color: var(--testo2); }
.btn.sol-leggero:hover { color: var(--testo); }
.btn.sol-alto:disabled { opacity: 0.45; cursor: default; }
Expand Down
5 changes: 3 additions & 2 deletions src/ui/centroAI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,10 @@ function schedeRegistro(chiudi: () => void, controlla: () => void): HTMLElement
precedente.disabled = indice === 0; successiva.disabled = indice === pagine - 1; pagina.textContent = `${indice + 1} / ${pagine}`;
griglia.replaceChildren(...lista.slice(indice * 12, indice * 12 + 12).map((f) => {
const guida = FUNZIONI_AI.find((x) => x.id === f.id);
const nome = f.nome.replace(/ \(.*$/, '').slice(0, 24);
const nome = f.nome.replace(/ \(.*$/, '');
const manca = guida?.manca();
const descrizione = manca ? '⚠ ' + manca.slice(0, 52) : f.descrizione.split(/[.;(]/)[0].slice(0, 55);
// niente tagli a mano: se non sta in una riga ci pensa il CSS (puntini), e il testo intero è nel suggerimento
const descrizione = manca ? '⚠ ' + manca : f.descrizione.split(/\.\s|[;(]/)[0].replace(/\.$/, '');
const peso = !f.peso || /nessun modello/i.test(f.peso) ? 'Integrata' : f.id === 'rumore' ? 'da 9 MB' : f.id === 'sottotitoli' ? 'da 40 MB' : (f.peso.match(/[\d,.]+(?:–[\d,.]+)?\s*(?:MB|GB)/i)?.[0] ?? 'Peso da verificare');
const info = h('button', { class: 'btn-mini ai-info', 'aria-label': `Informazioni su ${f.nome}`, title: 'Dettagli e requisiti', on: { click: () => {
const d = dialogo(f.nome); d.corpo.append(h('p', null, f.descrizione), h('p', { class: 'sch-pesovram' }, pesoEVram(f).riga)); if (guida) d.corpo.append(h('p', null, guida.come.join(' · ')));
Expand Down
4 changes: 2 additions & 2 deletions src/ui/contenitore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const TIPI: Ramo[] = [
const LIBRERIA: Ramo[] = [
{ id: 'transizioni', nome: 'Transizioni', icona: 'transizione', figli: [['tr:dissolvenze', 'Dissolvenze'], ['tr:movimento', 'Movimento'], ['tr:3d', '3D e forme'], ['tr:luce', 'Luce'], ['tr:stile', 'Stile'], ['tr:tendine', 'Tendine SMPTE']] },
{ id: 'titoli', nome: 'Titoli', icona: 'titolo', figli: [['tit:titoli', 'Titoli'], ...GRUPPI_HTML.map((g): [string, string] => ['tit:html-' + g.id, 'Animati · ' + g.nome]), ['tit:sott', 'Sottotitoli'], ['tit:tv', 'TV e social'], ['tit:conto', 'Countdown'], ['tit:sala', 'Macchine della sala']] },
{ id: 'animazioni', nome: 'Animazioni', icona: 'effetti', figli: GRUPPI_LIBRERIA.map((g): [string, string] => ['an:' + g.id, g.nome]) },
{ id: 'animazioni', nome: 'Animazioni', icona: 'elastico', figli: GRUPPI_LIBRERIA.map((g): [string, string] => ['an:' + g.id, g.nome]) },
{ id: 'effetti', nome: 'Effetti', icona: 'effetti', figli: [['fx:rapidi', 'Rapidi'], ['fx:lunghi', 'Lunghi'], ['fx:luci', 'Luci'], ['fx:distorsioni', 'Distorsioni'], ['fx:colore', 'Colore'], ['fx:particelle', 'Particelle'], ['fx:clip', 'Stile della clip'], ['fx:audio', 'Audio']] },
];

Expand Down Expand Up @@ -247,7 +247,7 @@ export class Contenitore {
const voce = (id: string, nome: string, ic: string, livello: number, extra: { figli?: boolean; n?: number } = {}) => {
const chiuso = this.chiusi.has(id);
const el = h('button', {
class: 'bin-cat' + (id === this.nodo ? ' attiva' : '') + (extra.figli ? ' con-figli' : '') + (chiuso ? ' chiuso' : ''), 'data-c': id, title: nome,
class: 'bin-cat' + (id === this.nodo ? ' attiva' : '') + (extra.figli ? ' con-figli' : '') + (chiuso ? ' chiuso' : '') + (livello > 0 ? ' sotto' : ''), 'data-c': id, title: nome,
style: `--livello:${livello}`,
on: {
click: (e: MouseEvent) => {
Expand Down
12 changes: 10 additions & 2 deletions src/ui/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,16 @@ export function menuContesto(x: number, y: number, voci: VoceMenu[]) {
dentroLoSchermo(m, x, y);
menuAperto = m;
setTimeout(() => {
const via = (e: Event) => { if (!m.contains(e.target as Node)) { chiudiMenu(); document.removeEventListener('pointerdown', via, true); } };
const via = (e: Event) => { if (!m.contains(e.target as Node)) { chiudiMenu(); document.removeEventListener('pointerdown', via, true); document.removeEventListener('keydown', esc, true); } };
// Esc chiude il menu (e basta: non deve anche togliere la scelta alla clip)
const esc = (e: KeyboardEvent) => {
if (!m.isConnected) { document.removeEventListener('keydown', esc, true); document.removeEventListener('pointerdown', via, true); return; }
if (e.key !== 'Escape') return;
e.stopPropagation(); e.preventDefault(); chiudiMenu();
document.removeEventListener('keydown', esc, true); document.removeEventListener('pointerdown', via, true);
};
document.addEventListener('pointerdown', via, true);
document.addEventListener('keydown', esc, true);
});
}

Expand All @@ -245,7 +253,7 @@ export function costruisciMenu(voci: VoceMenu[]): HTMLElement {
const riga = h('button', {
class: 'voce' + (v.disattiva ? ' spenta' : '') + (v.sotto ? ' ha-sotto' : ''), role: 'menuitem', disabled: !!v.disattiva,
on: { click: (e: Event) => { if (v.sotto) { e.stopPropagation(); return; } chiudiMenu(); v.fn?.(); } },
}, h('span', { class: 'spunta' }, v.spunta ? '●' : ''), h('span', { class: 'nome' }, v.nome ?? ''), h('span', { class: 'tasto' }, v.tasto ?? (v.sotto ? '▸' : '')));
}, h('span', { class: 'spunta' }, v.spunta ? '●' : ''), h('span', { class: 'nome' }, v.nome ?? ''), h('span', { class: 'tasto' + (/^[A-Za-z]$/.test(v.tasto ?? '') ? ' lettera' : '') }, v.tasto ?? (v.sotto ? '▸' : '')));
if (v.sotto) {
const sub = costruisciMenu(v.sotto);
sub.classList.add('sotto');
Expand Down
6 changes: 6 additions & 0 deletions src/ui/finaleSchede.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ export function schedeFinale(pannelli: HTMLElement[], nomi?: string[], iniziale
pannelli.forEach((p, i) => nav.append(h('button', {
type: 'button', class: 'btn-mini', on: { click: () => scegli(i) },
}, nomi?.[i] ?? p.querySelector('h4, legend')?.textContent ?? `Sezione ${i + 1}`)));
// il titolo del pannello che ripete la scheda appena premuta è scritta in più: si nasconde
pannelli.forEach((p, i) => {
const t = p.querySelector(':scope > h4');
const scheda = nav.children[i]?.textContent?.trim().toLowerCase();
if (t && scheda && t.textContent?.trim().toLowerCase() === scheda) t.classList.add('fin-doppio');
});
scegli(iniziale);
return h('div', { class: 'fin-schede' }, nav, corpo);
}
Expand Down
4 changes: 2 additions & 2 deletions src/ui/ispettore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1295,8 +1295,8 @@ export class Ispettore {
scelte.append(h('button', { class: 'pp-mini-btn', 'data-gruppo': g.dataset.g, on: { click: () => apri(g) } }, g.querySelector('summary')?.childNodes[0]?.textContent ?? 'Controlli'));
contenuto.append(g);
}
const avanzate = h('button', { class: 'pp-mini-btn', on: { click: () => mostra('avanzate') } }, '⚙ Avanzate');
area.replaceChildren(h('div', { class: 'ec-titolo' }, h('h2', null, cat[2]), ...(id !== 'avanzate' && disponibili.some(([k]) => k === 'avanzate') ? [avanzate] : [])), ...(gruppi.length > 1 ? [scelte] : []), contenuto);
// «Avanzate» sta già nella colonna a sinistra: niente secondo pulsante uguale in alto
area.replaceChildren(h('div', { class: 'ec-titolo' }, h('h2', null, cat[2])), ...(gruppi.length > 1 ? [scelte] : []), contenuto);
apri(gruppi.find((g) => g.dataset.g === this.editorGruppo) ?? gruppi[0]);
};
for (const [id, ico, nome] of disponibili) nav.append(h('button', { type: 'button', 'data-sezione': id, on: { click: () => mostra(id) } }, h('span', { 'aria-hidden': 'true' }, ico), nome));
Expand Down
Loading
Loading