mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-22 10:06:44 +00:00
Launcher, app/base, sentry, update service
This commit is contained in:
@ -22,16 +22,14 @@ package qtie
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
qtcommon "github.com/ProtonMail/proton-bridge/internal/frontend/qt-common"
|
||||
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
||||
"github.com/ProtonMail/proton-bridge/internal/importexport"
|
||||
"github.com/ProtonMail/proton-bridge/internal/locations"
|
||||
"github.com/ProtonMail/proton-bridge/internal/transfer"
|
||||
"github.com/ProtonMail/proton-bridge/internal/updates"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/config"
|
||||
"github.com/ProtonMail/proton-bridge/internal/updater"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
|
||||
"github.com/therecipe/qt/core"
|
||||
@ -51,9 +49,9 @@ var log = logrus.WithField("pkg", "frontend-qt-ie")
|
||||
// Qt and QML objects. QML signals and slots are connected via methods of GoQMLInterface.
|
||||
type FrontendQt struct {
|
||||
panicHandler types.PanicHandler
|
||||
config *config.Config
|
||||
locations *locations.Locations
|
||||
eventListener listener.Listener
|
||||
updates types.Updater
|
||||
updater types.Updater
|
||||
ie types.ImportExporter
|
||||
|
||||
App *widgets.QApplication // Main Application pointer
|
||||
@ -72,44 +70,39 @@ type FrontendQt struct {
|
||||
transfer *transfer.Transfer
|
||||
progress *transfer.Progress
|
||||
|
||||
notifyHasNoKeychain bool
|
||||
restarter types.Restarter
|
||||
}
|
||||
|
||||
// New is constructor for Import-Export Qt-Go interface
|
||||
func New(
|
||||
version, buildVersion string,
|
||||
panicHandler types.PanicHandler,
|
||||
config *config.Config,
|
||||
|
||||
locations *locations.Locations,
|
||||
eventListener listener.Listener,
|
||||
updates types.Updater,
|
||||
updater types.Updater,
|
||||
ie types.ImportExporter,
|
||||
restarter types.Restarter,
|
||||
) *FrontendQt {
|
||||
f := &FrontendQt{
|
||||
panicHandler: panicHandler,
|
||||
config: config,
|
||||
locations: locations,
|
||||
programName: "ProtonMail Import-Export",
|
||||
programVersion: "v" + version,
|
||||
eventListener: eventListener,
|
||||
updater: updater,
|
||||
buildVersion: buildVersion,
|
||||
updates: updates,
|
||||
ie: ie,
|
||||
restarter: restarter,
|
||||
}
|
||||
|
||||
log.Debugf("New Qt frontend: %p", f)
|
||||
return f
|
||||
}
|
||||
|
||||
// IsAppRestarting for Import-Export is always false i.e never restarts
|
||||
func (f *FrontendQt) IsAppRestarting() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Loop function for Import-Export interface. It runs QtExecute in main thread
|
||||
// with no additional function.
|
||||
func (f *FrontendQt) Loop(setupError error) (err error) {
|
||||
if setupError != nil {
|
||||
f.notifyHasNoKeychain = true
|
||||
}
|
||||
func (f *FrontendQt) Loop() (err error) {
|
||||
go func() {
|
||||
defer f.panicHandler.HandlePanic()
|
||||
f.watchEvents()
|
||||
@ -118,9 +111,16 @@ func (f *FrontendQt) Loop(setupError error) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *FrontendQt) NotifyManualUpdate(update updater.VersionInfo) error {
|
||||
// NOTE: Save the update somewhere so that it can be installed when user chooses "install now".
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FrontendQt) watchEvents() {
|
||||
credentialsErrorCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.CredentialsErrorEvent)
|
||||
internetOffCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.InternetOffEvent)
|
||||
internetOnCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.InternetOnEvent)
|
||||
secondInstanceCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.SecondInstanceEvent)
|
||||
restartBridgeCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.RestartBridgeEvent)
|
||||
addressChangedCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.AddressChangedEvent)
|
||||
addressChangedLogoutCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.AddressChangedLogoutEvent)
|
||||
@ -129,12 +129,16 @@ func (f *FrontendQt) watchEvents() {
|
||||
newUserCh := qtcommon.MakeAndRegisterEvent(f.eventListener, events.UserRefreshEvent)
|
||||
for {
|
||||
select {
|
||||
case <-credentialsErrorCh:
|
||||
f.Qml.NotifyHasNoKeychain()
|
||||
case <-internetOffCh:
|
||||
f.Qml.SetConnectionStatus(false)
|
||||
case <-internetOnCh:
|
||||
f.Qml.SetConnectionStatus(true)
|
||||
case <-secondInstanceCh:
|
||||
f.Qml.ShowWindow()
|
||||
case <-restartBridgeCh:
|
||||
f.Qml.SetIsRestarting(true)
|
||||
f.restarter.SetToRestart()
|
||||
f.App.Quit()
|
||||
case address := <-addressChangedCh:
|
||||
f.Qml.NotifyAddressChanged(address)
|
||||
@ -165,7 +169,7 @@ func (f *FrontendQt) qtSetupQmlAndStructures() {
|
||||
f.View.RootContext().SetContextProperty("go", f.Qml)
|
||||
|
||||
// Add AccountsModel
|
||||
f.Accounts.SetupAccounts(f.Qml, f.ie)
|
||||
f.Accounts.SetupAccounts(f.Qml, f.ie, f.restarter)
|
||||
f.View.RootContext().SetContextProperty("accountsModel", f.Accounts.Model)
|
||||
|
||||
// Add TransferRules structure
|
||||
@ -189,11 +193,6 @@ func (f *FrontendQt) qtSetupQmlAndStructures() {
|
||||
} else {
|
||||
f.Qml.SetIsFirstStart(false)
|
||||
}
|
||||
|
||||
// Notify user about error during initialization.
|
||||
if f.notifyHasNoKeychain {
|
||||
f.Qml.NotifyHasNoKeychain()
|
||||
}
|
||||
}
|
||||
|
||||
// QtExecute in main for starting Qt application
|
||||
@ -233,7 +232,12 @@ func (f *FrontendQt) QtExecute(Procedure func(*FrontendQt) error) error {
|
||||
}
|
||||
|
||||
func (f *FrontendQt) openLogs() {
|
||||
go open.Run(f.config.GetLogDir())
|
||||
logsPath, err := f.locations.ProvideLogsPath()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
go open.Run(logsPath)
|
||||
}
|
||||
|
||||
func (f *FrontendQt) openReport() {
|
||||
@ -241,7 +245,7 @@ func (f *FrontendQt) openReport() {
|
||||
}
|
||||
|
||||
func (f *FrontendQt) openDownloadLink() {
|
||||
go open.Run(f.updates.GetDownloadLink())
|
||||
// NOTE: Fix this.
|
||||
}
|
||||
|
||||
// sendImportReport sends an anonymized import or export report file to our customer support
|
||||
@ -365,34 +369,8 @@ func (f *FrontendQt) setProgressManager(progress *transfer.Progress) {
|
||||
}()
|
||||
}
|
||||
|
||||
// StartUpdate is identical to bridge
|
||||
func (f *FrontendQt) StartUpdate() {
|
||||
progress := make(chan updates.Progress)
|
||||
go func() { // Update progress in QML.
|
||||
defer f.panicHandler.HandlePanic()
|
||||
for current := range progress {
|
||||
f.Qml.SetProgress(current.Processed)
|
||||
f.Qml.SetProgressDescription(strconv.Itoa(current.Description))
|
||||
// Error happend
|
||||
if current.Err != nil {
|
||||
log.Error("update progress: ", current.Err)
|
||||
f.Qml.UpdateFinished(true)
|
||||
return
|
||||
}
|
||||
// Finished everything OK.
|
||||
if current.Description >= updates.InfoQuitApp {
|
||||
f.Qml.UpdateFinished(false)
|
||||
time.Sleep(3 * time.Second) // Just notify.
|
||||
f.Qml.SetIsRestarting(current.Description == updates.InfoRestartApp)
|
||||
f.App.Quit()
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
go func() {
|
||||
defer f.panicHandler.HandlePanic()
|
||||
f.updates.StartUpgrade(progress)
|
||||
}()
|
||||
// NOTE: Fix this.
|
||||
}
|
||||
|
||||
// isNewVersionAvailable is identical to bridge
|
||||
@ -401,26 +379,11 @@ func (f *FrontendQt) StartUpdate() {
|
||||
func (f *FrontendQt) isNewVersionAvailable(showMessage bool) {
|
||||
go func() {
|
||||
defer f.Qml.ProcessFinished()
|
||||
isUpToDate, latestVersionInfo, err := f.updates.CheckIsUpToDate()
|
||||
if err != nil {
|
||||
log.Warnln("Cannot retrieve version info: ", err)
|
||||
f.checkInternet()
|
||||
return
|
||||
}
|
||||
f.Qml.SetConnectionStatus(true) // if we are here connection is ok
|
||||
if isUpToDate {
|
||||
f.Qml.SetUpdateState(StatusUpToDate)
|
||||
if showMessage {
|
||||
f.Qml.NotifyVersionIsTheLatest()
|
||||
}
|
||||
return
|
||||
f.Qml.SetUpdateState(StatusUpToDate)
|
||||
if showMessage {
|
||||
f.Qml.NotifyVersionIsTheLatest()
|
||||
}
|
||||
f.Qml.SetNewversion(latestVersionInfo.Version)
|
||||
f.Qml.SetChangelog(latestVersionInfo.ReleaseNotes)
|
||||
f.Qml.SetBugfixes(latestVersionInfo.ReleaseFixedBugs)
|
||||
f.Qml.SetLandingPage(latestVersionInfo.LandingPage)
|
||||
f.Qml.SetDownloadLink(latestVersionInfo.GetDownloadLink())
|
||||
f.Qml.SetUpdateState(StatusNewVersionAvailable)
|
||||
}()
|
||||
}
|
||||
|
||||
@ -434,16 +397,12 @@ func (f *FrontendQt) resetSource() {
|
||||
}
|
||||
|
||||
func (f *FrontendQt) openLicenseFile() {
|
||||
go open.Run(f.config.GetLicenseFilePath())
|
||||
go open.Run(f.locations.GetLicenseFilePath())
|
||||
}
|
||||
|
||||
// getLocalVersionInfo is identical to bridge.
|
||||
func (f *FrontendQt) getLocalVersionInfo() {
|
||||
defer f.Qml.ProcessFinished()
|
||||
localVersion := f.updates.GetLocalVersion()
|
||||
f.Qml.SetNewversion(localVersion.Version)
|
||||
f.Qml.SetChangelog(localVersion.ReleaseNotes)
|
||||
f.Qml.SetBugfixes(localVersion.ReleaseFixedBugs)
|
||||
// NOTE: Fix this.
|
||||
}
|
||||
|
||||
// LeastUsedColor is intended to return color for creating a new inbox or label.
|
||||
|
||||
@ -24,7 +24,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/frontend/types"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/config"
|
||||
"github.com/ProtonMail/proton-bridge/internal/locations"
|
||||
"github.com/ProtonMail/proton-bridge/internal/updater"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -33,23 +34,27 @@ var log = logrus.WithField("pkg", "frontend-nogui") //nolint[gochecknoglobals]
|
||||
|
||||
type FrontendHeadless struct{}
|
||||
|
||||
func (s *FrontendHeadless) Loop(credentialsError error) error {
|
||||
log.Info("Check status on localhost:8081")
|
||||
func (s *FrontendHeadless) Loop() error {
|
||||
log.Info("Check status on localhost:8082")
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "IE is running")
|
||||
})
|
||||
return http.ListenAndServe(":8081", nil)
|
||||
return http.ListenAndServe(":8082", nil)
|
||||
}
|
||||
|
||||
func (s *FrontendHeadless) IsAppRestarting() bool { return false }
|
||||
func (s *FrontendHeadless) NotifyManualUpdate(update updater.VersionInfo) error {
|
||||
// NOTE: Save the update somewhere so that it can be installed when user chooses "install now".
|
||||
return nil
|
||||
}
|
||||
|
||||
func New(
|
||||
version, buildVersion string,
|
||||
panicHandler types.PanicHandler,
|
||||
config *config.Config,
|
||||
locations *locations.Locations,
|
||||
eventListener listener.Listener,
|
||||
updates types.Updater,
|
||||
updater types.Updater,
|
||||
ie types.ImportExporter,
|
||||
restarter types.Restarter,
|
||||
) *FrontendHeadless {
|
||||
return &FrontendHeadless{}
|
||||
}
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// +build !nogui
|
||||
|
||||
package qtie
|
||||
|
||||
type panicHandler interface {
|
||||
HandlePanic()
|
||||
SendReport(interface{})
|
||||
}
|
||||
@ -37,7 +37,6 @@ type GoQMLInterface struct {
|
||||
_ string `property:"goos"`
|
||||
_ string `property:"credits"`
|
||||
_ bool `property:"isFirstStart"`
|
||||
_ bool `property:"isRestarting"`
|
||||
_ bool `property:"isConnectionOK"`
|
||||
|
||||
_ string `property:lastError`
|
||||
@ -68,6 +67,8 @@ type GoQMLInterface struct {
|
||||
_ func(updateState string) `signal:"setUpdateState"`
|
||||
_ func() `slot:"checkInternet"`
|
||||
|
||||
_ func() `slot:"setToRestart"`
|
||||
|
||||
_ func() `signal:"processFinished"`
|
||||
_ func(okay bool) `signal:"exportStructureLoadFinished"`
|
||||
_ func(okay bool) `signal:"importStructuresLoadFinished"`
|
||||
@ -77,6 +78,8 @@ type GoQMLInterface struct {
|
||||
_ func() `slot:"getLocalVersionInfo"`
|
||||
_ func() `slot:"loadImportReports"`
|
||||
|
||||
_ func() `signal:"showWindow"`
|
||||
|
||||
_ func() `slot:"quit"`
|
||||
_ func() `slot:"loadAccounts"`
|
||||
_ func() `slot:"openLogs"`
|
||||
@ -165,7 +168,6 @@ func (s *GoQMLInterface) SetFrontend(f *FrontendQt) {
|
||||
s.ConnectAddAccount(f.Accounts.AddAccount)
|
||||
|
||||
s.SetGoos(runtime.GOOS)
|
||||
s.SetIsRestarting(false)
|
||||
s.SetProgramTitle(f.programName)
|
||||
|
||||
s.ConnectOpenLicenseFile(f.openLicenseFile)
|
||||
@ -177,6 +179,8 @@ func (s *GoQMLInterface) SetFrontend(f *FrontendQt) {
|
||||
|
||||
s.ConnectCheckInternet(f.checkInternet)
|
||||
|
||||
s.ConnectSetToRestart(f.restarter.SetToRestart)
|
||||
|
||||
s.ConnectLoadStructureForExport(f.LoadStructureForExport)
|
||||
s.ConnectSetupAndLoadForImport(f.setupAndLoadForImport)
|
||||
s.ConnectResetSource(f.resetSource)
|
||||
|
||||
Reference in New Issue
Block a user