LINQT-1166 handle complete sip uri login
LINQT-1182 hide waiting timer in local sticker
LINQT-368 share contact (by copying its vcard, may be improved in the future)
fix notif ui
fix waiting room camera
fix missed notifications
windows ui fixes
fix LINQT-1189 start call on click not selected contact changed
This commit is contained in:
Gaelle Braud 2024-05-22 19:34:07 +02:00
parent 5cf6138bdb
commit 305c969bbb
29 changed files with 278 additions and 181 deletions

View file

@ -20,7 +20,6 @@
#include "AccountCore.hpp"
#include "core/App.hpp"
#include "model/core/CoreModel.hpp"
#include "tool/Utils.hpp"
#include "tool/thread/SafeConnection.hpp"
@ -95,6 +94,20 @@ void AccountCore::setSelf(QSharedPointer<AccountCore> me) {
mAccountModelConnection->makeConnectToCore(&AccountCore::lResetMissedCalls, [this]() {
mAccountModelConnection->invokeToModel([this]() { mAccountModel->resetMissedCallsCount(); });
});
mAccountModelConnection->makeConnectToCore(&AccountCore::lRefreshNotifications, [this]() {
mAccountModelConnection->invokeToModel([this]() { mAccountModel->refreshUnreadNotifications(); });
});
mCoreModelConnection = QSharedPointer<SafeConnection<AccountCore, CoreModel>>(
new SafeConnection<AccountCore, CoreModel>(me, CoreModel::getInstance()));
mAccountModelConnection->makeConnectToCore(&AccountCore::unreadCallNotificationsChanged, [this]() {
mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
});
mAccountModelConnection->makeConnectToCore(&AccountCore::unreadMessageNotificationsChanged, [this]() {
mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
});
mAccountModelConnection->makeConnectToCore(&AccountCore::unreadNotificationsChanged, [this]() {
mAccountModelConnection->invokeToModel([this]() { CoreModel::getInstance()->unreadNotificationsChanged(); });
});
}
QString AccountCore::getContactAddress() const {
@ -133,7 +146,7 @@ int AccountCore::getUnreadCallNotifications() const {
void AccountCore::setUnreadCallNotifications(int unread) {
if (mUnreadCallNotifications != unread) {
mUnreadCallNotifications = unread;
emit unreadNotificationsChanged(unread);
emit unreadCallNotificationsChanged(unread);
}
}
@ -143,7 +156,7 @@ int AccountCore::getUnreadMessageNotifications() const {
void AccountCore::setUnreadMessageNotifications(int unread) {
if (mUnreadMessageNotifications != unread) {
mUnreadMessageNotifications = unread;
emit unreadNotificationsChanged(unread);
emit unreadMessageNotificationsChanged(unread);
}
}

View file

@ -38,8 +38,9 @@ class AccountCore : public QObject, public AbstractObject {
LinphoneEnums::RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged)
Q_PROPERTY(bool isDefaultAccount READ getIsDefaultAccount NOTIFY defaultAccountChanged)
Q_PROPERTY(int unreadNotifications READ getUnreadNotifications NOTIFY unreadNotificationsChanged)
Q_PROPERTY(int unreadCallNotifications READ getUnreadCallNotifications NOTIFY unreadNotificationsChanged)
Q_PROPERTY(int unreadMessageNotifications READ getUnreadMessageNotifications NOTIFY unreadNotificationsChanged)
Q_PROPERTY(int unreadCallNotifications READ getUnreadCallNotifications NOTIFY unreadCallNotificationsChanged)
Q_PROPERTY(
int unreadMessageNotifications READ getUnreadMessageNotifications NOTIFY unreadMessageNotificationsChanged)
public:
static QSharedPointer<AccountCore> create(const std::shared_ptr<linphone::Account> &account);
@ -72,12 +73,15 @@ signals:
void pictureUriChanged();
void registrationStateChanged(const QString &message);
void defaultAccountChanged(bool isDefault);
void unreadNotificationsChanged(int unreadNotifications);
void unreadNotificationsChanged(int unread);
void unreadCallNotificationsChanged(int unread);
void unreadMessageNotificationsChanged(int unread);
// Account requests
void lSetPictureUri(QString pictureUri);
void lSetDefaultAccount();
void lResetMissedCalls();
void lRefreshNotifications();
private:
QString mContactAddress;
@ -90,6 +94,7 @@ private:
int mUnreadMessageNotifications = 0;
std::shared_ptr<AccountModel> mAccountModel;
QSharedPointer<SafeConnection<AccountCore, AccountModel>> mAccountModelConnection;
QSharedPointer<SafeConnection<AccountCore, CoreModel>> mCoreModelConnection;
DECLARE_ABSTRACT_OBJECT
};

View file

@ -36,7 +36,6 @@
class ConferenceCore : public QObject, public AbstractObject {
Q_OBJECT
public:
Q_PROPERTY(QString subject READ getSubject NOTIFY subjectChanged)
Q_PROPERTY(QDateTime startDate READ getStartDate CONSTANT)
// Q_PROPERTY(ParticipantDeviceList *participantDevices READ getParticipantDeviceList CONSTANT)
// Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged)
@ -72,7 +71,6 @@ public:
//---------------------------------------------------------------------------
signals:
void subjectChanged();
void isReadyChanged();
void participantDeviceCountChanged();
void activeSpeakerChanged();

View file

@ -55,8 +55,10 @@ void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
mCoreModelConnection->invokeToModel([this]() {
QList<QSharedPointer<ConferenceInfoCore>> *items = new QList<QSharedPointer<ConferenceInfoCore>>();
mustBeInLinphoneThread(getClassName());
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
if (!defaultAccount) return;
std::list<std::shared_ptr<linphone::ConferenceInfo>> conferenceInfos =
CoreModel::getInstance()->getCore()->getDefaultAccount()->getConferenceInformationList();
defaultAccount->getConferenceInformationList();
items->push_back(nullptr); // Add Dummy conference for today
for (auto conferenceInfo : conferenceInfos) {
auto confInfoCore = build(conferenceInfo);

View file

@ -59,6 +59,7 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact) : QObje
mJob = Utils::coreStringToAppString(vcard->getJobTitle());
mGivenName = Utils::coreStringToAppString(vcard->getGivenName());
mFamilyName = Utils::coreStringToAppString(vcard->getFamilyName());
mVCardString = Utils::coreStringToAppString(vcard->asVcard4String());
}
auto addresses = contact->getAddresses();
for (auto &address : addresses) {
@ -80,6 +81,7 @@ FriendCore::FriendCore(const std::shared_ptr<linphone::Friend> &contact) : QObje
mIsSaved = false;
mStarred = false;
}
connect(this, &FriendCore::addressChanged, &FriendCore::allAddressesChanged);
connect(this, &FriendCore::phoneNumberChanged, &FriendCore::allAddressesChanged);
}
@ -247,6 +249,10 @@ void FriendCore::onStarredChanged(bool starred) {
emit starredChanged();
}
QString FriendCore::getVCard() const {
return mVCardString;
}
QList<QVariant> FriendCore::getPhoneNumbers() const {
return mPhoneNumberList;
}
@ -480,6 +486,7 @@ void FriendCore::save() { // Save Values to model
mustBeInLinphoneThread(getClassName() + "::save()");
thisCopy->writeIntoModel(mFriendModel);
thisCopy->deleteLater();
mVCardString = mFriendModel->getVCardAsString();
mFriendModelConnection->invokeToCore([this]() { saved(); });
setIsSaved(true);
});
@ -501,6 +508,7 @@ void FriendCore::save() { // Save Values to model
mCoreModelConnection->invokeToModel([this, thisCopy] {
thisCopy->writeIntoModel(mFriendModel);
thisCopy->deleteLater();
mVCardString = mFriendModel->getVCardAsString();
});
saved();
});
@ -514,6 +522,7 @@ void FriendCore::save() { // Save Values to model
auto core = CoreModel::getInstance()->getCore();
thisCopy->writeIntoModel(mFriendModel);
thisCopy->deleteLater();
mVCardString = mFriendModel->getVCardAsString();
bool created =
(core->getDefaultFriendList()->addFriend(contact) == linphone::FriendList::Status::OK);
if (created) {

View file

@ -87,6 +87,8 @@ public:
bool getStarred() const;
void onStarredChanged(bool starred);
Q_INVOKABLE QString getVCard() const;
QList<QVariant> getPhoneNumbers() const;
QVariant getPhoneNumberAt(int index) const;
Q_INVOKABLE void appendPhoneNumber(const QString &label, const QString &number);
@ -164,6 +166,7 @@ protected:
QString mDefaultAddress;
QString mPictureUri;
bool mIsSaved;
QString mVCardString;
std::shared_ptr<FriendModel> mFriendModel;
QSharedPointer<SafeConnection<FriendCore, FriendModel>> mFriendModelConnection;
QSharedPointer<SafeConnection<FriendCore, CoreModel>> mCoreModelConnection;

View file

@ -176,7 +176,7 @@ QObject *Notifier::createNotification(Notifier::NotificationType type, QVariantM
engine->deleteLater();
exit(-1);
} else {
qWarning() << engine->rootObjects()[0];
lDebug() << engine->rootObjects()[0];
auto window = qobject_cast<QQuickWindow *>(obj);
if (window) {
int *screenHeightOffset = &mScreenHeightOffset[screen->name()]; // Access optimization
@ -191,7 +191,7 @@ QObject *Notifier::createNotification(Notifier::NotificationType type, QVariantM
window->property("width")
.toInt())); //*screen->devicePixelRatio()); when using manual scaler
window->setY(heightOffset - (*screenHeightOffset % heightOffset));
qWarning() << window->geometry();
lDebug() << window->geometry();
}
}
},

View file

@ -66,6 +66,7 @@ bool AccountManager::login(QString username, QString password, QString *errorMes
}
}
username = Utils::getUsername(username);
identity->setUsername(Utils::appStringToCoreString(username));
if (params->setIdentityAddress(identity)) {
qWarning() << log()

View file

@ -94,4 +94,17 @@ void AccountModel::resetMissedCallsCount() {
mMonitor->resetMissedCallsCount();
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
mMonitor->getMissedCallsCount()); // TODO
}
void AccountModel::refreshUnreadNotifications() {
emit unreadNotificationsChanged(0 /*mMonitor->getUnreadChatMessageCount()*/,
mMonitor->getMissedCallsCount()); // TODO
}
int AccountModel::getMissedCallsCount() const {
return mMonitor->getMissedCallsCount();
}
int AccountModel::getUnreadMessagesCount() const {
return mMonitor->getUnreadChatMessageCount();
}

