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:
@@ -29,6 +29,6 @@ speaks (validated live against a real instance).
|
||||
|
||||
## 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,
|
||||
Sailjail prompts, keyboard handling) still pending.
|
||||
|
||||
+17
-3
@@ -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`
|
||||
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
|
||||
|
||||
```bash
|
||||
cd /home/kaneda/workspace
|
||||
tar czf harbour-hermes-0.1.0.tar.gz \
|
||||
--transform 's,^harbour-hermes,harbour-hermes-0.1.0,' \
|
||||
tar czf harbour-hermes-0.1.1.tar.gz \
|
||||
--transform 's,^harbour-hermes,harbour-hermes-0.1.1,' \
|
||||
--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).
|
||||
|
||||
## 5. Dipendenze lato server (WebUI)
|
||||
|
||||
+25
-7
@@ -55,21 +55,21 @@ Page {
|
||||
}
|
||||
MenuItem {
|
||||
text: appSettings.ttsAutoRead ? qsTr("Auto-read: on") : qsTr("Auto-read: off")
|
||||
onClicked: appSettings.ttsAutoRead = !appSettings.ttsAutoRead
|
||||
onClicked: page.toggleAutoRead()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Stop playback")
|
||||
visible: player.playing
|
||||
onClicked: player.stop()
|
||||
onClicked: page.stopPlayback()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Cancel run")
|
||||
visible: chat.busy
|
||||
onClicked: chat.cancel()
|
||||
onClicked: page.cancelRun()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Resync")
|
||||
onClicked: chat.resync()
|
||||
onClicked: page.resync()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ Page {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: page.kbHeight
|
||||
height: compCol.height + Theme.paddingMedium
|
||||
color: Theme.highlightDimmerColor
|
||||
color: Theme.rgba(Theme.highlightBackgroundColor, 0.15)
|
||||
|
||||
Column {
|
||||
id: compCol
|
||||
@@ -141,7 +141,7 @@ Page {
|
||||
Button {
|
||||
id: micBtn
|
||||
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
|
||||
onClicked: {
|
||||
if (recorder.recording)
|
||||
@@ -157,7 +157,9 @@ Page {
|
||||
id: input
|
||||
width: parent.width - micBtn.width - sendBtn.width - 2 * parent.spacing
|
||||
placeholderText: qsTr("Message…")
|
||||
onAccepted: page.doSend()
|
||||
// Invio con EnterKey (vedi LoginPage)
|
||||
EnterKey.enabled: text.length > 0
|
||||
EnterKey.onClicked: page.doSend()
|
||||
}
|
||||
|
||||
Button {
|
||||
@@ -226,6 +228,22 @@ Page {
|
||||
api.speak(t)
|
||||
}
|
||||
|
||||
function toggleAutoRead() {
|
||||
appSettings.ttsAutoRead = !appSettings.ttsAutoRead
|
||||
}
|
||||
|
||||
function stopPlayback() {
|
||||
player.stop()
|
||||
}
|
||||
|
||||
function cancelRun() {
|
||||
chat.cancel()
|
||||
}
|
||||
|
||||
function resync() {
|
||||
chat.resync()
|
||||
}
|
||||
|
||||
function showNotice(text) {
|
||||
page.noticeText = text
|
||||
noticeClear.restart()
|
||||
|
||||
@@ -36,7 +36,10 @@ Page {
|
||||
label: qsTr("Password")
|
||||
echoMode: TextInput.Password
|
||||
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 {
|
||||
|
||||
@@ -24,15 +24,15 @@ Page {
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Refresh")
|
||||
onClicked: api.refreshSessions()
|
||||
onClicked: page.refresh()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Settings")
|
||||
onClicked: pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
|
||||
onClicked: page.openSettings()
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Sign out")
|
||||
onClicked: api.logout()
|
||||
onClicked: page.signOut()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ Page {
|
||||
width: parent.width
|
||||
truncationMode: TruncationMode.Fade
|
||||
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 {
|
||||
@@ -97,6 +97,18 @@ Page {
|
||||
|
||||
Component.onCompleted: api.refreshSessions()
|
||||
|
||||
function refresh() {
|
||||
api.refreshSessions()
|
||||
}
|
||||
|
||||
function openSettings() {
|
||||
pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
|
||||
}
|
||||
|
||||
function signOut() {
|
||||
api.logout()
|
||||
}
|
||||
|
||||
function openSession(id) {
|
||||
expectNewSession = false
|
||||
pageStack.push(Qt.resolvedUrl("ChatPage.qml"), { sessionId: id })
|
||||
|
||||
+33
-12
@@ -43,13 +43,27 @@ Page {
|
||||
ComboBox {
|
||||
label: qsTr("Read-aloud voice")
|
||||
currentIndex: Math.max(0, page.voiceNames.indexOf(appSettings.ttsVoice))
|
||||
// MenuItems espliciti (no Repeater: pattern non provato sul kit 5.1)
|
||||
menu: ContextMenu {
|
||||
Repeater {
|
||||
model: page.voiceNames
|
||||
MenuItem {
|
||||
text: modelData
|
||||
onClicked: appSettings.ttsVoice = modelData
|
||||
text: "it-IT-ElsaNeural"
|
||||
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")
|
||||
currentIndex: Math.max(0, page.engineNames.indexOf(appSettings.ttsEngine))
|
||||
menu: ContextMenu {
|
||||
Repeater {
|
||||
model: page.engineNames
|
||||
MenuItem {
|
||||
text: modelData
|
||||
onClicked: appSettings.ttsEngine = modelData
|
||||
text: "edge"
|
||||
onClicked: appSettings.ttsEngine = "edge"
|
||||
}
|
||||
MenuItem {
|
||||
text: "openai"
|
||||
onClicked: appSettings.ttsEngine = "openai"
|
||||
}
|
||||
MenuItem {
|
||||
text: "elevenlabs"
|
||||
onClicked: appSettings.ttsEngine = "elevenlabs"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,10 +99,7 @@ Page {
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Sign out")
|
||||
onClicked: {
|
||||
api.logout()
|
||||
pageStack.replace(Qt.resolvedUrl("LoginPage.qml"))
|
||||
}
|
||||
onClicked: page.signOut()
|
||||
}
|
||||
|
||||
SectionHeader { text: qsTr("About") }
|
||||
@@ -104,5 +120,10 @@ Page {
|
||||
VerticalScrollDecorator {}
|
||||
}
|
||||
|
||||
function signOut() {
|
||||
api.logout()
|
||||
pageStack.replace(Qt.resolvedUrl("LoginPage.qml"))
|
||||
}
|
||||
|
||||
Component.onCompleted: urlField.text = appSettings.baseUrl
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name: harbour-hermes
|
||||
Summary: Client for the Hermes Web UI with voice
|
||||
Version: 0.1.0
|
||||
Version: 0.1.1
|
||||
Release: 1
|
||||
Group: Qt/Qt
|
||||
License: MIT
|
||||
@@ -24,6 +24,10 @@ Sessions list, chat with live streaming replies, voice dictation
|
||||
(server-side TTS), plus a hands-free conversation mode.
|
||||
|
||||
%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
|
||||
- Prima release: login alla Web UI di Hermes, lista sessioni,
|
||||
chat con streaming SSE, dettatura vocale (registrazione OGG/Opus
|
||||
|
||||
Reference in New Issue
Block a user