mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-16 04:35:47 +02:00
feature: improve location sharing
- share position to different conversations at the same time - Be able to stop sharing positions with the current conversation only - UI improvements to know who is sharing and who you are sharing to - Watchdog Change-Id: I1402f0d1b1fc117087988b1cc45f1fd05d2a83ac GitLab: #888
This commit is contained in:
parent
e5b54ad787
commit
933cce8cef
14 changed files with 575 additions and 103 deletions
|
@ -178,6 +178,7 @@ set(COMMON_SOURCES
|
||||||
${APP_SRC_DIR}/utils.cpp
|
${APP_SRC_DIR}/utils.cpp
|
||||||
${APP_SRC_DIR}/mainapplication.cpp
|
${APP_SRC_DIR}/mainapplication.cpp
|
||||||
${APP_SRC_DIR}/messagesadapter.cpp
|
${APP_SRC_DIR}/messagesadapter.cpp
|
||||||
|
${APP_SRC_DIR}/positionobject.cpp
|
||||||
${APP_SRC_DIR}/positionmanager.cpp
|
${APP_SRC_DIR}/positionmanager.cpp
|
||||||
${APP_SRC_DIR}/accountadapter.cpp
|
${APP_SRC_DIR}/accountadapter.cpp
|
||||||
${APP_SRC_DIR}/calladapter.cpp
|
${APP_SRC_DIR}/calladapter.cpp
|
||||||
|
@ -233,6 +234,7 @@ set(COMMON_HEADERS
|
||||||
${APP_SRC_DIR}/mainapplication.h
|
${APP_SRC_DIR}/mainapplication.h
|
||||||
${APP_SRC_DIR}/qrimageprovider.h
|
${APP_SRC_DIR}/qrimageprovider.h
|
||||||
${APP_SRC_DIR}/messagesadapter.h
|
${APP_SRC_DIR}/messagesadapter.h
|
||||||
|
${APP_SRC_DIR}/positionobject.h
|
||||||
${APP_SRC_DIR}/positionmanager.h
|
${APP_SRC_DIR}/positionmanager.h
|
||||||
${APP_SRC_DIR}/accountadapter.h
|
${APP_SRC_DIR}/accountadapter.h
|
||||||
${APP_SRC_DIR}/calladapter.h
|
${APP_SRC_DIR}/calladapter.h
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
|
||||||
import net.jami.Adapters 1.1
|
import net.jami.Adapters 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
@ -45,6 +47,8 @@ Item {
|
||||||
|
|
||||||
property alias presenceStatus: presenceIndicator.status
|
property alias presenceStatus: presenceIndicator.status
|
||||||
property bool showPresenceIndicator: true
|
property bool showPresenceIndicator: true
|
||||||
|
property bool showSharePositionIndicator: false
|
||||||
|
property bool showSharedPositionIndicator: false
|
||||||
property alias fillMode: image.fillMode
|
property alias fillMode: image.fillMode
|
||||||
|
|
||||||
onImageIdChanged: image.updateSource()
|
onImageIdChanged: image.updateSource()
|
||||||
|
@ -116,4 +120,48 @@ Item {
|
||||||
|
|
||||||
visible: showPresenceIndicator
|
visible: showPresenceIndicator
|
||||||
}
|
}
|
||||||
|
RowLayout {
|
||||||
|
id: positionIndicatorLayout
|
||||||
|
anchors.left: root.left
|
||||||
|
anchors.leftMargin: -1
|
||||||
|
anchors.bottom: root.bottom
|
||||||
|
anchors.bottomMargin: -1
|
||||||
|
spacing: 0
|
||||||
|
property real sizeI: root.width * JamiTheme.avatarPresenceRatio
|
||||||
|
Rectangle {
|
||||||
|
id: sharePositionIndicator
|
||||||
|
visible: showSharePositionIndicator
|
||||||
|
Layout.preferredWidth: parent.sizeI
|
||||||
|
Layout.preferredHeight: parent.sizeI
|
||||||
|
color: JamiTheme.backgroundColor
|
||||||
|
radius: parent.sizeI * 0.5
|
||||||
|
Image {
|
||||||
|
anchors.fill: parent
|
||||||
|
ColorOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: parent
|
||||||
|
color: JamiTheme.sharePositionIndicatorColor
|
||||||
|
}
|
||||||
|
source: JamiResources.my_location_svg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
id: sharedPositionIndicator
|
||||||
|
visible: showSharedPositionIndicator
|
||||||
|
Layout.preferredWidth: parent.sizeI
|
||||||
|
Layout.preferredHeight: parent.sizeI
|
||||||
|
color: JamiTheme.backgroundColor
|
||||||
|
radius: parent.sizeI * 0.5
|
||||||
|
Image {
|
||||||
|
anchors.fill: parent
|
||||||
|
ColorOverlay {
|
||||||
|
anchors.fill: parent
|
||||||
|
source: parent
|
||||||
|
color: JamiTheme.sharedPositionIndicatorColor
|
||||||
|
}
|
||||||
|
source: JamiResources.my_location_svg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,15 +299,25 @@ Item {
|
||||||
property string raiseHand: qsTr("Raise hand")
|
property string raiseHand: qsTr("Raise hand")
|
||||||
property string layoutSettings: qsTr("Layout settings")
|
property string layoutSettings: qsTr("Layout settings")
|
||||||
|
|
||||||
// Share location
|
// Share location/position
|
||||||
property string shareLocation: qsTr("Share location")
|
property string shareLocation: qsTr("Share location")
|
||||||
property string stopSharingLocation: qsTr("Stop sharing location")
|
property string stopSharingLocation: qsTr("Stop sharing")
|
||||||
property string shortSharing: qsTr("10 minutes")
|
property string shortSharing: qsTr("10 minutes")
|
||||||
property string longSharing: qsTr("One hour")
|
property string longSharing: qsTr("One hour")
|
||||||
property string minutesLeft: qsTr("%1 minutes left")
|
property string minutesLeft: qsTr("%1 minutes left")
|
||||||
property string minuteLeft: qsTr("%1 minute left")
|
property string minuteLeft: qsTr("%1 minute left")
|
||||||
property string locationServicesError: qsTr("Jami needs to access to your location.\nIn Device Settings, please turn on Location Services.\nOther participants' location can still be received.")
|
property string locationServicesError: qsTr("Your precise location could not be determined.\nIn Device Settings, please turn on \"Location Services\".\nOther participants' location can still be received.")
|
||||||
property string locationServicesClosedError: qsTr("Please check your Internet connection.")
|
property string locationServicesClosedError: qsTr("Your precise location could not be determined. Please check your Internet connection.")
|
||||||
|
property string stopAllSharings: qsTr("Turn off location sharing");
|
||||||
|
property string stopConvSharing: qsTr("Stop location sharing in this conversation");
|
||||||
|
property string stopSharingPopupBody: qsTr("Location is shared in several conversations");
|
||||||
|
property string minimizeMapTooltip: qsTr("Minimize");
|
||||||
|
property string maximizeMapTooltip: qsTr("Maximize");
|
||||||
|
property string reduceMapTooltip: qsTr("Reduce");
|
||||||
|
property string extendMapTooltip: qsTr("Extend");
|
||||||
|
property string dragMapTooltip: qsTr("Drag");
|
||||||
|
property string centerMapTooltip: qsTr("Center");
|
||||||
|
property string closeMapTooltip: qsTr("Close");
|
||||||
|
|
||||||
// Chatview header
|
// Chatview header
|
||||||
property string hideChat: qsTr("Hide chat")
|
property string hideChat: qsTr("Hide chat")
|
||||||
|
|
|
@ -213,6 +213,8 @@ Item {
|
||||||
//mapPosition
|
//mapPosition
|
||||||
property color mapButtonsOverlayColor: darkTheme ? "#000000" : "#f0f0f0"
|
property color mapButtonsOverlayColor: darkTheme ? "#000000" : "#f0f0f0"
|
||||||
property color mapButtonColor: darkTheme ? "#f0f0f0" : "#000000"
|
property color mapButtonColor: darkTheme ? "#f0f0f0" : "#000000"
|
||||||
|
property color sharePositionIndicatorColor: red_
|
||||||
|
property color sharedPositionIndicatorColor: urgentOrange_
|
||||||
|
|
||||||
// Files To Send Container
|
// Files To Send Container
|
||||||
property color removeFileButtonColor: Qt.rgba(96, 95, 97, 0.5)
|
property color removeFileButtonColor: Qt.rgba(96, 95, 97, 0.5)
|
||||||
|
@ -318,7 +320,7 @@ Item {
|
||||||
property real preferredDialogWidth: 400
|
property real preferredDialogWidth: 400
|
||||||
property real preferredDialogHeight: 300
|
property real preferredDialogHeight: 300
|
||||||
property real minimumPreviewWidth: 120
|
property real minimumPreviewWidth: 120
|
||||||
property real minimumMapWidth: 230
|
property real minimumMapWidth: 250
|
||||||
property real pluginHandlersPopupViewHeight: 200
|
property real pluginHandlersPopupViewHeight: 200
|
||||||
property real pluginHandlersPopupViewDelegateHeight: 50
|
property real pluginHandlersPopupViewDelegateHeight: 50
|
||||||
property real secondaryDialogDimension: 500
|
property real secondaryDialogDimension: 500
|
||||||
|
|
|
@ -28,6 +28,8 @@ Item {
|
||||||
|
|
||||||
property alias imageId: avatar.imageId
|
property alias imageId: avatar.imageId
|
||||||
property alias showPresenceIndicator: avatar.showPresenceIndicator
|
property alias showPresenceIndicator: avatar.showPresenceIndicator
|
||||||
|
property alias showSharePositionIndicator: avatar.showSharePositionIndicator
|
||||||
|
property alias showSharedPositionIndicator: avatar.showSharedPositionIndicator
|
||||||
property alias animationMode: animation.mode
|
property alias animationMode: animation.mode
|
||||||
|
|
||||||
SpinningAnimation {
|
SpinningAnimation {
|
||||||
|
|
|
@ -68,10 +68,22 @@ ItemDelegate {
|
||||||
|
|
||||||
imageId: UID
|
imageId: UID
|
||||||
showPresenceIndicator: Presence !== undefined ? Presence : false
|
showPresenceIndicator: Presence !== undefined ? Presence : false
|
||||||
|
showSharePositionIndicator: PositionManager.isPositionSharedToConv(UID)
|
||||||
|
showSharedPositionIndicator: PositionManager.isConvSharingPosition(UID)
|
||||||
|
|
||||||
Layout.preferredWidth: JamiTheme.smartListAvatarSize
|
Layout.preferredWidth: JamiTheme.smartListAvatarSize
|
||||||
Layout.preferredHeight: JamiTheme.smartListAvatarSize
|
Layout.preferredHeight: JamiTheme.smartListAvatarSize
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: PositionManager
|
||||||
|
function onPositionShareConvIdsChanged () {
|
||||||
|
avatar.showSharePositionIndicator = PositionManager.isPositionSharedToConv(UID)
|
||||||
|
}
|
||||||
|
function onSharingUrisChanged () {
|
||||||
|
avatar.showSharedPositionIndicator = PositionManager.isConvSharingPosition(UID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: overlayHighlighted
|
id: overlayHighlighted
|
||||||
visible: highlighted && !interactive
|
visible: highlighted && !interactive
|
||||||
|
|
|
@ -28,7 +28,7 @@ Positioning::Positioning(QString uri, QObject* parent)
|
||||||
source_ = QGeoPositionInfoSource::createDefaultSource(this);
|
source_ = QGeoPositionInfoSource::createDefaultSource(this);
|
||||||
QTimer* timer = new QTimer(this);
|
QTimer* timer = new QTimer(this);
|
||||||
connect(timer, &QTimer::timeout, this, &Positioning::requestPosition);
|
connect(timer, &QTimer::timeout, this, &Positioning::requestPosition);
|
||||||
timer->start(2000);
|
timer->start(5000);
|
||||||
connect(source_, &QGeoPositionInfoSource::errorOccurred, this, &Positioning::slotError);
|
connect(source_, &QGeoPositionInfoSource::errorOccurred, this, &Positioning::slotError);
|
||||||
connect(source_, &QGeoPositionInfoSource::positionUpdated, this, &Positioning::positionUpdated);
|
connect(source_, &QGeoPositionInfoSource::positionUpdated, this, &Positioning::positionUpdated);
|
||||||
// if location services are activated, positioning will be activated automatically
|
// if location services are activated, positioning will be activated automatically
|
||||||
|
@ -38,11 +38,6 @@ Positioning::Positioning(QString uri, QObject* parent)
|
||||||
&Positioning::locationServicesActivated);
|
&Positioning::locationServicesActivated);
|
||||||
}
|
}
|
||||||
|
|
||||||
Positioning::~Positioning()
|
|
||||||
{
|
|
||||||
sendStopSharingMsg();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Positioning::start()
|
Positioning::start()
|
||||||
{
|
{
|
||||||
|
@ -60,16 +55,6 @@ Positioning::stop()
|
||||||
isPositioning = false;
|
isPositioning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Positioning::sendStopSharingMsg()
|
|
||||||
{
|
|
||||||
QJsonObject jsonObj;
|
|
||||||
jsonObj.insert("type", QJsonValue("Stop"));
|
|
||||||
QJsonDocument doc(jsonObj);
|
|
||||||
QString strJson(doc.toJson(QJsonDocument::Compact));
|
|
||||||
Q_EMIT newPosition(uri_, strJson, -1, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
QString
|
||||||
Positioning::convertToJson(const QGeoPositionInfo& info)
|
Positioning::convertToJson(const QGeoPositionInfo& info)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,8 +28,6 @@ class Positioning : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Positioning(QString uri, QObject* parent = 0);
|
Positioning(QString uri, QObject* parent = 0);
|
||||||
~Positioning();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* start to retreive the current position
|
* start to retreive the current position
|
||||||
*/
|
*/
|
||||||
|
@ -42,7 +40,6 @@ public:
|
||||||
* send a stop signal to other peers to tell them
|
* send a stop signal to other peers to tell them
|
||||||
* you stoped sharing yout position
|
* you stoped sharing yout position
|
||||||
*/
|
*/
|
||||||
void sendStopSharingMsg();
|
|
||||||
QString convertToJson(const QGeoPositionInfo& info);
|
QString convertToJson(const QGeoPositionInfo& info);
|
||||||
|
|
||||||
void setUri(QString uri);
|
void setUri(QString uri);
|
||||||
|
|
|
@ -19,8 +19,10 @@ PositionManager::PositionManager(LRCInstance* instance, QObject* parent)
|
||||||
});
|
});
|
||||||
connect(timerStopSharing_, &QTimer::timeout, [=] { stopSharingPosition(); });
|
connect(timerStopSharing_, &QTimer::timeout, [=] { stopSharingPosition(); });
|
||||||
connect(lrcInstance_, &LRCInstance::selectedConvUidChanged, [this]() {
|
connect(lrcInstance_, &LRCInstance::selectedConvUidChanged, [this]() {
|
||||||
|
Q_EMIT positionShareConvIdsChanged();
|
||||||
set_mapAutoOpening(true);
|
set_mapAutoOpening(true);
|
||||||
});
|
});
|
||||||
|
set_isMapActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -28,8 +30,14 @@ PositionManager::safeInit()
|
||||||
{
|
{
|
||||||
connect(lrcInstance_, &LRCInstance::currentAccountIdChanged, [this]() {
|
connect(lrcInstance_, &LRCInstance::currentAccountIdChanged, [this]() {
|
||||||
connectConversationModel();
|
connectConversationModel();
|
||||||
|
set_sharingUris({});
|
||||||
|
objectListSharingUris_.clear();
|
||||||
|
set_positionShareConvIds({});
|
||||||
localPositioning_->setUri(lrcInstance_->getCurrentAccountInfo().profileInfo.uri);
|
localPositioning_->setUri(lrcInstance_->getCurrentAccountInfo().profileInfo.uri);
|
||||||
});
|
});
|
||||||
|
set_sharingUris({});
|
||||||
|
objectListSharingUris_.clear();
|
||||||
|
set_positionShareConvIds({});
|
||||||
localPositioning_.reset(new Positioning(lrcInstance_->getCurrentAccountInfo().profileInfo.uri));
|
localPositioning_.reset(new Positioning(lrcInstance_->getCurrentAccountInfo().profileInfo.uri));
|
||||||
connectConversationModel();
|
connectConversationModel();
|
||||||
}
|
}
|
||||||
|
@ -49,8 +57,7 @@ PositionManager::connectConversationModel()
|
||||||
void
|
void
|
||||||
PositionManager::startPositioning()
|
PositionManager::startPositioning()
|
||||||
{
|
{
|
||||||
sharingUris_.clear();
|
currentConvSharingUris_.clear();
|
||||||
|
|
||||||
localPositioning_->start();
|
localPositioning_->start();
|
||||||
connect(localPositioning_.get(),
|
connect(localPositioning_.get(),
|
||||||
&Positioning::newPosition,
|
&Positioning::newPosition,
|
||||||
|
@ -70,8 +77,54 @@ PositionManager::stopPositioning()
|
||||||
localPositioning_->stop();
|
localPositioning_->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
PositionManager::getSelectedConvId()
|
||||||
|
{
|
||||||
|
return lrcInstance_->get_selectedConvUid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PositionManager::isConvSharingPosition(const QString& convUri)
|
||||||
|
{
|
||||||
|
const auto& convParticipants = lrcInstance_->getConversationFromConvUid(convUri)
|
||||||
|
.participantsUris();
|
||||||
|
Q_FOREACH (const auto& id, convParticipants) {
|
||||||
|
if (id != lrcInstance_->getCurrentAccountInfo().profileInfo.uri) {
|
||||||
|
if (sharingUris_.contains(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PositionManager::onOwnPositionReceived(const QString& peerId, const QString& body)
|
PositionManager::loadPreviousLocations()
|
||||||
|
{
|
||||||
|
QVariantMap shareInfo;
|
||||||
|
for (auto it = objectListSharingUris_.begin(); it != objectListSharingUris_.end(); it++) {
|
||||||
|
QJsonObject jsonObj;
|
||||||
|
jsonObj.insert("type", QJsonValue("Position"));
|
||||||
|
jsonObj.insert("lat", it.value()->getLatitude().toString());
|
||||||
|
jsonObj.insert("long", it.value()->getLongitude().toString());
|
||||||
|
QJsonDocument doc(jsonObj);
|
||||||
|
QString strJson(doc.toJson(QJsonDocument::Compact));
|
||||||
|
onPositionReceived(it.key(), strJson, -1, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PositionManager::isPositionSharedToConv(const QString& convUri)
|
||||||
|
{
|
||||||
|
if (positionShareConvIds_.length()) {
|
||||||
|
auto iter = std::find(positionShareConvIds_.begin(), positionShareConvIds_.end(), convUri);
|
||||||
|
return (iter != positionShareConvIds_.end());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PositionManager::sendPosition(const QString& peerId, const QString& body)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Q_FOREACH (const auto& id, positionShareConvIds_) {
|
Q_FOREACH (const auto& id, positionShareConvIds_) {
|
||||||
|
@ -89,13 +142,26 @@ PositionManager::onOwnPositionReceived(const QString& peerId, const QString& bod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PositionManager::onWatchdogTimeout()
|
||||||
|
{
|
||||||
|
QObject* obj = sender();
|
||||||
|
auto it = std::find_if(objectListSharingUris_.cbegin(),
|
||||||
|
objectListSharingUris_.cend(),
|
||||||
|
[obj](const auto& it) { return it == obj; });
|
||||||
|
if (it != objectListSharingUris_.cend()) {
|
||||||
|
QString stopMsg("{\"type\":\"Stop\"}");
|
||||||
|
onPositionReceived(it.key(), stopMsg, -1, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PositionManager::sharePosition(int maximumTime)
|
PositionManager::sharePosition(int maximumTime)
|
||||||
{
|
{
|
||||||
connect(localPositioning_.get(),
|
connect(localPositioning_.get(),
|
||||||
&Positioning::newPosition,
|
&Positioning::newPosition,
|
||||||
this,
|
this,
|
||||||
&PositionManager::onOwnPositionReceived,
|
&PositionManager::sendPosition,
|
||||||
Qt::UniqueConnection);
|
Qt::UniqueConnection);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -109,11 +175,29 @@ PositionManager::sharePosition(int maximumTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PositionManager::stopSharingPosition()
|
PositionManager::stopSharingPosition(const QString convId)
|
||||||
{
|
{
|
||||||
localPositioning_->sendStopSharingMsg();
|
QString stopMsg;
|
||||||
stopPositionTimers();
|
stopMsg = "{\"type\":\"Stop\"}";
|
||||||
set_positionShareConvIds({});
|
if (convId == "") {
|
||||||
|
sendPosition(lrcInstance_->getCurrentAccountInfo().profileInfo.uri, stopMsg);
|
||||||
|
stopPositionTimers();
|
||||||
|
set_positionShareConvIds({});
|
||||||
|
} else {
|
||||||
|
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId);
|
||||||
|
Q_FOREACH (const QString& uri, convInfo.participantsUris()) {
|
||||||
|
if (lrcInstance_->getCurrentAccountInfo().profileInfo.uri != uri) {
|
||||||
|
lrcInstance_->getCurrentAccountInfo().contactModel->sendDhtMessage(uri,
|
||||||
|
stopMsg,
|
||||||
|
APPLICATION_GEO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto iter = std::find(positionShareConvIds_.begin(), positionShareConvIds_.end(), convId);
|
||||||
|
if (iter != positionShareConvIds_.end()) {
|
||||||
|
positionShareConvIds_.remove(std::distance(positionShareConvIds_.begin(), iter));
|
||||||
|
}
|
||||||
|
Q_EMIT positionShareConvIdsChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -197,10 +281,9 @@ PositionManager::onPositionReceived(const QString& peerId,
|
||||||
->getConversationFromConvUid(
|
->getConversationFromConvUid(
|
||||||
lrcInstance_->get_selectedConvUid())
|
lrcInstance_->get_selectedConvUid())
|
||||||
.participantsUris();
|
.participantsUris();
|
||||||
|
// to know if the position received is from someone in the current conversation
|
||||||
bool isPeerIdInConv = (std::find(convParticipants.begin(), convParticipants.end(), peerId)
|
bool isPeerIdInConv = (std::find(convParticipants.begin(), convParticipants.end(), peerId)
|
||||||
!= convParticipants.end());
|
!= convParticipants.end());
|
||||||
if (!isPeerIdInConv)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QVariantMap newPosition = parseJsonPosition(body, peerId);
|
QVariantMap newPosition = parseJsonPosition(body, peerId);
|
||||||
auto getShareInfo = [&](bool update) -> QVariantMap {
|
auto getShareInfo = [&](bool update) -> QVariantMap {
|
||||||
|
@ -217,36 +300,79 @@ PositionManager::onPositionReceived(const QString& peerId,
|
||||||
|
|
||||||
if (!endSharing) {
|
if (!endSharing) {
|
||||||
// open map on position reception
|
// open map on position reception
|
||||||
if (!isMapActive_ && mapAutoOpening_
|
if (!isMapActive_ && mapAutoOpening_ && isPeerIdInConv
|
||||||
&& peerId != lrcInstance_->getCurrentAccountInfo().profileInfo.uri) {
|
&& peerId != lrcInstance_->getCurrentAccountInfo().profileInfo.uri) {
|
||||||
set_isMapActive(true);
|
set_isMapActive(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto iter = std::find(sharingUris_.begin(), sharingUris_.end(), peerId);
|
auto iter = std::find(currentConvSharingUris_.begin(), currentConvSharingUris_.end(), peerId);
|
||||||
if (iter == sharingUris_.end()) {
|
if (iter == currentConvSharingUris_.end()) {
|
||||||
// New share
|
// New share
|
||||||
if (!endSharing) {
|
if (!endSharing) {
|
||||||
sharingUris_.insert(peerId);
|
sharingUris_.insert(peerId);
|
||||||
Q_EMIT positionShareAdded(getShareInfo(false));
|
Q_EMIT sharingUrisChanged();
|
||||||
}
|
|
||||||
|
|
||||||
|
// list to save more information on position + watchdog
|
||||||
|
auto it = objectListSharingUris_.find(peerId);
|
||||||
|
if (it == objectListSharingUris_.end()) {
|
||||||
|
auto obj = new PositionObject(newPosition["lat"], newPosition["long"], this);
|
||||||
|
|
||||||
|
objectListSharingUris_.insert(peerId, obj);
|
||||||
|
connect(obj,
|
||||||
|
&PositionObject::timeout,
|
||||||
|
this,
|
||||||
|
&PositionManager::onWatchdogTimeout,
|
||||||
|
Qt::DirectConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPeerIdInConv) {
|
||||||
|
currentConvSharingUris_.insert(peerId);
|
||||||
|
Q_EMIT positionShareAdded(getShareInfo(false));
|
||||||
|
}
|
||||||
|
// stop sharing position
|
||||||
|
} else {
|
||||||
|
sharingUris_.remove(peerId);
|
||||||
|
Q_EMIT sharingUrisChanged();
|
||||||
|
auto it = objectListSharingUris_.find(peerId);
|
||||||
|
if (it != objectListSharingUris_.end()) {
|
||||||
|
it.value()->deleteLater();
|
||||||
|
objectListSharingUris_.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Update/remove existing
|
// Update/remove existing
|
||||||
if (endSharing) {
|
if (endSharing) {
|
||||||
// Remove (avoid self)
|
// Remove
|
||||||
if (peerId != lrcInstance_->getCurrentAccountInfo().profileInfo.uri) {
|
|
||||||
sharingUris_.remove(peerId);
|
sharingUris_.remove(peerId);
|
||||||
|
Q_EMIT sharingUrisChanged();
|
||||||
|
auto it = objectListSharingUris_.find(peerId);
|
||||||
|
if (it != objectListSharingUris_.end()) {
|
||||||
|
it.value()->deleteLater();
|
||||||
|
objectListSharingUris_.erase(it);
|
||||||
|
}
|
||||||
|
if (isPeerIdInConv) {
|
||||||
|
currentConvSharingUris_.remove(peerId);
|
||||||
Q_EMIT positionShareRemoved(peerId);
|
Q_EMIT positionShareRemoved(peerId);
|
||||||
// close the map if you're not sharing and the only remaining position is yours
|
// close the map if you're not sharing and you don't receive position anymore
|
||||||
if (!positionShareConvIds_.length() && sharingUris_.size() == 1
|
if (!positionShareConvIds_.length()
|
||||||
&& sharingUris_.contains(
|
&& ((sharingUris_.size() == 1
|
||||||
lrcInstance_->getCurrentAccountInfo().profileInfo.uri)) {
|
&& sharingUris_.contains(
|
||||||
|
lrcInstance_->getCurrentAccountInfo().profileInfo.uri))
|
||||||
|
|| sharingUris_.size() == 0)) {
|
||||||
set_isMapActive(false);
|
set_isMapActive(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Update
|
// Update
|
||||||
Q_EMIT positionShareUpdated(getShareInfo(true));
|
if (isPeerIdInConv)
|
||||||
|
Q_EMIT positionShareUpdated(getShareInfo(true));
|
||||||
|
// reset watchdog
|
||||||
|
|
||||||
|
auto it = objectListSharingUris_.find(peerId);
|
||||||
|
if (it != objectListSharingUris_.end()) {
|
||||||
|
it.value()->resetWatchdog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "lrcinstance.h"
|
#include "lrcinstance.h"
|
||||||
#include "qmladapterbase.h"
|
#include "qmladapterbase.h"
|
||||||
#include "positioning.h"
|
#include "positioning.h"
|
||||||
|
#include "positionobject.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
@ -31,6 +32,7 @@ class PositionManager : public QmlAdapterBase
|
||||||
QML_RO_PROPERTY(bool, isMapActive)
|
QML_RO_PROPERTY(bool, isMapActive)
|
||||||
QML_RO_PROPERTY(int, timeSharingRemaining)
|
QML_RO_PROPERTY(int, timeSharingRemaining)
|
||||||
QML_PROPERTY(QList<QString>, positionShareConvIds)
|
QML_PROPERTY(QList<QString>, positionShareConvIds)
|
||||||
|
QML_PROPERTY(QSet<QString>, sharingUris)
|
||||||
QML_PROPERTY(bool, mapAutoOpening)
|
QML_PROPERTY(bool, mapAutoOpening)
|
||||||
public:
|
public:
|
||||||
explicit PositionManager(LRCInstance* instance, QObject* parent = nullptr);
|
explicit PositionManager(LRCInstance* instance, QObject* parent = nullptr);
|
||||||
|
@ -54,9 +56,16 @@ protected:
|
||||||
Q_INVOKABLE void connectConversationModel();
|
Q_INVOKABLE void connectConversationModel();
|
||||||
Q_INVOKABLE void setMapActive(bool state);
|
Q_INVOKABLE void setMapActive(bool state);
|
||||||
Q_INVOKABLE void sharePosition(int maximumTime);
|
Q_INVOKABLE void sharePosition(int maximumTime);
|
||||||
|
Q_INVOKABLE void stopSharingPosition(const QString convId = "");
|
||||||
|
|
||||||
Q_INVOKABLE void startPositioning();
|
Q_INVOKABLE void startPositioning();
|
||||||
Q_INVOKABLE void stopPositioning();
|
Q_INVOKABLE void stopPositioning();
|
||||||
Q_INVOKABLE void stopSharingPosition();
|
|
||||||
|
Q_INVOKABLE QString getSelectedConvId();
|
||||||
|
Q_INVOKABLE bool isPositionSharedToConv(const QString& convUri);
|
||||||
|
Q_INVOKABLE bool isConvSharingPosition(const QString& convUri);
|
||||||
|
|
||||||
|
Q_INVOKABLE void loadPreviousLocations();
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void onPositionErrorReceived(const QString error);
|
void onPositionErrorReceived(const QString error);
|
||||||
|
@ -64,11 +73,13 @@ private Q_SLOTS:
|
||||||
const QString& body,
|
const QString& body,
|
||||||
const uint64_t& timestamp,
|
const uint64_t& timestamp,
|
||||||
const QString& daemonId);
|
const QString& daemonId);
|
||||||
void onOwnPositionReceived(const QString& peerId, const QString& body);
|
void sendPosition(const QString& peerId, const QString& body);
|
||||||
|
void onWatchdogTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Positioning> localPositioning_;
|
std::unique_ptr<Positioning> localPositioning_;
|
||||||
QTimer* timerTimeLeftSharing_ = nullptr;
|
QTimer* timerTimeLeftSharing_ = nullptr;
|
||||||
QTimer* timerStopSharing_ = nullptr;
|
QTimer* timerStopSharing_ = nullptr;
|
||||||
QSet<QString> sharingUris_;
|
QSet<QString> currentConvSharingUris_;
|
||||||
|
QMap<QString, PositionObject*> objectListSharingUris_;
|
||||||
};
|
};
|
||||||
|
|
30
src/app/positionobject.cpp
Normal file
30
src/app/positionobject.cpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include "positionobject.h"
|
||||||
|
|
||||||
|
PositionObject::PositionObject(QVariant latitude, QVariant longitude, QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, resetTime(20000)
|
||||||
|
, longitude_(longitude)
|
||||||
|
, latitude_(latitude)
|
||||||
|
|
||||||
|
{
|
||||||
|
watchdog_ = new QTimer(this);
|
||||||
|
watchdog_->start(resetTime);
|
||||||
|
connect(watchdog_, &QTimer::timeout, this, &PositionObject::timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PositionObject::resetWatchdog()
|
||||||
|
{
|
||||||
|
watchdog_->start(resetTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
PositionObject::getLongitude()
|
||||||
|
{
|
||||||
|
return longitude_;
|
||||||
|
}
|
||||||
|
QVariant
|
||||||
|
PositionObject::getLatitude()
|
||||||
|
{
|
||||||
|
return latitude_;
|
||||||
|
}
|
28
src/app/positionobject.h
Normal file
28
src/app/positionobject.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qvariant.h"
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class PositionObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PositionObject(QVariant latitude, QVariant longitude, QObject* parent = nullptr);
|
||||||
|
|
||||||
|
Q_SIGNAL void timeout();
|
||||||
|
|
||||||
|
void resetWatchdog();
|
||||||
|
|
||||||
|
QVariant getLongitude();
|
||||||
|
QVariant getLatitude();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVariant latitude_;
|
||||||
|
QVariant longitude_;
|
||||||
|
int resetTime;
|
||||||
|
QTimer* watchdog_;
|
||||||
|
};
|
|
@ -106,10 +106,6 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Component.onDestruction: {
|
|
||||||
PositionManager.stopSharingPosition();
|
|
||||||
PositionManager.stopPositioning();
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
loadHtml(UtilsAdapter.qStringFromFile(mapHtml), mapHtml)
|
loadHtml(UtilsAdapter.qStringFromFile(mapHtml), mapHtml)
|
||||||
|
@ -122,6 +118,8 @@ Rectangle {
|
||||||
webView.isLoaded = true
|
webView.isLoaded = true
|
||||||
runJavaScript("setMapView([" + 0 + ","+ 0 + "], " + 1 + " );" );
|
runJavaScript("setMapView([" + 0 + ","+ 0 + "], " + 1 + " );" );
|
||||||
PositionManager.startPositioning()
|
PositionManager.startPositioning()
|
||||||
|
//load locations that were received before this conversation was opened
|
||||||
|
PositionManager.loadPreviousLocations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,7 +150,6 @@ Rectangle {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
buttonsChoseSharing.shortSharing = true
|
buttonsChoseSharing.shortSharing = true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialButton {
|
MaterialButton {
|
||||||
|
@ -195,69 +192,108 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialButton {
|
RowLayout {
|
||||||
id: sharePositionButton
|
id: sharePositionLayout
|
||||||
|
|
||||||
preferredWidth: text.contentWidth
|
|
||||||
textLeftPadding: JamiTheme.buttontextPadding
|
|
||||||
textRightPadding: JamiTheme.buttontextPadding
|
|
||||||
primary: true
|
|
||||||
text: webView.isSharing ? JamiStrings.stopSharingLocation : JamiStrings.shareLocation
|
|
||||||
color: isError
|
|
||||||
? JamiTheme.buttonTintedGreyInactive
|
|
||||||
: webView.isSharing ? JamiTheme.buttonTintedRed : JamiTheme.buttonTintedBlue
|
|
||||||
hoveredColor: isError
|
|
||||||
? JamiTheme.buttonTintedGreyInactive
|
|
||||||
: webView.isSharing ? JamiTheme.buttonTintedRedHovered : JamiTheme.buttonTintedBlueHovered
|
|
||||||
pressedColor: isError
|
|
||||||
? JamiTheme.buttonTintedGreyInactive
|
|
||||||
: webView.isSharing ? JamiTheme.buttonTintedRedPressed: JamiTheme.buttonTintedBluePressed
|
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
property bool isHovered: false
|
MaterialButton {
|
||||||
property string positioningError: "default"
|
id: sharePositionButton
|
||||||
property bool isError: positioningError.length
|
|
||||||
|
|
||||||
function errorString(posError) {
|
preferredWidth: text.contentWidth
|
||||||
if (posError === "locationServicesError")
|
textLeftPadding: JamiTheme.buttontextPadding
|
||||||
return JamiStrings.locationServicesError
|
textRightPadding: JamiTheme.buttontextPadding
|
||||||
return JamiStrings.locationServicesClosedError
|
primary: true
|
||||||
}
|
visible: ! PositionManager.isPositionSharedToConv(PositionManager.getSelectedConvId())
|
||||||
|
text: JamiStrings.shareLocation
|
||||||
|
color: isError
|
||||||
|
? JamiTheme.buttonTintedGreyInactive
|
||||||
|
: JamiTheme.buttonTintedBlue
|
||||||
|
hoveredColor: isError
|
||||||
|
? JamiTheme.buttonTintedGreyInactive
|
||||||
|
: JamiTheme.buttonTintedBlueHovered
|
||||||
|
pressedColor: isError
|
||||||
|
? JamiTheme.buttonTintedGreyInactive
|
||||||
|
: JamiTheme.buttonTintedBluePressed
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
property bool isHovered: false
|
||||||
|
property string positioningError: "default"
|
||||||
|
property bool isError: positioningError.length
|
||||||
|
function errorString(posError) {
|
||||||
|
if (posError === "locationServicesError")
|
||||||
|
return JamiStrings.locationServicesError
|
||||||
|
return JamiStrings.locationServicesClosedError
|
||||||
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!isError) {
|
if (!isError) {
|
||||||
if (webView.isSharing) {
|
if( buttonsChoseSharing.shortSharing)
|
||||||
PositionManager.stopSharingPosition();
|
|
||||||
} else {
|
|
||||||
if (buttonsChoseSharing.shortSharing)
|
|
||||||
PositionManager.sharePosition(10 * 60 * 1000);
|
PositionManager.sharePosition(10 * 60 * 1000);
|
||||||
else
|
else
|
||||||
PositionManager.sharePosition(60 * 60 * 1000);
|
PositionManager.sharePosition(60 * 60 * 1000);
|
||||||
|
visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onHoveredChanged: {
|
||||||
|
isHovered = !isHovered
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialToolTip {
|
||||||
|
visible: sharePositionButton.isHovered
|
||||||
|
&& sharePositionButton.isError && (sharePositionButton.positioningError !== "default")
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
text: sharePositionButton.errorString(sharePositionButton.positioningError)
|
||||||
|
}
|
||||||
|
Connections {
|
||||||
|
target: PositionManager
|
||||||
|
function onPositioningError (err) {
|
||||||
|
sharePositionButton.positioningError = err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MaterialButton {
|
||||||
|
id: stopSharingPositionButton
|
||||||
|
|
||||||
onHoveredChanged: {
|
preferredWidth: text.contentWidth
|
||||||
isHovered = !isHovered
|
textLeftPadding: JamiTheme.buttontextPadding
|
||||||
}
|
textRightPadding: JamiTheme.buttontextPadding
|
||||||
|
primary: true
|
||||||
MaterialToolTip {
|
visible: webView.isSharing
|
||||||
visible: sharePositionButton.isHovered
|
text: JamiStrings.stopSharingLocation
|
||||||
&& sharePositionButton.isError && (sharePositionButton.positioningError !== "default")
|
color: isError
|
||||||
x: 0
|
? JamiTheme.buttonTintedGreyInactive
|
||||||
y: 0
|
: JamiTheme.buttonTintedRed
|
||||||
text: sharePositionButton.errorString(sharePositionButton.positioningError)
|
hoveredColor: isError
|
||||||
}
|
? JamiTheme.buttonTintedGreyInactive
|
||||||
|
: JamiTheme.buttonTintedRedHovered
|
||||||
Connections {
|
pressedColor: isError
|
||||||
target: PositionManager
|
? JamiTheme.buttonTintedGreyInactive
|
||||||
function onPositioningError (err) {
|
: JamiTheme.buttonTintedRedPressed
|
||||||
sharePositionButton.positioningError = err;
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
property bool isHovered: false
|
||||||
|
property string positioningError
|
||||||
|
property bool isError: positioningError.length
|
||||||
|
onClicked: {
|
||||||
|
if (!isError) {
|
||||||
|
if (PositionManager.positionShareConvIds.length >= 2) {
|
||||||
|
stopSharingPositionPopup.open()
|
||||||
|
} else {
|
||||||
|
PositionManager.stopSharingPosition();
|
||||||
|
sharePositionButton.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StopSharingPositionPopup {
|
||||||
|
id: stopSharingPositionPopup
|
||||||
|
|
||||||
|
property alias shareButtonVisibility: sharePositionButton.visible
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: buttonOverlay
|
id: buttonOverlay
|
||||||
|
|
||||||
|
@ -277,6 +313,7 @@ Rectangle {
|
||||||
PushButton {
|
PushButton {
|
||||||
id: btnCenter
|
id: btnCenter
|
||||||
|
|
||||||
|
toolTipText: JamiStrings.centerMapTooltip
|
||||||
imageColor: JamiTheme.mapButtonColor
|
imageColor: JamiTheme.mapButtonColor
|
||||||
normalColor: JamiTheme.transparentColor
|
normalColor: JamiTheme.transparentColor
|
||||||
source: JamiResources.share_location_svg
|
source: JamiResources.share_location_svg
|
||||||
|
@ -288,6 +325,7 @@ Rectangle {
|
||||||
PushButton {
|
PushButton {
|
||||||
id: btnMove
|
id: btnMove
|
||||||
|
|
||||||
|
toolTipText: JamiStrings.dragMapTooltip
|
||||||
imageColor: JamiTheme.mapButtonColor
|
imageColor: JamiTheme.mapButtonColor
|
||||||
normalColor: JamiTheme.transparentColor
|
normalColor: JamiTheme.transparentColor
|
||||||
source: JamiResources.move_svg
|
source: JamiResources.move_svg
|
||||||
|
@ -303,8 +341,11 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
PushButton {
|
PushButton {
|
||||||
id: btnminimise
|
id: btnminimize
|
||||||
|
|
||||||
|
toolTipText: isMinimised
|
||||||
|
? JamiStrings.extendMapTooltip
|
||||||
|
: JamiStrings.minimizeMapTooltip
|
||||||
imageColor: JamiTheme.mapButtonColor
|
imageColor: JamiTheme.mapButtonColor
|
||||||
normalColor: JamiTheme.transparentColor
|
normalColor: JamiTheme.transparentColor
|
||||||
source: isMinimised
|
source: isMinimised
|
||||||
|
@ -319,6 +360,9 @@ Rectangle {
|
||||||
PushButton {
|
PushButton {
|
||||||
id: btnmaximise
|
id: btnmaximise
|
||||||
|
|
||||||
|
toolTipText: isFullScreen
|
||||||
|
? JamiStrings.reduceMapTooltip
|
||||||
|
: JamiStrings.maximizeMapTooltip
|
||||||
imageColor: JamiTheme.mapButtonColor
|
imageColor: JamiTheme.mapButtonColor
|
||||||
normalColor: JamiTheme.transparentColor
|
normalColor: JamiTheme.transparentColor
|
||||||
source: isFullScreen? JamiResources.close_fullscreen_24dp_svg : JamiResources.open_in_full_24dp_svg
|
source: isFullScreen? JamiResources.close_fullscreen_24dp_svg : JamiResources.open_in_full_24dp_svg
|
||||||
|
@ -335,11 +379,13 @@ Rectangle {
|
||||||
PushButton {
|
PushButton {
|
||||||
id: btnClose
|
id: btnClose
|
||||||
|
|
||||||
|
toolTipText: JamiStrings.closeMapTooltip
|
||||||
imageColor: JamiTheme.mapButtonColor
|
imageColor: JamiTheme.mapButtonColor
|
||||||
normalColor: JamiTheme.transparentColor
|
normalColor: JamiTheme.transparentColor
|
||||||
source: JamiResources.round_close_24dp_svg
|
source: JamiResources.round_close_24dp_svg
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
PositionManager.stopPositioning();
|
||||||
PositionManager.setMapActive(false);
|
PositionManager.setMapActive(false);
|
||||||
PositionManager.mapAutoOpening = false;
|
PositionManager.mapAutoOpening = false;
|
||||||
|
|
||||||
|
|
173
src/app/webengine/map/StopSharingPositionPopup.qml
Normal file
173
src/app/webengine/map/StopSharingPositionPopup.qml
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Savoir-faire Linux Inc.
|
||||||
|
* Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import QtQuick.Controls
|
||||||
|
|
||||||
|
import net.jami.Models 1.1
|
||||||
|
import net.jami.Adapters 1.1
|
||||||
|
import net.jami.Constants 1.1
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
|
||||||
|
|
||||||
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
Popup {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
width: popupContent.width
|
||||||
|
height: popupContent.height
|
||||||
|
|
||||||
|
parent: Overlay.overlay
|
||||||
|
|
||||||
|
// center in parent
|
||||||
|
x: Math.round((parent.width - width) / 2)
|
||||||
|
y: Math.round((parent.height - height) / 2)
|
||||||
|
|
||||||
|
signal joinClicked
|
||||||
|
|
||||||
|
modal:true
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
visible: false
|
||||||
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
Rectangle {
|
||||||
|
id: container
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: JamiTheme.modalPopupRadius
|
||||||
|
color: JamiTheme.secondaryBackgroundColor
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: popupContent
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
|
||||||
|
PushButton {
|
||||||
|
id: btnClose
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
width: 30
|
||||||
|
height: 30
|
||||||
|
imageContainerWidth: 30
|
||||||
|
imageContainerHeight : 30
|
||||||
|
Layout.margins: 8
|
||||||
|
radius : 5
|
||||||
|
imageColor: "grey"
|
||||||
|
normalColor: JamiTheme.transparentColor
|
||||||
|
source: JamiResources.round_close_24dp_svg
|
||||||
|
onClicked: { root.visible = false }
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
Layout.leftMargin: 20
|
||||||
|
Layout.rightMargin: 20
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
font.pixelSize: JamiTheme.popuptextSize
|
||||||
|
font.weight: Font.Medium
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
color: JamiTheme.textColor
|
||||||
|
text: JamiStrings.stopSharingPopupBody
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout{
|
||||||
|
Layout.margins: JamiTheme.popupButtonsMargin
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
|
||||||
|
MaterialButton {
|
||||||
|
preferredWidth: text.contentWidth
|
||||||
|
textLeftPadding: JamiTheme.buttontextPadding
|
||||||
|
textRightPadding: JamiTheme.buttontextPadding
|
||||||
|
|
||||||
|
color: JamiTheme.buttonTintedBlue
|
||||||
|
hoveredColor: JamiTheme.buttonTintedBlueHovered
|
||||||
|
pressedColor: JamiTheme.buttonTintedBluePressed
|
||||||
|
text: JamiStrings.stopConvSharing
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
PositionManager.stopSharingPosition(PositionManager.getSelectedConvId())
|
||||||
|
shareButtonVisibility = true
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialButton {
|
||||||
|
preferredWidth: text.contentWidth
|
||||||
|
textLeftPadding: JamiTheme.buttontextPadding
|
||||||
|
textRightPadding: JamiTheme.buttontextPadding
|
||||||
|
|
||||||
|
color: JamiTheme.buttonTintedRed
|
||||||
|
hoveredColor: JamiTheme.buttonTintedRedHovered
|
||||||
|
pressedColor: JamiTheme.buttonTintedRedPressed
|
||||||
|
|
||||||
|
text: JamiStrings.stopAllSharings
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
PositionManager.stopSharingPosition()
|
||||||
|
shareButtonVisibility = true
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: JamiTheme.transparentColor
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlay.modal: Rectangle {
|
||||||
|
color: JamiTheme.transparentColor
|
||||||
|
// Color animation for overlay when pop up is shown.
|
||||||
|
ColorAnimation on color {
|
||||||
|
to: JamiTheme.popupOverlayColor
|
||||||
|
duration: 500
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DropShadow {
|
||||||
|
z: -1
|
||||||
|
width: root.width
|
||||||
|
height: root.height
|
||||||
|
horizontalOffset: 3.0
|
||||||
|
verticalOffset: 3.0
|
||||||
|
radius: container.radius * 4
|
||||||
|
color: JamiTheme.shadowColor
|
||||||
|
source: container
|
||||||
|
transparentBorder: true
|
||||||
|
}
|
||||||
|
|
||||||
|
enter: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
properties: "opacity"; from: 0.0; to: 1.0
|
||||||
|
duration: JamiTheme.shortFadeDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit: Transition {
|
||||||
|
NumberAnimation {
|
||||||
|
properties: "opacity"; from: 1.0; to: 0.0
|
||||||
|
duration: JamiTheme.shortFadeDuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue