feat: v0.1.0 — client Sailfish per hermes-webui con voce
- ApiClient HTTP/SSE: login, sessioni, chat/start, stream SSE, transcribe, tts - ChatModel: streaming live + risincronizzazione dallo stato del server - CookieJar persistente (0600, mai la password); Settings - Recorder OGG/Opus (fallback WAV/PCM, retry); Player TTS (QMediaPlayer) - UI Silica: splash, login, sessioni, chat (dettatura + read-aloud), settings, cover - Sailjail Internet;Audio;Microphone; icone; spec RPM; docs PROTOCOL/BUILD - tests/core_test: unit parser SSE + integrazione live (probe :8899)
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Page {
|
||||
id: page
|
||||
|
||||
property var voiceNames: [
|
||||
"it-IT-ElsaNeural",
|
||||
"it-IT-DiegoNeural",
|
||||
"it-IT-IsabellaNeural",
|
||||
"it-IT-GiuseppeMultilingualNeural",
|
||||
"en-US-AriaNeural"
|
||||
]
|
||||
property var engineNames: ["edge", "openai", "elevenlabs"]
|
||||
|
||||
SilicaFlickable {
|
||||
anchors.fill: parent
|
||||
contentHeight: col.height + Theme.paddingLarge
|
||||
|
||||
Column {
|
||||
id: col
|
||||
width: parent.width
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
PageHeader { title: qsTr("Settings") }
|
||||
|
||||
SectionHeader { text: qsTr("Server") }
|
||||
|
||||
TextField {
|
||||
id: urlField
|
||||
width: parent.width
|
||||
label: qsTr("Web UI address")
|
||||
placeholderText: "https://hermes.example.com"
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly | Qt.ImhNoAutoUppercase
|
||||
onTextChanged: {
|
||||
if (text !== appSettings.baseUrl)
|
||||
appSettings.baseUrl = text
|
||||
}
|
||||
}
|
||||
|
||||
SectionHeader { text: qsTr("Voice") }
|
||||
|
||||
ComboBox {
|
||||
label: qsTr("Read-aloud voice")
|
||||
currentIndex: Math.max(0, page.voiceNames.indexOf(appSettings.ttsVoice))
|
||||
menu: ContextMenu {
|
||||
Repeater {
|
||||
model: page.voiceNames
|
||||
MenuItem {
|
||||
text: modelData
|
||||
onClicked: appSettings.ttsVoice = modelData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
text: qsTr("Read replies aloud")
|
||||
description: qsTr("Speak every completed reply automatically")
|
||||
checked: appSettings.ttsAutoRead
|
||||
onCheckedChanged: appSettings.ttsAutoRead = checked
|
||||
}
|
||||
|
||||
SectionHeader { text: qsTr("Account") }
|
||||
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Sign out")
|
||||
onClicked: {
|
||||
api.logout()
|
||||
pageStack.replace(Qt.resolvedUrl("LoginPage.qml"))
|
||||
}
|
||||
}
|
||||
|
||||
SectionHeader { text: qsTr("About") }
|
||||
|
||||
Label {
|
||||
x: Theme.horizontalPageMargin
|
||||
width: parent.width - 2 * Theme.horizontalPageMargin
|
||||
wrapMode: Text.WordWrap
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.secondaryColor
|
||||
text: "harbour-hermes " + appVersion + "\n\n" +
|
||||
qsTr("Native client for the Hermes Web UI (hermes-webui): " +
|
||||
"sessions, live streaming chat, server-side voice " +
|
||||
"dictation and read-aloud.")
|
||||
}
|
||||
}
|
||||
|
||||
VerticalScrollDecorator {}
|
||||
}
|
||||
|
||||
Component.onCompleted: urlField.text = appSettings.baseUrl
|
||||
}
|
||||
Reference in New Issue
Block a user