From f0d05aeb79e0f2abee5915f0e1103d6c99092f98 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 9 Dec 2021 11:50:42 +0100 Subject: [PATCH] GODT-1458: Splash screen and wording. --- internal/bridge/bridge.go | 18 ++- internal/frontend/qml/Bridge_test.qml | 15 +- internal/frontend/qml/MainWindow.qml | 19 ++- internal/frontend/qml/SMTPSettings.qml | 2 +- internal/frontend/qml/SignIn.qml | 1 - internal/frontend/qml/SplashScreen.qml | 148 ++++++++++++++++++ .../frontend/qml/icons/ic-card-identity.svg | 62 ++++++++ internal/frontend/qml/icons/ic-drive.svg | 3 + .../icons/ic-illustrative-view-html-code.svg | 8 + internal/frontend/qt/frontend_init.go | 23 +++ internal/frontend/qt/qml_backend.go | 2 + internal/frontend/types/types.go | 2 + 12 files changed, 289 insertions(+), 14 deletions(-) create mode 100644 internal/frontend/qml/SplashScreen.qml create mode 100644 internal/frontend/qml/icons/ic-card-identity.svg create mode 100644 internal/frontend/qml/icons/ic-drive.svg create mode 100644 internal/frontend/qml/icons/ic-illustrative-view-html-code.svg diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 4ad90754..f498de9c 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -57,7 +57,8 @@ type Bridge struct { // Bridge's global errors list. errors []error - lastVersion string + isFirstStart bool + lastVersion string } func New( @@ -91,8 +92,7 @@ func New( ) b := &Bridge{ - Users: u, - + Users: u, locations: locations, settings: setting, clientManager: clientManager, @@ -100,9 +100,11 @@ func New( versioner: versioner, cacheProvider: cacheProvider, autostart: autostart, + isFirstStart: false, } if setting.GetBool(settings.FirstStartKey) { + b.isFirstStart = true if err := b.SendMetric(metrics.New(metrics.Setup, metrics.FirstStart, metrics.Label(constants.Version))); err != nil { logrus.WithError(err).Error("Failed to send metric") } @@ -110,7 +112,6 @@ func New( if err := b.EnableAutostart(); err != nil { log.WithError(err).Error("Failed to enable autostart") } - setting.SetBool(settings.FirstStartKey, false) } @@ -294,7 +295,14 @@ func (b *Bridge) HasError(err error) bool { return false } -// GetLastVersion returns the version which was used in previous execution of Bridge. +// GetLastVersion returns the version which was used in previous execution of +// Bridge. func (b *Bridge) GetLastVersion() string { return b.lastVersion } + +// IsFirstStart returns true when Bridge is running for first time or after +// factory reset. +func (b *Bridge) IsFirstStart() bool { + return b.isFirstStart +} diff --git a/internal/frontend/qml/Bridge_test.qml b/internal/frontend/qml/Bridge_test.qml index 5aa4e42e..e45e5c2a 100644 --- a/internal/frontend/qml/Bridge_test.qml +++ b/internal/frontend/qml/Bridge_test.qml @@ -292,9 +292,7 @@ Window { StackLayout { anchors.fill: parent - currentIndex: tabBar.currentIndex - anchors.margins: 10 RowLayout { @@ -341,8 +339,6 @@ Window { ProtonStyle.currentStyle = ProtonStyle.darkStyle } } - - } CheckBox { @@ -355,6 +351,16 @@ Window { } } + CheckBox { + id: showSplashScreen + colorScheme: root.colorScheme + text: "Show splash screen" + checked: root.showSplashScreen + onCheckedChanged: { + root.showSplashScreen = checked + } + } + Button { colorScheme: root.colorScheme //Layout.fillWidth: true @@ -802,6 +808,7 @@ Window { signal userDisconnected(string username) signal apiCertIssue() + property bool showSplashScreen: true function login(username, password) { diff --git a/internal/frontend/qml/MainWindow.qml b/internal/frontend/qml/MainWindow.qml index e94ad3ae..c4b62520 100644 --- a/internal/frontend/qml/MainWindow.qml +++ b/internal/frontend/qml/MainWindow.qml @@ -98,6 +98,10 @@ ApplicationWindow { property bool _showSetup: false currentIndex: { + if (backend.showSplashScreen) { + return 3 + } + // show welcome when there are no users or only one non-logged-in user is present if (backend.users.count === 0) { return 1 @@ -122,7 +126,7 @@ ApplicationWindow { return 0 } - ContentWrapper { + ContentWrapper { // 0 id: contentWrapper colorScheme: root.colorScheme backend: root.backend @@ -136,7 +140,7 @@ ApplicationWindow { } } - WelcomeGuide { + WelcomeGuide { // 1 colorScheme: root.colorScheme backend: root.backend @@ -144,7 +148,7 @@ ApplicationWindow { Layout.fillWidth: true } - SetupGuide { + SetupGuide { // 2 id: setupGuide colorScheme: root.colorScheme backend: root.backend @@ -163,6 +167,15 @@ ApplicationWindow { root.showSetup(null,"") } } + + SplashScreen { // 3 + id: splashScreen + colorScheme: root.colorScheme + backend: root.backend + + Layout.fillHeight: true + Layout.fillWidth: true + } } NotificationPopups { diff --git a/internal/frontend/qml/SMTPSettings.qml b/internal/frontend/qml/SMTPSettings.qml index 66502109..5c3ded60 100644 --- a/internal/frontend/qml/SMTPSettings.qml +++ b/internal/frontend/qml/SMTPSettings.qml @@ -65,7 +65,7 @@ SettingsView { id: starttlsButton colorScheme: root.colorScheme ButtonGroup.group: protocolSelection - text: qsTr("STARTLS") + text: qsTr("STARTTLS") } } diff --git a/internal/frontend/qml/SignIn.qml b/internal/frontend/qml/SignIn.qml index 09725265..32195b81 100644 --- a/internal/frontend/qml/SignIn.qml +++ b/internal/frontend/qml/SignIn.qml @@ -289,7 +289,6 @@ Item { onLinkActivated: { Qt.openUrlExternally(link) } - } } diff --git a/internal/frontend/qml/SplashScreen.qml b/internal/frontend/qml/SplashScreen.qml new file mode 100644 index 00000000..c7799168 --- /dev/null +++ b/internal/frontend/qml/SplashScreen.qml @@ -0,0 +1,148 @@ +// Copyright (c) 2021 Proton Technologies AG +// +// This file is part of ProtonMail Bridge. +// +// ProtonMail Bridge 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. +// +// ProtonMail Bridge 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 ProtonMail Bridge. If not, see . + +import QtQml 2.12 +import QtQuick 2.13 +import QtQuick.Layouts 1.12 +import QtQuick.Controls 2.12 +import QtQuick.Controls.impl 2.12 + +import Proton 4.0 + +Rectangle { + id: root + + property ColorScheme colorScheme + property var backend + + color: root.colorScheme.background_norm + + ColumnLayout { + anchors.centerIn: root + + //width: 320 + + spacing: 20 + + Label { + Layout.bottomMargin: 12; + Layout.alignment: Qt.AlignHCenter; + + colorScheme: root.colorScheme; + text: "What's new in Bridge" + type: Label.Heading + horizontalAlignment: Text.AlignCenter + } + + Repeater { + model: ListModel { + ListElement { icon: "ic-illustrative-view-html-code" ; title: qsTr("New interface") ; description: qsTr("Entirely redesigned GUI with more intuitive setup.")} + ListElement { icon: "ic-card-identity" ; title: qsTr("Status view") ; description: qsTr("Important notifications and available storage at a glance.")} + ListElement { icon: "ic-drive" ; title: qsTr("Local cache") ; description: qsTr("New and improved cache for major stability and performance enhancements.")} + } + + Item { + implicitWidth: children[0].implicitWidth + implicitHeight: children[0].implicitHeight + + RowLayout { + id: row + spacing: 25 + + Item { + Layout.topMargin: itemTitle.height/2 + Layout.alignment: Qt.AlignTop + Layout.preferredWidth: 24 + Layout.preferredHeight: 24 + + ColorImage { + anchors.top: parent.top + anchors.left: parent.left + + color: root.colorScheme.interaction_norm + source: "./icons/"+model.icon+".svg" + width: parent.width + sourceSize.width: parent.width + } + } + + ColumnLayout { + spacing: 0 + + Label { + id: itemTitle + colorScheme: root.colorScheme + text: model.title + type: Label.Body_bold + } + + Label { + Layout.preferredWidth: 320 + colorScheme: root.colorScheme + text: model.description + wrapMode: Text.WordWrap + } + } + } + } + + } + + Item { + Layout.alignment: Qt.AlignHCenter; + implicitWidth: children[0].width + implicitHeight: children[0].height + + RowLayout { + spacing: 10 + + Label { + colorScheme: root.colorScheme; + text: qsTr("Full release notes") + Layout.alignment: Qt.AlignHCenter + type: Label.LabelType.Body + onLinkActivated: Qt.openUrlExternally(link) + color: root.colorScheme.interaction_norm + } + + ColorImage { + color: root.colorScheme.interaction_norm + source: "./icons/ic-external-link.svg" + width: 16 + sourceSize.width: 16 + } + + } + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: Qt.openUrlExternally(root.backend.releaseNotesLink) + } + } + + + Button { + Layout.topMargin: 12 + Layout.fillWidth: true + colorScheme: root.colorScheme + text: "Start using Bridge" + onClicked: root.backend.showSplashScreen = false + } + } +} + diff --git a/internal/frontend/qml/icons/ic-card-identity.svg b/internal/frontend/qml/icons/ic-card-identity.svg new file mode 100644 index 00000000..fdf93b7b --- /dev/null +++ b/internal/frontend/qml/icons/ic-card-identity.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + diff --git a/internal/frontend/qml/icons/ic-drive.svg b/internal/frontend/qml/icons/ic-drive.svg new file mode 100644 index 00000000..deb4e0fb --- /dev/null +++ b/internal/frontend/qml/icons/ic-drive.svg @@ -0,0 +1,3 @@ + + + diff --git a/internal/frontend/qml/icons/ic-illustrative-view-html-code.svg b/internal/frontend/qml/icons/ic-illustrative-view-html-code.svg new file mode 100644 index 00000000..3e39a5a6 --- /dev/null +++ b/internal/frontend/qml/icons/ic-illustrative-view-html-code.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/internal/frontend/qt/frontend_init.go b/internal/frontend/qt/frontend_init.go index 29d01fa6..f3d43a10 100644 --- a/internal/frontend/qt/frontend_init.go +++ b/internal/frontend/qt/frontend_init.go @@ -25,6 +25,7 @@ import ( "os" "runtime" + "github.com/Masterminds/semver/v3" qmlLog "github.com/ProtonMail/proton-bridge/internal/frontend/qt/log" "github.com/therecipe/qt/core" "github.com/therecipe/qt/qml" @@ -94,3 +95,25 @@ func (f *FrontendQt) initiateQtApplication() error { return nil } + +func (f *FrontendQt) setShowSplashScreen() { + f.qml.SetShowSplashScreen(false) + + // Splash screen should not be shown to new users or after factory reset. + if f.bridge.IsFirstStart() { + return + } + + ver, err := semver.NewVersion(f.bridge.GetLastVersion()) + if err != nil { + f.log.WithError(err).WithField("last", f.bridge.GetLastVersion()).Debug("Cannot parse last version") + return + } + + // Current splash screen contains update on "What's new" in facelift. + // Therefore, it should be shown only if the last used version was less + // than 1.9.0. + if ver.LessThan(semver.MustParse("1.9.0")) { + f.qml.SetShowSplashScreen(true) + } +} diff --git a/internal/frontend/qt/qml_backend.go b/internal/frontend/qt/qml_backend.go index 72bc56e0..62b229b7 100644 --- a/internal/frontend/qt/qml_backend.go +++ b/internal/frontend/qt/qml_backend.go @@ -43,6 +43,7 @@ type QMLBackend struct { _ func() `slot:"restart"` _ bool `property:showOnStartup` + _ bool `property:showSplashScreen` _ bool `property:dockIconVisible` @@ -255,6 +256,7 @@ func (q *QMLBackend) setup(f *FrontendQt) { }() }) + f.setShowSplashScreen() f.setVersion() f.setLogsPath() // release notes link is set by update diff --git a/internal/frontend/types/types.go b/internal/frontend/types/types.go index fa053bc5..b411d82a 100644 --- a/internal/frontend/types/types.go +++ b/internal/frontend/types/types.go @@ -90,6 +90,8 @@ type Bridger interface { IsAutostartEnabled() bool EnableAutostart() error DisableAutostart() error + GetLastVersion() string + IsFirstStart() bool } type bridgeWrap struct {