Meeting invitation display in chat conversations

This commit is contained in:
Christophe Deschamps 2025-05-19 15:50:14 +00:00
parent ac7164fb0b
commit f8276ac834
13 changed files with 479 additions and 20 deletions

View file

@ -39,6 +39,8 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
mChatMessageModel = Utils::makeQObject_ptr<ChatMessageModel>(chatmessage);
mChatMessageModel->setSelf(mChatMessageModel);
mText = mChatMessageModel->getText();
mUtf8Text = mChatMessageModel->getUtf8Text();
mHasTextContent = mChatMessageModel->getHasTextContent();
mTimestamp = QDateTime::fromSecsSinceEpoch(chatmessage->getTime());
auto from = chatmessage->getFromAddress();
auto to = chatmessage->getLocalAddress();
@ -56,6 +58,12 @@ ChatMessageCore::ChatMessageCore(const std::shared_ptr<linphone::ChatMessage> &c
mIsRead = chatmessage->isRead();
mMessageState = LinphoneEnums::fromLinphone(chatmessage->getState());
mMessageId = Utils::coreStringToAppString(chatmessage->getMessageId());
for (auto content : chatmessage->getContents()) {
if (content->isIcalendar()) {
auto conferenceInfo = linphone::Factory::get()->createConferenceInfoFromIcalendarContent(content);
mConferenceInfo = ConferenceInfoCore::create(conferenceInfo);
}
}
}
ChatMessageCore::~ChatMessageCore() {
@ -165,3 +173,7 @@ void ChatMessageCore::setMessageState(LinphoneEnums::ChatMessageState state) {
std::shared_ptr<ChatMessageModel> ChatMessageCore::getModel() const {
return mChatMessageModel;
}
ConferenceInfoGui *ChatMessageCore::getConferenceInfoGui() const {
return mConferenceInfo ? new ConferenceInfoGui(mConferenceInfo) : nullptr;
}

View file

@ -21,6 +21,8 @@
#ifndef CHATMESSAGECORE_H_
#define CHATMESSAGECORE_H_
#include "core/conference/ConferenceInfoCore.hpp"
#include "core/conference/ConferenceInfoGui.hpp"
#include "model/chat/message/ChatMessageModel.hpp"
#include "tool/AbstractObject.hpp"
#include "tool/thread/SafeConnection.hpp"
@ -35,6 +37,8 @@ class ChatMessageCore : public QObject, public AbstractObject {
Q_OBJECT
Q_PROPERTY(QDateTime timestamp READ getTimestamp WRITE setTimestamp NOTIFY timestampChanged)
Q_PROPERTY(QString text READ getText WRITE setText NOTIFY textChanged)
Q_PROPERTY(QString utf8Text MEMBER mUtf8Text CONSTANT)
Q_PROPERTY(bool hasTextContent MEMBER mHasTextContent CONSTANT)
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
Q_PROPERTY(QString fromAddress READ getFromAddress CONSTANT)
Q_PROPERTY(QString toAddress READ getToAddress CONSTANT)
@ -45,6 +49,7 @@ class ChatMessageCore : public QObject, public AbstractObject {
Q_PROPERTY(bool isRemoteMessage READ isRemoteMessage CONSTANT)
Q_PROPERTY(bool isFromChatGroup READ isFromChatGroup CONSTANT)
Q_PROPERTY(bool isRead READ isRead WRITE setIsRead NOTIFY isReadChanged)
Q_PROPERTY(ConferenceInfoGui *conferenceInfo READ getConferenceInfoGui CONSTANT)
public:
static QSharedPointer<ChatMessageCore> create(const std::shared_ptr<linphone::ChatMessage> &chatmessage);
@ -75,10 +80,12 @@ public:
void setMessageState(LinphoneEnums::ChatMessageState state);
std::shared_ptr<ChatMessageModel> getModel() const;
ConferenceInfoGui *getConferenceInfoGui() const;
signals:
void timestampChanged(QDateTime timestamp);
void textChanged(QString text);
void utf8TextChanged(QString text);
void isReadChanged(bool read);
void isRemoteMessageChanged(bool isRemote);
void messageStateChanged();
@ -90,6 +97,8 @@ signals:
private:
DECLARE_ABSTRACT_OBJECT QString mText;
QString mUtf8Text;
bool mHasTextContent;
QString mPeerAddress;
QString mFromAddress;
QString mToAddress;
@ -101,6 +110,7 @@ private:
bool mIsFromChatGroup = false;
bool mIsRead = false;
LinphoneEnums::ChatMessageState mMessageState;
QSharedPointer<ConferenceInfoCore> mConferenceInfo = nullptr;
std::shared_ptr<ChatMessageModel> mChatMessageModel;
QSharedPointer<SafeConnection<ChatMessageCore, ChatMessageModel>> mChatMessageModelConnection;

View file

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) 2021 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
@ -74,11 +74,7 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr<linphone::ConferenceInfo>
mEndDateTime = mDateTime.addSecs(mDuration * 60);
mIsScheduled = mDateTime.isValid();
mOrganizerAddress = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->asStringUriOnly());
mOrganizerName = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->getDisplayName());
if (mOrganizerName.isEmpty()) {
mOrganizerName = Utils::coreStringToAppString(conferenceInfo->getOrganizer()->getUsername());
mOrganizerName.replace(".", " ");
}
mOrganizerName = mConferenceInfoModel->getOrganizerName();
mSubject = Utils::coreStringToAppString(conferenceInfo->getSubject());
mDescription = Utils::coreStringToAppString(conferenceInfo->getDescription());
mIsEnded = getDateTimeUtc().addSecs(mDuration * 60) < QDateTime::currentDateTimeUtc();

View file

@ -4316,6 +4316,24 @@ To enable them in a commercial project, please contact us.</translation>
<source>unknown_audio_device_name</source>
<translation>Unknown device name</translation>
</message>
<message>
<location filename="../../model/chat/message/ChatMessageModel.cpp"/>
<source>conference_invitation</source>
<extracomment>&quot;Invitation à une réunion;&quot;</extracomment>
<translation>Meeting invitation</translation>
</message>
<message>
<location filename="../../model/chat/message/ChatMessageModel.cpp"/>
<source>conference_invitation_cancelled</source>
<extracomment>&quot;Annulation d'une réunion;&quot;</extracomment>
<translation>Meeting cancellation</translation>
</message>
<message>
<location filename="../../model/chat/message/ChatMessageModel.cpp"/>
<source>conference_invitation_updated</source>
<extracomment>&quot;Modification d'une réunion;&quot;</extracomment>
<translation>Meeting modification</translation>
</message>
</context>
<context>
<name>Utils</name>
@ -5831,4 +5849,55 @@ Failed to create 1-1 conversation with %1 !</extracomment>
<translation>Ok</translation>
</message>
</context>
<context>
<name>ChatMessageInvitationBubble</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_organiser_invites_you_to</source>
<extracomment>&quot; vous invite à :;&quot;</extracomment>
<translation> invites you to :</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_organiser_modified</source>
<extracomment>&quot; a modifié :;&quot;</extracomment>
<translation> modified :</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_organiser_cancelled</source>
<extracomment>&quot; a annulé :;&quot;</extracomment>
<translation> cancelled :</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_meeting_from</source>
<extracomment>&quot;de ;&quot;</extracomment>
<translation>from </translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_meeting_to</source>
<extracomment>&quot; à ;&quot;</extracomment>
<translation> to </translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_description_title</source>
<extracomment>&quot;Description;&quot;</extracomment>
<translation>Description</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_join</source>
<extracomment>&quot;Rejoindre;&quot;</extracomment>
<translation>Join</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_participants</source>
<extracomment>&quot; participants;&quot;</extracomment>
<translation> participants</translation>
</message>
</context>
</TS>

View file

@ -4331,6 +4331,24 @@ Pour les activer dans un projet commercial, merci de nous contacter.</translatio
<source>unknown_audio_device_name</source>
<translation>Appareil inconnu</translation>
</message>
<message>
<location filename="../../model/chat/message/ChatMessageModel.cpp"/>
<source>conference_invitation</source>
<extracomment>&quot;Invitation à une réunion;&quot;</extracomment>
<translation>Invitation à une réunion</translation>
</message>
<message>
<location filename="../../model/chat/message/ChatMessageModel.cpp"/>
<source>conference_invitation_cancelled</source>
<extracomment>&quot;Annulation d'une réunion;&quot;</extracomment>
<translation>Annulation d'une réunion</translation>
</message>
<message>
<location filename="../../model/chat/message/ChatMessageModel.cpp"/>
<source>conference_invitation_updated</source>
<extracomment>&quot;Modification d'une réunion;&quot;</extracomment>
<translation>Modification d'une réunion</translation>
</message>
</context>
<context>
<name>Utils</name>
@ -5846,4 +5864,55 @@ Failed to create 1-1 conversation with %1 !</extracomment>
<translation>Ok</translation>
</message>
</context>
<context>
<name>ChatMessageInvitationBubble</name>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_organiser_invites_you_to</source>
<extracomment>&quot; vous invite à :&quot;</extracomment>
<translation> vous invite à :</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_organiser_modified</source>
<extracomment>&quot; a modifié :;&quot;</extracomment>
<translation> a modifié :</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_organiser_cancelled</source>
<extracomment>&quot; a annulé :;&quot;</extracomment>
<translation> a annulé :</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_meeting_from</source>
<extracomment>&quot;de ;&quot;</extracomment>
<translation>de </translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_meeting_to</source>
<extracomment>&quot; à ;&quot;</extracomment>
<translation> à </translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_description_title</source>
<extracomment>&quot;Description;&quot;</extracomment>
<translation>Description</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_join</source>
<extracomment>&quot;Rejoindre;&quot;</extracomment>
<translation>Rejoindre</translation>
</message>
<message>
<location filename="../../view/Control/Display/Chat/ChatMessageInvitationBubble.qml"/>
<source>ics_bubble_participants</source>
<extracomment>&quot; participants;&quot;</extracomment>
<translation> participants</translation>
</message>
</context>
</TS>

View file

@ -44,6 +44,17 @@ QString ChatMessageModel::getText() const {
return ToolModel::getMessageFromContent(mMonitor->getContents());
}
QString ChatMessageModel::getUtf8Text() const {
return Utils::coreStringToAppString(mMonitor->getUtf8Text());
}
bool ChatMessageModel::getHasTextContent() const {
for (auto content : mMonitor->getContents()) {
if (content->isText()) return true;
}
return false;
}
QString ChatMessageModel::getPeerAddress() const {
return Utils::coreStringToAppString(mMonitor->getPeerAddress()->asStringUriOnly());
}

View file

@ -38,6 +38,9 @@ public:
~ChatMessageModel();
QString getText() const;
QString getUtf8Text() const;
bool getHasTextContent() const;
QDateTime getTimestamp() const;
QString getPeerAddress() const;

View file

@ -111,9 +111,7 @@ linphone::ConferenceInfo::State ConferenceInfoModel::getState() const {
QString ConferenceInfoModel::getOrganizerName() const {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto organizer = mConferenceInfo->getOrganizer()->clone();
auto name = Utils::coreStringToAppString(organizer->getDisplayName());
if (name.isEmpty()) name = ToolModel::getDisplayName(organizer);
return name;
return ToolModel::getDisplayName(organizer);
}
QString ConferenceInfoModel::getOrganizerAddress() const {

View file

@ -28,6 +28,7 @@
#include <QDirIterator>
#include <QLibrary>
#include <QTest>
#include "core/conference/ConferenceInfoCore.hpp"
DEFINE_ABSTRACT_OBJECT(ToolModel)
@ -385,13 +386,21 @@ bool ToolModel::friendIsInFriendList(const std::shared_ptr<linphone::FriendList>
}
QString ToolModel::getMessageFromContent(std::list<std::shared_ptr<linphone::Content>> contents) {
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
for (auto &content : contents) {
if (content->isText()) {
return Utils::coreStringToAppString(content->getUtf8Text());
} else if (content->isFile()) {
return Utils::coreStringToAppString(content->getName());
} else if (content->isIcalendar()) {
return QString("Invitation à une réunion");
auto conferenceInfo = linphone::Factory::get()->createConferenceInfoFromIcalendarContent(content);
auto conferenceInfoCore = ConferenceInfoCore::create(conferenceInfo);
if (conferenceInfoCore->getConferenceInfoState() == LinphoneEnums::ConferenceInfoState::New)
return tr("conference_invitation");
if (conferenceInfoCore->getConferenceInfoState() == LinphoneEnums::ConferenceInfoState::Updated)
return tr("conference_invitation_updated");
if (conferenceInfoCore->getConferenceInfoState() == LinphoneEnums::ConferenceInfoState::Cancelled)
return tr("conference_invitation_cancelled");
} else if (content->isMultipart()) {
return getMessageFromContent(content->getParts());
}

View file

@ -54,6 +54,7 @@ list(APPEND _LINPHONEAPP_QML_FILES
view/Control/Display/Call/CallStatistics.qml
view/Control/Display/Chat/ChatListView.qml
view/Control/Display/Chat/ChatMessage.qml
view/Control/Display/Chat/ChatMessageInvitationBubble.qml
view/Control/Display/Chat/ChatMessagesListView.qml
view/Control/Display/Contact/Avatar.qml
view/Control/Display/Contact/Contact.qml

View file

@ -20,7 +20,7 @@ Control.Control {
property bool isRemoteMessage: chatMessage? chatMessage.core.isRemoteMessage : false
property bool isFromChatGroup: chatMessage? chatMessage.core.isFromChatGroup : false
property var msgState: chatMessage ? chatMessage.core.messageState : LinphoneEnums.ChatMessageState.StateIdle
property string richFormatText: UtilsCpp.encodeTextToQmlRichFormat(modelData.core.text)
property string richFormatText: modelData.core.hasTextContent ? UtilsCpp.encodeTextToQmlRichFormat(modelData.core.utf8Text) : ""
hoverEnabled: true
property bool linkHovered: false
@ -43,6 +43,12 @@ Control.Control {
}
}
}
function handleDefaultMouseEvent(event) {
if (event.button === Qt.RightButton) {
optionsMenu.open()
}
}
contentItem: RowLayout {
spacing: 0
@ -69,15 +75,13 @@ Control.Control {
leftPadding: Math.round(12 * DefaultStyle.dp)
rightPadding: Math.round(12 * DefaultStyle.dp)
MouseArea {
MouseArea { // Default mouse area. Each sub bubble can control the mouse and pass on to the main mouse handler. Child bubble mouse area must cover the entire bubble.
id: defaultMouseArea
visible: invitationLoader.status !== Loader.Ready // Add other bubbles here that could control the mouse themselves, then add in bubble a signal onMouseEvent
anchors.fill: parent
acceptedButtons: Qt.RightButton
onClicked: (mouse) => {
if (mouse.button === Qt.RightButton) {
optionsMenu.open()
}
}
cursorShape: mainItem.linkHovered ? Qt.PointingHandCursor : Qt.IBeamCursor
onClicked: (mouse) => mainItem.handleDefaultMouseEvent(mouse)
cursorShape: mainItem.linkHovered ? Qt.PointingHandCursor : Qt.ArrowCursor
}
background: Item {
@ -110,7 +114,7 @@ Control.Control {
visible: mainItem.imgUrl != undefined
id: contentimage
}
Text {
Text { // Uses default mouse area for link hovering.
id: textElement
visible: mainItem.richFormatText !== ""
text: mainItem.richFormatText
@ -134,6 +138,25 @@ Control.Control {
mainItem.linkHovered = hoveredLink !== ""
}
}
// Meeting invitation bubble
/////////////////////////////
Loader {
id: invitationLoader
active: modelData.core.conferenceInfo !== null
sourceComponent: invitationComponent
}
Component {
id: invitationComponent
ChatMessageInvitationBubble {
conferenceInfoGui: modelData.core.conferenceInfo
Layout.fillWidth: true
Layout.fillHeight: true
onMouseEvent: mainItem.handleDefaultMouseEvent(event)
}
}
/////////////////////////////
RowLayout {
Layout.alignment: Qt.AlignRight
Text {

View file

@ -0,0 +1,258 @@
import QtQuick
import QtQuick.Effects
import QtQuick.Layouts
import QtQuick.Controls.Basic as Control
import Linphone
import UtilsCpp
import SettingsCpp
import "qrc:/qt/qml/Linphone/view/Style/buttonStyle.js" as ButtonStyle
import "qrc:/qt/qml/Linphone/view/Control/Tool/Helper/utils.js" as Utils
Rectangle {
id: mainItem
width: 490 * DefaultStyle.dp
height: content.implicitHeight
radius: 10 * DefaultStyle.dp
clip: true
antialiasing: true
property var conferenceInfoGui: ConferenceInfoGui
property var conferenceInfo: conferenceInfoGui?.core
property string timeRangeText: ""
property bool linkHovered: false
signal mouseEvent(MouseEvent event)
MouseArea {
anchors.fill: parent
cursorShape: mainItem.linkHovered ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: (mouse) => mouseEvent(mouse)
acceptedButtons: Qt.AllButtons // Send all to parent
}
function updateTimeRange() {
if (!conferenceInfo || !conferenceInfo.dateTime || !conferenceInfo.duration)
return;
let locale = Qt.locale();
let startDate = conferenceInfo.dateTime;
let endDate = new Date(startDate.getTime() + (conferenceInfo.duration * 60 * 1000));
let startTime = startDate.toLocaleTimeString(locale, "hh:mm");
let endTime = endDate.toLocaleTimeString(locale, "hh:mm");
let offsetMinutes = -startDate.getTimezoneOffset();
let offsetHours = Math.floor(offsetMinutes / 60);
let timeZone = "UTC" + (offsetHours >= 0 ? "+" : "") + offsetHours;
timeRangeText =
qsTr("ics_bubble_meeting_from") + startTime +
qsTr("ics_bubble_meeting_to") + endTime + " (" + timeZone + ")";
}
ColumnLayout {
id: content
anchors.fill: parent
spacing: 0
Rectangle {
Layout.fillWidth: true
height: row1.implicitHeight + 32 * DefaultStyle.dp
color: DefaultStyle.grey_100
radius: 10 * DefaultStyle.dp // rounded all, but only top visible
ColumnLayout {
id: row1
anchors.fill: parent
anchors.margins: 16 * DefaultStyle.dp
Text {
text: conferenceInfo.organizerName + (
conferenceInfo.state == LinphoneEnums.ConferenceInfoState.New ?
qsTr("ics_bubble_organiser_invites_you_to") :
conferenceInfo.state == LinphoneEnums.ConferenceInfoState.Updated ?
qsTr("ics_bubble_organiser_modified") :
conferenceInfo.state == LinphoneEnums.ConferenceInfoState.Cancelled ?
qsTr("ics_bubble_organiser_cancelled") :
""
)
font: Typography.p2
color: conferenceInfo.state == LinphoneEnums.ConferenceInfoState.New ?
DefaultStyle.main2_600 :
conferenceInfo.state == LinphoneEnums.ConferenceInfoState.Updated ?
DefaultStyle.warning_600 :
conferenceInfo.state == LinphoneEnums.ConferenceInfoState.Cancelled ?
DefaultStyle.danger_500main :
DefaultStyle.main2_600
}
RowLayout {
Layout.fillWidth: true
spacing: 10 * DefaultStyle.dp
Rectangle {
width: 48 * DefaultStyle.dp
height: 48 * DefaultStyle.dp
radius: 10 * DefaultStyle.dp
color: "transparent"
Rectangle {
anchors.fill: parent
color: "#33000000"
radius: 10 * DefaultStyle.dp
anchors.verticalCenterOffset: 4 * DefaultStyle.dp
z: -1
}
Rectangle {
id: dayRect
anchors.fill: parent
radius: 10 * DefaultStyle.dp
color: DefaultStyle.grey_0
Column {
anchors.centerIn: parent
spacing: 2 * DefaultStyle.dp
Text {
text: conferenceInfo.dateTime.toLocaleString(Qt.locale(), "ddd") + "."
color: DefaultStyle.main2_500main
font: Typography.p4
horizontalAlignment: Text.AlignHCenter
anchors.horizontalCenter: parent.horizontalCenter
}
Rectangle {
width: 23 * DefaultStyle.dp
height: 23 * DefaultStyle.dp
radius: width / 2
color: DefaultStyle.main1_500_main
anchors.horizontalCenter: parent.horizontalCenter
Text {
text: conferenceInfo.dateTime.getDate().toString()
color: DefaultStyle.grey_0
font: Typography.h4
anchors.centerIn: parent
}
}
}
}
}
// Info
ColumnLayout {
RowLayout {
EffectImage {
imageSource: AppIcons.usersThree
colorizationColor: DefaultStyle.main2_600
Layout.preferredWidth: Math.round(24 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(24 * DefaultStyle.dp)
}
Text {
text: conferenceInfo.subject
font: Typography.p2
wrapMode: Text.WordWrap
color: DefaultStyle.main2_600
}
}
Text {
text: conferenceInfo.dateTime.toLocaleString(Qt.locale(), "dddd d MMMM yyyy")
font: Typography.p4
color: DefaultStyle.main2_500main
}
Text {
text: timeRangeText
font: Typography.p4
color: DefaultStyle.main2_500main
}
}
}
}
}
Rectangle {
Layout.fillWidth: true
height: 10 * DefaultStyle.dp
color: DefaultStyle.grey_100
Layout.topMargin: -10 * DefaultStyle.dp
}
Rectangle {
Layout.fillWidth: true
height: row2.implicitHeight + 32 * DefaultStyle.dp
color: DefaultStyle.grey_0
radius: 10 * DefaultStyle.dp
ColumnLayout {
id: row2
spacing: 10 * DefaultStyle.dp
anchors.fill: parent
anchors.margins: 16 * DefaultStyle.dp
Text {
text: qsTr("ics_bubble_description_title")
font: Typography.p4
color: DefaultStyle.main2_800
visible: conferenceInfo.description.length > 0
}
Text {
text: UtilsCpp.encodeTextToQmlRichFormat(conferenceInfo.description)
wrapMode: Text.WordWrap
textFormat: Text.RichText
font: Typography.p4
color: DefaultStyle.main2_500main
visible: conferenceInfo.description.length > 0
onLinkActivated: {
if (link.startsWith('sip'))
UtilsCpp.createCall(link)
else
Qt.openUrlExternally(link)
}
onHoveredLinkChanged: {
mainItem.linkHovered = hoveredLink !== ""
}
}
RowLayout {
Layout.fillHeight: true
Layout.preferredHeight: 30 * DefaultStyle.dp
spacing: 10 * DefaultStyle.dp
EffectImage {
imageSource: AppIcons.usersTwo
colorizationColor: DefaultStyle.main2_600
Layout.preferredWidth: Math.round(14 * DefaultStyle.dp)
Layout.preferredHeight: Math.round(14 * DefaultStyle.dp)
}
Text {
text: conferenceInfo.participantCount + qsTr("ics_bubble_participants")
font: Typography.p4
color: DefaultStyle.main2_800
}
Item {
Layout.fillWidth: true
}
MediumButton {
style: ButtonStyle.ButtonStyle
//: "Rejoindre"
text: qsTr("ics_bubble_join")
visible: !SettingsCpp.disableMeetingsFeature && conferenceInfo.state != LinphoneEnums.ConferenceInfoState.Cancelled
onClicked: {
var callsWindow = UtilsCpp.getCallsWindow()
callsWindow.setupConference(mainItem.conferenceInfoGui)
UtilsCpp.smartShowWindow(callsWindow)
}
}
}
Item {
Layout.fillHeight: true
}
}
}
}
}

View file

@ -23,7 +23,7 @@ QtObject {
pixelSize: Math.round(20 * DefaultStyle.dp),
weight: Math.min(Math.round(800 * DefaultStyle.dp), 1000)
})
// Title/H2 - Large bloc title
property font h2: Qt.font( {
family: DefaultStyle.defaultFont,