fix(qml): correzioni Silica post-primo-test su device (v0.1.1)

Pagine non caricabili ("Impossibile caricare la pagina") per API
inesistenti nella Silica del kit Sailfish 5.1 / Qt 5.6 — verificate
sui docs ufficiali (pagine -members) e incrociate coi pattern
provati su device (tide/calibreweb/quill):

- TextField: rimosso onAccepted (segnale "accepted" inesistente)
  -> EnterKey.enabled/.onClicked (LoginPage, ChatPage)
- Button: rimosso "highlighted" (inesistente su Button) dal mic
- ComboBox: menu con MenuItem espliciti (via Repeater non provato)
- Theme.highlightDimmerColor -> Theme.rgba(highlightBackgroundColor)
- Azioni nei menu instradate via funzioni della Page (pattern tide)
- SessionsPage: titolo delegato piu' robusto (no "undefined")
This commit is contained in:
2026-09-12 08:09:30 +02:00
parent 9c6a1242f7
commit 98139be96a
7 changed files with 105 additions and 33 deletions
+1 -1
View File
@@ -29,6 +29,6 @@ speaks (validated live against a real instance).
## Status ## Status
Version 0.1.0 — protocol and C++ core validated against a real `hermes-webui` Version 0.1.1 — protocol and C++ core validated against a real `hermes-webui`
(login, sessions, streaming chat, TTS, STT); on-device testing (audio paths, (login, sessions, streaming chat, TTS, STT); on-device testing (audio paths,
Sailjail prompts, keyboard handling) still pending. Sailjail prompts, keyboard handling) still pending.
+17 -3
View File
@@ -58,16 +58,30 @@ Nota desktop: se manca `libGL.so` di sviluppo, creare un symlink
`core_test.pro` punti lì (`GLSTUB`), oppure lanciare con `LD_LIBRARY_PATH` `core_test.pro` punti lì (`GLSTUB`), oppure lanciare con `LD_LIBRARY_PATH`
puntato alla lib dir di Qt. puntato alla lib dir di Qt.
Nota desktop 2: Qt5Multimedia richiede `libpulse-mainloop-glib.so.0`
(pacchetto `libpulse-mainloop-glib0`, non installato su questo server).
Senza sudo si estrae dal .deb:
```bash
mkdir -p /tmp/hh-libs && cd /tmp/hh-libs
apt-get download libpulse-mainloop-glib0
dpkg-deb -x libpulse-mainloop-glib0_*.deb ext
export LD_LIBRARY_PATH=/tmp/hh-libs/ext/usr/lib/x86_64-linux-gnu:<Qt>/gcc_64/lib
```
Esecuzione: `./core-test` (unit) e `./core-test --live` (integrazione,
richiede il probe WebUI su :8899). Esito 12/09/2026: unit 9/9, live completo OK.
## 4. Tarball per la build da Qt Creator ## 4. Tarball per la build da Qt Creator
```bash ```bash
cd /home/kaneda/workspace cd /home/kaneda/workspace
tar czf harbour-hermes-0.1.0.tar.gz \ tar czf harbour-hermes-0.1.1.tar.gz \
--transform 's,^harbour-hermes,harbour-hermes-0.1.0,' \ --transform 's,^harbour-hermes,harbour-hermes-0.1.1,' \
--exclude='.git' harbour-hermes --exclude='.git' harbour-hermes
``` ```
Lo spec si aspetta la directory `harbour-hermes-0.1.0/` (pattern degli altri Lo spec si aspetta la directory `harbour-hermes-0.1.1/` (pattern degli altri
progetti: cercato in modo robusto anche per i sorgenti live di sfdk). progetti: cercato in modo robusto anche per i sorgenti live di sfdk).
## 5. Dipendenze lato server (WebUI) ## 5. Dipendenze lato server (WebUI)
+25 -7
View File
@@ -55,21 +55,21 @@ Page {
} }
MenuItem { MenuItem {
text: appSettings.ttsAutoRead ? qsTr("Auto-read: on") : qsTr("Auto-read: off") text: appSettings.ttsAutoRead ? qsTr("Auto-read: on") : qsTr("Auto-read: off")
onClicked: appSettings.ttsAutoRead = !appSettings.ttsAutoRead onClicked: page.toggleAutoRead()
} }
MenuItem { MenuItem {
text: qsTr("Stop playback") text: qsTr("Stop playback")
visible: player.playing visible: player.playing
onClicked: player.stop() onClicked: page.stopPlayback()
} }
MenuItem { MenuItem {
text: qsTr("Cancel run") text: qsTr("Cancel run")
visible: chat.busy visible: chat.busy
onClicked: chat.cancel() onClicked: page.cancelRun()
} }
MenuItem { MenuItem {
text: qsTr("Resync") text: qsTr("Resync")
onClicked: chat.resync() onClicked: page.resync()
} }
} }
@@ -111,7 +111,7 @@ Page {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: page.kbHeight anchors.bottomMargin: page.kbHeight
height: compCol.height + Theme.paddingMedium height: compCol.height + Theme.paddingMedium
color: Theme.highlightDimmerColor color: Theme.rgba(Theme.highlightBackgroundColor, 0.15)
Column { Column {
id: compCol id: compCol
@@ -141,7 +141,7 @@ Page {
Button { Button {
id: micBtn id: micBtn
text: recorder.recording ? qsTr("Stop") : qsTr("Mic") text: recorder.recording ? qsTr("Stop") : qsTr("Mic")
highlighted: recorder.recording // Button non ha "highlighted": lo stato è nel testo (Mic/Stop)
enabled: !api.transcribing && !chat.busy || recorder.recording enabled: !api.transcribing && !chat.busy || recorder.recording
onClicked: { onClicked: {
if (recorder.recording) if (recorder.recording)
@@ -157,7 +157,9 @@ Page {
id: input id: input
width: parent.width - micBtn.width - sendBtn.width - 2 * parent.spacing width: parent.width - micBtn.width - sendBtn.width - 2 * parent.spacing
placeholderText: qsTr("Message…") placeholderText: qsTr("Message…")
onAccepted: page.doSend() // Invio con EnterKey (vedi LoginPage)
EnterKey.enabled: text.length > 0
EnterKey.onClicked: page.doSend()
} }
Button { Button {
@@ -226,6 +228,22 @@ Page {
api.speak(t) api.speak(t)
} }
function toggleAutoRead() {
appSettings.ttsAutoRead = !appSettings.ttsAutoRead
}
function stopPlayback() {
player.stop()
}
function cancelRun() {
chat.cancel()
}
function resync() {
chat.resync()
}
function showNotice(text) { function showNotice(text) {
page.noticeText = text page.noticeText = text
noticeClear.restart() noticeClear.restart()
+4 -1
View File
@@ -36,7 +36,10 @@ Page {
label: qsTr("Password") label: qsTr("Password")
echoMode: TextInput.Password echoMode: TextInput.Password
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText
onAccepted: page.doLogin() // Silica TextField NON ha il segnale "accepted": l'invio si gestisce
// con la proprietà allegata EnterKey (pattern provato sul device).
EnterKey.enabled: text.length > 0
EnterKey.onClicked: page.doLogin()
} }
Button { Button {
+16 -4
View File
@@ -24,15 +24,15 @@ Page {
} }
MenuItem { MenuItem {
text: qsTr("Refresh") text: qsTr("Refresh")
onClicked: api.refreshSessions() onClicked: page.refresh()
} }
MenuItem { MenuItem {
text: qsTr("Settings") text: qsTr("Settings")
onClicked: pageStack.push(Qt.resolvedUrl("SettingsPage.qml")) onClicked: page.openSettings()
} }
MenuItem { MenuItem {
text: qsTr("Sign out") text: qsTr("Sign out")
onClicked: api.logout() onClicked: page.signOut()
} }
} }
@@ -51,7 +51,7 @@ Page {
width: parent.width width: parent.width
truncationMode: TruncationMode.Fade truncationMode: TruncationMode.Fade
color: item.highlighted ? Theme.highlightColor : Theme.primaryColor color: item.highlighted ? Theme.highlightColor : Theme.primaryColor
text: ("" + model.title).length > 0 ? model.title : model.session_id text: model.title ? model.title : model.session_id
} }
Label { Label {
@@ -97,6 +97,18 @@ Page {
Component.onCompleted: api.refreshSessions() Component.onCompleted: api.refreshSessions()
function refresh() {
api.refreshSessions()
}
function openSettings() {
pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
}
function signOut() {
api.logout()
}
function openSession(id) { function openSession(id) {
expectNewSession = false expectNewSession = false
pageStack.push(Qt.resolvedUrl("ChatPage.qml"), { sessionId: id }) pageStack.push(Qt.resolvedUrl("ChatPage.qml"), { sessionId: id })
+33 -12
View File
@@ -43,13 +43,27 @@ Page {
ComboBox { ComboBox {
label: qsTr("Read-aloud voice") label: qsTr("Read-aloud voice")
currentIndex: Math.max(0, page.voiceNames.indexOf(appSettings.ttsVoice)) currentIndex: Math.max(0, page.voiceNames.indexOf(appSettings.ttsVoice))
// MenuItems espliciti (no Repeater: pattern non provato sul kit 5.1)
menu: ContextMenu { menu: ContextMenu {
Repeater {
model: page.voiceNames
MenuItem { MenuItem {
text: modelData text: "it-IT-ElsaNeural"
onClicked: appSettings.ttsVoice = modelData onClicked: appSettings.ttsVoice = "it-IT-ElsaNeural"
} }
MenuItem {
text: "it-IT-DiegoNeural"
onClicked: appSettings.ttsVoice = "it-IT-DiegoNeural"
}
MenuItem {
text: "it-IT-IsabellaNeural"
onClicked: appSettings.ttsVoice = "it-IT-IsabellaNeural"
}
MenuItem {
text: "it-IT-GiuseppeMultilingualNeural"
onClicked: appSettings.ttsVoice = "it-IT-GiuseppeMultilingualNeural"
}
MenuItem {
text: "en-US-AriaNeural"
onClicked: appSettings.ttsVoice = "en-US-AriaNeural"
} }
} }
} }
@@ -58,12 +72,17 @@ Page {
label: qsTr("TTS engine") label: qsTr("TTS engine")
currentIndex: Math.max(0, page.engineNames.indexOf(appSettings.ttsEngine)) currentIndex: Math.max(0, page.engineNames.indexOf(appSettings.ttsEngine))
menu: ContextMenu { menu: ContextMenu {
Repeater {
model: page.engineNames
MenuItem { MenuItem {
text: modelData text: "edge"
onClicked: appSettings.ttsEngine = modelData onClicked: appSettings.ttsEngine = "edge"
} }
MenuItem {
text: "openai"
onClicked: appSettings.ttsEngine = "openai"
}
MenuItem {
text: "elevenlabs"
onClicked: appSettings.ttsEngine = "elevenlabs"
} }
} }
} }
@@ -80,10 +99,7 @@ Page {
Button { Button {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Sign out") text: qsTr("Sign out")
onClicked: { onClicked: page.signOut()
api.logout()
pageStack.replace(Qt.resolvedUrl("LoginPage.qml"))
}
} }
SectionHeader { text: qsTr("About") } SectionHeader { text: qsTr("About") }
@@ -104,5 +120,10 @@ Page {
VerticalScrollDecorator {} VerticalScrollDecorator {}
} }
function signOut() {
api.logout()
pageStack.replace(Qt.resolvedUrl("LoginPage.qml"))
}
Component.onCompleted: urlField.text = appSettings.baseUrl Component.onCompleted: urlField.text = appSettings.baseUrl
} }
+5 -1
View File
@@ -1,6 +1,6 @@
Name: harbour-hermes Name: harbour-hermes
Summary: Client for the Hermes Web UI with voice Summary: Client for the Hermes Web UI with voice
Version: 0.1.0 Version: 0.1.1
Release: 1 Release: 1
Group: Qt/Qt Group: Qt/Qt
License: MIT License: MIT
@@ -24,6 +24,10 @@ Sessions list, chat with live streaming replies, voice dictation
(server-side TTS), plus a hands-free conversation mode. (server-side TTS), plus a hands-free conversation mode.
%changelog %changelog
* Sat Sep 12 2026 Carlo Baratto <carlo@carlobaratto.it> - 0.1.1-1
- Fix pagine non caricabili sul device: TextField.onAccepted inesistente
-> EnterKey; Button.highlighted rimosso; ComboBox senza Repeater;
Theme.highlightDimmerColor -> Theme.rgba; azioni menu via Page
* Sat Sep 12 2026 Carlo Baratto <carlo@carlobaratto.it> - 0.1.0-1 * Sat Sep 12 2026 Carlo Baratto <carlo@carlobaratto.it> - 0.1.0-1
- Prima release: login alla Web UI di Hermes, lista sessioni, - Prima release: login alla Web UI di Hermes, lista sessioni,
chat con streaming SSE, dettatura vocale (registrazione OGG/Opus chat con streaming SSE, dettatura vocale (registrazione OGG/Opus