diff --git a/.gitlab-ci-files/job-linux-desktop-centos7.yml b/.gitlab-ci-files/job-linux-desktop-centos7.yml index 041e5abc8..421ec3636 100644 --- a/.gitlab-ci-files/job-linux-desktop-centos7.yml +++ b/.gitlab-ci-files/job-linux-desktop-centos7.yml @@ -16,7 +16,7 @@ #job-centos7-makefile-clang: # tags: [ "docker-centos7" ] -# image: gitlab.linphone.org:4567/bc/public/linphone-sdk/bc-dev-centos:7 +# image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-centos7-fuse-qt-wget:$CENTOS_7_QT_IMAGE_VERSION # only: # variables: # - $NIGHTLY_MASTER diff --git a/.gitlab-ci-files/job-linux-desktop-ubuntu-rolling.yml b/.gitlab-ci-files/job-linux-desktop-ubuntu-rolling.yml index 7028d1cf8..d072b9116 100644 --- a/.gitlab-ci-files/job-linux-desktop-ubuntu-rolling.yml +++ b/.gitlab-ci-files/job-linux-desktop-ubuntu-rolling.yml @@ -1,7 +1,7 @@ job-ubuntu-rolling-ninja-clang: tags: [ "docker-ubuntu-rolling" ] - image: gitlab.linphone.org:4567/bc/public/linphone-sdk/bc-dev-ubuntu-rolling:$UBUNTU_ROLLING_IMAGE_VERSION + image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-rolling-qt-fuse-wget-gpg2:$UBUNTU_ROLLING_IMAGE_VERSION except: refs: - schedules @@ -20,7 +20,7 @@ job-ubuntu-rolling-ninja-clang: job-ubuntu-rolling-makefile-gcc: tags: [ "docker-ubuntu-rolling" ] - image: gitlab.linphone.org:4567/bc/public/linphone-sdk/bc-dev-ubuntu-rolling:$UBUNTU_ROLLING_IMAGE_VERSION + image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-rolling-qt-fuse-wget-gpg2:$UBUNTU_ROLLING_IMAGE_VERSION only: variables: - $NIGHTLY_MASTER @@ -34,7 +34,7 @@ job-ubuntu-rolling-makefile-gcc: job-ubuntu-rolling-makefile-clang: tags: [ "docker-ubuntu-rolling" ] - image: gitlab.linphone.org:4567/bc/public/linphone-sdk/bc-dev-ubuntu-rolling:$UBUNTU_ROLLING_IMAGE_VERSION + image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-rolling-qt-fuse-wget-gpg2:$UBUNTU_ROLLING_IMAGE_VERSION only: variables: - $NIGHTLY_MASTER @@ -48,7 +48,7 @@ job-ubuntu-rolling-makefile-clang: job-ubuntu-rolling-ninja-gcc: tags: [ "docker-ubuntu-rolling" ] - image: gitlab.linphone.org:4567/bc/public/linphone-sdk/bc-dev-ubuntu-rolling:$UBUNTU_ROLLING_IMAGE_VERSION + image: gitlab.linphone.org:4567/bc/public/linphone-desktop/bc-dev-ubuntu-rolling-qt-fuse-wget-gpg2:$UBUNTU_ROLLING_IMAGE_VERSION only: variables: - $NIGHTLY_MASTER diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a354cbf3c..75d66981f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,10 +22,10 @@ variables: # Docker image version ARCHLINUX_IMAGE_VERSION: latestupdated - CENTOS_7_QT_IMAGE_VERSION: 20210401_python3 + CENTOS_7_QT_IMAGE_VERSION: 20211012_add_qtwebview DEBIAN_9_QT_IMAGE_VERSION: 20211027_update_qt_5.12.12 DEBIAN_10_IMAGE_VERSION: 20210217_python3 - UBUNTU_ROLLING_IMAGE_VERSION: 20210217_python3 + UBUNTU_ROLLING_IMAGE_VERSION: 20211012_add_qtwebview ################################################# # Platforms to test diff --git a/docker-files/bc-dev-centos7-fuse-qt-wget b/docker-files/bc-dev-centos7-fuse-qt-wget index 3f18fc2ce..44de63aff 100644 --- a/docker-files/bc-dev-centos7-fuse-qt-wget +++ b/docker-files/bc-dev-centos7-fuse-qt-wget @@ -9,11 +9,11 @@ RUN scl enable devtoolset-7 bash # Configure AppImages dependencies RUN sudo yum install -y fuse fuse-libs wget -# Build qt5.12.5 +# Build qt5.12 RUN git clone -b master --single-branch https://gitlab.linphone.org/BC/public/linphone-desktop.git && \ ./linphone-desktop/tools/build_qt_rpm && \ - sudo rpm -i ./linphone-desktop/rpm-linphone-qt-5.12.5/rpmbuild/RPMS/x86_64/*.rpm && \ - sudo mv ./linphone-desktop/rpm-linphone-qt-5.12.5/rpmbuild/RPMS/x86_64/*.rpm / && \ + sudo rpm -i ./linphone-desktop/rpm-linphone-qt-5.12/rpmbuild/RPMS/x86_64/*.rpm && \ + sudo mv ./linphone-desktop/rpm-linphone-qt-5.12/rpmbuild/RPMS/x86_64/*.rpm / && \ sudo rm -rf ./linphone-desktop diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index 34e94ddb3..b2aaa473e 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -96,7 +96,7 @@ if( WIN32) endif() set(CMAKE_INCLUDE_CURRENT_DIR ON)#useful for config.h -set(QT5_PACKAGES Core Gui Quick Widgets QuickControls2 Svg LinguistTools Concurrent Network Test) +set(QT5_PACKAGES Core Gui Quick Widgets QuickControls2 Svg LinguistTools Concurrent Network Test WebView) if (UNIX AND NOT APPLE) list(APPEND QT5_PACKAGES DBus) endif () diff --git a/linphone-app/build/rpm/qt5.spec b/linphone-app/build/rpm/qt5.spec index 5f0ce4b94..80b84888b 100644 --- a/linphone-app/build/rpm/qt5.spec +++ b/linphone-app/build/rpm/qt5.spec @@ -83,6 +83,17 @@ make install INSTALL_ROOT=%{buildroot} -j12 # Some files got ambiguous python shebangs, we fix them to avoid install errors # Because in centos8 shebangs like #!/usr/bin/python are FORBIDDEN (see https://fedoraproject.org/wiki/Changes/Make_ambiguous_python_shebangs_error) +%build qtwebengine +cd qtwebengine +qmake +make -j12 + +find . \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i 's/#!\/usr\/bin\/python/#!\/usr\/bin\/python3/g' +make install INSTALL_ROOT=%{buildroot} -j12 + +cd .. + + %files %defattr(-,root,root,-) %license LICENSE.LGPL* LICENSE.FDL diff --git a/linphone-app/src/app/main.cpp b/linphone-app/src/app/main.cpp index 4cabd7c3d..c3385da91 100644 --- a/linphone-app/src/app/main.cpp +++ b/linphone-app/src/app/main.cpp @@ -20,6 +20,7 @@ #include "AppController.hpp" #include +#include #ifdef QT_QML_DEBUG #include #endif @@ -29,11 +30,13 @@ int main (int argc, char *argv[]) { AppController controller(argc, argv); + QtWebView::initialize(); #ifdef QT_QML_DEBUG QQmlDebuggingEnabler enabler; #endif //QLoggingCategory::setFilterRules("*.debug=true;qml=false"); App *app = controller.getApp(); + if (app->isSecondary()) { qInfo() << QStringLiteral("Running secondary app success. Kill it now."); diff --git a/linphone-app/src/components/settings/AccountSettingsModel.cpp b/linphone-app/src/components/settings/AccountSettingsModel.cpp index 72c8a86ec..481791f15 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.cpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.cpp @@ -251,7 +251,8 @@ bool AccountSettingsModel::addOrUpdateProxyConfig ( // Sip address. { - shared_ptr address = linphone::Factory::get()->createAddress(Utils::appStringToCoreString(literal)); + + shared_ptr address = Utils::interpretUrl(literal); if (!address) { qWarning() << QStringLiteral("Unable to create sip address object from: `%1`.").arg(literal); return false; @@ -274,17 +275,26 @@ bool AccountSettingsModel::addOrUpdateProxyConfig ( } } - proxyConfig->setPublishExpires(data["registrationDuration"].toInt()); - proxyConfig->setRoute(Utils::appStringToCoreString(data["route"].toString())); + if(data.contains("registrationDuration")) + proxyConfig->setPublishExpires(data["registrationDuration"].toInt()); + if(data.contains("route")) + proxyConfig->setRoute(Utils::appStringToCoreString(data["route"].toString())); QString conferenceURI = data["conferenceUri"].toString(); if(!conferenceURI.isEmpty()) proxyConfig->setConferenceFactoryUri(Utils::appStringToCoreString(conferenceURI)); - proxyConfig->setContactParameters(Utils::appStringToCoreString(data["contactParams"].toString())); - proxyConfig->setAvpfRrInterval(uint8_t(data["avpfInterval"].toInt())); - proxyConfig->enableRegister(data["registerEnabled"].toBool()); - newPublishPresence = proxyConfig->publishEnabled() != data["publishPresence"].toBool(); - proxyConfig->enablePublish(data["publishPresence"].toBool()); - proxyConfig->setAvpfMode(data["avpfEnabled"].toBool() + if(data.contains("contactParams")) + proxyConfig->setContactParameters(Utils::appStringToCoreString(data["contactParams"].toString())); + if(data.contains("avpfInterval")) + proxyConfig->setAvpfRrInterval(uint8_t(data["avpfInterval"].toInt())); + if(data.contains("registerEnabled")) + proxyConfig->enableRegister(data.contains("registerEnabled") ? data["registerEnabled"].toBool() : true); + if(data.contains("publishPresence")) { + newPublishPresence = proxyConfig->publishEnabled() != data["publishPresence"].toBool(); + proxyConfig->enablePublish(data["publishPresence"].toBool()); + }else + newPublishPresence = proxyConfig->publishEnabled(); + if(data.contains("avpfEnabled")) + proxyConfig->setAvpfMode(data["avpfEnabled"].toBool() ? linphone::AVPFMode::Enabled : linphone::AVPFMode::Default ); @@ -293,13 +303,17 @@ bool AccountSettingsModel::addOrUpdateProxyConfig ( bool createdNat = !natPolicy; if (createdNat) natPolicy = proxyConfig->getCore()->createNatPolicy(); - natPolicy->enableIce(data["iceEnabled"].toBool()); - natPolicy->enableStun(data["iceEnabled"].toBool()); - - const string turnUser(Utils::appStringToCoreString(data["turnUser"].toString())); - const string stunServer(Utils::appStringToCoreString(data["stunServer"].toString())); - - natPolicy->enableTurn(data["turnEnabled"].toBool()); + if(data.contains("iceEnabled")) + natPolicy->enableIce(data["iceEnabled"].toBool()); + if(data.contains("iceEnabled")) + natPolicy->enableStun(data["iceEnabled"].toBool()); + string turnUser, stunServer; + if(data.contains("turnUser")) + turnUser = Utils::appStringToCoreString(data["turnUser"].toString()); + if(data.contains("stunServer")) + stunServer = Utils::appStringToCoreString(data["stunServer"].toString()); + if(data.contains("turnEnabled")) + natPolicy->enableTurn(data["turnEnabled"].toBool()); natPolicy->setStunServerUsername(turnUser); natPolicy->setStunServer(stunServer); @@ -313,7 +327,6 @@ bool AccountSettingsModel::addOrUpdateProxyConfig ( clonedAuthInfo->setUserid(turnUser); clonedAuthInfo->setUsername(turnUser); clonedAuthInfo->setPassword(Utils::appStringToCoreString(data["turnPassword"].toString())); - core->addAuthInfo(clonedAuthInfo); core->removeAuthInfo(authInfo); } else @@ -330,13 +343,26 @@ bool AccountSettingsModel::addOrUpdateProxyConfig ( return addOrUpdateProxyConfig(proxyConfig); } -shared_ptr AccountSettingsModel::createProxyConfig () { +bool AccountSettingsModel::addOrUpdateProxyConfig ( + const QVariantMap &data +) { + shared_ptr proxyConfig; + QString sipAddress = data["sipAddress"].toString(); + shared_ptr address = CoreManager::getInstance()->getCore()->interpretUrl(sipAddress.toStdString()); + + for (const auto &databaseProxyConfig : CoreManager::getInstance()->getCore()->getProxyConfigList()) + if (databaseProxyConfig->getIdentityAddress()->weakEqual(address)) { + proxyConfig = databaseProxyConfig; + } + if(!proxyConfig) + proxyConfig = createProxyConfig(data.contains("configFilename") ? data["configFilename"].toString() : "create-app-sip-account.rc" ); + return addOrUpdateProxyConfig(proxyConfig, data); +} + +shared_ptr AccountSettingsModel::createProxyConfig (const QString& assistantFile) { shared_ptr core = CoreManager::getInstance()->getCore(); - - core->getConfig()->loadFromXmlFile( - Paths::getAssistantConfigDirPath() + "create-app-sip-account.rc" - ); - + qInfo() << QStringLiteral("Set config on assistant: `%1`.").arg(assistantFile); + core->getConfig()->loadFromXmlFile(Paths::getAssistantConfigDirPath() + assistantFile.toStdString()); return core->createProxyConfig(); } diff --git a/linphone-app/src/components/settings/AccountSettingsModel.hpp b/linphone-app/src/components/settings/AccountSettingsModel.hpp index 40913901b..95d07a935 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.hpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.hpp @@ -74,9 +74,10 @@ public: Q_INVOKABLE void setDefaultProxyConfigFromSipAddress (const QString &sipAddress); Q_INVOKABLE bool addOrUpdateProxyConfig (const std::shared_ptr &proxyConfig, const QVariantMap &data); + Q_INVOKABLE bool addOrUpdateProxyConfig (const QVariantMap &data);// Create default proxy config and apply data Q_INVOKABLE void removeProxyConfig (const std::shared_ptr &proxyConfig); - Q_INVOKABLE std::shared_ptr createProxyConfig (); + Q_INVOKABLE std::shared_ptr createProxyConfig (const QString& assistantFile); Q_INVOKABLE void addAuthInfo ( const std::shared_ptr &authInfo, diff --git a/linphone-app/src/components/settings/SettingsModel.cpp b/linphone-app/src/components/settings/SettingsModel.cpp index 6f711bbfa..e97125ad8 100644 --- a/linphone-app/src/components/settings/SettingsModel.cpp +++ b/linphone-app/src/components/settings/SettingsModel.cpp @@ -163,6 +163,33 @@ void SettingsModel::setAssistantSupportsPhoneNumbers (bool status) { emit assistantSupportsPhoneNumbersChanged(status); } +QString SettingsModel::getAssistantRegistrationUrl () const { + return Utils::coreStringToAppString(mConfig->getString(UiSection, "assistant_registration_url", Constants::DefaultAssistantRegistrationUrl)); +} + +void SettingsModel::setAssistantRegistrationUrl (QString url) { + mConfig->setString(UiSection, "assistant_registration_url", Utils::appStringToCoreString(url)); + emit assistantRegistrationUrlChanged(url); +} + +QString SettingsModel::getAssistantLoginUrl () const { + return Utils::coreStringToAppString(mConfig->getString(UiSection, "assistant_login_url", Constants::DefaultAssistantLoginUrl)); +} + +void SettingsModel::setAssistantLoginUrl (QString url) { + mConfig->setString(UiSection, "assistant_login_url", Utils::appStringToCoreString(url)); + emit assistantLoginUrlChanged(url); +} + +QString SettingsModel::getAssistantLogoutUrl () const { + return Utils::coreStringToAppString(mConfig->getString(UiSection, "assistant_logout_url", Constants::DefaultAssistantLogoutUrl)); +} + +void SettingsModel::setAssistantLogoutUrl (QString url) { + mConfig->setString(UiSection, "assistant_logout_url", Utils::appStringToCoreString(url)); + emit assistantLogoutUrlChanged(url); +} + // ============================================================================= // Audio. // ============================================================================= diff --git a/linphone-app/src/components/settings/SettingsModel.hpp b/linphone-app/src/components/settings/SettingsModel.hpp index e8c0289c0..df5b3acb1 100644 --- a/linphone-app/src/components/settings/SettingsModel.hpp +++ b/linphone-app/src/components/settings/SettingsModel.hpp @@ -41,14 +41,17 @@ class SettingsModel : public QObject { // =========================================================================== // Assistant. ---------------------------------------------------------------- - + Q_PROPERTY(bool createAppSipAccountEnabled READ getCreateAppSipAccountEnabled WRITE setCreateAppSipAccountEnabled NOTIFY createAppSipAccountEnabledChanged) Q_PROPERTY(bool fetchRemoteConfigurationEnabled READ getFetchRemoteConfigurationEnabled WRITE setFetchRemoteConfigurationEnabled NOTIFY fetchRemoteConfigurationEnabledChanged) Q_PROPERTY(bool useAppSipAccountEnabled READ getUseAppSipAccountEnabled WRITE setUseAppSipAccountEnabled NOTIFY useAppSipAccountEnabledChanged) Q_PROPERTY(bool useOtherSipAccountEnabled READ getUseOtherSipAccountEnabled WRITE setUseOtherSipAccountEnabled NOTIFY useOtherSipAccountEnabledChanged) Q_PROPERTY(bool assistantSupportsPhoneNumbers READ getAssistantSupportsPhoneNumbers WRITE setAssistantSupportsPhoneNumbers NOTIFY assistantSupportsPhoneNumbersChanged) - + Q_PROPERTY(QString assistantRegistrationUrl READ getAssistantRegistrationUrl WRITE setAssistantRegistrationUrl NOTIFY assistantRegistrationUrlChanged) + Q_PROPERTY(QString assistantLoginUrl READ getAssistantLoginUrl WRITE setAssistantLoginUrl NOTIFY assistantLoginUrlChanged) + Q_PROPERTY(QString assistantLogoutUrl READ getAssistantLogoutUrl WRITE setAssistantLogoutUrl NOTIFY assistantLogoutUrlChanged) + // Audio. -------------------------------------------------------------------- Q_PROPERTY(bool captureGraphRunning READ getCaptureGraphRunning NOTIFY captureGraphRunningChanged) @@ -234,7 +237,16 @@ public: bool getAssistantSupportsPhoneNumbers () const; void setAssistantSupportsPhoneNumbers (bool status); + + QString getAssistantRegistrationUrl () const; + void setAssistantRegistrationUrl (QString url); + + QString getAssistantLoginUrl () const; + void setAssistantLoginUrl (QString url); + QString getAssistantLogoutUrl () const; + void setAssistantLogoutUrl (QString url); + // Audio. -------------------------------------------------------------------- void createCaptureGraph(); @@ -529,7 +541,11 @@ signals: void useOtherSipAccountEnabledChanged (bool status); void assistantSupportsPhoneNumbersChanged (bool status); - + + void assistantRegistrationUrlChanged (QString url); + void assistantLoginUrlChanged (QString url); + void assistantLogoutUrlChanged (QString url); + // Audio. -------------------------------------------------------------------- void captureGraphRunningChanged(bool running); diff --git a/linphone-app/src/utils/Constants.cpp b/linphone-app/src/utils/Constants.cpp index a848d7fd3..14971cb8f 100644 --- a/linphone-app/src/utils/Constants.cpp +++ b/linphone-app/src/utils/Constants.cpp @@ -67,6 +67,9 @@ constexpr char Constants::DefaultXmlrpcUri[]; constexpr char Constants::DefaultConferenceURI[]; constexpr char Constants::DefaultLimeServerURL[]; constexpr char Constants::RemoteProvisioningURL[]; +constexpr char Constants::DefaultAssistantRegistrationUrl[]; +constexpr char Constants::DefaultAssistantLoginUrl[]; +constexpr char Constants::DefaultAssistantLogoutUrl[]; #if defined(Q_OS_LINUX) || defined(Q_OS_WIN) constexpr char Constants::H264Description[]; diff --git a/linphone-app/src/utils/Constants.hpp b/linphone-app/src/utils/Constants.hpp index 00738ed8a..35f414a7f 100644 --- a/linphone-app/src/utils/Constants.hpp +++ b/linphone-app/src/utils/Constants.hpp @@ -67,6 +67,9 @@ public: static constexpr char RemoteProvisioningURL[] = "https://subscribe.linphone.org/flexiapi/provisioning"; Q_PROPERTY(QString PasswordRecoveryUrl MEMBER PasswordRecoveryUrl CONSTANT) + static constexpr char DefaultAssistantRegistrationUrl[] = "https://subscribe.linphone.org/register"; + static constexpr char DefaultAssistantLoginUrl[] = "https://subscribe.linphone.org/login"; + static constexpr char DefaultAssistantLogoutUrl[] = "https://subscribe.linphone.org/logout"; // Max image size in bytes. (100Kb) static constexpr qint64 MaxImageSize = 102400;// In Bytes. diff --git a/linphone-app/ui/views/App/Main/Assistant.qml b/linphone-app/ui/views/App/Main/Assistant.qml index 2112b44de..42ae6c143 100644 --- a/linphone-app/ui/views/App/Main/Assistant.qml +++ b/linphone-app/ui/views/App/Main/Assistant.qml @@ -46,14 +46,10 @@ Item { StackView { id: stack + clip:true anchors { - fill: parent - - bottomMargin: AssistantStyle.bottomMargin - leftMargin: AssistantStyle.leftMargin - rightMargin: AssistantStyle.rightMargin - topMargin: AssistantStyle.topMargin + fill: parent } initialItem: assistant.viewsPath + 'AssistantHome.qml' diff --git a/linphone-app/ui/views/App/Main/Assistant/AssistantAbstractView.qml b/linphone-app/ui/views/App/Main/Assistant/AssistantAbstractView.qml index 7c03b48f7..ab2b87142 100644 --- a/linphone-app/ui/views/App/Main/Assistant/AssistantAbstractView.qml +++ b/linphone-app/ui/views/App/Main/Assistant/AssistantAbstractView.qml @@ -8,105 +8,112 @@ import App.Styles 1.0 // ============================================================================= Item { - id: view - - // --------------------------------------------------------------------------- - - property alias mainActionEnabled: mainActionButton.enabled - property alias mainActionLabel: mainActionButton.text - property var mainAction - - property alias description: description.text - property alias title: title.text - - property bool backEnabled: true - - default property alias _content: content.data - - // --------------------------------------------------------------------------- - - height: stack.height - width: stack.width - - // --------------------------------------------------------------------------- - // Info. - // --------------------------------------------------------------------------- - - Column { - anchors.centerIn: parent - - spacing: AssistantAbstractViewStyle.info.spacing - width: parent.width - - Text { - id: title - - color: AssistantAbstractViewStyle.info.title.color - elide: Text.ElideRight - - font { - pointSize: AssistantAbstractViewStyle.info.title.pointSize - bold: true - } - - horizontalAlignment: Text.AlignHCenter - width: parent.width - } - - Text { - id: description - - color: AssistantAbstractViewStyle.info.description.color - elide: Text.ElideRight - - font.pointSize: AssistantAbstractViewStyle.info.description.pointSize - - horizontalAlignment: Text.AlignHCenter - width: parent.width - - visible: text.length > 0 - } - - // ------------------------------------------------------------------------- - // Content. - // ------------------------------------------------------------------------- - - Item { - id: content - - anchors.horizontalCenter: parent.horizontalCenter - height: AssistantAbstractViewStyle.content.height - width: AssistantAbstractViewStyle.content.width - } - } - - // --------------------------------------------------------------------------- - // Nav buttons. - // --------------------------------------------------------------------------- - - Row { - id: buttons - - anchors { - bottom: parent.bottom - horizontalCenter: parent.horizontalCenter - } - - spacing: AssistantAbstractViewStyle.buttons.spacing - - TextButtonA { - text: qsTr('back') - visible: view.backEnabled - - onClicked: assistant.popView() - } - - TextButtonB { - id: mainActionButton - - visible: !!view.mainAction - - onClicked: view.mainAction() - } - } + id: view + + // --------------------------------------------------------------------------- + + property alias mainActionEnabled: mainActionButton.enabled + property alias mainActionLabel: mainActionButton.text + property var mainAction + + property alias description: description.text + property alias title: title.text + + property bool backEnabled: true + property bool maximized: false // Used to stretch content to fit all the view (the title will be set to top) + + default property alias _content: content.data + property alias contentItem: content + + // --------------------------------------------------------------------------- + + height: (maximized?stack.height:AssistantAbstractViewStyle.content.height) + width: (maximized?stack.width:AssistantAbstractViewStyle.content.width) + + // --------------------------------------------------------------------------- + // Info. + // --------------------------------------------------------------------------- + Text { + id: title + anchors.top:parent.top + anchors.topMargin:(visible?AssistantAbstractViewStyle.info.spacing:0) + anchors.horizontalCenter: parent.horizontalCenter + color: AssistantAbstractViewStyle.info.title.color + elide: Text.ElideRight + + font { + pointSize: AssistantAbstractViewStyle.info.title.pointSize + bold: true + } + + horizontalAlignment: Text.AlignHCenter + width: parent.width + visible: text.length > 0 + height:(visible?contentHeight:0) + } + + Text { + id: description + anchors.top:title.bottom + anchors.topMargin:(visible?AssistantAbstractViewStyle.info.spacing:0) + anchors.horizontalCenter: parent.horizontalCenter + + color: AssistantAbstractViewStyle.info.description.color + elide: Text.ElideRight + + font.pointSize: AssistantAbstractViewStyle.info.description.pointSize + + horizontalAlignment: Text.AlignHCenter + width: parent.width + + visible: text.length > 0 + height:(visible?contentHeight:0) + } + + // ------------------------------------------------------------------------- + // Content. + // ------------------------------------------------------------------------- + + Item { + id: content + anchors.top:description.bottom + anchors.topMargin:(description.visible || title.visible?AssistantAbstractViewStyle.info.spacing:0) + anchors.bottom:buttons.top + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + } + + // --------------------------------------------------------------------------- + // Nav buttons. + // --------------------------------------------------------------------------- + + Row { + id: buttons + + anchors { + bottom: parent.bottom + bottomMargin:AssistantAbstractViewStyle.info.spacing + horizontalCenter: parent.horizontalCenter + + } + + spacing: AssistantAbstractViewStyle.buttons.spacing + + TextButtonA { + text: qsTr('back') + visible: view.backEnabled + + onClicked: assistant.popView() + anchors.verticalCenter: parent.verticalCenter + } + + TextButtonB { + id: mainActionButton + + visible: !!view.mainAction + + onClicked: view.mainAction() + anchors.verticalCenter: parent.verticalCenter + } + } } diff --git a/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml b/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml index e34dee327..6986ed202 100644 --- a/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml +++ b/linphone-app/ui/views/App/Main/Assistant/AssistantHome.qml @@ -10,7 +10,7 @@ import App.Styles 1.0 ColumnLayout { spacing: 0 - + // --------------------------------------------------------------------------- // Info. // --------------------------------------------------------------------------- @@ -76,6 +76,9 @@ ColumnLayout { Layout.fillWidth: true Layout.maximumWidth: AssistantHomeStyle.buttons.maxWidth Layout.preferredHeight: AssistantHomeStyle.buttons.height + Layout.leftMargin: AssistantStyle.leftMargin + Layout.rightMargin: AssistantStyle.rightMargin + Layout.bottomMargin: AssistantStyle.bottomMargin cellHeight: height / 2 cellWidth: width / 2 @@ -93,7 +96,7 @@ ColumnLayout { enabled: SettingsModel[$viewType.charAt(0).toLowerCase() + $viewType.slice(1) + "Enabled"] text: $text.replace('%1', Qt.application.name.toUpperCase()) - onClicked: assistant.pushView($view) + onClicked:{ assistant.pushView($view, $props) } } } @@ -101,43 +104,29 @@ ColumnLayout { Component.onCompleted: { insert(0, { $text: qsTr('createAppSipAccount'), - $view: SettingsModel.assistantSupportsPhoneNumbers - ? 'CreateAppSipAccount' - : 'CreateAppSipAccountWithEmail', - $viewType: 'CreateAppSipAccount' + $view: 'CreateAppSipAccount', + $viewType: 'CreateAppSipAccount', + $props:{defaultUrl: SettingsModel.assistantRegistrationUrl, defaultLogoutUrl:SettingsModel.assistantLogoutUrl, configFilename: 'create-app-sip-account.rc'} + }) + append({ + $text: qsTr('useAppSipAccount'), + $view: 'CreateAppSipAccount', + $viewType: 'UseAppSipAccount', + $props:{defaultUrl: SettingsModel.assistantLoginUrl, defaultLogoutUrl:SettingsModel.assistantLogoutUrl, configFilename: 'use-app-sip-account.rc'} + }) + append({ + $text: qsTr('useOtherSipAccount'), + $view: 'UseOtherSipAccount', + $viewType: 'UseOtherSipAccount' + }) + append( { + $text: qsTr('fetchRemoteConfiguration'), + $view: 'FetchRemoteConfiguration', + $viewType: 'FetchRemoteConfiguration' }) - } - - ListElement { - $text: qsTr('useAppSipAccount') - $view: 'UseAppSipAccount' - $viewType: 'UseAppSipAccount' - } - - ListElement { - $text: qsTr('useOtherSipAccount') - $view: 'UseOtherSipAccount' - $viewType: 'UseOtherSipAccount' - } - - ListElement { - $text: qsTr('fetchRemoteConfiguration') - $view: 'FetchRemoteConfiguration' - $viewType: 'FetchRemoteConfiguration' } } interactive: false - - Connections { - target: SettingsModel - onAssistantSupportsPhoneNumbersChanged: buttons.model.setProperty( - 0, - '$view', - SettingsModel.assistantSupportsPhoneNumbers ? - 'CreateAppSipAccount' : - 'CreateAppSipAccountWithEmail' - ) - } } } diff --git a/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccount.qml b/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccount.qml index 4d8a83179..986fc5b54 100644 --- a/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccount.qml +++ b/linphone-app/ui/views/App/Main/Assistant/CreateAppSipAccount.qml @@ -1,40 +1,167 @@ import QtQuick 2.7 +import QtWebView 1.1 +import QtQuick.Controls 1.3 // Busy indicator import Common 1.0 +import Linphone 1.0 as Linphone import App.Styles 1.0 // ============================================================================= AssistantAbstractView { - description: qsTr('createAppSipAccountDescription') - title: qsTr('createAppSipAccountTitle').replace('%1', Qt.application.name.toUpperCase()) + id: view + maximized:true + height: (parent?parent.height:0) + width: (parent?parent.width:0) + property string defaultUrl + property string defaultLogoutUrl + property string configFilename + property bool printed : stack.currentItem == view + onPrintedChanged: { + webviewLoader.active = printed + } + + //------------------------------- + + property int status : 0 // 0:nothing, -1:error, 1:ok + property bool newPage : true + + + // --------------------------------------------------------------------------- + // Menu. + // --------------------------------------------------------------------------- +// Note : Use opacity and not visibility to allow smooth updating (when moving visibility to true, we could show the old page) + Component{ + id: webviewComponent + WebView{ + id:webview + property bool isLogingOut : true + state: 'hidden' + Component.onCompleted: {if(webview.httpUserAgent != undefined) webview.httpUserAgent = Linphone.App.getUserAgent() // only available on Qt 5.15 (QtWebView 1.15) + isLogingOut = true + webview.url = view.defaultLogoutUrl + } + function getData(){// Check if account_infos exists in the page and retrieve data to make/update an account + if(webview.loading){ + view.status = 0 + }else { + var js = "(typeof account_infos !== 'undefined'?account_infos:'')"; + webview.runJavaScript(js, function(result) { + if( result == ''){ + view.status = 0 + }else{ + webview.state = 'hidden' + reloadTimer.stop(); + console.log("[CreateAccount] SIP : " +result.sip); + console.log("[CreateAccount] Username : " +result.username); + console.log("[CreateAccount] Registrar : " +result.registrar_address); + console.log("[CreateAccount] Domain : " +result.domain); + if (Linphone.AccountSettingsModel.addOrUpdateProxyConfig( { + sipAddress: result.sip, + serverAddress: result.registrar_address, + configFilename: view.configFilename + })) { + + console.log("[CreateAccount] Account created") + view.status = 1 + Linphone.AccountSettingsModel.setDefaultProxyConfigFromSipAddress("sip:"+result.sip) + } else { + console.error("[CreateAccount] Cannot create account. Check logs.") + view.status = -1 + } + + } + }); + } + } + + Timer {// Check data + id:reloadTimer + interval: 1000; + running: true; repeat: true + onTriggered: {webview.getData();} + } + + onLoadingChanged: { + if (loadRequest.errorString) + console.error("[CreateAccount] error on loading page : " +loadRequest.errorString); + if(loading){ + view.newPage = true; + }else if(view.newPage) { + view.newPage = false; + webview.runJavaScript("document.querySelector('nav').remove(); document.querySelector('footer').remove();"); + } + webview.state = (loading || isLogingOut ? 'hidden' : 'showed') + if(!loading){ + if(isLogingOut){ + isLogingOut = false + webview.url = view.defaultUrl + }else{ + reloadTimer.stop(); + webview.getData(); + if(view.status == 0) + reloadTimer.start(); + } + }else + reloadTimer.stop(); + } + states: [ + State { + name: 'hidden' + PropertyChanges { target: webview; opacity: 0 } + }, + State { + name: 'showed' + PropertyChanges { target: webview; opacity: 1 } + } + ] + transitions: [ + Transition { + from: '*'; to: 'showed' + SequentialAnimation{ + NumberAnimation{ properties: "opacity"; easing.type: Easing.OutBounce; duration: 500 } + } + }, + Transition { + SequentialAnimation{ + NumberAnimation{ properties: "opacity"; duration: 1000 } + } + } + ] + } + } + Loader{ + id: webviewLoader + active: false + anchors.fill:parent + sourceComponent: webviewComponent + + } - // --------------------------------------------------------------------------- - // Menu. - // --------------------------------------------------------------------------- + Rectangle{ + id:statusPage + anchors.fill:parent + visible: webviewLoader.item && (webviewLoader.item.loading || webviewLoader.item.isLogingOut || webviewLoader.item.state == 'hidden') + BusyIndicator{ + id:busy + anchors.centerIn : parent + running:true + width:CreateAppSipAccountStyle.busy.size + height:CreateAppSipAccountStyle.busy.size + } - Column { - anchors.centerIn: parent - spacing: CreateAppSipAccountStyle.buttons.spacing - width: CreateAppSipAccountStyle.buttons.button.width - - TextButtonA { - text: qsTr('withPhoneNumber') - - height: CreateAppSipAccountStyle.buttons.button.height - width: parent.width - - onClicked: assistant.pushView('CreateAppSipAccountWithPhoneNumber') - } - - TextButtonA { - text: qsTr('withEmailAddress') - - height: CreateAppSipAccountStyle.buttons.button.height - width: parent.width - - onClicked: assistant.pushView('CreateAppSipAccountWithEmail') - } - } + Icon{ + visible: view.status != 0 + icon: (view.status>0?"chat_read":"chat_error") + iconSize:busy.width + anchors.fill:busy + MouseArea{ + anchors.fill:parent + onClicked: { + assistant.popView() + } + } + } + } } diff --git a/linphone-app/ui/views/App/Main/Assistant/FetchRemoteConfiguration.qml b/linphone-app/ui/views/App/Main/Assistant/FetchRemoteConfiguration.qml index 62219587d..835b39ddb 100644 --- a/linphone-app/ui/views/App/Main/Assistant/FetchRemoteConfiguration.qml +++ b/linphone-app/ui/views/App/Main/Assistant/FetchRemoteConfiguration.qml @@ -4,72 +4,79 @@ import Common 1.0 import Linphone 1.0 import Utils 1.0 +import App.Styles 1.0 // ============================================================================= - -AssistantAbstractView { - mainAction: requestBlock.execute - mainActionEnabled: url.text.length > 0 - mainActionLabel: qsTr('confirmAction') - - title: qsTr('fetchRemoteConfigurationTitle') - - // --------------------------------------------------------------------------- - - Connections { - target: SettingsModel +Item{ + AssistantAbstractView { + mainAction: requestBlock.execute + mainActionEnabled: url.text.length > 0 + mainActionLabel: qsTr('confirmAction') - onRemoteProvisioningChanged: { - requestBlock.stop('') + title: qsTr('fetchRemoteConfigurationTitle') + width: AssistantAbstractViewStyle.content.width + height: AssistantAbstractViewStyle.content.height + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + // --------------------------------------------------------------------------- + + Connections { + target: SettingsModel - window.detachVirtualWindow() - window.attachVirtualWindow(Utils.buildDialogUri('ConfirmDialog'), { - descriptionText: qsTr('remoteProvisioningUpdateDescription'), - }, function (status) { - if (status) { - App.restart() - } else { - window.setView('Home') - } - }) + onRemoteProvisioningChanged: { + requestBlock.stop('') + window.detachVirtualWindow() + window.attachVirtualWindow(Utils.buildDialogUri('ConfirmDialog'), { + descriptionText: qsTr('remoteProvisioningUpdateDescription'), + }, function (status) { + if (status) { + App.restart() + } else { + window.setView('Home') + } + }) + } + + onRemoteProvisioningNotChanged: requestBlock.stop(qsTr('remoteProvisioningError')) } - onRemoteProvisioningNotChanged: requestBlock.stop(qsTr('remoteProvisioningError')) - } - - // --------------------------------------------------------------------------- - - Column { - anchors.fill: parent + // --------------------------------------------------------------------------- - Form { - orientation: Qt.Vertical - width: parent.width + Column { + anchors.fill: parent.contentItem + anchors.topMargin: AssistantAbstractViewStyle.info.spacing + width: AssistantAbstractViewStyle.content.width + height: AssistantAbstractViewStyle.content.height - FormLine { - FormGroup { - label: qsTr('urlLabel') - - TextField { - id: url + Form { + orientation: Qt.Vertical + width: parent.width + + FormLine { + FormGroup { + label: qsTr('urlLabel') + + TextField { + id: url + } } } } + + RequestBlock { + id: requestBlock + + action: (function () { + SettingsModel.remoteProvisioning = url.text + }) + + width: parent.width + } } - RequestBlock { - id: requestBlock - - action: (function () { - SettingsModel.remoteProvisioning = url.text - }) - - width: parent.width - } } Component.onCompleted: { if( !CoreManager.isLastRemoteProvisioningGood() ) //: 'Last remote provisioning failed' : Test to warn the user that the last fetch of remote provisioning has failed. requestBlock.stop(qsTr('lastProvisioningFailed')) } - } diff --git a/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml b/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml index daf1c9792..1006a94b8 100644 --- a/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml +++ b/linphone-app/ui/views/App/Main/Assistant/UseAppSipAccount.qml @@ -11,7 +11,6 @@ import App.Styles 1.0 AssistantAbstractView { id: view - readonly property bool usePhoneNumber: SettingsModel.assistantSupportsPhoneNumbers && !checkBox.checked mainAction: requestBlock.execute diff --git a/linphone-app/ui/views/App/Main/Assistant/UseOtherSipAccount.qml b/linphone-app/ui/views/App/Main/Assistant/UseOtherSipAccount.qml index 49d743e35..4cb9f4eea 100644 --- a/linphone-app/ui/views/App/Main/Assistant/UseOtherSipAccount.qml +++ b/linphone-app/ui/views/App/Main/Assistant/UseOtherSipAccount.qml @@ -3,102 +3,112 @@ import QtQuick 2.7 import Common 1.0 import Linphone 1.0 +import App.Styles 1.0 + // ============================================================================= +Item{ + + AssistantAbstractView { + mainAction: requestBlock.execute + + mainActionEnabled: username.text.length && + sipDomain.text.length && + password.text.length -AssistantAbstractView { - mainAction: requestBlock.execute + mainActionLabel: qsTr('confirmAction') - mainActionEnabled: username.text.length && - sipDomain.text.length && - password.text.length + title: qsTr('useOtherSipAccountTitle') - mainActionLabel: qsTr('confirmAction') + width: AssistantAbstractViewStyle.content.width + height: AssistantAbstractViewStyle.content.height + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter - title: qsTr('useOtherSipAccountTitle') + // --------------------------------------------------------------------------- + //anchors.centerIn: parent + //anchors.horizontalCenter:parent.horizontalCenter + Column { + anchors.fill: parent.contentItem + width: AssistantAbstractViewStyle.content.width + height: AssistantAbstractViewStyle.content.height - // --------------------------------------------------------------------------- + Form { + orientation: Qt.Vertical + width: parent.width - Column { - anchors.fill: parent + FormLine { + FormGroup { + label: qsTr('usernameLabel') - Form { - orientation: Qt.Vertical - width: parent.width + TextField { + id: username + } + } - FormLine { - FormGroup { - label: qsTr('usernameLabel') + FormGroup { + label: qsTr('displayNameLabel') - TextField { - id: username - } - } + TextField { + id: displayName + } + } + } - FormGroup { - label: qsTr('displayNameLabel') + FormLine { + FormGroup { + label: qsTr('sipDomainLabel') - TextField { - id: displayName - } - } - } + TextField { + id: sipDomain + } + } + } - FormLine { - FormGroup { - label: qsTr('sipDomainLabel') + FormLine { + FormGroup { + label: qsTr('passwordLabel') - TextField { - id: sipDomain - } - } - } + PasswordField { + id: password + } + } + } - FormLine { - FormGroup { - label: qsTr('passwordLabel') + FormLine { + FormGroup { + label: qsTr('transportLabel') - PasswordField { - id: password - } - } - } + ComboBox { + id: transport + model: [ 'UDP', 'TCP', 'TLS'] + } + } + } + } - FormLine { - FormGroup { - label: qsTr('transportLabel') + RequestBlock { + id: requestBlock + width: parent.width - ComboBox { - id: transport - model: [ 'UDP', 'TCP', 'TLS'] - } - } - } - } - - RequestBlock { - id: requestBlock - - action: (function () { - if (!assistantModel.addOtherSipAccount({ - username: username.text, - displayName: displayName.text, - sipDomain: sipDomain.text, - password: password.text, - transport: transport.model[transport.currentIndex] - })) { - requestBlock.stop(qsTr('addOtherSipAccountError')) - } else { - requestBlock.stop('') - window.setView('Home') - } - }) - - width: parent.width - } - } - - AssistantModel { - id: assistantModel - configFilename: 'use-other-sip-account.rc' - } + action: (function () { + if (!assistantModel.addOtherSipAccount({ + username: username.text, + displayName: displayName.text, + sipDomain: sipDomain.text, + password: password.text, + transport: transport.model[transport.currentIndex] + })) { + requestBlock.stop(qsTr('addOtherSipAccountError')) + } else { + requestBlock.stop('') + window.setView('Home') + } + }) + } + } + AssistantModel { + id: assistantModel + configFilename: 'use-other-sip-account.rc' + } + } } diff --git a/linphone-app/ui/views/App/Settings/SettingsSipAccounts.qml b/linphone-app/ui/views/App/Settings/SettingsSipAccounts.qml index 2e2672b48..2f75a3225 100644 --- a/linphone-app/ui/views/App/Settings/SettingsSipAccounts.qml +++ b/linphone-app/ui/views/App/Settings/SettingsSipAccounts.qml @@ -58,7 +58,7 @@ TabContainer { } } } - + // ------------------------------------------------------------------------- // Proxy accounts. // ------------------------------------------------------------------------- @@ -131,10 +131,35 @@ TabContainer { Form { title: qsTr('assistantTitle') - visible: SettingsModel.developerSettingsEnabled + width: parent.width + + FormLine { + FormGroup { + label: 'Registration URL' + + TextField { + text: SettingsModel.assistantRegistrationUrl + + onEditingFinished: SettingsModel.assistantRegistrationUrl = text + } + } + } + + FormLine { + FormGroup { + label: 'Login URL' + + TextField { + text: SettingsModel.assistantLoginUrl + + onEditingFinished: SettingsModel.assistantLoginUrl = text + } + } + } FormLine { + visible: SettingsModel.developerSettingsEnabled FormGroup { label: qsTr('createAppSipAccountEnabledLabel') @@ -157,6 +182,7 @@ TabContainer { } FormLine { + visible: SettingsModel.developerSettingsEnabled FormGroup { label: qsTr('useOtherSipAccountEnabledLabel') @@ -179,6 +205,7 @@ TabContainer { } FormLine { + visible: SettingsModel.developerSettingsEnabled FormGroup { label: qsTr('assistantSupportsPhoneNumbersLabel') diff --git a/linphone-app/ui/views/App/Styles/Main/Assistant/AssistantAbstractViewStyle.qml b/linphone-app/ui/views/App/Styles/Main/Assistant/AssistantAbstractViewStyle.qml index 1c97b4d6f..dae7e1fce 100644 --- a/linphone-app/ui/views/App/Styles/Main/Assistant/AssistantAbstractViewStyle.qml +++ b/linphone-app/ui/views/App/Styles/Main/Assistant/AssistantAbstractViewStyle.qml @@ -13,7 +13,7 @@ QtObject { } property QtObject content: QtObject { - property int height: 375 + property int height: 375+60//+button bar property int width: 400 } diff --git a/linphone-app/ui/views/App/Styles/Main/Assistant/CreateAppSipAccountStyle.qml b/linphone-app/ui/views/App/Styles/Main/Assistant/CreateAppSipAccountStyle.qml index 2a582464a..4e3e4b380 100644 --- a/linphone-app/ui/views/App/Styles/Main/Assistant/CreateAppSipAccountStyle.qml +++ b/linphone-app/ui/views/App/Styles/Main/Assistant/CreateAppSipAccountStyle.qml @@ -12,4 +12,8 @@ QtObject { property int width: 258 } } + + property QtObject busy: QtObject { + property int size: 40 + } }