419 lines
17 KiB
QML
419 lines
17 KiB
QML
// Copyright (c) 2020 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 ImportExportUI 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 alias winMain: winMain
|
|
property bool isFirstWindow: true
|
|
property int warningFlags: 0
|
|
|
|
property var locale : Qt.locale("en_US")
|
|
property date netBday : new Date("1989-03-13T00:00:00")
|
|
property var allYears : getYearList(1970,(new Date()).getFullYear())
|
|
property var allMonths : getMonthList(1,12)
|
|
property var allDays : getDayList(1,31)
|
|
|
|
property var enums : JSON.parse('{"pathOK":1,"pathEmptyPath":2,"pathWrongPath":4,"pathNotADir":8,"pathWrongPermissions":16,"pathDirEmpty":32,"errUnknownError":0,"errEventAPILogout":1,"errUpdateAPI":2,"errUpdateJSON":3,"errUserAuth":4,"errQApplication":18,"errEmailExportFailed":6,"errEmailExportMissing":7,"errNothingToImport":8,"errEmailImportFailed":12,"errDraftImportFailed":13,"errDraftLabelFailed":14,"errEncryptMessageAttachment":15,"errEncryptMessage":16,"errNoInternetWhileImport":17,"errUnlockUser":5,"errSourceMessageNotSelected":19,"errCannotParseMail":5000,"errWrongLoginOrPassword":5001,"errWrongServerPathOrPort":5002,"errWrongAuthMethod":5003,"errIMAPFetchFailed":5004,"errLocalSourceLoadFailed":1000,"errPMLoadFailed":1001,"errRemoteSourceLoadFailed":1002,"errLoadAccountList":1005,"errExit":1006,"errRetry":1007,"errAsk":1008,"errImportFailed":1009,"errCreateLabelFailed":1010,"errCreateFolderFailed":1011,"errUpdateLabelFailed":1012,"errUpdateFolderFailed":1013,"errFillFolderName":1014,"errSelectFolderColor":1015,"errNoInternet":1016,"folderTypeSystem":"system","folderTypeLabel":"label","folderTypeFolder":"folder","folderTypeExternal":"external","progressInit":"init","progressLooping":"looping","statusNoInternet":"noInternet","statusCheckingInternet":"internetCheck","statusNewVersionAvailable":"oldVersion","statusUpToDate":"upToDate","statusForceUpdate":"forceupdate"}')
|
|
|
|
IEStyle{}
|
|
|
|
MainWindow {
|
|
id: winMain
|
|
|
|
visible : true
|
|
Component.onCompleted: {
|
|
winMain.showAndRise()
|
|
}
|
|
}
|
|
|
|
BugReportWindow {
|
|
id:bugreportWin
|
|
clientVersion.visible: false
|
|
onPrefill : {
|
|
userAddress.text=""
|
|
if (accountsModel.count>0) {
|
|
var addressList = accountsModel.get(0).aliases.split(";")
|
|
if (addressList.length>0) {
|
|
userAddress.text = addressList[0]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Signals from Go
|
|
Connections {
|
|
target: go
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onProcessFinished : {
|
|
winMain.dialogAddUser.hide()
|
|
winMain.dialogGlobal.hide()
|
|
}
|
|
onOpenManual : Qt.openUrlExternally("https://protonmail.com/support/categories/import-export/")
|
|
|
|
onNotifyBubble : {
|
|
//go.highlightSystray()
|
|
winMain.bubleNote.text = message
|
|
winMain.bubleNote.place(tabIndex)
|
|
winMain.bubleNote.show()
|
|
winMain.showAndRise()
|
|
}
|
|
onBubbleClosed : {
|
|
if (winMain.updateState=="uptodate") {
|
|
//go.normalSystray()
|
|
}
|
|
}
|
|
|
|
onSetConnectionStatus: {
|
|
go.isConnectionOK = isAvailable
|
|
if (go.isConnectionOK) {
|
|
if( winMain.updateState==gui.enums.statusNoInternet) {
|
|
go.setUpdateState(gui.enums.statusUpToDate)
|
|
}
|
|
} else {
|
|
go.setUpdateState(gui.enums.statusNoInternet)
|
|
}
|
|
}
|
|
|
|
onRunCheckVersion : {
|
|
go.setUpdateState(gui.enums.statusUpToDate)
|
|
winMain.dialogGlobal.state=gui.enums.statusCheckingInternet
|
|
winMain.dialogGlobal.show()
|
|
go.isNewVersionAvailable(showMessage)
|
|
}
|
|
|
|
onSetUpdateState : {
|
|
// once app is outdated prevent from state change
|
|
if (winMain.updateState != gui.enums.statusForceUpdate) {
|
|
winMain.updateState = updateState
|
|
}
|
|
}
|
|
|
|
onSetAddAccountWarning : winMain.dialogAddUser.setWarning(message, 0)
|
|
|
|
onNotifyVersionIsTheLatest : {
|
|
winMain.popupMessage.show(
|
|
qsTr("You have the latest version!", "todo")
|
|
)
|
|
}
|
|
|
|
onNotifyError : {
|
|
var sep = go.errorDescription.indexOf("\n") < 0 ? go.errorDescription.length : go.errorDescription.indexOf("\n")
|
|
var name = go.errorDescription.slice(0, sep)
|
|
var errorMessage = go.errorDescription.slice(sep)
|
|
switch (errCode) {
|
|
case gui.enums.errPMLoadFailed :
|
|
winMain.popupMessage.show ( qsTr ( "Loading ProtonMail folders and labels was not successful." , "Error message" ) )
|
|
winMain.dialogExport.hide()
|
|
break
|
|
case gui.enums.errLocalSourceLoadFailed :
|
|
winMain.popupMessage.show(qsTr(
|
|
"Loading local folder structure was not successful. "+
|
|
"Folder does not contain valid MBOX or EML file.",
|
|
"Error message when can not find correct files in folder."
|
|
))
|
|
winMain.dialogImport.hide()
|
|
break
|
|
case gui.enums.errRemoteSourceLoadFailed :
|
|
winMain.popupMessage.show ( qsTr ( "Loading remote source structure was not successful." , "Error message" ) )
|
|
winMain.dialogImport.hide()
|
|
break
|
|
case gui.enums.errWrongServerPathOrPort :
|
|
winMain.popupMessage.show ( qsTr ( "Cannot contact server - incorrect server address and port." , "Error message" ) )
|
|
winMain.dialogImport.decrementCurrentIndex()
|
|
break
|
|
case gui.enums.errWrongLoginOrPassword :
|
|
winMain.popupMessage.show ( qsTr ( "Cannot authenticate - Incorrect email or password." , "Error message" ) )
|
|
winMain.dialogImport.decrementCurrentIndex()
|
|
break ;
|
|
case gui.enums.errWrongAuthMethod :
|
|
winMain.popupMessage.show ( qsTr ( "Cannot authenticate - Please use secured authentication method." , "Error message" ) )
|
|
winMain.dialogImport.decrementCurrentIndex()
|
|
break ;
|
|
|
|
|
|
case gui.enums.errFillFolderName:
|
|
winMain.popupMessage.show(qsTr (
|
|
"Please fill the name.",
|
|
"Error message when user did not fill the name of folder or label"
|
|
))
|
|
break
|
|
case gui.enums.errCreateLabelFailed:
|
|
winMain.popupMessage.show(qsTr(
|
|
"Cannot create label with name \"%1\"\n%2",
|
|
"Error message when it is not possible to create new label, arg1 folder name, arg2 error reason"
|
|
).arg(name).arg(errorMessage))
|
|
break
|
|
case gui.enums.errCreateFolderFailed:
|
|
winMain.popupMessage.show(qsTr(
|
|
"Cannot create folder with name \"%1\"\n%2",
|
|
"Error message when it is not possible to create new folder, arg1 folder name, arg2 error reason"
|
|
).arg(name).arg(errorMessage))
|
|
break
|
|
|
|
case gui.enums.errNothingToImport:
|
|
winMain.popupMessage.show ( qsTr ( "No emails left to import after date range applied. Please, change the date range to continue." , "Error message" ) )
|
|
winMain.dialogImport.decrementCurrentIndex()
|
|
break
|
|
|
|
case gui.enums.errNoInternetWhileImport:
|
|
case gui.enums.errNoInternet:
|
|
go.setConnectionStatus(false)
|
|
winMain.popupMessage.show ( go.canNotReachAPI )
|
|
break
|
|
|
|
case gui.enums.errPMAPIMessageTooLarge:
|
|
case gui.enums.errIMAPFetchFailed:
|
|
case gui.enums.errEmailImportFailed :
|
|
case gui.enums.errDraftImportFailed :
|
|
case gui.enums.errDraftLabelFailed :
|
|
case gui.enums.errEncryptMessageAttachment:
|
|
case gui.enums.errEncryptMessage:
|
|
//winMain.dialogImport.ask_retry_skip_cancel(name, errorMessage)
|
|
console.log("Import error", errCode, go.errorDescription)
|
|
winMain.popupMessage.show(qsTr("Error during import: \n%1\n please see log files for more details.", "message of generic error").arg(go.errorDescription))
|
|
winMain.dialogImport.hide()
|
|
break;
|
|
|
|
case gui.enums.errUnknownError : default:
|
|
console.log("Unknown Error", errCode, go.errorDescription)
|
|
winMain.popupMessage.show(qsTr("The program encounter an unknown error \n%1\n please see log files for more details.", "message of generic error").arg(go.errorDescription))
|
|
winMain.dialogExport.hide()
|
|
winMain.dialogImport.hide()
|
|
winMain.dialogAddUser.hide()
|
|
winMain.dialogGlobal.hide()
|
|
}
|
|
}
|
|
|
|
onNotifyUpdate : {
|
|
go.setUpdateState("forceUpdate")
|
|
if (!winMain.dialogUpdate.visible) {
|
|
gui.openMainWindow(true)
|
|
go.runCheckVersion(false)
|
|
winMain.dialogUpdate.show()
|
|
}
|
|
}
|
|
|
|
onNotifyLogout : {
|
|
go.notifyBubble(0, qsTr("Account %1 has been disconnected. Please log in to continue to use the Import-Export app 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) )
|
|
}
|
|
|
|
|
|
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()
|
|
}
|
|
|
|
|
|
onExportStructureLoadFinished: {
|
|
if (okay) winMain.dialogExport.okay()
|
|
else winMain.dialogExport.cancel()
|
|
}
|
|
onImportStructuresLoadFinished: {
|
|
if (okay) winMain.dialogImport.okay()
|
|
else winMain.dialogImport.cancel()
|
|
}
|
|
|
|
onSimpleErrorHappen: {
|
|
if (winMain.dialogImport.visible == true) {
|
|
winMain.dialogImport.hide()
|
|
}
|
|
if (winMain.dialogExport.visible == true) {
|
|
winMain.dialogExport.hide()
|
|
}
|
|
}
|
|
}
|
|
|
|
function folderIcon(folderName, folderType) { // translations
|
|
switch (folderName.toLowerCase()) {
|
|
case "inbox" : return Style.fa.inbox
|
|
case "sent" : return Style.fa.send
|
|
case "spam" :
|
|
case "junk" : return Style.fa.ban
|
|
case "draft" : return Style.fa.file_o
|
|
case "starred" : return Style.fa.star_o
|
|
case "trash" : return Style.fa.trash_o
|
|
case "archive" : return Style.fa.archive
|
|
default: return folderType == gui.enums.folderTypeLabel ? Style.fa.tag : Style.fa.folder_open
|
|
}
|
|
return Style.fa.sticky_note_o
|
|
}
|
|
|
|
function folderTypeTitle(folderType) { // translations
|
|
if (folderType==gui.enums.folderTypeSystem ) return ""
|
|
if (folderType==gui.enums.folderTypeLabel ) return qsTr("Labels" , "todo")
|
|
if (folderType==gui.enums.folderTypeFolder ) return qsTr("Folders" , "todo")
|
|
return "Undef"
|
|
}
|
|
|
|
function isFolderEmpty() {
|
|
return "true"
|
|
}
|
|
|
|
function getUnixTime(dateString) {
|
|
var d = new Date(dateString)
|
|
var n = d.getTime()
|
|
if (n != n) return -1
|
|
return n
|
|
}
|
|
|
|
function getYearList(minY,maxY) {
|
|
var years = new Array()
|
|
for (var i=0; i<=maxY-minY;i++) {
|
|
years[i] = (maxY-i).toString()
|
|
}
|
|
//console.log("getYearList:", years)
|
|
return years
|
|
}
|
|
|
|
function getMonthList(minM,maxM) {
|
|
var months = new Array()
|
|
for (var i=0; i<=maxM-minM;i++) {
|
|
var iMonth = new Date(1989,(i+minM-1),13)
|
|
months[i] = iMonth.toLocaleString(gui.locale, "MMM")
|
|
}
|
|
//console.log("getMonthList:", months[0], months)
|
|
return months
|
|
}
|
|
|
|
function getDayList(minD,maxD) {
|
|
var days = new Array()
|
|
for (var i=0; i<=maxD-minD;i++) {
|
|
days[i] = gui.prependZeros(i+minD,2)
|
|
}
|
|
return days
|
|
}
|
|
|
|
function prependZeros(num,desiredLength) {
|
|
var s = num+""
|
|
while (s.length < desiredLength) s="0"+s
|
|
return s
|
|
}
|
|
|
|
function daysInMonth(year,month) {
|
|
if (typeof(year) !== 'number') {
|
|
year = parseInt(year)
|
|
}
|
|
if (typeof(month) !== 'number') {
|
|
month = Date.fromLocaleDateString( gui.locale, "1970-"+month+"-10", "yyyy-MMM-dd").getMonth()+1
|
|
}
|
|
var maxDays = (new Date(year,month,0)).getDate()
|
|
if (isNaN(maxDays)) maxDays = 0
|
|
//console.log(" daysInMonth", year, month, maxDays)
|
|
return maxDays
|
|
}
|
|
|
|
function niceDateTime() {
|
|
var stamp = new Date()
|
|
var nice = getMonthList(stamp.getMonth()+1, stamp.getMonth()+1)[0]
|
|
nice += "-" + getDayList(stamp.getDate(), stamp.getDate())[0]
|
|
nice += "-" + getYearList(stamp.getFullYear(), stamp.getFullYear())[0]
|
|
nice += " " + gui.prependZeros(stamp.getHours(),2)
|
|
nice += ":" + gui.prependZeros(stamp.getMinutes(),2)
|
|
return nice
|
|
}
|
|
|
|
/*
|
|
// Debug
|
|
Connections {
|
|
target: structureExternal
|
|
|
|
onDataChanged: {
|
|
console.log("external data changed")
|
|
}
|
|
}
|
|
|
|
// Debug
|
|
Connections {
|
|
target: structurePM
|
|
|
|
onSelectedLabelsChanged: console.log("PM sel labels:", structurePM.selectedLabels)
|
|
onSelectedFoldersChanged: console.log("PM sel folders:", structurePM.selectedFolders)
|
|
onDataChanged: {
|
|
console.log("PM data changed")
|
|
}
|
|
}
|
|
*/
|
|
|
|
Timer {
|
|
id: checkVersionTimer
|
|
repeat : true
|
|
triggeredOnStart: false
|
|
interval : Style.main.verCheckRepeatTime
|
|
onTriggered : go.runCheckVersion(false)
|
|
}
|
|
|
|
property string areYouSureYouWantToQuit : qsTr("There are incomplete processes - some items are not yet transferred. Do you really want to stop and quit?")
|
|
// On start
|
|
Component.onCompleted : {
|
|
// set spell messages
|
|
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.bugNotSent = qsTr("Unable to submit bug report." , "notification", -1)
|
|
go.bugReportSent = qsTr("Bug report successfully sent." , "notification", -1)
|
|
|
|
go.runCheckVersion(false)
|
|
checkVersionTimer.start()
|
|
|
|
gui.allMonths = getMonthList(1,12)
|
|
gui.allMonthsChanged()
|
|
}
|
|
}
|