feat(GODT-2772): implemented internal help links.

This commit is contained in:
Xavier Michelon
2023-09-01 08:43:05 +02:00
parent ea26dc0e97
commit 5d4f8f7d40
14 changed files with 142 additions and 30 deletions

View File

@ -1099,6 +1099,28 @@ void QMLBackend::setUpdateTrayIcon(QString const &stateString, QString const &st
}
//****************************************************************************************************************************************************
/// \param[in] helpFileName The name of the help file with extension (e.g. "WhyBridge.html").
//****************************************************************************************************************************************************
void QMLBackend::showHelpOverlay(QString const &helpFileName) {
QDir const basePath(":/qml/Resources/Help");
QString const templatePath = basePath.filePath("Template.html");
QFile templateFile(templatePath);
if (!templateFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
app().log().error("Could not load help overlay HTML template");
return;
}
QFile helpFile(basePath.filePath(helpFileName));
if (!helpFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
app().log().error(QString("Could not load help overlay HTML file %1").arg(helpFileName));
return;
}
emit showWebFrameOverlayHTML(QString::fromUtf8(templateFile.readAll()).arg(QString::fromUtf8(helpFile.readAll())));
}
//****************************************************************************************************************************************************
/// \param[in] isOn Does bridge consider internet as on.
//****************************************************************************************************************************************************

View File

@ -211,6 +211,7 @@ public slots: // slots for functions that need to be processed locally.
void setErrorTrayIcon(QString const& stateString, QString const &statusIcon); ///< Set the tray icon to 'error' state.
void setWarnTrayIcon(QString const& stateString, QString const &statusIcon); ///< Set the tray icon to 'warn' state.
void setUpdateTrayIcon(QString const& stateString, QString const &statusIcon); ///< Set the tray icon to 'update' state.
void showHelpOverlay(QString const &helpFileName); ///< Slot triggering the display of help content as an overlay.
public slots: // slot for signals received from gRPC that need transformation instead of simple forwarding
void internetStatusChanged(bool isOn); ///< Check if bridge considers internet as on.
@ -279,6 +280,7 @@ signals: // Signals received from the Go backend, to be forwarded to QML
void showSettings(); ///< Signal for the 'showHelp' event (from the context menu).
void showWebFrameWindow(QString const &url); ///< Signal the the 'showWebFrameWindow' event
void showWebFrameOverlay(QString const &url); ////< Signal for the 'showWebFrameOverlay' event.
void showWebFrameOverlayHTML(QString const &html); ///< Signal to display HTML content in a web frame overlay.
void selectUser(QString const& userID, bool forceShowWindow); ///< Signal emitted in order to selected a user with a given ID in the list.
void genericError(QString const &title, QString const &description); ///< Signal for the 'genericError' gRPC stream event.
void imapLoginWhileSignedOut(QString const& username); ///< Signal for the notification of IMAP login attempt on a signed out account.

View File

@ -110,6 +110,10 @@
<file>qml/Proton/WebFrame.qml</file>
<file>qml/QuestionItem.qml</file>
<file>qml/Resources/bug_report_flow.json</file>
<file>qml/Resources/Help/Template.html</file>
<file>qml/Resources/Help/WhyBridge.html</file>
<file>qml/Resources/Help/WhyCertificate.html</file>
<file>qml/Resources/Help/WhyProfileWarning.html</file>
<file>qml/SettingsItem.qml</file>
<file>qml/SettingsView.qml</file>
<file>qml/SetupWizard/ClientListItem.qml</file>

View File

