From 2077041c045c976c645604d5e863a9279c459cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Thu, 28 Jul 2022 13:22:47 -0400 Subject: [PATCH] welcomeview: implement new design GitLab: #767 Change-Id: Ia2ae77e8e9d3d5abe560ced0a84d828057824845 --- CMakeLists.txt | 6 +- qml.qrc | 1 + resources/icons/keyboard_black_24dp.svg | 1 + src/app/MainApplicationWindow.qml | 1 + src/app/appsettingsmanager.h | 1 + src/app/commoncomponents/EditableLineEdit.qml | 8 +- src/app/commoncomponents/MaterialButton.qml | 2 +- src/app/commoncomponents/PhotoboothView.qml | 10 + .../commoncomponents/TextMessageDelegate.qml | 3 +- src/app/constant/JamiStrings.qml | 8 +- src/app/constant/JamiTheme.qml | 5 + src/app/mainapplication.cpp | 2 +- .../mainview/components/JamiIdentifier.qml | 93 +++++-- src/app/mainview/components/TipBox.qml | 219 ++++++++++++++++ src/app/mainview/components/WelcomePage.qml | 245 +++++++++++------- src/app/qmlregister.cpp | 3 + src/app/tipsmodel.cpp | 167 ++++++++++++ src/app/tipsmodel.h | 60 +++++ .../components/AdvancedAccountSettings.qml | 32 ++- .../ConnectToAccountManagerPage.qml | 2 + .../components/CreateAccountPage.qml | 2 +- .../components/CreateSIPAccountPage.qml | 1 + 22 files changed, 727 insertions(+), 145 deletions(-) create mode 100644 resources/icons/keyboard_black_24dp.svg create mode 100644 src/app/mainview/components/TipBox.qml create mode 100644 src/app/tipsmodel.cpp create mode 100644 src/app/tipsmodel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b5b4c257..444deb59c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,7 +181,8 @@ set(COMMON_SOURCES ${APP_SRC_DIR}/currentaccount.cpp ${APP_SRC_DIR}/videodevices.cpp ${APP_SRC_DIR}/videoprovider.cpp - ${APP_SRC_DIR}/callparticipantsmodel.cpp) + ${APP_SRC_DIR}/callparticipantsmodel.cpp + ${APP_SRC_DIR}/tipsmodel.cpp) set(COMMON_HEADERS ${APP_SRC_DIR}/avatarimageprovider.h @@ -236,7 +237,8 @@ set(COMMON_HEADERS ${APP_SRC_DIR}/currentaccount.h ${APP_SRC_DIR}/videodevices.h ${APP_SRC_DIR}/videoprovider.h - ${APP_SRC_DIR}/callparticipantsmodel.h) + ${APP_SRC_DIR}/callparticipantsmodel.h + ${APP_SRC_DIR}/tipsmodel.h) if(WITH_WEBENGINE) list(APPEND COMMON_SOURCES diff --git a/qml.qrc b/qml.qrc index 2c399e1ae..42a243ac2 100644 --- a/qml.qrc +++ b/qml.qrc @@ -195,5 +195,6 @@ <file>src/app/wizardview/components/NoUsernamePopup.qml</file> <file>src/app/wizardview/components/AdvancedAccountSettings.qml</file> <file>src/app/commoncomponents/InfoBox.qml</file> + <file>src/app/mainview/components/TipBox.qml</file> </qresource> </RCC> diff --git a/resources/icons/keyboard_black_24dp.svg b/resources/icons/keyboard_black_24dp.svg new file mode 100644 index 000000000..a30439e10 --- /dev/null +++ b/resources/icons/keyboard_black_24dp.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z"/><path d="M0 0h24v24H0zm0 0h24v24H0z" fill="none"/></svg> \ No newline at end of file diff --git a/src/app/MainApplicationWindow.qml b/src/app/MainApplicationWindow.qml index 0011976b8..bc9b53bbe 100644 --- a/src/app/MainApplicationWindow.qml +++ b/src/app/MainApplicationWindow.qml @@ -39,6 +39,7 @@ import "commoncomponents" ApplicationWindow { id: root + flags: Qt.WA_TranslucentBackground enum LoadedSource { WizardView = 0, diff --git a/src/app/appsettingsmanager.h b/src/app/appsettingsmanager.h index 797e752fc..3ecc4a88d 100644 --- a/src/app/appsettingsmanager.h +++ b/src/app/appsettingsmanager.h @@ -50,6 +50,7 @@ extern const QString defaultDownloadPath; X(StartMinimized, false) \ X(ShowChatviewHorizontally, true) \ X(NeverShowMeAgain, false) \ + X(HiddenTips, QStringList()) \ X(WindowGeometry, QRectF(qQNaN(), qQNaN(), 0., 0.)) \ X(WindowState, QWindow::AutomaticVisibility) \ X(LANG, "SYSTEM") diff --git a/src/app/commoncomponents/EditableLineEdit.qml b/src/app/commoncomponents/EditableLineEdit.qml index ac5d0ca9a..8daab3375 100644 --- a/src/app/commoncomponents/EditableLineEdit.qml +++ b/src/app/commoncomponents/EditableLineEdit.qml @@ -263,9 +263,7 @@ Item { duration: JamiTheme.longFadeDuration } } - } - } @@ -303,4 +301,10 @@ Item { } } + + onFocusChanged: function(focus) { + if (focus) + lineEdit.forceActiveFocus(); + } + } diff --git a/src/app/commoncomponents/MaterialButton.qml b/src/app/commoncomponents/MaterialButton.qml index 56366f27f..79a9ca515 100644 --- a/src/app/commoncomponents/MaterialButton.qml +++ b/src/app/commoncomponents/MaterialButton.qml @@ -173,7 +173,7 @@ AbstractButton { Layout.alignment: Qt.AlignHCenter text: root.text - + font.weight: Font.Medium elide: Text.ElideRight verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter diff --git a/src/app/commoncomponents/PhotoboothView.qml b/src/app/commoncomponents/PhotoboothView.qml index cc35c0b88..116a54d50 100644 --- a/src/app/commoncomponents/PhotoboothView.qml +++ b/src/app/commoncomponents/PhotoboothView.qml @@ -31,6 +31,7 @@ Item { id: root property alias imageId: avatar.imageId + property alias cancelButton: cancelButton.visible property bool newItem: false property bool readOnly: false @@ -61,6 +62,8 @@ Item { onVisibleChanged: { if (!visible) { + imageLayer.visible = true + buttonsRowLayout.visible = false stopBooth() } } @@ -192,6 +195,8 @@ Item { height: buttonSize width: buttonSize + imageContainerWidth: buttonSize + imageContainerHeight: buttonSize radius: height / 2 border.width: 2 border.color: darkTheme ? "white" : JamiTheme.buttonTintedBlue @@ -245,6 +250,8 @@ Item { height: buttonSize width: buttonSize + imageContainerWidth: buttonSize + imageContainerHeight: buttonSize radius: height / 2 border.width: 2 border.color: darkTheme ? "white" : JamiTheme.buttonTintedBlue @@ -286,6 +293,8 @@ Item { height: buttonSize width: buttonSize + imageContainerWidth: buttonSize + imageContainerHeight: buttonSize radius: height / 2 border.width: 2 border.color: darkTheme ? "white" : JamiTheme.buttonTintedBlue @@ -331,6 +340,7 @@ Item { PushButton { id: cancelButton + visible: true preferredSize: 18 width: 18 height: 18 diff --git a/src/app/commoncomponents/TextMessageDelegate.qml b/src/app/commoncomponents/TextMessageDelegate.qml index 75e942b0a..a041fd723 100644 --- a/src/app/commoncomponents/TextMessageDelegate.qml +++ b/src/app/commoncomponents/TextMessageDelegate.qml @@ -62,8 +62,9 @@ SBSMessageBase { height: implicitHeight wrapMode: Label.WrapAtWordBoundaryOrAnywhere selectByMouse: true + font.pixelSize: JamiTheme.chatviewFontSize - font.family: 'Ubuntu' + font.hintingPreference: Font.PreferNoHinting renderType: Text.NativeRendering textFormat: Text.MarkdownText diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml index 21541c5ac..4b2423a8e 100644 --- a/src/app/constant/JamiStrings.qml +++ b/src/app/constant/JamiStrings.qml @@ -253,6 +253,7 @@ Item { // LineEditContextMenu property string copy: qsTr("Copy") + property string share: qsTr("Share") property string cut: qsTr("Cut") property string paste: qsTr("Paste") @@ -487,6 +488,7 @@ Item { // KeyboardShortCutTable property string keyboardShortcutTableWindowTitle: qsTr("Keyboard Shortcut Table") + property string keyboardShortcuts: qsTr("Keyboard Shortcuts") property string generalKeyboardShortcuts: qsTr("General") property string conversationKeyboardShortcuts: qsTr("Conversation") property string callKeyboardShortcuts: qsTr("Call") @@ -651,10 +653,9 @@ Item { property string introductionJami: qsTr("Share, freely and privately with Jami") property string alreadyHaveAccount: qsTr("I already have an account") property string useExistingAccount: qsTr("Use existing Jami account") - property string recommendationMessage: qsTr("Here are some recommendations to improve your experience on Jami") - property string noRecommendations: qsTr("Never show recommendations again") property string welcomeToJami: qsTr("Welcome to Jami") property string identifierDescription: qsTr("Share this Jami identifier to be contacted on this account!") + property string hereIsIdentifier: qsTr("Here is your Jami identifier, don't hesitate to share it in order to be contacted more easily!") // SmartList property string clearText: qsTr("Clear Text") @@ -751,5 +752,6 @@ Item { property string tips: qsTr("Tips") property string customizeText: qsTr("Add a picture and a nickname to complete your profile") property string customizationDescription: qsTr("This profile is only shared with this account’s contacts") - + property string customizationDescription2: qsTr("Your profile is only shared with your contacts") + property string whySaveAccount: qsTr("Why should I save my account ?") } diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index f1c0e38cd..ac10daa65 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -426,6 +426,11 @@ Item { property real infoBoxTitleFontSize: calcSize(13) property real infoBoxDescFontSize: calcSize(12) + //Tipbox + + property real tipBoxTitleFontSize: calcSize(13) + property real tipBoxContentFontSize: calcSize(12) + // MaterialLineEdit property real materialLineEditPointSize: calcSize(10 + fontSizeOffset) diff --git a/src/app/mainapplication.cpp b/src/app/mainapplication.cpp index fdf964627..92a581d28 100644 --- a/src/app/mainapplication.cpp +++ b/src/app/mainapplication.cpp @@ -328,7 +328,7 @@ void MainApplication::setApplicationFont() { QFont font; - font.setFamily("Segoe UI"); + font.setFamily("Ubuntu"); setFont(font); QFontDatabase::addApplicationFont(":/fonts/FontAwesome.otf"); } diff --git a/src/app/mainview/components/JamiIdentifier.qml b/src/app/mainview/components/JamiIdentifier.qml index 69afd6043..6b0046463 100644 --- a/src/app/mainview/components/JamiIdentifier.qml +++ b/src/app/mainview/components/JamiIdentifier.qml @@ -25,28 +25,37 @@ import net.jami.Adapters 1.1 import net.jami.Constants 1.1 import "../../commoncomponents" - +import "../../settingsview/components" Rectangle { id: root + NameRegistrationDialog { + id : nameRegistrationDialog + + onAccepted: jamiRegisteredNameText.nameRegistrationState = + UsernameLineEdit.NameRegistrationState.BLANK + } + property bool editable: false + property bool editing: false radius: 20 Layout.bottomMargin: JamiTheme.jamiIdMargins Layout.leftMargin: JamiTheme.jamiIdMargins - height: 91 - color: JamiTheme.whiteColor + property var minWidth: mainRectangle.width + secondLine.implicitWidth + width: Math.max(minWidth, jamiRegisteredNameText.width + 2 * JamiTheme.preferredMarginSize) + height: component.implicitHeight + color: JamiTheme.secondaryBackgroundColor ColumnLayout { - anchors.fill: parent + id: component RowLayout { id: firstLine - - Layout.preferredWidth: parent.width Layout.alignment: Qt.AlignTop + Layout.preferredWidth: root.width Rectangle { id: mainRectangle @@ -58,13 +67,11 @@ Rectangle { Rectangle { - id: rectForRadius anchors.bottom: parent.bottom width: 20 height: 20 color: JamiTheme.mainColor - } ResponsiveImage { @@ -81,25 +88,49 @@ Rectangle { } RowLayout { + id: secondLine Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - Layout.fillWidth: true PushButton { id: btnEdit - imageColor: JamiTheme.buttonTintedBlue + imageColor: enabled ? JamiTheme.buttonTintedBlue : JamiTheme.buttonTintedBlack normalColor: JamiTheme.transparentColor Layout.topMargin: JamiTheme.pushButtonMargin hoverEnabled: false preferredSize : 30 imageContainerWidth: JamiTheme.pushButtonSize imageContainerHeight: JamiTheme.pushButtonSize - visible: false //(editable) Not visible for the moment - border.color: JamiTheme.buttonTintedBlue + visible: editable && CurrentAccount.registeredName === "" + border.color: enabled ? JamiTheme.buttonTintedBlue : JamiTheme.buttonTintedBlack + + enabled: { + switch(jamiRegisteredNameText.nameRegistrationState) { + case UsernameLineEdit.NameRegistrationState.BLANK: + case UsernameLineEdit.NameRegistrationState.FREE: + return true + case UsernameLineEdit.NameRegistrationState.SEARCHING: + case UsernameLineEdit.NameRegistrationState.INVALID: + case UsernameLineEdit.NameRegistrationState.TAKEN: + return false + } + } source: JamiResources.round_edit_24dp_svg - onClicked: { } + onClicked: { + if (!root.editing) { + root.editing = !root.editing + source = JamiResources.check_black_24dp_svg + jamiRegisteredNameText.text = "" + jamiRegisteredNameText.forceActiveFocus() + } else { + root.editing = !root.editing + source = JamiResources.round_edit_24dp_svg + jamiRegisteredNameText.accepted() + jamiRegisteredNameText.focus = false + } + } } PushButton { @@ -107,21 +138,19 @@ Rectangle { imageColor: JamiTheme.buttonTintedBlue normalColor: JamiTheme.transparentColor + hoveredColor: JamiTheme.transparentColor Layout.topMargin: JamiTheme.pushButtonMargin - preferredSize : 30 imageContainerWidth: JamiTheme.pushButtonSize imageContainerHeight: JamiTheme.pushButtonSize - hoverEnabled: false border.color: JamiTheme.tintedBlue source: JamiResources.content_copy_24dp_svg + toolTipText: JamiStrings.copy - onClicked: { - UtilsAdapter.setClipboardText(CurrentAccount.bestId) - } + onClicked: UtilsAdapter.setClipboardText(CurrentAccount.bestId) } PushButton { @@ -129,34 +158,48 @@ Rectangle { imageColor: JamiTheme.buttonTintedBlue normalColor: JamiTheme.transparentColor + hoveredColor: JamiTheme.transparentColor Layout.topMargin: JamiTheme.pushButtonMargin Layout.rightMargin: JamiTheme.pushButtonMargin preferredSize : 30 imageContainerWidth: JamiTheme.pushButtonSize imageContainerHeight: JamiTheme.pushButtonSize - hoverEnabled: false border.color: JamiTheme.buttonTintedBlue source: JamiResources.share_24dp_svg + toolTipText: JamiStrings.share - onClicked: { qrDialog.open() } + onClicked: qrDialog.open() } } } - ElidedTextLabel { + UsernameLineEdit { id: jamiRegisteredNameText + readOnly: !root.editing + Layout.preferredWidth: 330 - Layout.alignment: Qt.AlignBottom | Qt.AlignCenter - Layout.bottomMargin: JamiTheme.preferredMarginSize + horizontalAlignment: Qt.AlignHCenter + Layout.leftMargin: JamiTheme.preferredMarginSize + Layout.rightMargin: JamiTheme.preferredMarginSize + backgroundColor: JamiTheme.secondaryBackgroundColor font.pointSize: JamiTheme.textFontSize + 1 text: CurrentAccount.bestId - color: JamiTheme.blackColor - + color: JamiTheme.textColor + + onAccepted: { + if (!btnEdit.enabled) + return + if (text.length === 0) { + text = CurrentAccount.bestId + } else { + nameRegistrationDialog.openNameRegistrationDialog(text) + } + } } } diff --git a/src/app/mainview/components/TipBox.qml b/src/app/mainview/components/TipBox.qml new file mode 100644 index 000000000..25b095139 --- /dev/null +++ b/src/app/mainview/components/TipBox.qml @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2020-2022 Savoir-faire Linux Inc. + * Author: Fadi Shehadeh <fadi.shehadeh@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.Controls +import QtQuick.Layouts + +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +import Qt5Compat.GraphicalEffects + +import "../../commoncomponents" + +Item { + + id: root + property var title: "" + property var description: "" + property int tipId: 0 + property bool isTip : true + property bool hovered: false + property bool clicked : false + property bool opened : false + property string alias: "" + + width: 200 + height: tipColumnLayout.implicitHeight + 2 * JamiTheme.preferredMarginSize + + signal ignoreClicked + + Rectangle { + + id: rect + anchors.fill: parent + + color: JamiTheme.secondaryBackgroundColor + border.color: opened || hovered ? "transparent" : Qt.rgba(0, 0.34,0.6,0.16) + radius: 20 + + ColumnLayout { + + id: tipColumnLayout + anchors.top: parent.top + width: parent.width + anchors.topMargin: 10 + + + RowLayout { + + Layout.leftMargin: 15 + Layout.alignment: Qt.AlignLeft + + ResponsiveImage { + id: icon + + visible: !opened + + Layout.alignment: Qt.AlignLeft + Layout.topMargin: 5 + Layout.preferredWidth: 26 + Layout.preferredHeight: 26 + + containerHeight: Layout.preferredHeight + containerWidth: Layout.preferredWidth + + source: !isTip ? JamiResources.noun_paint_svg : JamiResources.glasses_tips_svg + color: "#005699" + } + + Label { + text: root.isTip ? JamiStrings.tips : JamiStrings.customize + color: JamiTheme.textColor + font.weight: Font.Medium + Layout.topMargin: 5 + visible: !opened + Layout.alignment: Qt.AlignLeft + Layout.leftMargin: isTip ? 8 : 5 + font.pixelSize: JamiTheme.tipBoxTitleFontSize + } + } + + Text { + + Layout.preferredWidth: root.isTip ? opened ? 140 : 150 : 170 + Layout.leftMargin: 20 + Layout.topMargin: root.isTip && opened ? 0 : 8 + Layout.bottomMargin: 15 + font.pixelSize: JamiTheme.tipBoxContentFontSize + visible: !opened || root.isTip + wrapMode: Text.WordWrap + font.weight: root.isTip && opened ? Font.Medium : Font.Normal + text: !isTip ? JamiStrings.customizeText : root.title + color: JamiTheme.textColor + } + + + PhotoboothView { + id: setAvatarWidget + Layout.preferredWidth: JamiTheme.accountListAvatarSize + Layout.preferredHeight: JamiTheme.accountListAvatarSize + Layout.topMargin: 10 + Layout.alignment: Qt.AlignHCenter + darkTheme: UtilsAdapter.luma(JamiTheme.primaryBackgroundColor) + visible: opened &&! isTip + enabled: true + buttonSize: 35 + imageId: CurrentAccount.id + avatarSize: 53 + cancelButton: false + + } + + EditableLineEdit { + + id: displayNameLineEdit + + visible: !isTip && opened + + Layout.alignment: Qt.AlignCenter + Layout.preferredWidth: root.width - 32 + + text: CurrentAccount.alias + placeholderText: JamiStrings.enterNickname + color: JamiTheme.textColor + + fontSize: JamiTheme.tipBoxContentFontSize + + onEditingFinished: root.alias = text + + } + + Text { + + Layout.preferredWidth: root.width - 32 + Layout.leftMargin: 20 + Layout.topMargin: 6 + font.pixelSize: JamiTheme.tipBoxContentFontSize + visible: opened && !isTip + wrapMode: Text.WordWrap + text: JamiStrings.customizationDescription2 + color: JamiTheme.textColor + } + + Text { + Layout.preferredWidth: root.width - 32 + Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter + font.pixelSize: JamiTheme.tipBoxContentFontSize + visible: opened && isTip + wrapMode: Text.WordWrap + text: root.description + color: JamiTheme.textColor + } + + } + + } + + HoverHandler { + target : rect + onHoveredChanged: root.hovered = hovered + cursorShape: Qt.PointingHandCursor + } + + TapHandler { + target: rect + onTapped: opened = !opened + } + + DropShadow { + z: -1 + visible: hovered || opened + width: root.width + height: root.height + horizontalOffset: 3.0 + verticalOffset: 3.0 + radius: 16 + color: Qt.rgba(0, 0.34,0.6,0.16) + source: rect + transparentBorder: true + } + + PushButton { + id: btnClose + + width: 20 + height: 20 + imageContainerWidth: 20 + imageContainerHeight : 20 + anchors.margins: 14 + anchors.top: parent.top + anchors.right: parent.right + visible: opened + circled: true + + imageColor: Qt.rgba(0, 86/255, 153/255, 1) + normalColor: "transparent" + + source: JamiResources.round_close_24dp_svg + + onClicked: root.ignoreClicked() + } +} diff --git a/src/app/mainview/components/WelcomePage.qml b/src/app/mainview/components/WelcomePage.qml index 06930c06c..7eb6df407 100644 --- a/src/app/mainview/components/WelcomePage.qml +++ b/src/app/mainview/components/WelcomePage.qml @@ -20,155 +20,204 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 +import net.jami.Enums 1.1 +import net.jami.Models 1.1 +import Qt.labs.lottieqt import "../../commoncomponents" +import "../js/keyboardshortcuttablecreation.js" as KeyboardShortcutTableCreation Rectangle { - id: root + id: root color: JamiTheme.secondaryBackgroundColor - ColumnLayout { - id: welcomePageColumnLayout - - anchors.centerIn: parent - width: Math.max(mainViewStackPreferredWidth, root.width - 100) - height: parent.height + JamiFlickable { + id: welcomeView + MouseArea { + anchors.fill: parent + enabled: visible + onClicked: { + for (var c in flow.children) { + flow.children[c].opened = false + } + } + } - ColumnLayout { - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: welcomePageColumnLayout.width - Layout.preferredHeight: implicitHeight - Layout.topMargin: JamiTheme.preferredMarginSize + anchors.fill: root - ResponsiveImage { - id: jamiLogoImage + contentHeight: Math.max(root.height, welcomePageLayout.implicitHeight) + contentWidth: Math.max(300, root.width) - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: Math.min(welcomePageColumnLayout.width, 330) - Layout.preferredHeight: Math.min(welcomePageColumnLayout.width / 3, 110) - Layout.bottomMargin: 10 + Item { + id: welcomePageLayout + width: Math.max(300, root.width) + height: parent.height - source: JamiTheme.darkTheme ? - JamiResources.logo_jami_standard_coul_white_svg : - JamiResources.logo_jami_standard_coul_svg - } + Item { + anchors.centerIn: parent + height: childrenRect.height - Label { - id: jamiIntroText + Rectangle { + id: welcomeInfo - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: welcomePageColumnLayout.width - Layout.preferredHeight: 80 - Layout.bottomMargin: 5 + radius: 30 + color: JamiTheme.rectColor + anchors.topMargin: 25 + anchors.horizontalCenter: parent.horizontalCenter + width: identifier.width + 2 * JamiTheme.preferredMarginSize + (welcomeLogo.visible ? welcomeLogo.width : 0) + height: childrenRect.height + opacity:1 - wrapMode: Text.WordWrap - font.pointSize: JamiTheme.textFontSize + 1 + Behavior on width { + NumberAnimation { duration: JamiTheme.shortFadeDuration } + } - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: JamiStrings.description - color: JamiTheme.textColor - } + Label { + id: welcome - Label { - id: jamiShareWithFriendText + anchors.top: parent.top + anchors.left: parent.left + anchors.topMargin: JamiTheme.preferredMarginSize + anchors.leftMargin: JamiTheme.preferredMarginSize + width: 300 - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: welcomePageColumnLayout.width - Layout.preferredHeight: 50 + font.pixelSize: JamiTheme.bigFontSize - wrapMode: Text.WordWrap - font.pointSize: JamiTheme.textFontSize + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + text: JamiStrings.welcomeToJami + color: JamiTheme.textColor + } - visible: LRCInstance.currentAccountType === Profile.Type.JAMI + Label { + id: identifierDescription + + anchors.top: welcome.bottom + anchors.left: parent.left + anchors.topMargin: JamiTheme.preferredMarginSize + anchors.leftMargin: JamiTheme.preferredMarginSize + width: 300 - text: JamiStrings.shareInvite - color: JamiTheme.faddedFontColor - } + font.pixelSize: JamiTheme.headerFontSize - Rectangle { - id: jamiRegisteredNameRect + wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: welcomePageColumnLayout.width - Layout.preferredHeight: 65 + text: JamiStrings.hereIsIdentifier + color: JamiTheme.textColor + } - color: JamiTheme.secondaryBackgroundColor + JamiIdentifier { + id: identifier + editable: true + + anchors.top: identifierDescription.bottom + anchors.left: parent.left + anchors.margins: JamiTheme.preferredMarginSize + } - visible: LRCInstance.currentAccountType === Profile.Type.JAMI - ColumnLayout { - id: jamiRegisteredNameRectColumnLayout - spacing: 0 + Image { + id: welcomeLogo - Text { - id: jamiRegisteredNameText + visible: root.width > 630 + width: 212 + height: 244 + anchors.top: parent.top + anchors.left: identifier.right + anchors.margins: JamiTheme.preferredMarginSize + anchors.topMargin: -20 + opacity: visible - Layout.alignment: Qt.AlignCenter - Layout.preferredWidth: welcomePageColumnLayout.width - Layout.preferredHeight: 30 + source: JamiResources.welcome_illustration_2_svg - font.pointSize: JamiTheme.textFontSize + 1 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: textMetricsjamiRegisteredNameText.elidedText - color: JamiTheme.textColor - TextMetrics { - id: textMetricsjamiRegisteredNameText - font: jamiRegisteredNameText.font - text: UtilsAdapter.getBestId(LRCInstance.currentAccountId) - elideWidth: welcomePageColumnLayout.width - elide: Qt.ElideMiddle + Behavior on opacity { + NumberAnimation { duration: JamiTheme.shortFadeDuration } } } + } - PushButton { - id: copyRegisterednameButton + JamiFlickable { + id: tipsFlow - Layout.alignment: Qt.AlignCenter + anchors.top: welcomeInfo.bottom + anchors.topMargin: JamiTheme.preferredMarginSize * 2 + anchors.horizontalCenter: parent.horizontalCenter + width: welcomeInfo.width + JamiTheme.preferredMarginSize * 2 + height: flow.height + JamiTheme.preferredMarginSize * 2 - preferredSize: 34 - imagePadding: 4 - imageColor: JamiTheme.textColor + clip: true - source: JamiResources.content_copy_24dp_svg + Flow { + id: flow + spacing: 12 - onClicked: { - UtilsAdapter.setClipboardText( - textMetricsjamiRegisteredNameText.text) + Repeater { + model: TipsModel + Layout.alignment: Qt.AlignCenter + + delegate: TipBox { + tipId: TipId + title: Title + description: Description + isTip: IsTip + visible: index < 3 + + onIgnoreClicked: TipsModel.remove(TipId) + } } } } } - } - MaterialButton { - id: btnAboutPopUp + Item { + id: bottomRow + width: Math.max(300, root.width) + height: aboutJami.height + JamiTheme.preferredMarginSize + anchors.bottom: parent.bottom + + MaterialButton { + id: aboutJami + tertiary: true - Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter - Layout.bottomMargin: JamiTheme.preferredMarginSize + anchors.horizontalCenter: parent.horizontalCenter + preferredWidth: JamiTheme.aboutButtonPreferredWidthth + text: JamiStrings.aboutJami - preferredWidth: JamiTheme.aboutButtonPreferredWidth + onClicked: aboutPopUpDialog.open() + } + + PushButton { + id: btnKeyboard - color: JamiTheme.buttonTintedBlack - hoveredColor: JamiTheme.buttonTintedBlackHovered - pressedColor: JamiTheme.buttonTintedBlackPressed - secondary: true + imageColor: JamiTheme.buttonTintedBlue + normalColor: JamiTheme.transparentColor + hoveredColor: JamiTheme.transparentColor + anchors.right: parent.right + anchors.rightMargin: JamiTheme.preferredMarginSize + preferredSize : 30 + imageContainerWidth: JamiTheme.pushButtonSize + imageContainerHeight: JamiTheme.pushButtonSize - text: JamiStrings.aboutJami + border.color: JamiTheme.buttonTintedBlue - onClicked: aboutPopUpDialog.open() + source: JamiResources.keyboard_black_24dp_svg + toolTipText: JamiStrings.keyboardShortcuts + + onClicked: { + KeyboardShortcutTableCreation.createKeyboardShortcutTableWindowObject() + KeyboardShortcutTableCreation.showKeyboardShortcutTableWindow() + } + } + } } } @@ -180,4 +229,6 @@ Rectangle { bBorderwidth: 0 borderColor: JamiTheme.tabbarBorderColor } + + } diff --git a/src/app/qmlregister.cpp b/src/app/qmlregister.cpp index 71f896d57..1fc0ea4c8 100644 --- a/src/app/qmlregister.cpp +++ b/src/app/qmlregister.cpp @@ -24,6 +24,7 @@ #include "contactadapter.h" #include "pluginadapter.h" #include "messagesadapter.h" +#include "tipsmodel.h" #include "previewengine.h" #include "utilsadapter.h" #include "conversationsadapter.h" @@ -117,11 +118,13 @@ registerTypes(QQmlEngine* engine, auto pluginAdapter = new PluginAdapter(lrcInstance, parent); auto currentConversation = new CurrentConversation(lrcInstance, parent); auto currentAccount = new CurrentAccount(lrcInstance, settingsManager, parent); + auto tipsModel = new TipsModel(settingsManager, parent); auto videoDevices = new VideoDevices(lrcInstance, parent); auto currentAccountToMigrate = new CurrentAccountToMigrate(lrcInstance, parent); // qml adapter registration QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, callAdapter, "CallAdapter"); + QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, tipsModel, "TipsModel"); QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, messagesAdapter, "MessagesAdapter"); QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, conversationsAdapter, "ConversationsAdapter"); QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, avAdapter, "AvAdapter"); diff --git a/src/app/tipsmodel.cpp b/src/app/tipsmodel.cpp new file mode 100644 index 000000000..fbc3ce4d8 --- /dev/null +++ b/src/app/tipsmodel.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@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 <http://www.gnu.org/licenses/>. + */ + +#include "tipsmodel.h" + +TipsModel::TipsModel(AppSettingsManager* settingsManager, QObject* parent) + : QAbstractListModel(parent) + , settingsManager_(settingsManager) +{ + tips_.append({{"id", "0"}, {"title", tr("Customize")}, {"desc", ""}, {"isTip", "false"}}); + tips_.append({{"id", "1"}, + {"title", tr("What does Jami mean?")}, + {"desc", + tr("The choice of the name Jami was inspired by the Swahili word jamii which " + "means community as a noun and together as an adverb.")}, + {"isTip", "true"}}); + tips_.append({{"id", "2"}, + {"title", tr("What is the green dot next to my account?")}, + {"desc", + tr("A red dot means that your account is disconnected from the network, it " + "turns green when its connected")}, + {"isTip", "true"}}); + tips_.append({{"id", "3"}, + {"title", tr("Why should I backup my account?")}, + {"desc", + tr("Jami is distributed and you're account is only stored on your device. If " + "you loose your password, or your datas you can't recover it")}, + {"isTip", "true"}}); + tips_.append( + {{"id", "4"}, + {"title", tr("Can I make a conference call?")}, + {"desc", tr("In a call, you can click on \"Add participants\" to add a contact to a call")}, + {"isTip", "true"}}); + tips_.append({{"id", "5"}, + {"title", tr("Does Jami have group chats?")}, + {"desc", tr("In the settings, you can enabled support for groups (experimental)")}, + {"isTip", "true"}}); + tips_.append({{"id", "6"}, + {"title", tr("What is a Jami account?")}, + {"desc", + tr("A Jami account is an asymmetric encryption key. Your account is identified " + "by a Jami ID, which is a fingerprint of your public key.")}, + {"isTip", "true"}}); + tips_.append({{"id", "7"}, + {"title", tr("What information do I need to provide to create a Jami account?")}, + {"desc", + tr("When you create a new Jami account, you don’t have to provide any private " + "information like an email, address, or phone number.")}, + {"isTip", "true"}}); + tips_.append({{"id", "8"}, + {"title", tr("Why don't I have to use a password?")}, + {"desc", + tr("With Jami, your account is stored in a folder on your device. The password " + "is only used to encrypt your account in order to protect you from someone " + "who has physical access to your device.")}, + {"isTip", "true"}}); + tips_.append( + {{"id", "9"}, + {"title", tr("Why don't I have to register a username?")}, + {"desc", + tr("The most permanent, secure identifier is your Jami ID, but since these are difficult " + "to use for some people, you also have the option of registering a username.")}, + {"isTip", "true"}}); + tips_.append( + {{"id", "10"}, + {"title", tr("How can I back up my account?")}, + {"desc", tr("In the account settings, a button is available to backup your account.")}, + {"isTip", "true"}}); + tips_.append({{"id", "11"}, + {"title", tr("What happens when I delete my account?")}, + {"desc", + tr("Your account is only stored on your own devices. If you delete your account " + "from each device, the account is gone and you cannot get it back.")}, + {"isTip", "true"}}); + tips_.append({{"id", "12"}, + {"title", tr("Can I use my account on multiple device?")}, + {"desc", + tr("Yes, you can link your account from the settings, or you can import your " + "back-up on another device.")}, + {"isTip", "true"}}); + + QStringList hiddenIds = settingsManager_->getValue(Settings::Key::HiddenTips).toStringList(); + + auto it = tips_.begin(); + while (it != tips_.end()) { + if (hiddenIds.contains((*it)["id"])) + it = tips_.erase(it); + else + it++; + } +} + +int +TipsModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + return 0; + return tips_.size(); +} + +QVariant +TipsModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + auto tip = tips_.at(index.row()); + + switch (role) { + case Tips::Role::TipId: + return QVariant::fromValue(tip["id"].toInt()); + case Tips::Role::Title: + return QVariant::fromValue(tip["title"]); + case Tips::Role::Description: + return QVariant::fromValue(tip["desc"]); + case Tips::Role::IsTip: + return QVariant::fromValue(tip["isTip"] == "true"); + } + return QVariant(); +} + +QHash<int, QByteArray> +TipsModel::roleNames() const +{ + using namespace Tips; + QHash<int, QByteArray> roles; +#define X(role) roles[role] = #role; + TIPS_ROLES +#undef X + return roles; +} + +void +TipsModel::remove(QVariant id) +{ + auto index = 0; + auto it = tips_.begin(); + while (it != tips_.end()) { + if ((*it)["id"] == id.toString()) { + beginRemoveRows(QModelIndex(), index, index); + QStringList hiddenIds = settingsManager_->getValue(Settings::Key::HiddenTips) + .toStringList(); + hiddenIds.append(id.toString()); + settingsManager_->setValue(Settings::Key::HiddenTips, hiddenIds); + tips_.erase(it); + endRemoveRows(); + return; + } + index++; + it++; + } +} diff --git a/src/app/tipsmodel.h b/src/app/tipsmodel.h new file mode 100644 index 000000000..2620bb493 --- /dev/null +++ b/src/app/tipsmodel.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@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 <http://www.gnu.org/licenses/>. + */ +#pragma once + +#include "lrcinstance.h" +#include "appsettingsmanager.h" +#include "qtutils.h" + +#include <QAbstractListModel> +#include <QObject> + +#define TIPS_ROLES \ + X(TipId) \ + X(Title) \ + X(Description) \ + X(IsTip) + +namespace Tips { +Q_NAMESPACE +enum Role { + DummyRole = Qt::UserRole + 1, +#define X(role) role, + TIPS_ROLES +#undef X +}; +Q_ENUM_NS(Role) +} // namespace Tips + +class TipsModel : public QAbstractListModel +{ + Q_OBJECT + +public: + TipsModel(AppSettingsManager* sm, QObject* parent = nullptr); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QHash<int, QByteArray> roleNames() const override; + + Q_INVOKABLE void remove(QVariant id); + +private: + VectorMapStringString tips_; + AppSettingsManager* settingsManager_; +}; \ No newline at end of file diff --git a/src/app/wizardview/components/AdvancedAccountSettings.qml b/src/app/wizardview/components/AdvancedAccountSettings.qml index e1f310924..794adc55c 100644 --- a/src/app/wizardview/components/AdvancedAccountSettings.qml +++ b/src/app/wizardview/components/AdvancedAccountSettings.qml @@ -78,7 +78,7 @@ Rectangle { Layout.margins: 50 text: JamiStrings.advancedAccountSettings color: JamiTheme.textColor - font.pixelSize: 22 + font.pixelSize: JamiTheme.bigFontSize } ColumnLayout { @@ -115,18 +115,21 @@ Rectangle { DropShadow { z: -1 - anchors.fill: parent + visible: openedPassword + width: parent.width + height: parent.height horizontalOffset: 3.0 verticalOffset: 3.0 radius: 16 - source: bg color: Qt.rgba(0, 0.34,0.6,0.16) + source: bg + transparentBorder: true } Rectangle { id: bg radius: JamiTheme.formsRadius - border.color: JamiTheme.lightBlue_ + border.color: openedPassword? JamiTheme.transparentColor : JamiTheme.lightBlue_ layer.enabled: true color: JamiTheme.secondaryBackgroundColor anchors.fill: parent @@ -138,7 +141,7 @@ Rectangle { width: parent.width /2 anchors.bottom: parent.bottom anchors.left: parent.left - border.color: JamiTheme.lightBlue_ + border.color: openedPassword? JamiTheme.transparentColor : JamiTheme.lightBlue_ color: JamiTheme.secondaryBackgroundColor Rectangle { @@ -148,7 +151,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.left: parent.left anchors.margins: 1 - border.color: JamiTheme.secondaryBackgroundColor + border.color: openedPassword? JamiTheme.transparentColor : JamiTheme.secondaryBackgroundColor color: JamiTheme.secondaryBackgroundColor } @@ -164,6 +167,7 @@ Rectangle { text: JamiStrings.encryptAccount font.pixelSize: JamiTheme.creditsTextSize + font.weight: Font.Medium Layout.fillWidth: true Layout.leftMargin: 35 Layout.topMargin: 25 @@ -283,7 +287,7 @@ Rectangle { color: openedPassword ? JamiTheme.lightBlue_ : JamiTheme.transparentColor Layout.alignment: Qt.AlignBottom | Qt.AlignLeft Layout.leftMargin: openedPassword ? 2 : openedNickname ? 0 : 20 - Layout.bottomMargin: openedPassword ? 1 : 0 + Layout.bottomMargin: openedPassword ? 2 : 0 Rectangle { @@ -359,19 +363,22 @@ Rectangle { DropShadow { z: -1 - anchors.fill: parent + visible: openedNickname + width: parent.width + height: parent.height horizontalOffset: 3.0 verticalOffset: 3.0 radius: 16 - source: bg2 color: Qt.rgba(0, 0.34,0.6,0.16) + source: bg2 + transparentBorder: true } Rectangle { id: bg2 radius: JamiTheme.formsRadius - border.color: JamiTheme.lightBlue_ + border.color: openedNickname ? JamiTheme.transparentColor : JamiTheme.lightBlue_ layer.enabled: true color: JamiTheme.secondaryBackgroundColor anchors.fill: parent @@ -382,7 +389,7 @@ Rectangle { width: parent.width /2 anchors.bottom: parent.bottom anchors.right: parent.right - border.color: JamiTheme.lightBlue_ + border.color: openedNickname ? JamiTheme.transparentColor : JamiTheme.lightBlue_ color: JamiTheme.secondaryBackgroundColor layer.enabled: true @@ -394,7 +401,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.right: parent.right anchors.margins: 1 - border.color: JamiTheme.secondaryBackgroundColor + border.color: openedNickname ? JamiTheme.transparentColor : JamiTheme.secondaryBackgroundColor color: JamiTheme.secondaryBackgroundColor } @@ -411,6 +418,7 @@ Rectangle { visible: openedNickname text: JamiStrings.customizeProfile elide: Text.ElideRight + font.weight: Font.Medium Layout.topMargin: 25 Layout.leftMargin: 35 font.pixelSize: JamiTheme.creditsTextSize diff --git a/src/app/wizardview/components/ConnectToAccountManagerPage.qml b/src/app/wizardview/components/ConnectToAccountManagerPage.qml index 2e70c0020..d8e1fe2ae 100644 --- a/src/app/wizardview/components/ConnectToAccountManagerPage.qml +++ b/src/app/wizardview/components/ConnectToAccountManagerPage.qml @@ -93,6 +93,8 @@ Rectangle { text: JamiStrings.enterJAMSURL Layout.alignment: Qt.AlignCenter Layout.topMargin: 30 + font.weight: Font.Medium + Layout.preferredWidth: Math.min(400, root.width - JamiTheme.preferredMarginSize * 2) horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/src/app/wizardview/components/CreateAccountPage.qml b/src/app/wizardview/components/CreateAccountPage.qml index e49fc9cc0..30f3b5e96 100644 --- a/src/app/wizardview/components/CreateAccountPage.qml +++ b/src/app/wizardview/components/CreateAccountPage.qml @@ -381,7 +381,7 @@ Rectangle { id: title text: JamiStrings.goodToKnow color: JamiTheme.textColor - + font.weight: Font.Medium Layout.topMargin: 15 Layout.alignment: Qt.AlignCenter | Qt.AlignTop diff --git a/src/app/wizardview/components/CreateSIPAccountPage.qml b/src/app/wizardview/components/CreateSIPAccountPage.qml index 317b21fa2..a72ce8d0f 100644 --- a/src/app/wizardview/components/CreateSIPAccountPage.qml +++ b/src/app/wizardview/components/CreateSIPAccountPage.qml @@ -100,6 +100,7 @@ Rectangle { Layout.topMargin: 15 Layout.alignment: Qt.AlignCenter font.pixelSize: JamiTheme.wizardViewDescriptionFontPixelSize + font.weight: Font.Medium wrapMode: Text.WordWrap horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter -- GitLab