1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-08-04 14:55:43 +02:00

accessibility: fix chatview

Add keyboard and screen-reader navigation for the chat view.

Change-Id: I11a5dc1ee3b0d6303f4598f10008ecc6979bb777
This commit is contained in:
pmagnier-slimani 2025-06-18 10:21:52 -04:00 committed by Page Magnier-Slimani
parent 905b2e858e
commit 8677349c4a
9 changed files with 205 additions and 88 deletions

View file

@ -53,6 +53,8 @@ ApplicationWindow {
focusOverlay.margin = 0;
focusOverlay.parent = activeFocusItem;
}
} else {
focusOverlay.parent = null;
}
} else {
focusOverlay.parent = null;

View file

@ -23,12 +23,12 @@ import net.jami.Adapters 1.1
import net.jami.Constants 1.1
SBSMessageBase {
id: root
id: rootDelegate
property var confId: ConfId
property var currentCallId: CurrentCall.id
component JoinCallButton: MaterialButton {
visible: root.isActive && root.currentCallId !== root.confId
visible: rootDelegate.isActive && rootDelegate.currentCallId !== rootDelegate.confId
toolTipText: JamiStrings.joinCall
color: JamiTheme.blackColor
background.opacity: hovered ? 0.2 : 0.1
@ -40,6 +40,20 @@ SBSMessageBase {
textRightPadding: 9
}
Accessible.role: Accessible.StaticText
Accessible.name: {
let name = isOutgoing ? JamiStrings.inReplyToYou : UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author);
return name + ": " + callLabel.text + " " + formattedDay;
}
Accessible.description: {
let status = "";
if (bubble.isEdited)
status += JamiStrings.edited + " ";
return status + (readers.length > 0 ? JamiStrings.readBy + " " + readers.map(function (uri) {
return UtilsAdapter.getBestNameForUri(CurrentAccount.id, uri);
}).join(", ") : "");
}
property bool isRemoteImage
isOutgoing: Author === CurrentAccount.uri
@ -48,17 +62,17 @@ SBSMessageBase {
formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
bubble.border.color: CurrentConversation.color
bubble.border.width: root.isActive ? 1.5 : 0
bubble.border.width: rootDelegate.isActive ? 1.5 : 0
bubble.color: JamiTheme.messageInBgColor
bubble.opacity: 1
Connections {
target: CurrentConversation
enabled: root.isActive
enabled: rootDelegate.isActive
function onActiveCallsChanged() {
root.isActive = LRCInstance.indexOfActiveCall(root.confId, ActionUri, DeviceId) !== -1;
if (root.isActive) {
rootDelegate.isActive = LRCInstance.indexOfActiveCall(rootDelegate.confId, ActionUri, DeviceId) !== -1;
if (rootDelegate.isActive) {
bubble.mask.border.color = CurrentConversation.color;
bubble.mask.border.width = 1.5;
bubble.mask.z = -2;
@ -66,8 +80,8 @@ SBSMessageBase {
}
}
property bool isActive: LRCInstance.indexOfActiveCall(root.confId, ActionUri, DeviceId) !== -1
visible: isActive || root.confId === "" || Duration > 0
property bool isActive: LRCInstance.indexOfActiveCall(rootDelegate.confId, ActionUri, DeviceId) !== -1
visible: isActive || rootDelegate.confId === "" || Duration > 0
property var baseColor: JamiTheme.messageInBgColor
@ -76,7 +90,7 @@ SBSMessageBase {
id: msg
anchors.right: isOutgoing ? parent.right : undefined
spacing: 10
visible: root.visible
visible: rootDelegate.visible
Image {
id: statusIcon
@ -84,10 +98,10 @@ SBSMessageBase {
width: 10
height: 10
verticalAlignment: Qt.AlignVCenter
visible: !root.isActive
visible: !rootDelegate.isActive
source: {
if (root.isOutgoing) {
if (rootDelegate.isOutgoing) {
if (Duration > 0)
return "qrc:/icons/outgoing-call.svg";
else
@ -104,12 +118,11 @@ SBSMessageBase {
effect: ColorOverlay {
color: {
if (Duration > 0)
return UtilsAdapter.luma(root.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
return JamiTheme.redColor
return UtilsAdapter.luma(rootDelegate.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
return JamiTheme.redColor;
}
}
}
}
Text {
@ -120,11 +133,11 @@ SBSMessageBase {
bottomPadding: 8
Layout.fillWidth: true
Layout.rightMargin: root.isActive && root.currentCallId !== root.confId ? 0 : root.timeWidth + 16
Layout.leftMargin: root.isActive ? 10 : -5 /* spacing is 10 and we want 5px with icon */
Layout.rightMargin: rootDelegate.isActive && rootDelegate.currentCallId !== rootDelegate.confId ? 0 : rootDelegate.timeWidth + 16
Layout.leftMargin: rootDelegate.isActive ? 10 : -5 /* spacing is 10 and we want 5px with icon */
text: {
if (root.isActive)
if (rootDelegate.isActive)
return JamiStrings.startedACall;
return Body;
}
@ -136,7 +149,7 @@ SBSMessageBase {
renderType: Text.NativeRendering
textFormat: Text.MarkdownText
color: UtilsAdapter.luma(root.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
color: UtilsAdapter.luma(rootDelegate.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
}
JoinCallButton {
@ -146,7 +159,7 @@ SBSMessageBase {
Layout.bottomMargin: 4
text: JamiStrings.joinWithAudio
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, root.confId, true)
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, rootDelegate.confId, true)
}
JoinCallButton {
@ -156,20 +169,20 @@ SBSMessageBase {
Layout.topMargin: 4
Layout.bottomMargin: 4
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, root.confId)
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, rootDelegate.confId)
Layout.rightMargin: 4
}
}
]
opacity: 0
Behavior on opacity {
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
Component.onCompleted: {
bubble.timestampItem.visible = !root.isActive || root.currentCallId === root.confId;
bubble.timestampItem.visible = !rootDelegate.isActive || rootDelegate.currentCallId === rootDelegate.confId;
opacity = 1;
}
}

View file

@ -21,8 +21,8 @@ import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
Column {
id: root
Control {
id: rootDelegate
property bool showTime: false
property bool showDay: false
@ -36,21 +36,41 @@ Column {
height: timestampItem.height + textLabel.height
spacing: 0
Item {
Accessible.name: {
let name = UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author);
return name + ": " + Body + " " + formattedTime + " " + formattedDay;
}
Accessible.description: {
let status = "";
if (IsLastSent)
status += JamiStrings.sent + " ";
return status;
}
background: Rectangle {
id: focusIndicator
visible: rootDelegate.activeFocus
border.color: JamiTheme.tintedBlue
border.width: 2
radius: 10
color: "transparent"
z: 1
}
contentItem: Item {
anchors.horizontalCenter: parent.horizontalCenter
height: timestampItem.height + textLabel.height
TimestampInfo {
id: timestampItem
showDay: root.showDay
showTime: root.showTime
formattedTime: root.formattedTime
formattedDay: root.formattedDay
showDay: rootDelegate.showDay
showTime: rootDelegate.showTime
formattedTime: rootDelegate.formattedTime
formattedDay: rootDelegate.formattedDay
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
}
Label {
@ -67,7 +87,7 @@ Column {
}
}
opacity: 0
Behavior on opacity {
Behavior on opacity {
NumberAnimation {
duration: 100
}

View file

@ -24,20 +24,32 @@ import net.jami.Constants 1.1
import net.jami.Adapters 1.1
Loader {
id: root
id: rootDelegate
property var mediaInfo
property bool showTime
property bool showDay
property int timestamp: Timestamp
property string formattedTime: MessagesAdapter.getFormattedTime(root.timestamp)
property string formattedDay: MessagesAdapter.getFormattedDay(root.timestamp)
property string formattedTime: MessagesAdapter.getFormattedTime(rootDelegate.timestamp)
property string formattedDay: MessagesAdapter.getFormattedDay(rootDelegate.timestamp)
property int seq: MsgSeq.single
property string author: Author
property string body: Body
property var tid: TID
property int transferStatus: TransferStatus
Accessible.name: {
let name = UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author);
return JamiStrings.dataTransfer + name + ": " + JamiStrings.status + TransferStatus + Body + " " + formattedTime + " " + formattedDay;
}
Accessible.description: {
let status = "";
if (IsLastSent)
status += JamiStrings.sent + " ";
return status;
}
onTidChanged: {
if (tid === "") {
sourceComponent = deletedMsgComp;
@ -48,7 +60,7 @@ Loader {
sourceComponent = deletedMsgComp;
return;
} else if (transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED) {
mediaInfo = MessagesAdapter.getMediaInfo(root.body);
mediaInfo = MessagesAdapter.getMediaInfo(rootDelegate.body);
if (Object.keys(mediaInfo).length !== 0 && WITH_WEBENGINE) {
sourceComponent = localMediaMsgComp;
return;
@ -74,13 +86,13 @@ Loader {
id: deletedItem
isOutgoing: Author === CurrentAccount.uri
showTime: root.showTime
seq: root.seq
showTime: rootDelegate.showTime
seq: rootDelegate.seq
author: Author
readers: Readers
timestamp: root.timestamp
formattedTime: root.formattedTime
formattedDay: root.formattedTime
timestamp: rootDelegate.timestamp
formattedTime: rootDelegate.formattedTime
formattedDay: rootDelegate.formattedTime
extraHeight: 0
textContentWidth: textEditId.width
textContentHeight: textEditId.height
@ -122,34 +134,34 @@ Loader {
id: dataTransferItem
transferId: Id
property var transferStats: MessagesAdapter.getTransferStats(transferId, root.transferStatus)
property bool canOpen: root.transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED || isOutgoing
property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth - buttonsLoader.width - 24 - 6 - 24
property var transferStats: MessagesAdapter.getTransferStats(transferId, rootDelegate.transferStatus)
property bool canOpen: rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED || isOutgoing
property real maxMsgWidth: rootDelegate.width - senderMargin - 2 * hPadding - avatarBlockWidth - buttonsLoader.width - 24 - 6 - 24
// Timer to update the translation bar
Loader {
id: timerLoader
active: root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
active: rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
sourceComponent: Timer {
interval: 1000 // Update every second
running: true
repeat: true
onTriggered: {
transferStats = MessagesAdapter.getTransferStats(transferId, root.transferStatus);
transferStats = MessagesAdapter.getTransferStats(transferId, rootDelegate.transferStatus);
}
}
}
isOutgoing: Author === CurrentAccount.uri
showTime: root.showTime
seq: root.seq
showTime: rootDelegate.showTime
seq: rootDelegate.seq
author: Author
location: Body
transferName: TransferName
readers: Readers
timestamp: root.timestamp
formattedTime: root.formattedTime
formattedDay: root.formattedTime
timestamp: rootDelegate.timestamp
formattedTime: rootDelegate.formattedTime
formattedDay: rootDelegate.formattedTime
extraHeight: progressBar.visible ? 25 : 0
innerContent.children: [
@ -178,7 +190,7 @@ Loader {
Layout.margins: 8
sourceComponent: {
switch (root.transferStatus) {
switch (rootDelegate.transferStatus) {
case Interaction.TransferStatus.TRANSFER_CREATED:
case Interaction.TransferStatus.TRANSFER_FINISHED:
iconSource = JamiResources.link_black_24dp_svg;
@ -225,7 +237,7 @@ Loader {
normalColor: JamiTheme.chatviewBgColor
imageColor: JamiTheme.chatviewButtonColor
onClicked: {
if (root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING) {
if (rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING) {
MessagesAdapter.cancelFile(transferId);
} else {
buttonsLoader.iconSource = JamiResources.connecting_black_24dp_svg;
@ -287,7 +299,7 @@ Loader {
ProgressBar {
id: progressBar
visible: root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
visible: rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
height: visible * implicitHeight
value: transferStats.progress / transferStats.totalSize
width: transferItem.width
@ -305,15 +317,15 @@ Loader {
isOutgoing: Author === CurrentAccount.uri
transferId: Id
property var transferStats: MessagesAdapter.getTransferStats(transferId, root.transferStatus)
showTime: root.showTime
seq: root.seq
property var transferStats: MessagesAdapter.getTransferStats(transferId, rootDelegate.transferStatus)
showTime: rootDelegate.showTime
seq: rootDelegate.seq
author: Author
location: Body
transferName: TransferName
readers: Readers
formattedTime: MessagesAdapter.getFormattedTime(root.timestamp)
formattedDay: MessagesAdapter.getFormattedDay(root.timestamp)
formattedTime: MessagesAdapter.getFormattedTime(rootDelegate.timestamp)
formattedDay: MessagesAdapter.getFormattedDay(rootDelegate.timestamp)
property real contentWidth

View file

@ -21,7 +21,7 @@ import net.jami.Adapters 1.1
import net.jami.Constants 1.1
Column {
id: root
id: rootDelegate
property bool showTime: false
property bool showDay: false
@ -34,6 +34,18 @@ Column {
spacing: 2
topPadding: 12
bottomPadding: 12
Accessible.name: {
let name = UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author);
return name + ": " + Body + " " + formattedTime + " " + formattedDay;
}
Accessible.description: {
let status = "";
if (IsLastSent)
status += JamiStrings.sent + " ";
return status;
}
ColumnLayout {
width: parent.width
@ -42,10 +54,10 @@ Column {
TimestampInfo {
id: timestampItem
showDay: root.showDay
showTime: root.showTime
formattedTime: root.formattedTime
formattedDay: root.formattedDay
showDay: rootDelegate.showDay
showTime: rootDelegate.showTime
formattedTime: rootDelegate.formattedTime
formattedDay: rootDelegate.formattedDay
Layout.alignment: Qt.AlignHCenter
}
@ -60,7 +72,7 @@ Column {
}
opacity: 0
Behavior on opacity {
Behavior on opacity {
NumberAnimation {
duration: 100
}

View file

@ -24,6 +24,7 @@ import net.jami.Constants 1.1
Control {
id: root
Accessible.role: Accessible.StaticText
property alias avatarBlockWidth: avatarBlock.width
property alias innerContent: innerContent
@ -64,6 +65,7 @@ Control {
property bool bigMsg
property bool timeUnderBubble: false
property var type: Type
property var shouldBeVisible: msgRowlayout.msgHovered || root.activeFocus || reply.activeFocus || more.activeFocus || share.activeFocus
// If the ListView attached properties are not available,
// then the root delegate is likely a Loader.
@ -81,6 +83,16 @@ Control {
rightPadding: hPadding
leftPadding: hPadding
background: Rectangle {
id: focusIndicator
visible: rootDelegate.activeFocus
radius: 4
border.color: JamiTheme.tintedBlue
border.width: 2
color: "transparent"
z: 1
}
contentItem: ColumnLayout {
id: mainColumnLayout
@ -301,7 +313,7 @@ Control {
anchors.verticalCenter: parent.verticalCenter
anchors.right: isOutgoing ? optionButtonItem.right : undefined
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
visible: msgRowlayout.msgHovered
visible: shouldBeVisible
source: JamiResources.more_vert_24dp_svg
width: optionButtonItem.width / 4
height: optionButtonItem.height
@ -311,7 +323,7 @@ Control {
function setBindings() {
more.isOpen = false;
visible = Qt.binding(() => msgRowlayout.msgHovered);
visible = Qt.binding(() => shouldBeVisible);
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
}
@ -356,7 +368,7 @@ Control {
anchors.rightMargin: 5
anchors.right: isOutgoing ? more.left : undefined
anchors.left: !isOutgoing ? more.right : undefined
visible: msgRowlayout.msgHovered
visible: shouldBeVisible
onClicked: {
MessagesAdapter.editId = "";
@ -380,13 +392,14 @@ Control {
anchors.rightMargin: 5
anchors.right: isOutgoing ? reply.left : undefined
anchors.left: !isOutgoing ? reply.right : undefined
visible: msgRowlayout.msgHovered
visible: shouldBeVisible
property bool isOpen: false
property var obj: undefined
function setBindings() { // when the popup is closed, setBindings is called to reset the icon's visual settings
share.isOpen = false;
visible = Qt.binding(() => msgRowlayout.msgHovered);
visible = Qt.binding(() => shouldBeVisible);
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
}

View file

@ -24,7 +24,21 @@ import net.jami.Constants 1.1
import net.jami.Enums 1.1
SBSMessageBase {
id: root
id: rootDelegate
Accessible.role: Accessible.StaticText
Accessible.name: {
let name = isOutgoing ? JamiStrings.inReplyToYou : UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author);
return name + ": " + Body + " " + formattedTime;
}
Accessible.description: {
let status = "";
if (bubble.isEdited)
status += JamiStrings.edited + " ";
return status + (readers.length > 0 ? JamiStrings.readBy + " " + readers.map(function (uri) {
return UtilsAdapter.getBestNameForUri(CurrentAccount.id, uri);
}).join(", ") : "");
}
property bool isRemoteImage
property bool isEmojiOnly: IsEmojiOnly
@ -34,11 +48,11 @@ SBSMessageBase {
Connections {
target: bubble
function onColorChanged(color) {
root.colorUrl = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark;
root.colorText = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
rootDelegate.colorUrl = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark;
rootDelegate.colorText = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
// Update parsed body with correct colors
if (Body !== "")
MessagesAdapter.parseMessage(Id, Body, UtilsAdapter.getAppValue(Settings.DisplayHyperlinkPreviews), root.colorUrl, bubble.color);
MessagesAdapter.parseMessage(Id, Body, UtilsAdapter.getAppValue(Settings.DisplayHyperlinkPreviews), rootDelegate.colorUrl, bubble.color);
}
}
@ -53,7 +67,7 @@ SBSMessageBase {
textContentWidth: textEditId.width
textContentHeight: textEditId.height
bigMsg: textContentWidth >= (2 / 3) * root.maxMsgWidth || extraContent.active
bigMsg: textContentWidth >= (2 / 3) * rootDelegate.maxMsgWidth || extraContent.active
innerContent.children: [
TextEdit {
@ -63,10 +77,10 @@ SBSMessageBase {
topPadding: bubble.isDeleted ? 6 : 10
bottomPadding: bubble.isDeleted ? 6 : 10
anchors.right: isOutgoing ? parent.right : undefined
anchors.rightMargin: isOutgoing && !isEmojiOnly && !bigMsg ? root.timeWidth + root.editedWidth : 0
anchors.rightMargin: isOutgoing && !isEmojiOnly && !bigMsg ? rootDelegate.timeWidth + rootDelegate.editedWidth : 0
text: {
if (Body !== "" && ParsedBody.length === 0) {
MessagesAdapter.parseMessage(Id, Body, UtilsAdapter.getAppValue(Settings.DisplayHyperlinkPreviews), root.colorUrl, bubble.color);
MessagesAdapter.parseMessage(Id, Body, UtilsAdapter.getAppValue(Settings.DisplayHyperlinkPreviews), rootDelegate.colorUrl, bubble.color);
return "";
}
if (ParsedBody !== "")
@ -82,11 +96,11 @@ SBSMessageBase {
width: {
if (extraContent.active)
Math.max(extraContent.width, Math.min((2 / 3) * root.maxMsgWidth, implicitWidth - avatarBlockWidth, extraContent.minSize) - senderMargin);
Math.max(extraContent.width, Math.min((2 / 3) * rootDelegate.maxMsgWidth, implicitWidth - avatarBlockWidth, extraContent.minSize) - senderMargin);
else if (isEmojiOnly)
Math.min((2 / 3) * root.maxMsgWidth, implicitWidth, innerContent.width - senderMargin - (innerContent.width - senderMargin) % (JamiTheme.chatviewEmojiSize + 2));
Math.min((2 / 3) * rootDelegate.maxMsgWidth, implicitWidth, innerContent.width - senderMargin - (innerContent.width - senderMargin) % (JamiTheme.chatviewEmojiSize + 2));
else
Math.min((2 / 3) * root.maxMsgWidth, implicitWidth + 5, innerContent.width - senderMargin + 5);
Math.min((2 / 3) * rootDelegate.maxMsgWidth, implicitWidth + 5, innerContent.width - senderMargin + 5);
}
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
@ -96,7 +110,7 @@ SBSMessageBase {
renderType: Text.NativeRendering
textFormat: Text.RichText
clip: true
onLinkHovered: root.hoveredLink = hoveredLink
onLinkHovered: rootDelegate.hoveredLink = hoveredLink
onLinkActivated: Qt.openUrlExternally(new URL(hoveredLink))
readOnly: true
color: (ParsedBody !== "") ? getBaseColor() : (UtilsAdapter.luma(bubble.color) ? "white" : "dark")
@ -150,7 +164,7 @@ SBSMessageBase {
HoverHandler {
target: previewContent
onHoveredChanged: {
root.hoveredLink = hovered ? LinkPreviewInfo.url : "";
rootDelegate.hoveredLink = hovered ? LinkPreviewInfo.url : "";
}
cursorShape: Qt.PointingHandCursor
}
@ -204,7 +218,7 @@ SBSMessageBase {
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
renderType: Text.NativeRendering
textFormat: TextEdit.RichText
color: root.colorText
color: rootDelegate.colorText
visible: LinkPreviewInfo.title.length > 0
text: LinkPreviewInfo.title
lineHeight: 1.3
@ -217,9 +231,9 @@ SBSMessageBase {
renderType: Text.NativeRendering
textFormat: TextEdit.RichText
visible: LinkPreviewInfo.description.length > 0
font.underline: root.hoveredLink
font.underline: rootDelegate.hoveredLink
text: LinkPreviewInfo.description
color: root.colorUrl
color: rootDelegate.colorUrl
lineHeight: 1.3
}
Label {
@ -229,7 +243,7 @@ SBSMessageBase {
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
renderType: Text.NativeRendering
textFormat: TextEdit.RichText
color: root.colorText
color: rootDelegate.colorText
text: LinkPreviewInfo.domain
lineHeight: 1.3
}

View file

@ -24,8 +24,26 @@ import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
JamiListView {
ListView {
id: root
property alias verticalScrollBar: verticalScrollBar
layer.mipmap: false
clip: true
ScrollBar.vertical: JamiScrollBar {
id: verticalScrollBar
attachedFlickableMoving: root.moving
}
keyNavigationEnabled: true
keyNavigationWraps: false
focus: true
activeFocusOnTab: true
Accessible.role: Accessible.List
Accessible.name: JamiStrings.conversationMessages
function getDistanceToBottom() {
const scrollDiff = ScrollBar.vertical.position - (1.0 - ScrollBar.vertical.size);
@ -139,7 +157,10 @@ JamiListView {
}
// fade-in mechanism
Component.onCompleted: fadeAnimation.start()
Component.onCompleted: {
positionViewAtBeginning();
fadeAnimation.start();
}
Rectangle {
id: overlay
anchors.fill: parent
@ -194,13 +215,19 @@ JamiListView {
boundsBehavior: Flickable.StopAtBounds
currentIndex: -1
Connections {
target: CurrentConversation
function onIdChanged() {
currentIndex = -1;
}
}
model: MessagesAdapter.messageListModel
delegate: DelegateChooser {
id: delegateChooser
role: "Type"
DelegateChoice {
id: delegateChoice
roleValue: Interaction.Type.TEXT
TextMessageDelegate {

View file

@ -947,4 +947,8 @@ Item {
property string tipDescription: qsTr("Tips to help you use Jami more effectively")
property string showMoreMessagingOptions: qsTr("Show more messaging options")
property string showMoreMessagingOptionsDescription: qsTr("Open a menu that allows you to send voice and video messages as well as sharing your location")
property string conversationMessages: qsTr("Conversation messages list. Use arrow keys to navigate through messages.")
property string dataTransfer: qsTr("Data transfer")
property string status: qsTr("Status")
property string readBy: qsTr("Read by")
}