diff --git a/Linphone/core/conference/ConferenceInfoCore.cpp b/Linphone/core/conference/ConferenceInfoCore.cpp index e8b73dee8..676faac46 100644 --- a/Linphone/core/conference/ConferenceInfoCore.cpp +++ b/Linphone/core/conference/ConferenceInfoCore.cpp @@ -21,12 +21,15 @@ #include "ConferenceInfoCore.hpp" #include "core/App.hpp" +#include "core/path/Paths.hpp" #include "core/proxy/ListProxy.hpp" #include "model/object/VariantObject.hpp" #include "model/tool/ToolModel.hpp" #include "tool/Utils.hpp" #include "tool/thread/SafeConnection.hpp" +#include + DEFINE_ABSTRACT_OBJECT(ConferenceInfoCore) QSharedPointer @@ -69,6 +72,7 @@ ConferenceInfoCore::ConferenceInfoCore(std::shared_ptr mUri = address && address->isValid() && !address->getDomain().empty() ? Utils::coreStringToAppString(address->asStringUriOnly()) : ""; + mIcalendarString = Utils::coreStringToAppString(conferenceInfo->getIcalendarString()); mDateTime = QDateTime::fromMSecsSinceEpoch(conferenceInfo->getDateTime() * 1000); mDuration = conferenceInfo->getDuration(); mEndDateTime = mDateTime.addSecs(mDuration * 60); @@ -123,6 +127,7 @@ ConferenceInfoCore::ConferenceInfoCore(const ConferenceInfoCore &conferenceInfoC mIsEnded = conferenceInfoCore.mIsEnded; mInviteEnabled = conferenceInfoCore.mInviteEnabled; mConferenceInfoState = conferenceInfoCore.mConferenceInfoState; + mIcalendarString = conferenceInfoCore.mIcalendarString; } ConferenceInfoCore::~ConferenceInfoCore() { @@ -653,3 +658,14 @@ bool ConferenceInfoCore::isAllDayConf() const { return mDateTime.time().hour() == 0 && mDateTime.time().minute() == 0 && mEndDateTime.time().hour() == 23 && mEndDateTime.time().minute() == 59; } + +void ConferenceInfoCore::exportConferenceToICS() const { + QString filePath(Paths::getAppLocalDirPath() + "conference.ics"); + QFile file(filePath); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream out(&file); + out << mIcalendarString; + file.close(); + } + QDesktopServices::openUrl(QUrl::fromLocalFile(filePath)); +} diff --git a/Linphone/core/conference/ConferenceInfoCore.hpp b/Linphone/core/conference/ConferenceInfoCore.hpp index 57de02a6a..1654f423e 100644 --- a/Linphone/core/conference/ConferenceInfoCore.hpp +++ b/Linphone/core/conference/ConferenceInfoCore.hpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2022 Belledonne Communications SARL. * * This file is part of linphone-desktop @@ -135,6 +135,8 @@ public: Q_INVOKABLE bool isAllDayConf() const; + Q_INVOKABLE void exportConferenceToICS() const; + signals: void dateTimeChanged(); void endDateTimeChanged(); @@ -177,6 +179,7 @@ private: QString mSubject; QString mDescription; QString mUri; + QString mIcalendarString; QVariantList mParticipants; QSharedPointer mTimeZoneModel; LinphoneEnums::ConferenceSchedulerState mConferenceSchedulerState; diff --git a/Linphone/data/image/calendar-plus.svg b/Linphone/data/image/calendar-plus.svg new file mode 100644 index 000000000..74a83ed3f --- /dev/null +++ b/Linphone/data/image/calendar-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Linphone/view/Control/Display/Chat/ChatMessageInvitationBubble.qml b/Linphone/view/Control/Display/Chat/ChatMessageInvitationBubble.qml index 0c12f4813..bcddae565 100644 --- a/Linphone/view/Control/Display/Chat/ChatMessageInvitationBubble.qml +++ b/Linphone/view/Control/Display/Chat/ChatMessageInvitationBubble.qml @@ -158,10 +158,21 @@ ColumnLayout { } } - Text { - text: conferenceInfo.dateTime.toLocaleString(Qt.locale(), "dddd d MMMM yyyy") - font: Typography.p4 - color: DefaultStyle.main2_500_main + RowLayout { + spacing: Utils.getSizeWithScreenRatio(8) + Text { + text: conferenceInfo.dateTime.toLocaleString(Qt.locale(), "dddd d MMMM yyyy") + font: Typography.p4 + color: DefaultStyle.main2_500_main + } + RoundButton { + id: calendarPlusButton + style: ButtonStyle.noBackground + icon.source: AppIcons.calendarPlus + onClicked: { + conferenceInfo.exportConferenceToICS() + } + } } Text { //: from %1 to %2 (UTC%3) diff --git a/Linphone/view/Page/Main/Meeting/MeetingPage.qml b/Linphone/view/Page/Main/Meeting/MeetingPage.qml index f0dac9a7f..1357dbc7d 100644 --- a/Linphone/view/Page/Main/Meeting/MeetingPage.qml +++ b/Linphone/view/Page/Main/Meeting/MeetingPage.qml @@ -738,7 +738,7 @@ AbstractMainPage { KeyNavigation.left: linkButton KeyNavigation.right: linkButton KeyNavigation.up: deletePopup - KeyNavigation.down: joinButton + KeyNavigation.down: calendarPlusButton onClicked: { var success = UtilsCpp.copyToClipboard(mainItem.selectedConference.core.uri) if (success) UtilsCpp.showInformationPopup(qsTr("saved"), @@ -767,6 +767,18 @@ AbstractMainPage { capitalization: Font.Capitalize } } + RoundButton { + id: calendarPlusButton + style: ButtonStyle.noBackground + icon.source: AppIcons.calendarPlus + KeyNavigation.left: calendarPlusButton + KeyNavigation.right: calendarPlusButton + KeyNavigation.up: shareNetworkButton + KeyNavigation.down: joinButton + onClicked: { + mainItem.selectedConference.core.exportConferenceToICS() + } + } } RowLayout { spacing: Utils.getSizeWithScreenRatio(8) diff --git a/Linphone/view/Style/AppIcons.qml b/Linphone/view/Style/AppIcons.qml index 0697a8d36..80a9a3b79 100644 --- a/Linphone/view/Style/AppIcons.qml +++ b/Linphone/view/Style/AppIcons.qml @@ -160,4 +160,5 @@ QtObject { property string ephemeralSettings: "image://internal/ephemeral-settings.svg" property string hourglass: "image://internal/hourglass-simple.svg" property string qtLogo: "image://internal/qt-logo.png" + property string calendarPlus: "image://internal/calendar-plus.svg" }