# Studio UX/UI — harbour-aira Come rendere le schermate più facili da usare, senza perdere quello che già funziona. Riguarda la versione 0.5.0 (Home / Dati / Impianto / Altri comandi / Impostazioni) e propone la 0.6.0. Immagini di questo studio (schemi, non anteprime): `docs/ux/`. --- ## 0. Cosa è stato deciso e cosa è stato fatto (0.6.0) **Prima build sul telefono:** la Home non si apriva — `Type MainPage unavailable`. Causa: due assegnazioni di `Component.onCompleted` nello stesso oggetto, che in Qt 5.6 impediscono la creazione della pagina. Corretto nella 0.6.1 e coperto da `tests/qml_check_bindings.py`. Tutto il resto dell'avvio funziona (configurazione letta, catalogo italiano caricato). Il primo giro sul device ha quindi già dato la sua risposta più importante: la riga `harbour-aira home: contenuto … schermo …` arriva nei log e si può leggere. Le quattro scelte, applicate: 1. La frase di stato lunga sta nella pagina **Impianto**; in Home resta la riga compatta con il pallino colorato. 2. "Altri comandi" è diventata **"Comandi impianto"**. 3. Le azioni rapide sono **pulsanti visibili** in Home. 4. Azioni sulla copertina: **rimandate** a dopo la prova di `CoverAction` sul kit. Problemi risolti: P1 (Home di consultazione), P2 (feedback ancorato), P3 (interruttori), P4 (un solo percorso per pagina), P5 (un blocco per grandezza, valori rapidi), P6 (numeri vecchi spenti + ora), P7 ("esterna"), P9, P10 (diagnostica in Impianto), P11. Rimandato: P8 (azioni sulla copertina), in attesa della prova sul telefono. Verifiche fatte qui: **79 verifiche del nucleo** (erano 61), `qmllint` pulito su tutti i file QML, 191/191 stringhe tradotte, anteprime rigenerate in inglese e italiano, contratto dei dati fra UI e bridge rispettato (`tests/ui_contract_check.py`). Da provare sul telefono: che `TextSwitch` si istanzi davvero, l'altezza reale della Home (la riga `harbour-aira home: contenuto … schermo …` è già nel codice, basta leggerla nei log) e l'uso con una mano sola. --- ## 1. Metodo Tre riferimenti, in quest'ordine: 1. **Il contesto d'uso reale**: un telefono, una mano, in piedi, a volte al freddo. La casa è una sola e l'impianto è lo stesso da mesi: le azioni frequenti sono pochissime. 2. **Le convenzioni Sailfish**: menù a tendina dall'alto per la navigazione, menù dal basso per le azioni, copertina come faccia dell'app, un gesto per tornare indietro. La UI deve sembrare un'app di sistema. 3. **I vincoli tecnici**: Qt 5.6, Silica 5.1, e la regola già pagata cara che un componente documentato può non esistere sul kit. Le euristiche di Nielsen (visibilità dello stato, controllo e libertà, coerenza, prevenzione dell'errore, riconoscere invece di ricordare) sono usate come griglia di controllo, non citate come teoria. **Cosa si può verificare qui e cosa no.** Qui si verificano: numero di componenti e altezze minime, chiavi lette dalla UI contro quelle che il bridge restituisce (`tests/ui_contract_check.py`), stringhe e traduzioni, sintassi QML. Sul telefono si verificano: che i componenti si istanzino davvero, l'altezza reale del contenuto (una riga di log con `contentHeight` alla prima build), la resa di giorno e l'uso con una mano sola. --- ## 2. Per chi, e in quali momenti | Momento | Frequenza | Cosa serve | Cosa non serve | |---|---|---|---| | Guardare com'è la casa (è calda? l'acqua è pronta?) | molte volte al giorno | due numeri, stato in una riga, se ci sono errori | scorrere, regolare | | Regolare una temperatura | qualche volta a settimana | valore attuale, obiettivo, conferma | tutto il resto | | Boost acqua calda / ospiti | qualche volta al mese | un tocco, sapere che è partito | leggere lo stato dell'impianto | | Assenza | quando si parte | accenderla e *vedere* che è accesa | navigare | | Impianto, versioni, diagnosi | raramente | dettagli, un posto solo | stare in mezzo alla home | Il caso più frequente — **guardare** — oggi costa uno scorrimento; il caso più raro (regolare) occupa metà della prima schermata. È il rovescio di quello che serve. --- ## 3. Problemi trovati Con gravità: **alta** = fa sbagliare o non capire; **media** = fa perdere tempo; **bassa** = rifinitura. | # | Dove | Problema | Gravità | |---|---|---|---| | P1 | Home | Non è una schermata di consultazione ma un modulo: stato, messaggio, scheda impianto, **2 slider con 2 pulsanti di conferma, 2 pulsanti boost, 3 pulsanti di navigazione** (7 pulsanti, 2 slider in tutto). Il contenuto supera l'altezza dello schermo: per vedere l'acqua calda bisogna scorrere | alta | | P2 | Home, Altri comandi | L'esito dei comandi (`page.notice`) e l'indicatore di attività stanno **dentro** la pagina che scorre, il primo in cima e il secondo in fondo. Premendo "Avvia boost" — che è in fondo — il messaggio compare sopra, fuori vista: non si sa se il comando è partito | alta | | P3 | Altri comandi | **12 pulsanti**, di cui 8 in coppie acceso/spento (assenza, riscaldamento forzato, funzione riscaldamento, ACS). Lo stato sta in 6 righe più in alto: per agire bisogna leggere, ricordare, poi scegliere il pulsante giusto. Due schermate per fare una cosa sola | alta | | P4 | Home | Le stesse pagine si raggiungono **due volte**: dal menù a tendina (5 voci: Aggiorna, Dati, Impianto, Altri comandi, Impostazioni) e da 3 pulsanti in fondo alla home. Il menù a tendina Sailfish è fatto per 2–4 voci; con 5 si scorre dentro la tendina | media | | P5 | Home | "Sposta lo slider, poi premi Imposta": due passi, e il valore mostrato dallo slider **non è ancora** quello dell'impianto. Con le dita fredde il cursore è difficile da centrare, e due slider nella stessa pagina che scorre si contendono il trascinamento verticale | media | | P6 | Home, Dati, Impianto | Se il bridge non risponde, i numeri **restano a schermo come se fossero attuali** (l'ultima risposta non viene svuotata) e l'errore passa in un banner temporaneo. Manca "aggiornato alle HH:MM" e uno stato visibile "non raggiungibile" | media | | P7 | Copertina | Dice "est. 18,0 °C" e "casa · obiettivo": abbreviato in modo poco chiaro, e "est." non si usa altrove (l'app dice "Esterna") | bassa | | P8 | Copertina | Due temperature e nient'altro: non si può fare nulla senza aprire l'app, nemmeno il boost | bassa | | P9 | Impostazioni | "Salva" e "Prova connessione": il secondo salva comunque, quindi i due pulsanti si sovrappongono | bassa | | P10 | Altri comandi / Impianto | La diagnostica è in due posti: "Verifica impianto" in Altri comandi, versioni ed errori in Impianto | bassa | ### P1 — il conto dei componenti Nella Home attuale: 1 intestazione di pagina, 2 righe di stato, 1 messaggio di 2 righe, 1 scheda impianto, **3 intestazioni di sezione, 7 pulsanti, 2 slider, 1 barra di avanzamento**, più note e indicatore di attività. Sommando le altezze minime dei componenti Silica (un pulsante ~80 px, uno slider ~100 px) si arriva ben oltre l'altezza di uno schermo: nel confronto affiancato (`docs/ux/confronto.png`) si vede dove il contenuto viene tagliato. L'altezza esatta si legge dal log `contentHeight` alla prima build sul telefono. ### P2 — dettaglio In `MainPage.qml` il banner dei messaggi è la prima `Label` della `Column` e il `BusyIndicator` è l'ultimo. Entrambi scorrono con il contenuto. Il caso peggiore è proprio il più probabile: i pulsanti boost sono in fondo alla pagina, quindi il messaggio di esito nasce fuori dallo schermo. --- ## 4. La proposta Tre movimenti, niente di più: 1. **La Home torna a essere una vista.** In alto quello che si guarda; quello che si tocca sta in una pagina sua. 2. **Le regolazioni hanno una pagina propria**, un soggetto per blocco, con il valore attuale sempre visibile e preimpostazioni per le dita fredde. 3. **Gli interruttori dicono lo stato**; i pulsanti restano per le azioni che uno stato non ce l'hanno (boost, legionella, notte, verifica). ### 4.1 Dove sta cosa, dopo ``` PRIMA DOPO ───────────────────────────── ───────────────────────────── Home Casa (una schermata, niente scroll) ├ stato + messaggio lungo ├ stato in una riga + ora ├ scheda impianto ├ Casa 22,8 °C · obiettivo 19,0 ├ Riscaldamento: slider + Imposta ├ Acqua calda 50,7 · obiettivo 55,0 ├ ACS: barra + slider + Imposta ├ Azioni rapide: Boost · Assenza · Altri comandi ├ Boost acceso / spento └ Esterna · Termostato · zona ├ Dettagli: Impianto · Dati ───────────────────────────── └ Altri comandi Regolazioni (nuova) ├───────────── ├ Riscaldamento · casa (valore + slider + preset) │ ├ Acqua calda (valore + slider + preset) Dati (invariata) └ Boost acqua calda Impianto (riordinata): stato · ───────────────────────────── termostato · versioni · errori Comandi impianto (ex Altri comandi) Altri comandi (12 pulsanti) ├ Modalità: Assenza · Forzato · Funzione (interruttori) Impostazioni ├ Acqua calda: interruttore + legionella ├ Rumore: notte un'ora Menù a tendina: 5 voci └ Diagnostica: verifica impianto ───────────────────────────── Dati (invariata) · Impianto (con diagnostica) Impostazioni: "Salva e prova" Menù a tendina: 4 voci ``` ### 4.2 Casa — `docs/ux/casa.png` I richiami numerati dell'immagine: 1. **Menù a tendina a 4 voci**: Aggiorna · Dati · Impianto · Impostazioni. Solo navigazione fra pagine, una voce per pagina: i pulsanti in fondo alla home non ci sono più (risolve P4). 2. **Stato in una riga**: pallino colorato + "Tutto regolare · Automatico" + ora dell'ultimo aggiornamento. Verde regolare, ambra attenzione, rosso errore o non raggiungibile (risolve P6). La frase estesa dell'app ufficiale ("Relax: la pompa funziona regolarmente") è bella ma occupa 2 righe in cima: sta meglio nella pagina Impianto (decisione 1). 3. **Due letture grandi, affiancate**: Casa 22,8 °C (obiettivo 19,0) e Acqua calda 50,7 °C (obiettivo 55,0) con la barretta di avanzamento della carica. Sono il motivo per cui si apre l'app: due tocchi sotto l'intestazione, senza scorrere. Ogni riquadro è **toccabile** e porta a Regolazioni (è il gesto dell'app ufficiale: tocco la scheda, vedo il dettaglio). 4. **"Tocca un valore per regolarlo"**: una riga che spiega il tocco. Sparisce se il tocco si capisce (decisione 4). 5. **Azioni rapide**: Boost ACS · Assenza · Altri comandi. Le due azioni frequenti più la porta verso tutti gli altri comandi, che il menù a tendina non porta (così resta una sola strada per pagina, non due). In alternativa le stesse due azioni possono stare nel menù dal basso, all'altezza del pollice: è la decisione 3. 6. **Letture di contorno**, in fondo e in una riga: Esterna, Termostato, zona. Servono di rado: non meritano una riga ciascuna in alto. 7. **"Aggiornato alle 21:18"** in fondo: la stessa informazione del richiamo 2, ripetuta dove finisce la lettura. Cosa sparisce: due slider, sette pulsanti, la scheda impianto separata (il suo contenuto si tocca dal riquadro), tre pulsanti di navigazione. Cosa resta: la frase di stato (spostata), la barra ACS, l'aggiornamento automatico. ### 4.3 Regolazioni — `docs/ux/regolazioni.png` 1. **Riscaldamento · casa**: valore attuale grande a destra, slider 5–30 °C, riga di preimpostazioni (16° 17° 18° 19° 20° 21°), pulsante "Imposta 19,0 °C". 2. **Acqua calda**: stessa struttura, 45–60 °C, preimpostazioni 45/47/50/55/60. 3. **Boost acqua calda**: Avvia / Ferma. Azione senza stato: resta un pulsante. 4. **Nota**: il comando passa dal bridge e lo stato si aggiorna da solo. Perché è meglio (risolve P5): - **Un solo slider per blocco** e due blocchi distinti: nessun trascinamento verticale che finisce sul cursore sbagliato. - **Il valore attuale non si muove**: lo slider è la proposta, il numero grande a destra è l'obiettivo reale finché non si preme Imposta. - **Le preimpostazioni** evitano il cursore con le dita fredde: un tocco invece di un trascinamento di precisione (l'impianto vuole passi di 0,5 °C: i preset coprono il caso normale, lo slider resta per il resto). - La conferma esplicita resta (com'è giusto per una scrittura sull'impianto). ### 4.4 Comandi impianto — `docs/ux/comandi.png` 1. **Modalità — interruttori**: Assenza (con la spiegazione "abbassa la casa e spegne l'acqua calda"), Riscaldamento forzato, Funzione riscaldamento. 2. **Acqua calda — interruttore + pulsante**: Riscaldamento ACS (interruttore), Ciclo legionella (pulsante). 3. **Diagnostica**: Verifica impianto, spostata qui da Altri comandi. 4. **Nota**: "Gli interruttori mostrano lo stato attuale: la sezione *Stato attuale* non serve più" (risolve P3 e P11). Da 12 pulsanti + 6 righe di stato a **4 interruttori + 3 pulsanti**. Il titolo della pagina diventa "Comandi impianto": dice cosa contiene. **Nota di realizzazione importante.** Un interruttore che cambia da solo quando lo tocchi mostra una bugia se il comando fallisce. Va legato allo stato che arriva dal bridge (`checked` sull'ultimo dato reale), non al tocco: al tocco si invia il comando, si mostra l'attività, e lo stato lo conferma l'aggiornamento. Se il comando non riesce, l'interruttore torna indietro da solo. È lo stesso principio del pulsante Imposta: la UI non anticipa l'impianto. ### 4.5 Copertina Resta com'è nelle letture (casa grande, ACS, esterna), con due migliorie basse: - Dicitura chiara: "esterna" invece di "est." (P7). - **Azioni sulla copertina**: Silica ha `CoverAction`/`CoverActionList` documentati ("un'azione per una copertina"). Una o due icone — boost e assenza — permettono di agire senza aprire l'app (P8). È rifinitura: da provare sul kit prima di contarla, come ultimo passo. ### 4.6 Feedback e stato non aggiornato (P2, P6) Fuori dalla parte che scorre: - **Banner dei messaggi ancorato al bordo inferiore della pagina**, non alla cima del contenuto: nasce dove si tocca, sempre visibile. Sfuma da solo dopo qualche secondo come oggi. - **Indicatore di attività ancorato** allo stesso punto (o nell'intestazione): non scorre via. - **Riga "Aggiornato alle HH:MM"** nell'intestazione della Home (richiamo 2) e **"non raggiungibile"** in ambra, con i numeri spenti invece che pieni quando l'ultima lettura non è recente. Serve una proprietà in più in C++ (`lastUpdate`, `stale`) per saperlo: piccolo, ma è la differenza fra un dato vecchio e un dato sbagliato. --- ## 5. Microcopy | Dove | Ora | Proposta | Perché | |---|---|---|---| | Copertina | est. 18,0 °C | esterna 18,0 °C | si capisce | | Home | Relax: la pompa di calore funziona regolarmente | ● Tutto regolare · Automatico | una riga; la frase estesa va in Impianto | | Home | (niente) | Aggiornato alle 21:18 | il dato ha un'età | | Altri comandi | Altri comandi | Comandi impianto | dice cosa c'è dentro | | Regolazioni | Imposta casa a 19,0 °C | Imposta 19,0 °C | il blocco dice già "casa" | | Assenza | Turn away mode on/off | interruttore Assenza | lo stato si vede | | Impostazioni | Salva · Prova connessione | Salva e prova | sono la stessa cosa | Le stringhe nuove o cambiate saranno una ventina; il catalogo è a 170 voci, l'aggiornamento è routine (`lupdate` + traduzione + `lrelease`). --- ## 6. Cosa non si tocca - **La pagina Dati**: riproduce i numeri dell'app ufficiale ed è già una schermata di sola lettura ben fatta. Nessuna modifica. - **La pagina Impianto** nella sostanza: si aggiunge la diagnostica (P10) e nient'altro. - **Il pulsante Imposta con la barra "scorri per confermare"** (RemorseItem) sui comandi che cambiano l'impianto: è la prevenzione dell'errore giusta in Sailfish, e in più non serve una finestra di conferma. - **Aggiornamento automatico all'apertura** e **menù a tendina come navigazione**: sono convenzioni, non decorazioni. - **Le due letture grandi** come criterio della Home: vengono dall'aver copiato l'organizzazione dell'app ufficiale, ed è la scelta che rende la Home utile. --- ## 7. Piano di verifica **Prima di compilare (qui, senza telefono)** 1. `qmllint` sui file QML toccati. 2. `tests/ui_contract_check.py`: ogni chiave letta dalla UI esiste nelle risposte del bridge (41 chiavi fra `/summary` e `/stats`). 3. Test del nucleo `tests/core_test.cpp` (61 verifiche) + nuove verifiche per `stale`/`lastUpdate` e per le etichette cambiate. 4. `lupdate` → nessuna stringa mancante → `lrelease`. 5. Anteprime rigenerate (`scripts/render_mockups.py`, it/en), così le immagini dei README restano vere. **Sul telefono (Carlo)** 1. Una riga di log all'avvio con `contentHeight` e altezza schermo: verifica numerica che la Home non scorre più. 2. Che `TextSwitch` e, se si fa, `CoverAction` si istanzino (lezione già presa con `Notices`: documentato non vuol dire disponibile). 3. Prova con una mano sola e alla luce del giorno. **Prova d'uso, 3 compiti** (si può fare in dieci minuti con una persona che non conosce l'app: basta un amico o la famiglia) | # | Compito | Riuscito se | |---|---|---| | T1 | "Quanto è calda l'acqua adesso, e quanto deve arrivare?" | risponde senza scorrere | | T2 | "Portala a 47 °C" | ≤3 tocchi, nessun dubbio su cosa è stato inviato | | T3 | "Metti la casa in assenza e dimmi se è attiva" | ≤2 tocchi + lo stato si vede dalla schermata | Si annotano: tempo, tocchi, scorrimenti, tocchi sbagliati. Un solo numero conta davvero: **quanti tocchi per T2 e T3**, prima e dopo. --- ## 8. Rischi tecnici | Rischio | Come si governa | |---|---| | `TextSwitch` documentato ma non istanziabile sul kit 5.1 | Provarlo in una pagina di prova alla prima build; ripiego: si resta sui pulsanti (già funzionanti) | | `CoverAction` idem | È l'ultimo passo; se non c'è, la copertina resta com'è | | Le anteprime non rappresentano lo scroll reale | La riga di log con `contentHeight` dà la misura vera | | Un interruttore che anticipa lo stato (bug classico) | `checked` legato ai dati del bridge, non al tocco (§4.4) | | Il cambio lingua ricarica la radice (Qt 5.6) | Nessun impatto: già così | --- ## 9. Quanto costa, e cosa decidere Tre blocchi di lavoro, in quest'ordine: 1. **Home + Regolazioni** (P1, P4, P5, P7, microcopy) — il grosso del guadagno. 2. **Comandi impianto con interruttori + diagnostica in Impianto** (P3, P9, P10). 3. **Feedback ancorato + stato aggiornato + copertina** (P2, P6, P8). Ogni blocco: una tornata di lavoro mia (codice + stringhe + anteprime + test), una build e un controllo tuo sul telefono. **Decisioni richieste** (le altre le ho prese seguendo le convenzioni): 1. **La frase di stato lunga** ("Relax: la pompa di calore funziona regolarmente"): la tengo in una riga sola sopra le letture come nell'app ufficiale, o la sposto nella pagina Impianto e lascio in Home la riga compatta come nel wireframe? 2. **"Altri comandi" → "Comandi impianto"**: rinominare? 3. **Azioni rapide**: pulsanti visibili sulla Home (proposta) o menù dal basso all'altezza del pollice? 4. **Copertina con le azioni**: la facciamo (dopo aver verificato `CoverAction` sul kit) o resta di sola lettura?