379 lines
13 KiB
QML
379 lines
13 KiB
QML
// 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 <https://www.gnu.org/licenses/>.
|
|
|
|
// This is main qml file
|
|
|
|
import QtQuick 2.8
|
|
import BridgeUI 1.0
|
|
import ProtonUI 1.0
|
|
|
|
// All imports from dynamic must be loaded before
|
|
import QtQuick.Window 2.2
|
|
import QtQuick.Controls 2.1
|
|
import QtQuick.Layouts 1.3
|
|
|
|
Item {
|
|
id: gui
|
|
property MainWindow winMain
|
|
property bool isFirstWindow: true
|
|
property int warningFlags: 0
|
|
|
|
InfoWindow { id: infoWin }
|
|
OutgoingNoEncPopup { id: outgoingNoEncPopup }
|
|
BugReportWindow {
|
|
id: bugreportWin
|
|
clientVersion.visible : true
|
|
|
|
// pre-fill the form
|
|
onPrefill : {
|
|
userAddress.text=""
|
|
if (accountsModel.count>0) {
|
|
var addressList = accountsModel.get(0).aliases.split(";")
|
|
if (addressList.length>0) {
|
|
userAddress.text = addressList[0]
|
|
}
|
|
}
|
|
clientVersion.text=go.getLastMailClient()
|
|
}
|
|
}
|
|
|
|
onWarningFlagsChanged : {
|
|
if (gui.warningFlags==Style.okInfoBar) {
|
|
go.normalSystray()
|
|
return
|
|
}
|
|
|
|
if ((gui.warningFlags & Style.errorInfoBar) == Style.errorInfoBar) {
|
|
go.errorSystray()
|
|
return
|
|
}
|
|
|
|
go.highlightSystray()
|
|
}
|
|
|
|
// Signals from Go
|
|
Connections {
|
|
target: go
|
|
|
|
onShowWindow : {
|
|
gui.openMainWindow()
|
|
}
|
|
onShowHelp : {
|
|
gui.openMainWindow(false)
|
|
winMain.tabbar.currentIndex = 2
|
|
winMain.showAndRise()
|
|
}
|
|
onShowQuit : {
|
|
gui.openMainWindow(false)
|
|
winMain.dialogGlobal.state="quit"
|
|
winMain.dialogGlobal.show()
|
|
winMain.showAndRise()
|
|
}
|
|
|
|
onProcessFinished : {
|
|
winMain.dialogGlobal.hide()
|
|
winMain.dialogAddUser.hide()
|
|
winMain.dialogChangePort.hide()
|
|
infoWin.hide()
|
|
}
|
|
onOpenManual : Qt.openUrlExternally("http://protonmail.com/bridge")
|
|
|
|
onNotifyBubble : {
|
|
gui.showBubble(tabIndex, message, true)
|
|
}
|
|
onSilentBubble : {
|
|
gui.showBubble(tabIndex, message, false)
|
|
}
|
|
onBubbleClosed : {
|
|
gui.warningFlags &= ~Style.warnBubbleMessage
|
|
}
|
|
|
|
onSetConnectionStatus: {
|
|
go.isConnectionOK = isAvailable
|
|
gui.openMainWindow(false)
|
|
if (go.isConnectionOK) {
|
|
if( winMain.updateState=="noInternet") {
|
|
go.updateState = "upToDate"
|
|
}
|
|
} else {
|
|
go.updateState = "noInternet"
|
|
}
|
|
}
|
|
|
|
onUpdateStateChanged : {
|
|
// Update tray icon if needed
|
|
switch (go.updateState) {
|
|
case "internetCheck":
|
|
break;
|
|
case "noInternet" :
|
|
gui.warningFlags |= Style.warnInfoBar
|
|
break;
|
|
case "oldVersion":
|
|
gui.warningFlags |= Style.warnInfoBar
|
|
break;
|
|
case "forceUpdate":
|
|
// Force update should presist once it happened and never be overwritten.
|
|
// That means that tray icon should allways remain in error state.
|
|
// But since we have only two sources of error icon in tray (force update
|
|
// + installation fail) and both are unrecoverable and we do not ever remove
|
|
// error flag from gui.warningFlags - it is ok to rely on gui.warningFlags and
|
|
// not on winMain.updateState (which presist forceUpdate)
|
|
gui.warningFlags |= Style.errorInfoBar
|
|
break;
|
|
case "upToDate":
|
|
gui.warningFlags &= ~Style.warnInfoBar
|
|
break;
|
|
case "updateRestart":
|
|
gui.warningFlags |= Style.warnInfoBar
|
|
break;
|
|
case "updateError":
|
|
gui.warningFlags |= Style.errorInfoBar
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
|
|
// if main window is closed - most probably it is destroyed (see closeMainWindow())
|
|
if (winMain == null) {
|
|
return
|
|
}
|
|
// once app is outdated prevent from state change
|
|
if (winMain.updateState != "forceUpdate") {
|
|
winMain.updateState = go.updateState
|
|
}
|
|
}
|
|
|
|
onSetAddAccountWarning : winMain.dialogAddUser.setWarning(message, 0)
|
|
|
|
|
|
onNotifyVersionIsTheLatest : {
|
|
go.silentBubble(2,qsTr("You have the latest version!", "notification", -1))
|
|
}
|
|
|
|
onNotifyManualUpdate: {
|
|
go.updateState = "oldVersion"
|
|
}
|
|
|
|
onNotifyManualUpdateRestartNeeded: {
|
|
if (!winMain.dialogUpdate.visible) {
|
|
winMain.dialogUpdate.show()
|
|
}
|
|
go.updateState = "updateRestart"
|
|
winMain.dialogUpdate.finished(false)
|
|
|
|
// after manual update - just retart immidiatly
|
|
go.setToRestart()
|
|
Qt.quit()
|
|
}
|
|
|
|
onNotifyManualUpdateError: {
|
|
if (!winMain.dialogUpdate.visible) {
|
|
winMain.dialogUpdate.show()
|
|
}
|
|
go.updateState = "updateError"
|
|
winMain.dialogUpdate.finished(true)
|
|
}
|
|
|
|
onNotifyForceUpdate : {
|
|
go.updateState = "forceUpdate"
|
|
if (!winMain.dialogUpdate.visible) {
|
|
winMain.dialogUpdate.show()
|
|
}
|
|
}
|
|
|
|
onNotifySilentUpdateRestartNeeded: {
|
|
go.updateState = "updateRestart"
|
|
}
|
|
|
|
onNotifySilentUpdateError: {
|
|
go.updateState = "updateError"
|
|
}
|
|
|
|
onNotifyLogout : {
|
|
go.notifyBubble(0, qsTr("Account %1 has been disconnected. Please log in to continue to use the Bridge with this account.").arg(accname) )
|
|
}
|
|
|
|
onNotifyAddressChanged : {
|
|
go.notifyBubble(0, qsTr("The address list has been changed for account %1. You may need to reconfigure the settings in your email client.").arg(accname) )
|
|
}
|
|
|
|
onNotifyAddressChangedLogout : {
|
|
go.notifyBubble(0, qsTr("The address list has been changed for account %1. You have to reconfigure the settings in your email client.").arg(accname) )
|
|
}
|
|
|
|
onNotifyPortIssue : { // busyPortIMAP , busyPortSMTP
|
|
if (!busyPortIMAP && !busyPortSMTP) { // at least one must have issues to show warning
|
|
return
|
|
}
|
|
gui.openMainWindow(false)
|
|
winMain.tabbar.currentIndex=1
|
|
go.isDefaultPort = false
|
|
var text
|
|
if (busyPortIMAP && busyPortSMTP) { // both have problems
|
|
text = qsTr("The default ports used by Bridge for IMAP (%1) and SMTP (%2) are occupied by one or more other applications." , "the first part of notification text (two ports)").arg(go.getIMAPPort()).arg(go.getSMTPPort())
|
|
text += " "
|
|
text += qsTr("To change the ports for these servers, go to Settings -> Advanced Settings.", "the second part of notification text (two ports)")
|
|
} else { // only one is occupied
|
|
var server, port
|
|
if (busyPortSMTP) {
|
|
server = "SMTP"
|
|
port = go.getSMTPPort()
|
|
} else {
|
|
server = "IMAP"
|
|
port = go.getIMAPPort()
|
|
}
|
|
text = qsTr("The default port used by Bridge for %1 (%2) is occupied by another application.", "the first part of notification text (one port)").arg(server).arg(port)
|
|
text += " "
|
|
text += qsTr("To change the port for this server, go to Settings -> Advanced Settings.", "the second part of notification text (one port)")
|
|
}
|
|
go.notifyBubble(1, text )
|
|
}
|
|
|
|
onNotifyKeychainRebuild : {
|
|
go.notifyBubble(1, qsTr(
|
|
"Your MacOS keychain is probably corrupted. Please consult the instructions in our <a href=\"https://protonmail.com/bridge/faq#c15\">FAQ</a>.",
|
|
"notification message"
|
|
))
|
|
}
|
|
|
|
onNotifyHasNoKeychain : {
|
|
gui.winMain.dialogGlobal.state="noKeychain"
|
|
gui.winMain.dialogGlobal.show()
|
|
}
|
|
|
|
onShowNoActiveKeyForRecipient : {
|
|
go.notifyBubble(0, qsTr(
|
|
"Key pinning is enabled for %1 but no active key is pinned. " +
|
|
"You must pin the key in order to send a message to this address. " +
|
|
"You can find instructions " +
|
|
"<a href=\"https://protonmail.com/support/knowledge-base/key-pinning/\">here</a>."
|
|
).arg(recipient))
|
|
}
|
|
|
|
onFailedAutostartCode : {
|
|
gui.openMainWindow(true)
|
|
switch (code) {
|
|
case "permission" : // linux+darwin
|
|
case "85070005" : // windows
|
|
go.notifyBubble(1, go.failedAutostartPerm)
|
|
break
|
|
case "81004003" : // windows
|
|
go.notifyBubble(1, go.failedAutostart+" "+qsTr("Can not create instance.", "for autostart"))
|
|
break
|
|
case "" :
|
|
default :
|
|
go.notifyBubble(1, go.failedAutostart)
|
|
}
|
|
}
|
|
|
|
onShowOutgoingNoEncPopup : {
|
|
outgoingNoEncPopup.show(messageID, subject)
|
|
}
|
|
|
|
onSetOutgoingNoEncPopupCoord : {
|
|
outgoingNoEncPopup.x = x
|
|
outgoingNoEncPopup.y = y
|
|
}
|
|
|
|
onShowCertIssue : {
|
|
winMain.tlsBarState="notOK"
|
|
}
|
|
|
|
onOpenReleaseNotesExternally: {
|
|
Qt.openUrlExternally(go.updateReleaseNotesLink)
|
|
}
|
|
|
|
}
|
|
|
|
function openMainWindow(showAndRise) {
|
|
// wait and check until font is loaded
|
|
while(true){
|
|
if (Style.fontawesome.status == FontLoader.Loading) continue
|
|
if (Style.fontawesome.status != FontLoader.Ready) console.log("Error while loading font")
|
|
break
|
|
}
|
|
|
|
if (typeof(showAndRise)==='undefined') {
|
|
showAndRise = true
|
|
}
|
|
if (gui.winMain == null) {
|
|
gui.winMain = Qt.createQmlObject(
|
|
'import BridgeUI 1.0; MainWindow {visible : false}',
|
|
gui, "winMain"
|
|
)
|
|
}
|
|
if (showAndRise) {
|
|
gui.winMain.showAndRise()
|
|
}
|
|
|
|
// restore update notification bar: trigger updateStateChanged
|
|
var tmp = go.updateState
|
|
go.updateState = ""
|
|
go.updateState = tmp
|
|
}
|
|
|
|
function closeMainWindow () {
|
|
// Historical reasons: once upon a time there was a report about high GPU
|
|
// usage on MacOS while bridge is closed. Legends say that destroying
|
|
// MainWindow solved this.
|
|
gui.winMain.hide()
|
|
gui.winMain.destroy(5000)
|
|
gui.winMain = null
|
|
gui.isFirstWindow = false
|
|
}
|
|
|
|
function showBubble(tabIndex, message, isWarning) {
|
|
gui.openMainWindow(true)
|
|
if (isWarning) {
|
|
gui.warningFlags |= Style.warnBubbleMessage
|
|
}
|
|
winMain.bubbleNote.text = message
|
|
winMain.bubbleNote.place(tabIndex)
|
|
winMain.bubbleNote.show()
|
|
}
|
|
|
|
function openReleaseNotes(){
|
|
if (go.updateReleaseNotesLink == "") {
|
|
go.checkAndOpenReleaseNotes()
|
|
return
|
|
}
|
|
go.openReleaseNotesExternally()
|
|
}
|
|
|
|
|
|
// On start
|
|
Component.onCompleted : {
|
|
// set messages for translations
|
|
go.wrongCredentials = qsTr("Incorrect username or password." , "notification", -1)
|
|
go.wrongMailboxPassword = qsTr("Incorrect mailbox password." , "notification", -1)
|
|
go.canNotReachAPI = qsTr("Cannot contact server, please check your internet connection." , "notification", -1)
|
|
go.versionCheckFailed = qsTr("Version check was unsuccessful. Please try again later." , "notification", -1)
|
|
go.credentialsNotRemoved = qsTr("Credentials could not be removed." , "notification", -1)
|
|
go.failedAutostartPerm = qsTr("Unable to configure automatic start due to permissions settings - see <a href=\"https://protonmail.com/bridge/faq#c11\">FAQ</a> for details.", "notification", -1)
|
|
go.failedAutostart = qsTr("Unable to configure automatic start." , "notification", -1)
|
|
go.genericErrSeeLogs = qsTr("An error happened during procedure. See logs for more details." , "notification", -1)
|
|
|
|
go.guiIsReady()
|
|
|
|
// start window
|
|
gui.openMainWindow(false)
|
|
if (go.isShownOnStart) {
|
|
gui.winMain.showAndRise()
|
|
}
|
|
}
|
|
}
|