diff --git a/internal/frontend/bridge-gui/bridge-gui/Resources.qrc b/internal/frontend/bridge-gui/bridge-gui/Resources.qrc index 5e1f823a..0e0d0d9f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/Resources.qrc +++ b/internal/frontend/bridge-gui/bridge-gui/Resources.qrc @@ -117,6 +117,7 @@ qml/Resources/Help/WhyProfileWarning.html qml/SettingsItem.qml qml/SettingsView.qml + qml/SetupWizard/ClientConfigCertInstall.qml qml/SetupWizard/ClientListItem.qml qml/SetupWizard/LeftPane.qml qml/SetupWizard/ClientConfigAppleMail.qml diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigAppleMail.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigAppleMail.qml index e17fb6af..225cd949 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigAppleMail.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigAppleMail.qml @@ -17,256 +17,77 @@ import QtQuick.Controls Item { id: root - enum Screen { - CertificateInstall, - ProfileInstall - } property var wizard - signal appleMailAutoconfigCertificateInstallPageShown - signal appleMailAutoconfigProfileInstallPageShow + property bool profilePaneLaunched: false - function showAutoconfig() { - if (Backend.isTLSCertificateInstalled()) { - showProfileInstall(); - } else { - showCertificateInstall(); - } - } - function showCertificateInstall() { - certificateInstall.reset(); - stack.currentIndex = ClientConfigAppleMail.Screen.CertificateInstall; - appleMailAutoconfigCertificateInstallPageShown(); - } - function showProfileInstall() { - profileInstall.reset(); - stack.currentIndex = ClientConfigAppleMail.Screen.ProfileInstall; - appleMailAutoconfigProfileInstallPageShow(); + function reset() { + profilePaneLaunched = false; } - StackLayout { - id: stack - anchors.fill: parent + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: ProtonStyle.wizard_spacing_large - // stack index 0 - Item { - id: certificateInstall - - property string errorString: "" - property bool showBugReportLink: false - property bool waitingForCert: false - - function clearError() { - errorString = ""; - showBugReportLink = false; - } - function reset() { - waitingForCert = false; - clearError(); - } - - Layout.fillHeight: true + ColumnLayout { Layout.fillWidth: true + spacing: ProtonStyle.wizard_spacing_medium - ColumnLayout { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: ProtonStyle.wizard_spacing_large - - Connections { - function onCertificateInstallCanceled() { - certificateInstall.waitingForCert = false; - certificateInstall.errorString = qsTr("Apple Mail cannot be configured if you do not install the certificate. Please retry."); - certificateInstall.showBugReportLink = false; - } - function onCertificateInstallFailed() { - certificateInstall.waitingForCert = false; - certificateInstall.errorString = qsTr("An error occurred while installing the certificate."); - certificateInstall.showBugReportLink = true; - } - function onCertificateInstallSuccess() { - certificateInstall.reset(); - root.showAutoconfig(); - } - - target: Backend - } - ColumnLayout { - Layout.fillWidth: true - spacing: ProtonStyle.wizard_spacing_medium - - Label { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - colorScheme: wizard.colorScheme - horizontalAlignment: Text.AlignHCenter - text: qsTr("Install the bridge certificate") - type: Label.LabelType.Title - wrapMode: Text.WordWrap - } - Label { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - color: colorScheme.text_weak - colorScheme: wizard.colorScheme - horizontalAlignment: Text.AlignHCenter - text: qsTr("After clicking on the button below, a system pop-up will ask you for your credentials, please enter your macOS user credentials (not your Proton account’s) and validate.") - type: Label.LabelType.Body - wrapMode: Text.WordWrap - } - } - Image { - Layout.alignment: Qt.AlignHCenter - height: 182 - opacity: certificateInstall.waitingForCert ? 0.3 : 1.0 - source: "/qml/icons/img-macos-cert-screenshot.png" - width: 140 - } - ColumnLayout { - Layout.fillWidth: true - spacing: ProtonStyle.wizard_spacing_medium - - Button { - Layout.fillWidth: true - colorScheme: wizard.colorScheme - enabled: !certificateInstall.waitingForCert - loading: certificateInstall.waitingForCert - text: qsTr("Install the certificate") - - onClicked: { - certificateInstall.clearError(); - certificateInstall.waitingForCert = true; - Backend.installTLSCertificate(); - } - } - Button { - Layout.fillWidth: true - colorScheme: wizard.colorScheme - enabled: !certificateInstall.waitingForCert - secondary: true - text: qsTr("Cancel") - - onClicked: { - wizard.closeWizard(); - } - } - ColumnLayout { - Layout.fillWidth: true - spacing: ProtonStyle.wizard_spacing_small - - RowLayout { - Layout.fillWidth: true - spacing: ProtonStyle.wizard_spacing_extra_small - - ColorImage { - color: wizard.colorScheme.signal_danger - height: errorLabel.lineHeight - source: "/qml/icons/ic-exclamation-circle-filled.svg" - sourceSize.height: errorLabel.lineHeight - visible: certificateInstall.errorString.length > 0 - } - Label { - id: errorLabel - Layout.fillWidth: true - color: wizard.colorScheme.signal_danger - colorScheme: wizard.colorScheme - horizontalAlignment: Text.AlignHCenter - text: certificateInstall.errorString - type: Label.LabelType.Body_semibold - wrapMode: Text.WordWrap - } - } - LinkLabel { - Layout.alignment: Qt.AlignHCenter - callback: wizard.showBugReport - colorScheme: wizard.colorScheme - link: "#" - text: qsTr("Report the problem") - visible: certificateInstall.showBugReportLink - } - } - } + Label { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + colorScheme: wizard.colorScheme + horizontalAlignment: Text.AlignHCenter + text: qsTr("Install the profile") + type: Label.LabelType.Title + wrapMode: Text.WordWrap + } + Label { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + color: colorScheme.text_weak + colorScheme: wizard.colorScheme + horizontalAlignment: Text.AlignHCenter + text: qsTr("A system pop-up will appear. Double click on the entry with your email, and click ’Install’ in the dialog that appears.") + type: Label.LabelType.Body + wrapMode: Text.WordWrap } } - // stack index 1 - Item { - id: profileInstall - - property bool profilePaneLaunched: false - - function reset() { - profilePaneLaunched = false; - } - - Layout.fillHeight: true + Image { + Layout.alignment: Qt.AlignHCenter + height: 102 + source: "/qml/icons/img-macos-profile-screenshot.png" + width: 364 + } + ColumnLayout { Layout.fillWidth: true + spacing: ProtonStyle.wizard_spacing_medium - ColumnLayout { - anchors.left: parent.left - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - spacing: ProtonStyle.wizard_spacing_large + Button { + Layout.fillWidth: true + colorScheme: wizard.colorScheme + text: profilePaneLaunched ? qsTr("I have installed the profile") : qsTr("Install the profile") - ColumnLayout { - Layout.fillWidth: true - spacing: ProtonStyle.wizard_spacing_medium - - Label { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - colorScheme: wizard.colorScheme - horizontalAlignment: Text.AlignHCenter - text: qsTr("Install the profile") - type: Label.LabelType.Title - wrapMode: Text.WordWrap - } - Label { - Layout.alignment: Qt.AlignHCenter - Layout.fillWidth: true - color: colorScheme.text_weak - colorScheme: wizard.colorScheme - horizontalAlignment: Text.AlignHCenter - text: qsTr("A system pop-up will appear. Double click on the entry with your email, and click ’Install’ in the dialog that appears.") - type: Label.LabelType.Body - wrapMode: Text.WordWrap + onClicked: { + if (profilePaneLaunched) { + wizard.showClientConfigEnd(); + } else { + wizard.user.configureAppleMail(wizard.address); + profilePaneLaunched = true; } } - Image { - Layout.alignment: Qt.AlignHCenter - height: 102 - source: "/qml/icons/img-macos-profile-screenshot.png" - width: 364 - } - ColumnLayout { - Layout.fillWidth: true - spacing: ProtonStyle.wizard_spacing_medium + } + Button { + Layout.fillWidth: true + colorScheme: wizard.colorScheme + secondary: true + text: qsTr("Cancel") - Button { - Layout.fillWidth: true - colorScheme: wizard.colorScheme - text: profileInstall.profilePaneLaunched ? qsTr("I have installed the profile") : qsTr("Install the profile") - - onClicked: { - if (profileInstall.profilePaneLaunched) { - wizard.showClientConfigEnd(); - } else { - wizard.user.configureAppleMail(wizard.address); - profileInstall.profilePaneLaunched = true; - } - } - } - Button { - Layout.fillWidth: true - colorScheme: wizard.colorScheme - secondary: true - text: qsTr("Cancel") - - onClicked: { - wizard.closeWizard(); - } - } + onClicked: { + wizard.closeWizard(); } } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigCertInstall.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigCertInstall.qml new file mode 100644 index 00000000..1ac498b0 --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigCertInstall.qml @@ -0,0 +1,153 @@ +// Copyright (c) 2024 Proton AG +// This file is part of Proton Mail Bridge. +// Proton Mail 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. +// Proton Mail 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 Proton Mail Bridge. If not, see . + +import QtQml +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +Item { + id: root + + property string errorString: "" + property bool showBugReportLink: false + property bool waitingForCert: false + property var wizard + + function clearError() { + errorString = ""; + showBugReportLink = false; + } + function reset() { + waitingForCert = false; + clearError(); + } + + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + spacing: ProtonStyle.wizard_spacing_large + + Connections { + function onCertificateInstallCanceled() { + root.waitingForCert = false; + root.errorString = qsTr("%1 cannot be configured if you do not install the certificate. Please retry.").arg(wizard.clientName()); + root.showBugReportLink = false; + } + function onCertificateInstallFailed() { + root.waitingForCert = false; + root.errorString = qsTr("An error occurred while installing the certificate."); + root.showBugReportLink = true; + } + + + target: Backend + } + ColumnLayout { + Layout.fillWidth: true + spacing: ProtonStyle.wizard_spacing_medium + + Label { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + colorScheme: wizard.colorScheme + horizontalAlignment: Text.AlignHCenter + text: qsTr("Install the bridge certificate") + type: Label.LabelType.Title + wrapMode: Text.WordWrap + } + Label { + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + color: colorScheme.text_weak + colorScheme: wizard.colorScheme + horizontalAlignment: Text.AlignHCenter + text: qsTr("After clicking on the button below, a system pop-up will ask you for your credentials, please enter your macOS user credentials (not your Proton account’s) and validate.") + type: Label.LabelType.Body + wrapMode: Text.WordWrap + } + } + Image { + Layout.alignment: Qt.AlignHCenter + height: 182 + opacity: root.waitingForCert ? 0.3 : 1.0 + source: "/qml/icons/img-macos-cert-screenshot.png" + width: 140 + } + ColumnLayout { + Layout.fillWidth: true + spacing: ProtonStyle.wizard_spacing_medium + + Button { + Layout.fillWidth: true + colorScheme: wizard.colorScheme + enabled: !root.waitingForCert + loading: root.waitingForCert + text: qsTr("Install the certificate") + + onClicked: { + root.clearError(); + root.waitingForCert = true; + Backend.installTLSCertificate(); + } + } + Button { + Layout.fillWidth: true + colorScheme: wizard.colorScheme + enabled: !root.waitingForCert + secondary: true + text: qsTr("Cancel") + + onClicked: { + wizard.closeWizard(); + } + } + ColumnLayout { + Layout.fillWidth: true + spacing: ProtonStyle.wizard_spacing_small + + RowLayout { + Layout.fillWidth: true + spacing: ProtonStyle.wizard_spacing_extra_small + + ColorImage { + color: wizard.colorScheme.signal_danger + height: errorLabel.lineHeight + source: "/qml/icons/ic-exclamation-circle-filled.svg" + sourceSize.height: errorLabel.lineHeight + visible: root.errorString.length > 0 + } + Label { + id: errorLabel + Layout.fillWidth: true + color: wizard.colorScheme.signal_danger + colorScheme: wizard.colorScheme + horizontalAlignment: Text.AlignHCenter + text: root.errorString + type: Label.LabelType.Body_semibold + wrapMode: Text.WordWrap + } + } + LinkLabel { + Layout.alignment: Qt.AlignHCenter + callback: wizard.showBugReport + colorScheme: wizard.colorScheme + link: "#" + text: qsTr("Report the problem") + visible: root.showBugReportLink + } + } + } + } +} \ No newline at end of file diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigSelector.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigSelector.qml index 2a309624..5ee0fa71 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigSelector.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/ClientConfigSelector.qml @@ -47,6 +47,10 @@ Item { onClicked: { wizard.client = SetupWizard.Client.AppleMail; + if (!Backend.isTLSCertificateInstalled()) { + wizard.showCertInstall(); + return + } wizard.showAppleMailAutoConfig(); } } @@ -59,6 +63,10 @@ Item { onClicked: { wizard.client = SetupWizard.Client.MicrosoftOutlook; + if (root.onMacOS && !Backend.isTLSCertificateInstalled()) { + wizard.showCertInstall(); + return + } wizard.showClientParams(); } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/LeftPane.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/LeftPane.qml index 640e5622..4e193959 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/LeftPane.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/LeftPane.qml @@ -34,13 +34,23 @@ Item { signal startSetup() - function showAppleMailAutoconfigCertificateInstall() { - showAppleMailAutoconfigCommon(); - descriptionLabel.text = qsTr("Apple Mail configuration is mostly automated, but in order to work, Bridge needs to install a certificate in your keychain."); - linkLabel1.setCallback(function() { Backend.openExternalLink("https://proton.me/support/apple-mail-certificate"); }, qsTr("Why is this certificate needed?"), true); + function showCertificateInstall() { + showClientConfigCommon(); + if (wizard.client === SetupWizard.Client.AppleMail) { + descriptionLabel.text = qsTr("Apple Mail configuration is mostly automated, but in order to work, Bridge needs to install a certificate in your keychain."); + linkLabel1.setCallback(function () { + Backend.openExternalLink("https://proton.me/support/apple-mail-certificate"); + }, qsTr("Why is this certificate needed?"), true); + } else { + descriptionLabel.text = qsTr("In order for Outlook to work, Bridge needs to install a certificate in your keychain."); + linkLabel1.setCallback(function () { + Backend.openExternalLink("https://proton.me/support/apple-mail-certificate"); + }, qsTr("Why is this certificate needed?"), true); + } linkLabel2.clear(); } - function showAppleMailAutoconfigCommon() { + + function showClientConfigCommon() { titleLabel.text = ""; linkLabel1.clear(); linkLabel2.clear(); @@ -49,7 +59,7 @@ Item { iconWidth = 80; } function showAppleMailAutoconfigProfileInstall() { - showAppleMailAutoconfigCommon(); + showClientConfigCommon(); descriptionLabel.text = qsTr("The final step before you can start using Apple Mail is to install the Bridge server profile in the system preferences.\n\nAdding a server profile is necessary to ensure that your Mac can receive and send Proton Mails."); linkLabel1.setCallback(function() { Backend.openExternalLink("https://proton.me/support/macos-certificate-warning"); }, qsTr("Why is there a yellow warning sign?"), true); linkLabel2.setCallback(wizard.showClientParams, qsTr("Configure Apple Mail manually"), false); diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/SetupWizard.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/SetupWizard.qml index bde35906..d10b98eb 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/SetupWizard.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupWizard/SetupWizard.qml @@ -27,6 +27,7 @@ Item { Onboarding, Login, ClientConfigSelector, + ClientConfigCertInstall, ClientConfigAppleMail } enum RootStack { @@ -96,7 +97,7 @@ Item { backAction = _showClientConfig; rootStackLayout.currentIndex = SetupWizard.RootStack.TwoPanesView; rightContent.currentIndex = SetupWizard.ContentStack.ClientConfigAppleMail; - clientConfigAppleMail.showAutoconfig(); // This will trigger signals that will display the appropriate left content. + leftContent.showAppleMailAutoconfigProfileInstall(); } function showBugReport() { closeWizard(); @@ -118,6 +119,15 @@ Item { backAction = _showClientConfig; rootStackLayout.currentIndex = SetupWizard.RootStack.ClientConfigParameters; } + + function showCertInstall() { + backAction = _showClientConfig; + clientConfigCertInstall.reset(); + rootStackLayout.currentIndex = SetupWizard.RootStack.TwoPanesView; + leftContent.showCertificateInstall() + rightContent.currentIndex = SetupWizard.ContentStack.ClientConfigCertInstall; + } + function showLogin(username = "") { backAction = null; rootStackLayout.currentIndex = SetupWizard.RootStack.TwoPanesView; @@ -146,7 +156,13 @@ Item { let address = user ? user.addresses[0] : ""; showClientConfig(user, address, true); } - + function onCertificateInstallSuccess() { + if (client === SetupWizard.Client.MicrosoftOutlook) { + showClientParams() + } else { + showAppleMailAutoConfig() + } + } target: Backend } StackLayout { @@ -176,17 +192,6 @@ Item { width: ProtonStyle.wizard_pane_width wizard: root - Connections { - function onAppleMailAutoconfigCertificateInstallPageShown() { - leftContent.showAppleMailAutoconfigCertificateInstall(); - } - function onAppleMailAutoconfigProfileInstallPageShow() { - leftContent.showAppleMailAutoconfigProfileInstall(); - } - - target: clientConfigAppleMail - } - Connections { function onLogin2FARequested() { leftContent.showLogin2FA(); @@ -247,6 +252,13 @@ Item { id: clientConfigSelector wizard: root } + + // rightContent stack index 2 + ClientConfigCertInstall { + id: clientConfigCertInstall + wizard: root + } + // rightContent stack index 3 ClientConfigAppleMail { id: clientConfigAppleMail