mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-05 15:25:51 +02:00
accessibility: fix chatview
Add keyboard and screen-reader navigation for the chat view. Change-Id: I11a5dc1ee3b0d6303f4598f10008ecc6979bb777
This commit is contained in:
parent
905b2e858e
commit
8677349c4a
9 changed files with 205 additions and 88 deletions
|
@ -53,6 +53,8 @@ ApplicationWindow {
|
||||||
focusOverlay.margin = 0;
|
focusOverlay.margin = 0;
|
||||||
focusOverlay.parent = activeFocusItem;
|
focusOverlay.parent = activeFocusItem;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
focusOverlay.parent = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
focusOverlay.parent = null;
|
focusOverlay.parent = null;
|
||||||
|
|
|
@ -23,12 +23,12 @@ import net.jami.Adapters 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
|
||||||
SBSMessageBase {
|
SBSMessageBase {
|
||||||
id: root
|
id: rootDelegate
|
||||||
|
|
||||||
property var confId: ConfId
|
property var confId: ConfId
|
||||||
property var currentCallId: CurrentCall.id
|
property var currentCallId: CurrentCall.id
|
||||||
component JoinCallButton: MaterialButton {
|
component JoinCallButton: MaterialButton {
|
||||||
visible: root.isActive && root.currentCallId !== root.confId
|
visible: rootDelegate.isActive && rootDelegate.currentCallId !== rootDelegate.confId
|
||||||
toolTipText: JamiStrings.joinCall
|
toolTipText: JamiStrings.joinCall
|
||||||
color: JamiTheme.blackColor
|
color: JamiTheme.blackColor
|
||||||
background.opacity: hovered ? 0.2 : 0.1
|
background.opacity: hovered ? 0.2 : 0.1
|
||||||
|
@ -40,6 +40,20 @@ SBSMessageBase {
|
||||||
textRightPadding: 9
|
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
|
property bool isRemoteImage
|
||||||
|
|
||||||
isOutgoing: Author === CurrentAccount.uri
|
isOutgoing: Author === CurrentAccount.uri
|
||||||
|
@ -48,17 +62,17 @@ SBSMessageBase {
|
||||||
formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
|
formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
|
||||||
|
|
||||||
bubble.border.color: CurrentConversation.color
|
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.color: JamiTheme.messageInBgColor
|
||||||
bubble.opacity: 1
|
bubble.opacity: 1
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: CurrentConversation
|
target: CurrentConversation
|
||||||
enabled: root.isActive
|
enabled: rootDelegate.isActive
|
||||||
|
|
||||||
function onActiveCallsChanged() {
|
function onActiveCallsChanged() {
|
||||||
root.isActive = LRCInstance.indexOfActiveCall(root.confId, ActionUri, DeviceId) !== -1;
|
rootDelegate.isActive = LRCInstance.indexOfActiveCall(rootDelegate.confId, ActionUri, DeviceId) !== -1;
|
||||||
if (root.isActive) {
|
if (rootDelegate.isActive) {
|
||||||
bubble.mask.border.color = CurrentConversation.color;
|
bubble.mask.border.color = CurrentConversation.color;
|
||||||
bubble.mask.border.width = 1.5;
|
bubble.mask.border.width = 1.5;
|
||||||
bubble.mask.z = -2;
|
bubble.mask.z = -2;
|
||||||
|
@ -66,8 +80,8 @@ SBSMessageBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property bool isActive: LRCInstance.indexOfActiveCall(root.confId, ActionUri, DeviceId) !== -1
|
property bool isActive: LRCInstance.indexOfActiveCall(rootDelegate.confId, ActionUri, DeviceId) !== -1
|
||||||
visible: isActive || root.confId === "" || Duration > 0
|
visible: isActive || rootDelegate.confId === "" || Duration > 0
|
||||||
|
|
||||||
property var baseColor: JamiTheme.messageInBgColor
|
property var baseColor: JamiTheme.messageInBgColor
|
||||||
|
|
||||||
|
@ -76,7 +90,7 @@ SBSMessageBase {
|
||||||
id: msg
|
id: msg
|
||||||
anchors.right: isOutgoing ? parent.right : undefined
|
anchors.right: isOutgoing ? parent.right : undefined
|
||||||
spacing: 10
|
spacing: 10
|
||||||
visible: root.visible
|
visible: rootDelegate.visible
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: statusIcon
|
id: statusIcon
|
||||||
|
@ -84,10 +98,10 @@ SBSMessageBase {
|
||||||
width: 10
|
width: 10
|
||||||
height: 10
|
height: 10
|
||||||
verticalAlignment: Qt.AlignVCenter
|
verticalAlignment: Qt.AlignVCenter
|
||||||
visible: !root.isActive
|
visible: !rootDelegate.isActive
|
||||||
|
|
||||||
source: {
|
source: {
|
||||||
if (root.isOutgoing) {
|
if (rootDelegate.isOutgoing) {
|
||||||
if (Duration > 0)
|
if (Duration > 0)
|
||||||
return "qrc:/icons/outgoing-call.svg";
|
return "qrc:/icons/outgoing-call.svg";
|
||||||
else
|
else
|
||||||
|
@ -104,12 +118,11 @@ SBSMessageBase {
|
||||||
effect: ColorOverlay {
|
effect: ColorOverlay {
|
||||||
color: {
|
color: {
|
||||||
if (Duration > 0)
|
if (Duration > 0)
|
||||||
return UtilsAdapter.luma(root.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
|
return UtilsAdapter.luma(rootDelegate.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
|
||||||
return JamiTheme.redColor
|
return JamiTheme.redColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
|
@ -120,11 +133,11 @@ SBSMessageBase {
|
||||||
bottomPadding: 8
|
bottomPadding: 8
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: root.isActive && root.currentCallId !== root.confId ? 0 : root.timeWidth + 16
|
Layout.rightMargin: rootDelegate.isActive && rootDelegate.currentCallId !== rootDelegate.confId ? 0 : rootDelegate.timeWidth + 16
|
||||||
Layout.leftMargin: root.isActive ? 10 : -5 /* spacing is 10 and we want 5px with icon */
|
Layout.leftMargin: rootDelegate.isActive ? 10 : -5 /* spacing is 10 and we want 5px with icon */
|
||||||
|
|
||||||
text: {
|
text: {
|
||||||
if (root.isActive)
|
if (rootDelegate.isActive)
|
||||||
return JamiStrings.startedACall;
|
return JamiStrings.startedACall;
|
||||||
return Body;
|
return Body;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +149,7 @@ SBSMessageBase {
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
textFormat: Text.MarkdownText
|
textFormat: Text.MarkdownText
|
||||||
|
|
||||||
color: UtilsAdapter.luma(root.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
|
color: UtilsAdapter.luma(rootDelegate.baseColor) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
|
||||||
}
|
}
|
||||||
|
|
||||||
JoinCallButton {
|
JoinCallButton {
|
||||||
|
@ -146,7 +159,7 @@ SBSMessageBase {
|
||||||
Layout.bottomMargin: 4
|
Layout.bottomMargin: 4
|
||||||
|
|
||||||
text: JamiStrings.joinWithAudio
|
text: JamiStrings.joinWithAudio
|
||||||
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, root.confId, true)
|
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, rootDelegate.confId, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
JoinCallButton {
|
JoinCallButton {
|
||||||
|
@ -156,7 +169,7 @@ SBSMessageBase {
|
||||||
Layout.topMargin: 4
|
Layout.topMargin: 4
|
||||||
Layout.bottomMargin: 4
|
Layout.bottomMargin: 4
|
||||||
|
|
||||||
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, root.confId)
|
onClicked: MessagesAdapter.joinCall(ActionUri, DeviceId, rootDelegate.confId)
|
||||||
Layout.rightMargin: 4
|
Layout.rightMargin: 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +182,7 @@ SBSMessageBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
bubble.timestampItem.visible = !root.isActive || root.currentCallId === root.confId;
|
bubble.timestampItem.visible = !rootDelegate.isActive || rootDelegate.currentCallId === rootDelegate.confId;
|
||||||
opacity = 1;
|
opacity = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ import net.jami.Models 1.1
|
||||||
import net.jami.Adapters 1.1
|
import net.jami.Adapters 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
|
||||||
Column {
|
Control {
|
||||||
id: root
|
id: rootDelegate
|
||||||
|
|
||||||
property bool showTime: false
|
property bool showTime: false
|
||||||
property bool showDay: false
|
property bool showDay: false
|
||||||
|
@ -36,21 +36,41 @@ Column {
|
||||||
height: timestampItem.height + textLabel.height
|
height: timestampItem.height + textLabel.height
|
||||||
spacing: 0
|
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
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
height: timestampItem.height + textLabel.height
|
height: timestampItem.height + textLabel.height
|
||||||
|
|
||||||
TimestampInfo {
|
TimestampInfo {
|
||||||
id: timestampItem
|
id: timestampItem
|
||||||
|
|
||||||
showDay: root.showDay
|
showDay: rootDelegate.showDay
|
||||||
showTime: root.showTime
|
showTime: rootDelegate.showTime
|
||||||
formattedTime: root.formattedTime
|
formattedTime: rootDelegate.formattedTime
|
||||||
formattedDay: root.formattedDay
|
formattedDay: rootDelegate.formattedDay
|
||||||
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
|
|
|
@ -24,20 +24,32 @@ import net.jami.Constants 1.1
|
||||||
import net.jami.Adapters 1.1
|
import net.jami.Adapters 1.1
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: root
|
id: rootDelegate
|
||||||
|
|
||||||
property var mediaInfo
|
property var mediaInfo
|
||||||
property bool showTime
|
property bool showTime
|
||||||
property bool showDay
|
property bool showDay
|
||||||
property int timestamp: Timestamp
|
property int timestamp: Timestamp
|
||||||
property string formattedTime: MessagesAdapter.getFormattedTime(root.timestamp)
|
property string formattedTime: MessagesAdapter.getFormattedTime(rootDelegate.timestamp)
|
||||||
property string formattedDay: MessagesAdapter.getFormattedDay(root.timestamp)
|
property string formattedDay: MessagesAdapter.getFormattedDay(rootDelegate.timestamp)
|
||||||
|
|
||||||
property int seq: MsgSeq.single
|
property int seq: MsgSeq.single
|
||||||
property string author: Author
|
property string author: Author
|
||||||
property string body: Body
|
property string body: Body
|
||||||
property var tid: TID
|
property var tid: TID
|
||||||
property int transferStatus: TransferStatus
|
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: {
|
onTidChanged: {
|
||||||
if (tid === "") {
|
if (tid === "") {
|
||||||
sourceComponent = deletedMsgComp;
|
sourceComponent = deletedMsgComp;
|
||||||
|
@ -48,7 +60,7 @@ Loader {
|
||||||
sourceComponent = deletedMsgComp;
|
sourceComponent = deletedMsgComp;
|
||||||
return;
|
return;
|
||||||
} else if (transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED) {
|
} 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) {
|
if (Object.keys(mediaInfo).length !== 0 && WITH_WEBENGINE) {
|
||||||
sourceComponent = localMediaMsgComp;
|
sourceComponent = localMediaMsgComp;
|
||||||
return;
|
return;
|
||||||
|
@ -74,13 +86,13 @@ Loader {
|
||||||
id: deletedItem
|
id: deletedItem
|
||||||
|
|
||||||
isOutgoing: Author === CurrentAccount.uri
|
isOutgoing: Author === CurrentAccount.uri
|
||||||
showTime: root.showTime
|
showTime: rootDelegate.showTime
|
||||||
seq: root.seq
|
seq: rootDelegate.seq
|
||||||
author: Author
|
author: Author
|
||||||
readers: Readers
|
readers: Readers
|
||||||
timestamp: root.timestamp
|
timestamp: rootDelegate.timestamp
|
||||||
formattedTime: root.formattedTime
|
formattedTime: rootDelegate.formattedTime
|
||||||
formattedDay: root.formattedTime
|
formattedDay: rootDelegate.formattedTime
|
||||||
extraHeight: 0
|
extraHeight: 0
|
||||||
textContentWidth: textEditId.width
|
textContentWidth: textEditId.width
|
||||||
textContentHeight: textEditId.height
|
textContentHeight: textEditId.height
|
||||||
|
@ -122,34 +134,34 @@ Loader {
|
||||||
id: dataTransferItem
|
id: dataTransferItem
|
||||||
|
|
||||||
transferId: Id
|
transferId: Id
|
||||||
property var transferStats: MessagesAdapter.getTransferStats(transferId, root.transferStatus)
|
property var transferStats: MessagesAdapter.getTransferStats(transferId, rootDelegate.transferStatus)
|
||||||
property bool canOpen: root.transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED || isOutgoing
|
property bool canOpen: rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_FINISHED || isOutgoing
|
||||||
property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth - buttonsLoader.width - 24 - 6 - 24
|
property real maxMsgWidth: rootDelegate.width - senderMargin - 2 * hPadding - avatarBlockWidth - buttonsLoader.width - 24 - 6 - 24
|
||||||
|
|
||||||
// Timer to update the translation bar
|
// Timer to update the translation bar
|
||||||
Loader {
|
Loader {
|
||||||
id: timerLoader
|
id: timerLoader
|
||||||
active: root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
|
active: rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
|
||||||
sourceComponent: Timer {
|
sourceComponent: Timer {
|
||||||
interval: 1000 // Update every second
|
interval: 1000 // Update every second
|
||||||
running: true
|
running: true
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
transferStats = MessagesAdapter.getTransferStats(transferId, root.transferStatus);
|
transferStats = MessagesAdapter.getTransferStats(transferId, rootDelegate.transferStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isOutgoing: Author === CurrentAccount.uri
|
isOutgoing: Author === CurrentAccount.uri
|
||||||
showTime: root.showTime
|
showTime: rootDelegate.showTime
|
||||||
seq: root.seq
|
seq: rootDelegate.seq
|
||||||
author: Author
|
author: Author
|
||||||
location: Body
|
location: Body
|
||||||
transferName: TransferName
|
transferName: TransferName
|
||||||
readers: Readers
|
readers: Readers
|
||||||
timestamp: root.timestamp
|
timestamp: rootDelegate.timestamp
|
||||||
formattedTime: root.formattedTime
|
formattedTime: rootDelegate.formattedTime
|
||||||
formattedDay: root.formattedTime
|
formattedDay: rootDelegate.formattedTime
|
||||||
extraHeight: progressBar.visible ? 25 : 0
|
extraHeight: progressBar.visible ? 25 : 0
|
||||||
|
|
||||||
innerContent.children: [
|
innerContent.children: [
|
||||||
|
@ -178,7 +190,7 @@ Loader {
|
||||||
Layout.margins: 8
|
Layout.margins: 8
|
||||||
|
|
||||||
sourceComponent: {
|
sourceComponent: {
|
||||||
switch (root.transferStatus) {
|
switch (rootDelegate.transferStatus) {
|
||||||
case Interaction.TransferStatus.TRANSFER_CREATED:
|
case Interaction.TransferStatus.TRANSFER_CREATED:
|
||||||
case Interaction.TransferStatus.TRANSFER_FINISHED:
|
case Interaction.TransferStatus.TRANSFER_FINISHED:
|
||||||
iconSource = JamiResources.link_black_24dp_svg;
|
iconSource = JamiResources.link_black_24dp_svg;
|
||||||
|
@ -225,7 +237,7 @@ Loader {
|
||||||
normalColor: JamiTheme.chatviewBgColor
|
normalColor: JamiTheme.chatviewBgColor
|
||||||
imageColor: JamiTheme.chatviewButtonColor
|
imageColor: JamiTheme.chatviewButtonColor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING) {
|
if (rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING) {
|
||||||
MessagesAdapter.cancelFile(transferId);
|
MessagesAdapter.cancelFile(transferId);
|
||||||
} else {
|
} else {
|
||||||
buttonsLoader.iconSource = JamiResources.connecting_black_24dp_svg;
|
buttonsLoader.iconSource = JamiResources.connecting_black_24dp_svg;
|
||||||
|
@ -287,7 +299,7 @@ Loader {
|
||||||
ProgressBar {
|
ProgressBar {
|
||||||
id: progressBar
|
id: progressBar
|
||||||
|
|
||||||
visible: root.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
|
visible: rootDelegate.transferStatus === Interaction.TransferStatus.TRANSFER_ONGOING
|
||||||
height: visible * implicitHeight
|
height: visible * implicitHeight
|
||||||
value: transferStats.progress / transferStats.totalSize
|
value: transferStats.progress / transferStats.totalSize
|
||||||
width: transferItem.width
|
width: transferItem.width
|
||||||
|
@ -305,15 +317,15 @@ Loader {
|
||||||
|
|
||||||
isOutgoing: Author === CurrentAccount.uri
|
isOutgoing: Author === CurrentAccount.uri
|
||||||
transferId: Id
|
transferId: Id
|
||||||
property var transferStats: MessagesAdapter.getTransferStats(transferId, root.transferStatus)
|
property var transferStats: MessagesAdapter.getTransferStats(transferId, rootDelegate.transferStatus)
|
||||||
showTime: root.showTime
|
showTime: rootDelegate.showTime
|
||||||
seq: root.seq
|
seq: rootDelegate.seq
|
||||||
author: Author
|
author: Author
|
||||||
location: Body
|
location: Body
|
||||||
transferName: TransferName
|
transferName: TransferName
|
||||||
readers: Readers
|
readers: Readers
|
||||||
formattedTime: MessagesAdapter.getFormattedTime(root.timestamp)
|
formattedTime: MessagesAdapter.getFormattedTime(rootDelegate.timestamp)
|
||||||
formattedDay: MessagesAdapter.getFormattedDay(root.timestamp)
|
formattedDay: MessagesAdapter.getFormattedDay(rootDelegate.timestamp)
|
||||||
|
|
||||||
property real contentWidth
|
property real contentWidth
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ import net.jami.Adapters 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: root
|
id: rootDelegate
|
||||||
|
|
||||||
property bool showTime: false
|
property bool showTime: false
|
||||||
property bool showDay: false
|
property bool showDay: false
|
||||||
|
@ -34,6 +34,18 @@ Column {
|
||||||
spacing: 2
|
spacing: 2
|
||||||
topPadding: 12
|
topPadding: 12
|
||||||
bottomPadding: 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 {
|
ColumnLayout {
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -42,10 +54,10 @@ Column {
|
||||||
TimestampInfo {
|
TimestampInfo {
|
||||||
id: timestampItem
|
id: timestampItem
|
||||||
|
|
||||||
showDay: root.showDay
|
showDay: rootDelegate.showDay
|
||||||
showTime: root.showTime
|
showTime: rootDelegate.showTime
|
||||||
formattedTime: root.formattedTime
|
formattedTime: rootDelegate.formattedTime
|
||||||
formattedDay: root.formattedDay
|
formattedDay: rootDelegate.formattedDay
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import net.jami.Constants 1.1
|
||||||
|
|
||||||
Control {
|
Control {
|
||||||
id: root
|
id: root
|
||||||
|
Accessible.role: Accessible.StaticText
|
||||||
|
|
||||||
property alias avatarBlockWidth: avatarBlock.width
|
property alias avatarBlockWidth: avatarBlock.width
|
||||||
property alias innerContent: innerContent
|
property alias innerContent: innerContent
|
||||||
|
@ -64,6 +65,7 @@ Control {
|
||||||
property bool bigMsg
|
property bool bigMsg
|
||||||
property bool timeUnderBubble: false
|
property bool timeUnderBubble: false
|
||||||
property var type: Type
|
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,
|
// If the ListView attached properties are not available,
|
||||||
// then the root delegate is likely a Loader.
|
// then the root delegate is likely a Loader.
|
||||||
|
@ -81,6 +83,16 @@ Control {
|
||||||
rightPadding: hPadding
|
rightPadding: hPadding
|
||||||
leftPadding: 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 {
|
contentItem: ColumnLayout {
|
||||||
id: mainColumnLayout
|
id: mainColumnLayout
|
||||||
|
|
||||||
|
@ -301,7 +313,7 @@ Control {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: isOutgoing ? optionButtonItem.right : undefined
|
anchors.right: isOutgoing ? optionButtonItem.right : undefined
|
||||||
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
|
anchors.left: !isOutgoing ? optionButtonItem.left : undefined
|
||||||
visible: msgRowlayout.msgHovered
|
visible: shouldBeVisible
|
||||||
source: JamiResources.more_vert_24dp_svg
|
source: JamiResources.more_vert_24dp_svg
|
||||||
width: optionButtonItem.width / 4
|
width: optionButtonItem.width / 4
|
||||||
height: optionButtonItem.height
|
height: optionButtonItem.height
|
||||||
|
@ -311,7 +323,7 @@ Control {
|
||||||
|
|
||||||
function setBindings() {
|
function setBindings() {
|
||||||
more.isOpen = false;
|
more.isOpen = false;
|
||||||
visible = Qt.binding(() => msgRowlayout.msgHovered);
|
visible = Qt.binding(() => shouldBeVisible);
|
||||||
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
||||||
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
||||||
}
|
}
|
||||||
|
@ -356,7 +368,7 @@ Control {
|
||||||
anchors.rightMargin: 5
|
anchors.rightMargin: 5
|
||||||
anchors.right: isOutgoing ? more.left : undefined
|
anchors.right: isOutgoing ? more.left : undefined
|
||||||
anchors.left: !isOutgoing ? more.right : undefined
|
anchors.left: !isOutgoing ? more.right : undefined
|
||||||
visible: msgRowlayout.msgHovered
|
visible: shouldBeVisible
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
MessagesAdapter.editId = "";
|
MessagesAdapter.editId = "";
|
||||||
|
@ -380,13 +392,14 @@ Control {
|
||||||
anchors.rightMargin: 5
|
anchors.rightMargin: 5
|
||||||
anchors.right: isOutgoing ? reply.left : undefined
|
anchors.right: isOutgoing ? reply.left : undefined
|
||||||
anchors.left: !isOutgoing ? reply.right : undefined
|
anchors.left: !isOutgoing ? reply.right : undefined
|
||||||
visible: msgRowlayout.msgHovered
|
|
||||||
|
visible: shouldBeVisible
|
||||||
property bool isOpen: false
|
property bool isOpen: false
|
||||||
property var obj: undefined
|
property var obj: undefined
|
||||||
|
|
||||||
function setBindings() { // when the popup is closed, setBindings is called to reset the icon's visual settings
|
function setBindings() { // when the popup is closed, setBindings is called to reset the icon's visual settings
|
||||||
share.isOpen = false;
|
share.isOpen = false;
|
||||||
visible = Qt.binding(() => msgRowlayout.msgHovered);
|
visible = Qt.binding(() => shouldBeVisible);
|
||||||
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
imageColor = Qt.binding(() => hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor);
|
||||||
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
normalColor = Qt.binding(() => JamiTheme.primaryBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,21 @@ import net.jami.Constants 1.1
|
||||||
import net.jami.Enums 1.1
|
import net.jami.Enums 1.1
|
||||||
|
|
||||||
SBSMessageBase {
|
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 isRemoteImage
|
||||||
property bool isEmojiOnly: IsEmojiOnly
|
property bool isEmojiOnly: IsEmojiOnly
|
||||||
|
@ -34,11 +48,11 @@ SBSMessageBase {
|
||||||
Connections {
|
Connections {
|
||||||
target: bubble
|
target: bubble
|
||||||
function onColorChanged(color) {
|
function onColorChanged(color) {
|
||||||
root.colorUrl = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark;
|
rootDelegate.colorUrl = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark;
|
||||||
root.colorText = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
|
rootDelegate.colorText = UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark;
|
||||||
// Update parsed body with correct colors
|
// Update parsed body with correct colors
|
||||||
if (Body !== "")
|
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
|
textContentWidth: textEditId.width
|
||||||
textContentHeight: textEditId.height
|
textContentHeight: textEditId.height
|
||||||
|
|
||||||
bigMsg: textContentWidth >= (2 / 3) * root.maxMsgWidth || extraContent.active
|
bigMsg: textContentWidth >= (2 / 3) * rootDelegate.maxMsgWidth || extraContent.active
|
||||||
|
|
||||||
innerContent.children: [
|
innerContent.children: [
|
||||||
TextEdit {
|
TextEdit {
|
||||||
|
@ -63,10 +77,10 @@ SBSMessageBase {
|
||||||
topPadding: bubble.isDeleted ? 6 : 10
|
topPadding: bubble.isDeleted ? 6 : 10
|
||||||
bottomPadding: bubble.isDeleted ? 6 : 10
|
bottomPadding: bubble.isDeleted ? 6 : 10
|
||||||
anchors.right: isOutgoing ? parent.right : undefined
|
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: {
|
text: {
|
||||||
if (Body !== "" && ParsedBody.length === 0) {
|
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 "";
|
return "";
|
||||||
}
|
}
|
||||||
if (ParsedBody !== "")
|
if (ParsedBody !== "")
|
||||||
|
@ -82,11 +96,11 @@ SBSMessageBase {
|
||||||
|
|
||||||
width: {
|
width: {
|
||||||
if (extraContent.active)
|
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)
|
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
|
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
|
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||||
|
@ -96,7 +110,7 @@ SBSMessageBase {
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
clip: true
|
clip: true
|
||||||
onLinkHovered: root.hoveredLink = hoveredLink
|
onLinkHovered: rootDelegate.hoveredLink = hoveredLink
|
||||||
onLinkActivated: Qt.openUrlExternally(new URL(hoveredLink))
|
onLinkActivated: Qt.openUrlExternally(new URL(hoveredLink))
|
||||||
readOnly: true
|
readOnly: true
|
||||||
color: (ParsedBody !== "") ? getBaseColor() : (UtilsAdapter.luma(bubble.color) ? "white" : "dark")
|
color: (ParsedBody !== "") ? getBaseColor() : (UtilsAdapter.luma(bubble.color) ? "white" : "dark")
|
||||||
|
@ -150,7 +164,7 @@ SBSMessageBase {
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
target: previewContent
|
target: previewContent
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
root.hoveredLink = hovered ? LinkPreviewInfo.url : "";
|
rootDelegate.hoveredLink = hovered ? LinkPreviewInfo.url : "";
|
||||||
}
|
}
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
}
|
}
|
||||||
|
@ -204,7 +218,7 @@ SBSMessageBase {
|
||||||
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
textFormat: TextEdit.RichText
|
textFormat: TextEdit.RichText
|
||||||
color: root.colorText
|
color: rootDelegate.colorText
|
||||||
visible: LinkPreviewInfo.title.length > 0
|
visible: LinkPreviewInfo.title.length > 0
|
||||||
text: LinkPreviewInfo.title
|
text: LinkPreviewInfo.title
|
||||||
lineHeight: 1.3
|
lineHeight: 1.3
|
||||||
|
@ -217,9 +231,9 @@ SBSMessageBase {
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
textFormat: TextEdit.RichText
|
textFormat: TextEdit.RichText
|
||||||
visible: LinkPreviewInfo.description.length > 0
|
visible: LinkPreviewInfo.description.length > 0
|
||||||
font.underline: root.hoveredLink
|
font.underline: rootDelegate.hoveredLink
|
||||||
text: LinkPreviewInfo.description
|
text: LinkPreviewInfo.description
|
||||||
color: root.colorUrl
|
color: rootDelegate.colorUrl
|
||||||
lineHeight: 1.3
|
lineHeight: 1.3
|
||||||
}
|
}
|
||||||
Label {
|
Label {
|
||||||
|
@ -229,7 +243,7 @@ SBSMessageBase {
|
||||||
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
textFormat: TextEdit.RichText
|
textFormat: TextEdit.RichText
|
||||||
color: root.colorText
|
color: rootDelegate.colorText
|
||||||
text: LinkPreviewInfo.domain
|
text: LinkPreviewInfo.domain
|
||||||
lineHeight: 1.3
|
lineHeight: 1.3
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,26 @@ import net.jami.Adapters 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
JamiListView {
|
ListView {
|
||||||
id: root
|
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() {
|
function getDistanceToBottom() {
|
||||||
const scrollDiff = ScrollBar.vertical.position - (1.0 - ScrollBar.vertical.size);
|
const scrollDiff = ScrollBar.vertical.position - (1.0 - ScrollBar.vertical.size);
|
||||||
|
@ -139,7 +157,10 @@ JamiListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fade-in mechanism
|
// fade-in mechanism
|
||||||
Component.onCompleted: fadeAnimation.start()
|
Component.onCompleted: {
|
||||||
|
positionViewAtBeginning();
|
||||||
|
fadeAnimation.start();
|
||||||
|
}
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: overlay
|
id: overlay
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -194,13 +215,19 @@ JamiListView {
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
currentIndex: -1
|
currentIndex: -1
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: CurrentConversation
|
||||||
|
function onIdChanged() {
|
||||||
|
currentIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
model: MessagesAdapter.messageListModel
|
model: MessagesAdapter.messageListModel
|
||||||
delegate: DelegateChooser {
|
delegate: DelegateChooser {
|
||||||
id: delegateChooser
|
id: delegateChooser
|
||||||
role: "Type"
|
role: "Type"
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
id: delegateChoice
|
|
||||||
roleValue: Interaction.Type.TEXT
|
roleValue: Interaction.Type.TEXT
|
||||||
|
|
||||||
TextMessageDelegate {
|
TextMessageDelegate {
|
||||||
|
|
|
@ -947,4 +947,8 @@ Item {
|
||||||
property string tipDescription: qsTr("Tips to help you use Jami more effectively")
|
property string tipDescription: qsTr("Tips to help you use Jami more effectively")
|
||||||
property string showMoreMessagingOptions: qsTr("Show more messaging options")
|
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 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")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue