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