@ -53,6 +53,9 @@ QtObject {
function onShowWebFrameOverlay(url) {
mainWindow.showWebFrameOverlay(url);
}
function onShowWebFrameOverlayHTML(html) {
mainWindow.showWebFrameOverlayHTML(html)
}
function onShowWebFrameWindow(url) {
webFrameWindow.url = url;
webFrameWindow.show();

View File

@ -72,6 +72,11 @@ ApplicationWindow {
webFrameOverlay.url = url;
}
function showWebFrameOverlayHTML(html) {
webFrameOverlay.loadHTML(html);
webFrameOverlay.visible = true;
}
colorScheme: ProtonStyle.currentStyle
height: ProtonStyle.window_default_height
minimumHeight:ProtonStyle.window_minimum_height
@ -176,9 +181,6 @@ ApplicationWindow {
onWizardEnded: {
contentLayout.currentIndex = 0;
}
onShowUnderConstruction: {
webFrameOverlay.showUnderConstruction();
}
}
}
WebFrame {

View File

@ -363,10 +363,11 @@ QtObject {
property int web_view_button_width: 320
property int web_view_corner_radius: 10
property int web_view_overlay_button_vertical_margin: 10
property int web_view_overlay_horizontal_margin: 10
property int web_view_overlay_margin: 50
property int web_view_overlay_horizontal_padding: 10
property int web_view_overlay_horizontal_margin: 250
property int web_view_overlay_vertical_margin: 50
property real web_view_overlay_opacity: 0.6
property int web_view_overlay_vertical_margin: web_view_corner_radius
property int web_view_overlay_vertical_padding: web_view_corner_radius
property int web_view_overley_border_width: 1
property int window_default_height: 780

View File

@ -27,15 +27,8 @@ Item {
function showBlankPage() {
webView.loadHtml("<!doctype html><meta charset=utf-8><title>blank</title>", "");
}
function showUnderConstruction() {
webView.loadHtml(`
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Coming soon</title><style> body { background-color: #888; font-family: sans-serif; } p { font-weight: bold; margin-top: 100px; text-align: center; }</style></head>
<body><p>The content of this page is under construction.</p></body></html>
`, "")
root.visible = true;
function loadHTML(html) {
webView.loadHtml(html)
}
Rectangle {
@ -46,16 +39,19 @@ Item {
}
Rectangle {
anchors.fill: parent
anchors.margins: overlay ? ProtonStyle.web_view_overlay_margin : 0
anchors.bottomMargin: overlay ? ProtonStyle.web_view_overlay_vertical_margin : 0
anchors.leftMargin: overlay ? ProtonStyle.web_view_overlay_horizontal_margin : 0
anchors.rightMargin: overlay ? ProtonStyle.web_view_overlay_horizontal_margin : 0
anchors.topMargin: overlay ? ProtonStyle.web_view_overlay_vertical_margin : 0
color: root.colorScheme.background_norm
radius: ProtonStyle.web_view_corner_radius
ColumnLayout {
anchors.bottomMargin: 0
anchors.fill: parent
anchors.leftMargin: overlay ? ProtonStyle.web_view_overlay_horizontal_margin : 0
anchors.rightMargin: overlay ? ProtonStyle.web_view_overlay_horizontal_margin : 0
anchors.topMargin: overlay ? ProtonStyle.web_view_overlay_vertical_margin : 0
anchors.leftMargin: overlay ? ProtonStyle.web_view_overlay_horizontal_padding : 0
anchors.rightMargin: overlay ? ProtonStyle.web_view_overlay_horizontal_padding : 0
anchors.topMargin: overlay ? ProtonStyle.web_view_overlay_vertical_padding : 0
spacing: 0
Rectangle {

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body {font-family: sans-serif}
h1 { font-size: 1.5em; text-align: center; margin-bottom: 2em;}
p {text-align: justify; margin-bottom: 2em; }
p.standfirst { font-weight: bold;}
</style>
</head>
<body>
%1
</body>
</html>

View File

@ -0,0 +1,19 @@
<h1>Why do I need bridge?</h1>
<p class="standfirst">
Proton does not have access to the content of your messages, so it cannot share your unencrypted messages with your email client from the
Proton servers.
</p>
<p>
Email clients such as Microsoft Outlook, Mozilla Thunderbird and Apple Mail use standard protocols named IMAP and SMTP to receive and send emails.
</p>
<p>
Even though the IMAP and SMTP protocols can use secure channels (using SSL/TLS), they do not offer support for encrypted messages.
Because Proton does not have access to the content of your messages, it is not possible to configure your email client to connect directly to
Proton servers.
</p>
<p>
The key to solving this problem is Bridge. Once installed on your computer and connected to your Proton account, Bridge can access your
encrypted messages stored on the Proton servers. Bridge integrates an IMAP and a SMTP server that run on your computer and are accessible only
to applications executing on your machine. Your email client connects to these local servers and Bridge is responsible for seamlessly encrypting
and decrypting the messages that you send and receive.
</p>

View File

@ -0,0 +1,19 @@
<h1>Why do I need to install a certificate when configuring Apple Mail with Bridge?</h1>
<p class="standfirst">
Apple Mail requires a secure channel for communications with email servers, and the server needs to be acknowledged as trusted.
</p>
<p>
In order to communicate with Bridge, Apple Mail requires secure connections using SSL/TLS. This cryptographic protocol includes an identity
verification system using certificates. For publicly available servers, certificates are normally issued and digitally signed by a certificate
authority, such as Let's Encrypt. This is not possible for Bridge, as the IMAP and SMTP servers are running on your own computer, and are not
accessible from any network (local or internet).
</p>
<p>
The solution is to use a self-signed certificate. When setting up an email account where the server provides a self-signed certificate, most
email clients will issue a warning asking you whether you trust the server or not, because the certificate was not issued by a certificate
authority.
</p>
<p>
Apple Mail requires an extra step. It will simply refuse to connect if the certificate is not set as trusted. Bridge solves this by storing this
certificate in the macOS keychain. This operation requires that you provide your macOS account password.
</p>

View File

@ -0,0 +1,21 @@
<h1>Why is there a warning sign when installing the Bridge profile on macOS?</h1>
<p class="standfirst">
This warning indicates that the certificate used to secure the communication channel between Bridge and your email client is not signed by a
trusted third party.
</p>
<p>
In order to communicate with Bridge, Apple Mail requires secure connections using SSL/TLS. This cryptographic protocol includes an identity
verification system using certificates. For publicly available servers, certificates are normally issued and digitally signed by a certificate
authority, such as Let's Encrypt. This is not possible for Bridge, as the IMAP and SMTP servers are running on your own computer, and are not
accessible from any network (local or internet).
</p>
<p>
The solution is to use a self-signed certificate. When setting up an email account where the server provides a self-signed certificate, most
email clients will issue a warning asking you whether you trust the server or not, because the certificate was not issued by a certificate
authority. The client has no way of verifying that the server is who it pretends to be.
</p>
<p>
You can safely ignore this warning. The check concerns only the communication between your email client and Bridge, which occurs within your
computer. On the other end, the communication between Bridge and the Proton servers uses the HTTPS protocol, and the identity of the remote
server is verified by Bridge.
</p>

View File

@ -28,7 +28,6 @@ Item {
signal appleMailAutoconfigProfileInstallPageShow
function showAutoconfig() {
certificateInstall.waitingForCert = false;
if (Backend.isTLSCertificateInstalled()) {
showProfileInstall();
} else {
@ -41,6 +40,7 @@ Item {
appleMailAutoconfigCertificateInstallPageShown();
}
function showProfileInstall() {
profileInstall.reset();
stack.currentIndex = ClientConfigAppleMail.Screen.ProfileInstall;
appleMailAutoconfigProfileInstallPageShow();
}
@ -193,6 +193,13 @@ Item {
// stack index 1
Item {
id: profileInstall
property bool profilePaneLaunched: false
function reset() {
profilePaneLaunched = false;
}
Layout.fillHeight: true
Layout.fillWidth: true
@ -239,11 +246,15 @@ Item {
Button {
Layout.fillWidth: true
colorScheme: wizard.colorScheme
text: qsTr("Install the profile")
text: profileInstall.profilePaneLaunched ? qsTr("I have installed the profile") : qsTr("Install the profile")
onClicked: {
wizard.user.configureAppleMail(wizard.address);
wizard.showClientConfigEnd();
if (profileInstall.profilePaneLaunched) {
wizard.showClientConfigEnd();
} else {
wizard.user.configureAppleMail(wizard.address);
profileInstall.profilePaneLaunched = true;
}
}
}
Button {

View File

@ -26,7 +26,7 @@ Item {
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(showUnderConstruction, qsTr("Why is this certificate needed?"), false);
linkLabel1.setCallback(function() { Backend.showHelpOverlay("WhyCertificate.html"); }, qsTr("Why is this certificate needed?"), false);
}
function showAppleMailAutoconfigCommon() {
titleLabel.text = "";
@ -39,7 +39,7 @@ Item {
function showAppleMailAutoconfigProfileInstall() {
showAppleMailAutoconfigCommon();
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(showUnderConstruction, qsTr("Why is there a yellow warning sign?"), false);
linkLabel1.setCallback(function() { Backend.showHelpOverlay("WhyProfileWarning.html"); }, qsTr("Why is there a yellow warning sign?"), false);
linkLabel2.setCallback(wizard.showClientParams, qsTr("Configure Apple Mail manually"), false);
}
function showClientSelector(newAccount = true) {
@ -63,15 +63,12 @@ Item {
function showOnboarding() {
titleLabel.text = (Backend.users.count === 0) ? qsTr("Welcome to\nProton Mail Bridge") : qsTr("Add a Proton Mail account");
descriptionLabel.text = qsTr("Bridge is the gateway between your Proton account and your email client. It runs in the background and encrypts and decrypts your messages seamlessly. ");
linkLabel1.setCallback(showUnderConstruction, qsTr("Why do I need Bridge?"), false);
linkLabel1.setCallback(function() { Backend.showHelpOverlay("WhyBridge.html"); }, qsTr("Why do I need Bridge?"), false);
linkLabel2.clear();
root.iconSource = "/qml/icons/img-welcome.svg";
root.iconHeight = 148;
root.iconWidth = 265;
}
function showUnderConstruction() {
wizard.showUnderConstruction();
}
Connections {
function onLogin2FARequested() {

View File

@ -43,7 +43,6 @@ Item {
signal bugReportRequested
signal wizardEnded
signal showUnderConstruction
function _showClientConfig() {
showClientConfig(root.user, root.address, false);