Add "Read Text Aloud" context menu action for messages

This merge request adds a simple "Read Text Aloud" menu action to the context menu for chat messages. When clicked, the message text will be read aloud using text-to-speech.

The intention behind this change is to make it easier for myself and other low-vision users to use Matrix, without needing to use a system-wide screen reader, in cases where the user still has enough sight left to navigate a computer faster without a screen reader.

I'd eventually like to have it read " said ," so that the message sender gets read aloud as well, but for now it just reads the plaintext message contents.

Another problem, at least on my computer specifically, is that the voice's accent doesn't seem correct. For whatever reason, on my system, messages are read in a Scottish accent which is harder for me to understand. Other apps don't do that, so I'm not sure what's going on there. I do not want to hardcode a specific voice/locale, since I want this feature to work well for everyone and not just me.

@teams/qa Please do break my code! :)  - I've only tested with basic text messages.

@teams/usability Not sure if I put the context menu action in an ideal place, it's grouped in the same area as clipboard actions like "Copy Text."

@teams/localization How could I go about getting author names to be read aloud in a way that's properly translated for other languages? I'm not experienced with i18n.
This commit is contained in:
Ritchie Frodomar
2025-04-03 19:51:40 +00:00
committed by Tobias Fella
parent 054f87cae2
commit 7a078b2d34
4 changed files with 42 additions and 0 deletions

View File

@@ -200,6 +200,10 @@ add_library(neochat STATIC
models/pollanswermodel.h
)
set_source_files_properties(qml/TextToSpeechWrapper.qml PROPERTIES
QT_QML_SINGLETON_TYPE TRUE
)
set_source_files_properties(qml/OsmLocationPlugin.qml PROPERTIES
QT_QML_SINGLETON_TYPE TRUE
)
@@ -260,6 +264,7 @@ ecm_add_qml_module(neochat URI org.kde.neochat GENERATE_PLUGIN_SOURCE
qml/AvatarTabButton.qml
qml/SpaceDrawer.qml
qml/OsmLocationPlugin.qml
qml/TextToSpeechWrapper.qml
qml/FullScreenMap.qml
qml/LocationsPage.qml
qml/LocationMapItem.qml

View File

@@ -189,6 +189,7 @@ Kirigami.ApplicationWindow {
NeoChatSettingsView.window = root;
NeoChatSettingsView.connection = root.connection;
WindowController.setBlur(pageStack, NeoChatConfig.blur && !NeoChatConfig.compactLayout);
TextToSpeechWrapper.warmUp();
if (ShareHandler.text && root.connection) {
root.handleShare()
}

View File

@@ -4,8 +4,13 @@
import QtQuick
import QtQuick.Controls as QQC2
import QtTextToSpeech
import QtQuick.Layouts
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.components as KirigamiComponents
import org.kde.kirigamiaddons.formcard as FormCard
import org.kde.neochat
import org.kde.kirigamiaddons.components as KirigamiComponents
import org.kde.kirigamiaddons.formcard as FormCard
@@ -83,6 +88,13 @@ DelegateContextMenu {
Clipboard.saveText("https://matrix.to/#/" + currentRoom.id + "/" + root.eventId);
}
}
QQC2.Action {
text: i18nc("@action:inmenu", "Read Text Aloud")
icon.name: "audio-speakers-symbolic"
onTriggered: {
TextToSpeechWrapper.say(i18nc("@info text-to-speech %1 is author %2 is message text", "%1 said %2", root.author.displayName, root.plainText))
}
}
Kirigami.Action {
separator: true
}

View File

@@ -0,0 +1,24 @@
// SPDX-FileCopyrightText: 2025 Ritchie Frodomar <alkalinethunder@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
pragma Singleton
import QtQuick
import QtTextToSpeech
QtObject {
id: root
readonly property TextToSpeech tts: TextToSpeech {
id: tts
}
function warmUp() {
// TODO: This method is called on startup to avoid a UI freeze the first time you read a message aloud, but there's nothing for it to do.
// This would be a good place to check if TTS can actually be used.
}
function say(text: String) {
tts.say(text)
}
}