View file

@ -44,6 +44,9 @@ public:
void setDefault();
void removeAccount();
void resetMissedCallsCount();
void refreshUnreadNotifications();
int getMissedCallsCount() const;
int getUnreadMessagesCount() const;
signals:
void registrationStateChanged(const std::shared_ptr<linphone::Account> &account,

View file

@ -141,11 +141,22 @@ void FriendModel::clearAddresses() {
}
QString FriendModel::getName() const {
return Utils::coreStringToAppString(mMonitor->getName());
auto vcard = mMonitor->getVcard();
bool created = false;
if (!vcard) {
created = mMonitor->createVcard(mMonitor->getName());
}
if (mMonitor->getVcard()) return Utils::coreStringToAppString(mMonitor->getName());
else return QString();
}
void FriendModel::setName(const QString &name) {
mMonitor->setName(Utils::appStringToCoreString(name));
auto vcard = mMonitor->getVcard();
bool created = false;
if (!vcard) {
created = mMonitor->createVcard(Utils::appStringToCoreString(name));
}
if (mMonitor->getVcard()) mMonitor->setName(Utils::appStringToCoreString(name));
}
QString FriendModel::getGivenName() const {
@ -259,6 +270,11 @@ QString FriendModel::getPictureUri() const {
else return QString();
}
QString FriendModel::getVCardAsString() const {
assert(mMonitor->getVcard());
return Utils::coreStringToAppString(mMonitor->getVcard()->asVcard4String());
}
void FriendModel::setPictureUri(const QString &uri) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto oldPictureUri = Utils::coreStringToAppString(mMonitor->getPhoto());

View file

@ -53,6 +53,7 @@ public:
bool getStarred() const;
std::shared_ptr<linphone::Friend> getFriend() const;
QString getPictureUri() const;
QString getVCardAsString() const;
protected:
void setAddress(const std::shared_ptr<linphone::Address> &address);

View file

@ -62,6 +62,14 @@ VariantObject *Utils::getDisplayName(const QString &address) {
return data;
}
QString Utils::getUsername(const QString &address) {
QString res = address;
if (res.startsWith("sip:")) res.remove("sip:");
int splitIndex = res.lastIndexOf('@');
if (splitIndex != -1) res.truncate(splitIndex);
return res;
}
QString Utils::getGivenNameFromFullName(const QString &fullName) {
if (fullName.isEmpty()) return QString();
auto nameSplitted = fullName.split(" ");

View file

@ -54,6 +54,7 @@ public:
}
Q_INVOKABLE static VariantObject *getDisplayName(const QString &address);
Q_INVOKABLE static QString getUsername(const QString &address);
Q_INVOKABLE static QString getGivenNameFromFullName(const QString &fullName);
Q_INVOKABLE static QString getFamilyNameFromFullName(const QString &fullName);
Q_INVOKABLE static QString getInitials(const QString &username); // Support UTF32

View file

@ -31,6 +31,11 @@ Item {
contactPage.createContact(name, address)
}
AccountProxy {
id: accountProxy
onDefaultAccountChanged: if (tabbar.currentIndex === 0) defaultAccount.core.lResetMissedCalls()
}
Timer {
id: autoClosePopup
interval: 5000
@ -120,11 +125,13 @@ Item {
id: tabbar
Layout.fillHeight: true
Layout.preferredWidth: 82 * DefaultStyle.dp
defaultAccount: accountProxy.defaultAccount
property int unreadMessages: defaultAccount.core.unreadMessageNotifications
model: [
{icon: AppIcons.phone, selectedIcon: AppIcons.phoneSelected, label: qsTr("Appels"), unreadNotifications: accountProxy.defaultAccount.core.unreadCallNotifications},
{icon: AppIcons.adressBook, selectedIcon: AppIcons.adressBookSelected, label: qsTr("Contacts"), unreadNotifications: 0},
{icon: AppIcons.chatTeardropText, selectedIcon: AppIcons.chatTeardropTextSelected, label: qsTr("Conversations"), unreadNotifications: accountProxy.defaultAccount.core.unreadMessageNotifications},
{icon: AppIcons.videoconference, selectedIcon: AppIcons.videoconferenceSelected, label: qsTr("Réunions"), unreadNotifications: 0}
{icon: AppIcons.phone, selectedIcon: AppIcons.phoneSelected, label: qsTr("Appels")},
{icon: AppIcons.adressBook, selectedIcon: AppIcons.adressBookSelected, label: qsTr("Contacts")},
{icon: AppIcons.chatTeardropText, selectedIcon: AppIcons.chatTeardropTextSelected, label: qsTr("Conversations")},
{icon: AppIcons.videoconference, selectedIcon: AppIcons.videoconferenceSelected, label: qsTr("Réunions")}
]
onCurrentIndexChanged: {
if (currentIndex === 0) accountProxy.defaultAccount.core.lResetMissedCalls()
@ -294,10 +301,6 @@ Item {
spacing: 10 * DefaultStyle.dp
PopupButton {
id: avatarButton
AccountProxy{
id: accountProxy
//property bool haveAvatar: defaultAccount && defaultAccount.core.pictureUri || false
}
background.visible: false
Layout.preferredWidth: 54 * DefaultStyle.dp
Layout.preferredHeight: width
@ -312,6 +315,7 @@ Item {
popup.contentItem: ColumnLayout {
Accounts {
id: accounts
accountProxy: accountProxy
onAddAccountRequest: mainItem.addAccountRequest()
}
}

View file

@ -15,6 +15,7 @@ Item {
readonly property int leftPadding: 32 * DefaultStyle.dp
readonly property int rightPadding: 32 * DefaultStyle.dp
readonly property int spacing: 16 * DefaultStyle.dp
property AccountProxy accountProxy
signal addAccountRequest()
implicitHeight: list.contentHeight + topPadding + bottomPadding + 32 * DefaultStyle.dp + 1 + newAccountArea.height
@ -33,7 +34,7 @@ Item {
Layout.preferredHeight: contentHeight
Layout.fillWidth: true
spacing: mainItem.spacing
model: AccountProxy{}
model: mainItem.accountProxy
delegate: Contact{
id: contactItem
width: list.width

View file

@ -210,14 +210,14 @@ Item {
model: MagicSearchProxy {
searchText: searchBar.text.length === 0 ? "*" : searchBar.text
}
onSelectedContactChanged: {
if (selectedContact) {
if (selectedContact.core.allAddresses.length > 1) {
startCallPopup.contact = selectedContact
onContactClicked: (contact) => {
if (contact) {
if (contact.core.allAddresses.length > 1) {
startCallPopup.contact = contact
startCallPopup.open()
} else {
mainItem.callButtonPressed(selectedContact.core.defaultAddress)
mainItem.callButtonPressed(contact.core.defaultAddress)
}
}
}

View file

@ -42,13 +42,14 @@ RowLayout {
id: videoButton
iconUrl: AppIcons.videoCamera
checkedIconUrl: AppIcons.videoCameraSlash
checked: !mainItem.localVideoEnabled
color: DefaultStyle.grey_500
contentImageColor: DefaultStyle.main2_0
Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
icon.width: 32 * DefaultStyle.dp
icon.height: 32 * DefaultStyle.dp
onCheckedChanged: mainItem.localVideoEnabled = !mainItem.localVideoEnabled
onClicked: mainItem.localVideoEnabled = !mainItem.localVideoEnabled
}
CheckableButton {
id: microButton

View file

@ -11,6 +11,7 @@ import UtilsCpp
Rectangle{
id: mainItem
property AccountGui account
signal avatarClicked()
signal backgroundClicked()
@ -22,25 +23,27 @@ Rectangle{
RowLayout{
anchors.fill: parent
spacing: 0
Avatar{
id: avatar
Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp
account: mainItem.account
MouseArea{
anchors.fill: parent
onClicked: mainItem.avatarClicked()
}
}
Item {
Layout.preferredWidth: 200 * DefaultStyle.dp
Layout.fillHeight: true
Layout.leftMargin: 10 * DefaultStyle.dp
Layout.rightMargin: 10 * DefaultStyle.dp
ContactDescription{
id: description
anchors.fill: parent
RowLayout {
spacing: 10 * DefaultStyle.dp
Avatar{
id: avatar
Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp
account: mainItem.account
MouseArea{
anchors.fill: parent
onClicked: mainItem.avatarClicked()
}
}
Item {
Layout.preferredWidth: 200 * DefaultStyle.dp
Layout.fillHeight: true
Layout.rightMargin: 10 * DefaultStyle.dp
ContactDescription{
id: description
anchors.fill: parent
account: mainItem.account
}
}
}
Control.Control {
@ -96,20 +99,17 @@ Rectangle{
: qsTr("Erreur")
}
}
// Item {
// Layout.fillWidth: true
// }
Item{
Layout.preferredWidth: 27 * DefaultStyle.dp
Layout.preferredHeight: 27 * DefaultStyle.dp
Layout.preferredWidth: 26 * DefaultStyle.dp
Layout.preferredHeight: 26 * DefaultStyle.dp
Layout.fillHeight: true
Layout.leftMargin: 40 * DefaultStyle.dp
visible: mainItem.account.core.unreadCallNotifications > 0
Rectangle{
id: unreadNotifications
anchors.verticalCenter: parent.verticalCenter
property int unread: mainItem.account.core.unreadNotifications
visible: unread > 0
width: 27 * DefaultStyle.dp
height: 27 * DefaultStyle.dp
width: 26 * DefaultStyle.dp
height: 26 * DefaultStyle.dp
radius: width/2
color: DefaultStyle.danger_500main
border.color: DefaultStyle.grey_0
@ -125,7 +125,7 @@ Rectangle{
fontSizeMode: Text.Fit
font.pixelSize: 11 * DefaultStyle.dp
font.weight: 700 * DefaultStyle.dp
text: parent.unread > 100 ? '99+' : parent.unread
text: mainItem.account.core.unreadCallNotifications >= 100 ? '99+' : mainItem.account.core.unreadCallNotifications
}
}
MultiEffect {
@ -136,6 +136,7 @@ Rectangle{
shadowOpacity: 0.15
}
}
Item{Layout.fillWidth: true}
EffectImage {
id: manageAccount
imageSource: AppIcons.manageProfile

View file

@ -45,6 +45,7 @@ ListView {
signal contactStarredChanged()
signal contactDeletionRequested(FriendGui contact)
signal contactAddedToSelection()
signal contactClicked(FriendGui contact)
function addContactToSelection(address) {
if (multiSelectionEnabled) {
@ -112,7 +113,7 @@ ListView {
id: contactDelegate
anchors.left: initial.visible ? initial.right : parent.left
anchors.leftMargin: 10 * DefaultStyle.dp
anchors.right: parent.right
anchors.right: actionsRow.left
// anchors.rightMargin: 10 * DefaultStyle.dp
anchors.verticalCenter: parent.verticalCenter
spacing: 10 * DefaultStyle.dp
@ -182,7 +183,7 @@ ListView {
PopupButton {
id: friendPopup
z: 1
Layout.rightMargin: 5 * DefaultStyle.dp
Layout.rightMargin: 13 * DefaultStyle.dp
Layout.alignment: Qt.AlignVCenter
popup.x: 0
popup.padding: 10 * DefaultStyle.dp
@ -249,8 +250,9 @@ ListView {
MouseArea {
id: contactArea
hoverEnabled: mainItem.hoverEnabled
anchors.fill: contactDelegate
anchors.fill: itemDelegate
height: mainItem.height
z: -1
Rectangle {
anchors.fill: contactArea
opacity: 0.7
@ -259,6 +261,7 @@ ListView {
}
onClicked: {
mainItem.currentIndex = index
mainItem.contactClicked(modelData)
if (mainItem.multiSelectionEnabled) {
var indexInSelection = mainItem.selectedContacts.indexOf(modelData.core.defaultAddress)
if (indexInSelection == -1) {

View file

@ -82,6 +82,7 @@ Item {
Text {
id: waitingTime
property int seconds
visible: !UtilsCpp.isMe(mainItem.peerAddress)
text: UtilsCpp.formatElapsedTime(seconds)
color: DefaultStyle.grey_0
Layout.alignment: Qt.AlignHCenter

View file

@ -8,52 +8,53 @@ import Qt.labs.platform 1.0
// =============================================================================
Window {
id: mainItem
id: mainItem
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
property bool requestActivate: false
//property int flags: Qt.SplashScreen
color: "transparent"
property bool requestActivate: false
//property int flags: Qt.SplashScreen
default property alias _content: content.data
property bool _isOpen: false
signal isOpened()
signal isClosed()
signal dataChanged()
default property alias _content: content.data
property bool _isOpen: false
signal isOpened()
signal isClosed()
signal dataChanged()
on_ContentChanged: dataChanged(_content)
// ---------------------------------------------------------------------------
on_ContentChanged: dataChanged(_content)
// ---------------------------------------------------------------------------
function open () {
_isOpen = true;
isOpened();
}
/*
function close () {
_isOpen = false
isClosed()
}
*/
// ---------------------------------------------------------------------------
function open () {
_isOpen = true;
isOpened();
}
/*
function close () {
_isOpen = false
isClosed()
}
*/
// ---------------------------------------------------------------------------
objectName: '__internalWindow'
property bool isFrameLess : false;
property bool showAsTool : false
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
opacity: 1.0
height: _content[0] != null ? _content[0].height : 0
width: _content[0] != null ? _content[0].width : 0
visible:true
Item {
id: content
anchors.fill:parent
objectName: '__internalWindow'
property bool isFrameLess : false;
property bool showAsTool : false
// Don't use Popup for flags : it could lead to error in geometry. On Mac, Using Tool ensure to have the Window on Top and fullscreen independant
flags: Qt.BypassWindowManagerHint | (showAsTool?Qt.Tool:Qt.WindowStaysOnTopHint) | Qt.Window | Qt.FramelessWindowHint;
opacity: 1.0
height: _content[0] != null ? _content[0].height : 0
width: _content[0] != null ? _content[0].width : 0
visible:true
Item {
id: content
anchors.fill:parent
property var $parent: mainItem
}
property var $parent: mainItem
}
// ---------------------------------------------------------------------------
/*

View file

@ -101,10 +101,12 @@ ColumnLayout {
target: LoginPageCpp
onRegistrationStateChanged: {
if (LoginPageCpp.registrationState != LinphoneEnums.RegistrationState.Progress) {
connectionButton.enabled = true
connectionButtonContent.currentIndex = 0
}
}
onErrorMessageChanged: {
connectionButton.enabled = true
connectionButtonContent.currentIndex = 0
}
}
@ -123,6 +125,7 @@ ColumnLayout {
return
}
LoginPageCpp.login(usernameEdit.text, passwordEdit.text)
connectionButton.enabled = false
connectionButtonContent.currentIndex = 1
}

View file

@ -19,7 +19,7 @@ ListView {
spacing: 8 * DefaultStyle.dp
currentIndex: confInfoProxy.currentDateIndex
onCountChanged: selectedConference = model && currentIndex != -1 ? model.getAt(currentIndex) : null
onCountChanged: selectedConference = model && currentIndex != -1 && currentIndex < model.count ? model.getAt(currentIndex) : null
onCurrentIndexChanged: {
selectedConference = model.getAt(currentIndex)
}

View file

@ -1,17 +1,19 @@
import QtQuick 2.7
import QtQuick.Effects
import Linphone
// =============================================================================
DesktopPopup {
id: notification
id: mainItem
property var notificationData: ({
timelineModel : null
})
property int overriddenHeight
property int overriddenWidth
property int overriddenHeight: 120 * DefaultStyle.dp
property int overriddenWidth: 300 * DefaultStyle.dp
property double radius: 0
default property alias _content: content.data
signal deleteNotification (var notification)
@ -29,13 +31,15 @@ DesktopPopup {
}
Rectangle {
color: "#FFFFFF"
height: overriddenHeight || 120
width: overriddenWidth || 300
id: background
color: DefaultStyle.grey_0
height: mainItem.overriddenHeight
width: mainItem.overriddenWidth
radius: mainItem.radius
border {
color: "#A1A1A1"
width: 1
color: DefaultStyle.grey_400
width: 1 * DefaultStyle.dp
}
Item {
@ -55,4 +59,12 @@ DesktopPopup {
}
}
MultiEffect {
source: background
anchors.fill: background
shadowEnabled: true
shadowColor: DefaultStyle.grey_1000
shadowOpacity: 0.1
shadowBlur: 1
}
}

View file

@ -6,112 +6,95 @@ import UtilsCpp
Notification {
id: mainItem
// ---------------------------------------------------------------------------
radius: 20 * DefaultStyle.dp
overriddenHeight: 101 * DefaultStyle.dp
overriddenWidth: 422 * DefaultStyle.dp
readonly property var call: notificationData && notificationData.call
property var state: call.core.state
onStateChanged:{
console.log("state notif", state, this)
if(state != LinphoneEnums.CallState.IncomingReceived){
if (state != LinphoneEnums.CallState.IncomingReceived){
close()
}
}
// overridenWidth: 320 * DefaultStyle.dp
// overridenHeight: 150 * DefaultStyle.dp
// ---------------------------------------------------------------------------
ColumnLayout {
RowLayout {
anchors.fill: parent
anchors.leftMargin: 15
anchors.rightMargin: 15
anchors.bottomMargin:15
anchors.topMargin:15
// ---------------------------------------------------------------------
// Action buttons.
// ---------------------------------------------------------------------
anchors.leftMargin: 19 * DefaultStyle.dp
anchors.rightMargin: 19 * DefaultStyle.dp
anchors.bottomMargin: 15 * DefaultStyle.dp
anchors.topMargin: 15 * DefaultStyle.dp
spacing: 30 * DefaultStyle.dp
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft
spacing: 15 * DefaultStyle.dp
spacing: 13 * DefaultStyle.dp
Avatar {
Layout.preferredWidth: 40 * DefaultStyle.dp
Layout.preferredHeight: 40 * DefaultStyle.dp
Layout.preferredWidth: 45 * DefaultStyle.dp
Layout.preferredHeight: 45 * DefaultStyle.dp
call: mainItem.call
}
ColumnLayout {
Text {
property var remoteAddress: UtilsCpp.getDisplayName(call.core.peerAddress)
text: remoteAddress ? remoteAddress.value : ""
color: DefaultStyle.grey_600
font {
pixelSize: 14 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
pixelSize: 20 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
capitalization: Font.Capitalize
}
}
Text {
text: call.core.peerAddress
RowLayout {
EffectImage {
imageSource: AppIcons.arrowDownLeft
colorizationColor: DefaultStyle.success_500main
Layout.preferredWidth: 24 * DefaultStyle.dp
Layout.preferredHeight: 24 * DefaultStyle.dp
}
Text {
Layout.fillWidth: true
elide: Text.ElideRight
property var localAddress: UtilsCpp.getDisplayName(call.core.localAddress)
text: qsTr("Appel entrant%1").arg(localAddress ? qsTr(" pour %1").arg(localAddress.value) : "") //call.core.peerAddress
color: DefaultStyle.grey_600
font {
pixelSize: 13 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
}
}
}
RowLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
spacing: 10 * DefaultStyle.dp
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
RowLayout {
Layout.alignment: Qt.AlignHCenter
spacing: 3 * DefaultStyle.dp
Button {
color: DefaultStyle.success_500main
Layout.preferredWidth: 40 * DefaultStyle.dp
Layout.preferredHeight: 40 * DefaultStyle.dp
contentItem: EffectImage {
colorizationColor: DefaultStyle.grey_0
imageSource: AppIcons.phone
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
onClicked: {
mainItem.call.core.lAccept(false)
UtilsCpp.openCallsWindow(mainItem.call)
}
Layout.fillWidth: true
spacing: 26 * DefaultStyle.dp
Button {
color: DefaultStyle.success_500main
Layout.preferredWidth: 75 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
contentItem: EffectImage {
colorizationColor: DefaultStyle.grey_0
imageSource: AppIcons.phone
imageWidth: 32 * DefaultStyle.dp
imageHeight: 32 * DefaultStyle.dp
}
Button {
color: DefaultStyle.success_500main
Layout.preferredWidth: 40 * DefaultStyle.dp
Layout.preferredHeight: 40 * DefaultStyle.dp
contentItem: EffectImage {
colorizationColor: DefaultStyle.grey_0
imageSource: AppIcons.videoCamera
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
}
onClicked: {
mainItem.call.core.lAccept(true)
UtilsCpp.openCallsWindow(mainItem.call)
}
onClicked: {
mainItem.call.core.lAccept(false)
UtilsCpp.openCallsWindow(mainItem.call)
}
}
Item{
Layout.fillWidth: true
Layout.fillHeight: true
}
Button {
color: DefaultStyle.danger_500main
Layout.rightMargin: 20 * DefaultStyle.dp
Layout.preferredWidth: 55 * DefaultStyle.dp
Layout.preferredHeight: 40 * DefaultStyle.dp
Layout.preferredWidth: 75 * DefaultStyle.dp
Layout.preferredHeight: 55 * DefaultStyle.dp
contentItem: EffectImage {
colorizationColor: DefaultStyle.grey_0
imageSource: AppIcons.endCall
imageWidth: 24 * DefaultStyle.dp
imageHeight: 24 * DefaultStyle.dp
imageWidth: 32 * DefaultStyle.dp
imageHeight: 32 * DefaultStyle.dp
}
onClicked: {
mainItem.call.core.lDecline()

View file

@ -10,6 +10,7 @@ Control.TextField {
leftPadding: 15 * DefaultStyle.dp
rightPadding: eyeButton.visible ? 5 * DefaultStyle.dp + eyeButton.width + eyeButton.rightMargin : 15 * DefaultStyle.dp
echoMode: (hidden && !eyeButton.checked) ? TextInput.Password : TextInput.Normal
verticalAlignment: TextInput.AlignVCenter
color: DefaultStyle.main2_600
font {
family: DefaultStyle.defaultFont
@ -47,10 +48,12 @@ Control.TextField {
? DefaultStyle.main1_500_main
: mainItem.backgroundBorderColor
}
cursorDelegate: Rectangle {
id: cursor
color: DefaultStyle.main1_500_main
width: 1 * DefaultStyle.dp
anchors.verticalCenter: mainItem.verticalCenter
SequentialAnimation {
loops: Animation.Infinite

View file

@ -13,6 +13,11 @@ Control.TabBar {
property var model
readonly property alias cornerRadius: bottomLeftCorner.radius
property AccountGui defaultAccount
onDefaultAccountChanged: {
defaultAccount.core.lRefreshNotifications()
}
component UnreadNotification: Rectangle {
id: unreadNotifications
property int unread: 0
@ -82,7 +87,7 @@ Control.TabBar {
width: mainItem.width
UnreadNotification {
unread: modelData.unreadNotifications
unread: index == 0 ? defaultAccount.core.unreadCallNotifications : index == 2 ? defaultAccount.core.unreadMessageNotifications : 0// modelData.unreadNotifications
anchors.right: parent.right
anchors.rightMargin: 15 * DefaultStyle.dp
anchors.top: parent.top

View file

@ -549,7 +549,13 @@ AbstractMainPage {
iconSize: 24 * DefaultStyle.dp
iconSource: AppIcons.shareNetwork
text: qsTr("Share")
onClicked: console.log("TODO : share contact")
onClicked: {
if (mainItem.selectedContact) {
var vcard = mainItem.selectedContact.core.getVCard()
UtilsCpp.copyToClipboard(vcard)
UtilsCpp.showInformationPopup(qsTr("Copié"), qsTr("VCard copiée dans le presse-papier"))
}
}
}
Rectangle {
Layout.fillWidth: true