mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-23 02:26:42 +00:00
GODT-1381: Use in-memory cache in case local cache is unavailable
- change: refactor GUI notification object - add: global bridge errors - add: when cache on disk cannot be initialized fallback to memory cache - add: show notification for CoD failure - change: do not allow login to IMAP and SMTP when CoD init failed
This commit is contained in:
@ -24,7 +24,7 @@ import (
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/api"
|
||||
"github.com/ProtonMail/proton-bridge/internal/app/base"
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
pkgBridge "github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/config/settings"
|
||||
pkgTLS "github.com/ProtonMail/proton-bridge/internal/config/tls"
|
||||
"github.com/ProtonMail/proton-bridge/internal/constants"
|
||||
@ -46,6 +46,10 @@ const (
|
||||
flagLogSMTP = "log-smtp"
|
||||
flagNoWindow = "no-window"
|
||||
flagNonInteractive = "noninteractive"
|
||||
|
||||
// Memory cache was estimated by empirical usage in past and it was set to 100MB.
|
||||
// NOTE: This value must not be less than maximal size of one email (~30MB).
|
||||
inMemoryCacheLimnit = 100 * (1 << 20)
|
||||
)
|
||||
|
||||
func New(base *base.Base) *cli.App {
|
||||
@ -75,9 +79,9 @@ func run(b *base.Base, c *cli.Context) error { // nolint[funlen]
|
||||
return err
|
||||
}
|
||||
|
||||
cache, err := loadMessageCache(b)
|
||||
if err != nil {
|
||||
return err
|
||||
cache, cacheErr := loadMessageCache(b)
|
||||
if cacheErr != nil {
|
||||
logrus.WithError(cacheErr).Error("Could not load local cache.")
|
||||
}
|
||||
|
||||
builder := message.NewBuilder(
|
||||
@ -85,10 +89,14 @@ func run(b *base.Base, c *cli.Context) error { // nolint[funlen]
|
||||
b.Settings.GetInt(settings.AttachmentWorkers),
|
||||
)
|
||||
|
||||
bridge := bridge.New(b.Locations, b.Cache, b.Settings, b.SentryReporter, b.CrashHandler, b.Listener, cache, builder, b.CM, b.Creds, b.Updater, b.Versioner)
|
||||
bridge := pkgBridge.New(b.Locations, b.Cache, b.Settings, b.SentryReporter, b.CrashHandler, b.Listener, cache, builder, b.CM, b.Creds, b.Updater, b.Versioner)
|
||||
imapBackend := imap.NewIMAPBackend(b.CrashHandler, b.Listener, b.Cache, b.Settings, bridge)
|
||||
smtpBackend := smtp.NewSMTPBackend(b.CrashHandler, b.Listener, b.Settings, bridge)
|
||||
|
||||
if cacheErr != nil {
|
||||
bridge.AddError(pkgBridge.ErrLocalCacheUnavailable)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer b.CrashHandler.HandlePanic()
|
||||
api.NewAPIServer(b.Settings, b.Listener).ListenAndServe()
|
||||
@ -248,13 +256,12 @@ func checkAndHandleUpdate(u types.Updater, f frontend.Frontend, autoUpdate bool)
|
||||
f.NotifySilentUpdateInstalled()
|
||||
}
|
||||
|
||||
// loadMessageCache loads local cache in case it is enabled in settings and available.
|
||||
// In any other case it is returning in-memory cache. Could also return an error in case
|
||||
// local cache is enabled but unavailable (in-memory cache will be returned nevertheless).
|
||||
func loadMessageCache(b *base.Base) (cache.Cache, error) {
|
||||
if !b.Settings.GetBool(settings.CacheEnabledKey) {
|
||||
// Memory cache was estimated by empirical usage in past and it
|
||||
// was set to 100MB.
|
||||
// NOTE: This value must not be less than maximal size of one
|
||||
// email (~30MB).
|
||||
return cache.NewInMemoryCache(100 << 20), nil
|
||||
return cache.NewInMemoryCache(inMemoryCacheLimnit), nil
|
||||
}
|
||||
|
||||
var compressor cache.Compressor
|
||||
@ -283,10 +290,16 @@ func loadMessageCache(b *base.Base) (cache.Cache, error) {
|
||||
// build jobs.
|
||||
store.SetBuildAndCacheJobLimit(b.Settings.GetInt(settings.CacheConcurrencyWrite))
|
||||
|
||||
return cache.NewOnDiskCache(path, compressor, cache.Options{
|
||||
messageCache, err := cache.NewOnDiskCache(path, compressor, cache.Options{
|
||||
MinFreeAbs: uint64(b.Settings.GetInt(settings.CacheMinFreeAbsKey)),
|
||||
MinFreeRat: b.Settings.GetFloat64(settings.CacheMinFreeRatKey),
|
||||
ConcurrentRead: b.Settings.GetInt(settings.CacheConcurrencyRead),
|
||||
ConcurrentWrite: b.Settings.GetInt(settings.CacheConcurrencyWrite),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return cache.NewInMemoryCache(inMemoryCacheLimnit), err
|
||||
}
|
||||
|
||||
return messageCache, nil
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
package bridge
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
@ -40,6 +41,8 @@ import (
|
||||
|
||||
var log = logrus.WithField("pkg", "bridge") //nolint[gochecknoglobals]
|
||||
|
||||
var ErrLocalCacheUnavailable = errors.New("local cache is unavailable")
|
||||
|
||||
type Bridge struct {
|
||||
*users.Users
|
||||
|
||||
@ -49,6 +52,8 @@ type Bridge struct {
|
||||
updater Updater
|
||||
versioner Versioner
|
||||
cacheProvider CacheProvider
|
||||
// Bridge's global errors list.
|
||||
errors []error
|
||||
}
|
||||
|
||||
func New(
|
||||
@ -241,3 +246,36 @@ func (b *Bridge) SetProxyAllowed(proxyAllowed bool) {
|
||||
func (b *Bridge) GetProxyAllowed() bool {
|
||||
return b.settings.GetBool(settings.AllowProxyKey)
|
||||
}
|
||||
|
||||
// AddError add an error to a global error list if it does not contain it yet. Adding nil is noop.
|
||||
func (b *Bridge) AddError(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
if b.HasError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
b.errors = append(b.errors, err)
|
||||
}
|
||||
|
||||
// DelError removes an error from global error list.
|
||||
func (b *Bridge) DelError(err error) {
|
||||
for idx, val := range b.errors {
|
||||
if val == err {
|
||||
b.errors = append(b.errors[:idx], b.errors[idx+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HasError returnes true if global error list contains an err.
|
||||
func (b *Bridge) HasError(err error) bool {
|
||||
for _, val := range b.errors {
|
||||
if val == err {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@ -80,13 +80,13 @@ Popup {
|
||||
}
|
||||
|
||||
switch (root.notification.type) {
|
||||
case Notification.NotificationType.Info:
|
||||
case Notification.NotificationType.Info:
|
||||
return root.colorScheme.signal_info
|
||||
case Notification.NotificationType.Success:
|
||||
case Notification.NotificationType.Success:
|
||||
return root.colorScheme.signal_success
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Warning:
|
||||
return root.colorScheme.signal_warning
|
||||
case Notification.NotificationType.Danger:
|
||||
case Notification.NotificationType.Danger:
|
||||
return root.colorScheme.signal_danger
|
||||
}
|
||||
}
|
||||
@ -118,13 +118,13 @@ Popup {
|
||||
}
|
||||
|
||||
switch (root.notification.type) {
|
||||
case Notification.NotificationType.Info:
|
||||
case Notification.NotificationType.Info:
|
||||
return "./icons/ic-info-circle-filled.svg"
|
||||
case Notification.NotificationType.Success:
|
||||
case Notification.NotificationType.Success:
|
||||
return "./icons/ic-info-circle-filled.svg"
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Warning:
|
||||
return "./icons/ic-exclamation-circle-filled.svg"
|
||||
case Notification.NotificationType.Danger:
|
||||
case Notification.NotificationType.Danger:
|
||||
return "./icons/ic-exclamation-circle-filled.svg"
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ Popup {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
color: root.colorScheme.text_invert
|
||||
text: root.notification ? root.notification.text : ""
|
||||
text: root.notification ? root.notification.description : ""
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
@ -152,13 +152,13 @@ Popup {
|
||||
}
|
||||
|
||||
switch (root.notification.type) {
|
||||
case Notification.NotificationType.Info:
|
||||
case Notification.NotificationType.Info:
|
||||
return root.colorScheme.signal_info_active
|
||||
case Notification.NotificationType.Success:
|
||||
case Notification.NotificationType.Success:
|
||||
return root.colorScheme.signal_success_active
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Warning:
|
||||
return root.colorScheme.signal_warning_active
|
||||
case Notification.NotificationType.Danger:
|
||||
case Notification.NotificationType.Danger:
|
||||
return root.colorScheme.signal_danger_active
|
||||
}
|
||||
}
|
||||
@ -190,22 +190,22 @@ Popup {
|
||||
var active
|
||||
|
||||
switch (root.notification.type) {
|
||||
case Notification.NotificationType.Info:
|
||||
case Notification.NotificationType.Info:
|
||||
norm = root.colorScheme.signal_info
|
||||
hover = root.colorScheme.signal_info_hover
|
||||
active = root.colorScheme.signal_info_active
|
||||
break;
|
||||
case Notification.NotificationType.Success:
|
||||
case Notification.NotificationType.Success:
|
||||
norm = root.colorScheme.signal_success
|
||||
hover = root.colorScheme.signal_success_hover
|
||||
active = root.colorScheme.signal_success_active
|
||||
break;
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Warning:
|
||||
norm = root.colorScheme.signal_warning
|
||||
hover = root.colorScheme.signal_warning_hover
|
||||
active = root.colorScheme.signal_warning_active
|
||||
break;
|
||||
case Notification.NotificationType.Danger:
|
||||
case Notification.NotificationType.Danger:
|
||||
norm = root.colorScheme.signal_danger
|
||||
hover = root.colorScheme.signal_danger_hover
|
||||
active = root.colorScheme.signal_danger_active
|
||||
|
||||
@ -52,6 +52,13 @@ QtObject {
|
||||
onVisibleChanged: {
|
||||
backend.dockIconVisible = visible
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.backend
|
||||
onCacheUnavailable: {
|
||||
mainWindow.showAndRise()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property StatusWindow _statusWindow: StatusWindow {
|
||||
|
||||
@ -55,12 +55,12 @@ Dialog {
|
||||
}
|
||||
|
||||
switch (root.notification.type) {
|
||||
case Notification.NotificationType.Info:
|
||||
case Notification.NotificationType.Info:
|
||||
return "./icons/ic-info.svg"
|
||||
case Notification.NotificationType.Success:
|
||||
case Notification.NotificationType.Success:
|
||||
return "./icons/ic-success.svg"
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Danger:
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Danger:
|
||||
return "./icons/ic-alert.svg"
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ Dialog {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 8
|
||||
colorScheme: root.colorScheme
|
||||
text: root.notification.text
|
||||
text: root.notification.title
|
||||
type: Label.LabelType.Title
|
||||
}
|
||||
|
||||
|
||||
@ -30,8 +30,13 @@ QtObject {
|
||||
Danger = 3
|
||||
}
|
||||
|
||||
property string text
|
||||
// title is used in dialogs only
|
||||
property string title
|
||||
// description is used in banners and in dialogs as description
|
||||
property string description
|
||||
// brief is used in status view only
|
||||
property string brief
|
||||
|
||||
property string icon
|
||||
property list<Action> action
|
||||
property int type
|
||||
|
||||
@ -74,7 +74,8 @@ QtObject {
|
||||
|
||||
// Connection
|
||||
property Notification noInternet: Notification {
|
||||
text: qsTr("No connection")
|
||||
description: qsTr("Bridge is not able to contact the server, please check your internet connection.")
|
||||
brief: qsTr("No connection")
|
||||
icon: "./icons/ic-no-connection.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Connection
|
||||
@ -93,8 +94,9 @@ QtObject {
|
||||
|
||||
// Updates
|
||||
property Notification updateManualReady: Notification {
|
||||
text: qsTr("Update to Bridge") + " " + (data ? data.version : "")
|
||||
title: qsTr("Update to Bridge %1").arg(data ? data.version : "")
|
||||
description: qsTr("A new version of ProtonMail Bridge is available. See what's changed.")
|
||||
brief: qsTr("Update available. (See what's new.)")
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Info
|
||||
group: Notifications.Group.Update | Notifications.Group.Dialogs
|
||||
@ -135,7 +137,8 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateManualRestartNeeded: Notification {
|
||||
text: qsTr("Bridge update is ready")
|
||||
description: qsTr("Bridge update is ready")
|
||||
brief: description
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Info
|
||||
group: Notifications.Group.Update
|
||||
@ -158,7 +161,8 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateManualError: Notification {
|
||||
text: qsTr("Bridge couldn’t update. Please update manually.")
|
||||
description: qsTr("Bridge couldn’t update")
|
||||
brief: description
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Update
|
||||
@ -190,8 +194,9 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateForce: Notification {
|
||||
text: qsTr("Update to ProtonMail Bridge") + " " + (data ? data.version : "")
|
||||
title: qsTr("Update to Bridge %1").arg(data ? data.version : "")
|
||||
description: qsTr("This version of Bridge is no longer supported, please update.")
|
||||
brief: qsTr("Bridge is outdated")
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Update | Notifications.Group.Dialogs
|
||||
@ -234,8 +239,9 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateForceError: Notification {
|
||||
text: qsTr("Bridge coudn’t update")
|
||||
description: qsTr("You must update manually.")
|
||||
title: qsTr("Bridge coudn’t update")
|
||||
description: qsTr("You must update manually. Go to: https:/protonmail.com/bridge/download")
|
||||
brief: title
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Update | Notifications.Group.Dialogs
|
||||
@ -269,7 +275,8 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateSilentRestartNeeded: Notification {
|
||||
text: qsTr("Bridge update is ready")
|
||||
description: qsTr("Bridge update is ready")
|
||||
brief: description
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Info
|
||||
group: Notifications.Group.Update
|
||||
@ -292,7 +299,8 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateSilentError: Notification {
|
||||
text: qsTr("Bridge couldn’t update")
|
||||
description: qsTr("Bridge couldn’t update")
|
||||
brief: description
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Update
|
||||
@ -315,7 +323,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification updateIsLatestVersion: Notification {
|
||||
text: qsTr("Bridge is up to date")
|
||||
description: qsTr("Bridge is up to date")
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Info
|
||||
group: Notifications.Group.Update
|
||||
@ -337,7 +345,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification enableBeta: Notification {
|
||||
text: qsTr("Enable Beta access")
|
||||
title: qsTr("Enable Beta access")
|
||||
description: qsTr("Be the first to get new updates and use new features. Bridge will update to the latest beta version.")
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Info
|
||||
@ -370,7 +378,7 @@ QtObject {
|
||||
|
||||
// login
|
||||
property Notification loginConnectionError: Notification {
|
||||
text: qsTr("Bridge is not able to contact the server, please check your internet connection.")
|
||||
description: qsTr("Bridge is not able to contact the server, please check your internet connection.")
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Configuration
|
||||
@ -393,7 +401,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification onlyPaidUsers: Notification {
|
||||
text: qsTr("Bridge is exclusive to our paid plans. Upgrade your account to use Bridge.")
|
||||
description: qsTr("Bridge is exclusive to our paid plans. Upgrade your account to use Bridge.")
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Configuration
|
||||
@ -416,7 +424,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification alreadyLoggedIn: Notification {
|
||||
text: qsTr("This account is already signed it.")
|
||||
description: qsTr("This account is already signed it.")
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Info
|
||||
group: Notifications.Group.Configuration
|
||||
@ -440,7 +448,7 @@ QtObject {
|
||||
|
||||
// Bug reports
|
||||
property Notification bugReportSendSuccess: Notification {
|
||||
text: qsTr("Thank you for the report. We'll get back to you as soon as we can.")
|
||||
description: qsTr("Thank you for the report. We'll get back to you as soon as we can.")
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Success
|
||||
group: Notifications.Group.Configuration
|
||||
@ -463,7 +471,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification bugReportSendError: Notification {
|
||||
text: qsTr("Report could not be sent. Try again or email us directly.")
|
||||
description: qsTr("Report could not be sent. Try again or email us directly.")
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Configuration
|
||||
@ -485,8 +493,9 @@ QtObject {
|
||||
|
||||
// Cache
|
||||
property Notification cacheUnavailable: Notification {
|
||||
text: qsTr("Cache location is unavailable")
|
||||
title: qsTr("Cache location is unavailable")
|
||||
description: qsTr("Check the directory or change it in your settings.")
|
||||
brief: qsTr("The current cache location is unavailable. Check the directory or change it in your settings.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
|
||||
@ -516,7 +525,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification cacheCantMove: Notification {
|
||||
text: qsTr("Can’t move cache")
|
||||
title: qsTr("Can’t move cache")
|
||||
description: qsTr("The location you have selected is not available. Make sure you have enough free space or choose another location.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
@ -546,7 +555,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification cacheLocationChangeSuccess: Notification {
|
||||
text: qsTr("Cache location successfully changed")
|
||||
description: qsTr("Cache location successfully changed")
|
||||
icon: "./icons/ic-info-circle-filled.svg"
|
||||
type: Notification.NotificationType.Success
|
||||
group: Notifications.Group.Configuration
|
||||
@ -571,7 +580,8 @@ QtObject {
|
||||
|
||||
// Other
|
||||
property Notification accountChanged: Notification {
|
||||
text: qsTr("The address list for your account has changed")
|
||||
description: qsTr("The address list for .... account has changed. You need to reconfigure your email client.")
|
||||
brief: qsTr("The address list for your account has changed. Reconfigure your email client.")
|
||||
icon: "./icons/ic-exclamation-circle-filled.svg"
|
||||
type: Notification.NotificationType.Danger
|
||||
group: Notifications.Group.Configuration
|
||||
@ -586,8 +596,9 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification diskFull: Notification {
|
||||
text: qsTr("Your disk is almost full")
|
||||
title: qsTr("Your disk is almost full")
|
||||
description: qsTr("Quit Bridge and free disk space or disable the local cache (not recommended).")
|
||||
brief: qsTr("Your disk is almost full. Free disk space or disable the local cache.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
|
||||
@ -617,8 +628,8 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification enableSplitMode: Notification {
|
||||
text: qsTr("Enable split mode?")
|
||||
description: qsTr("Changing between split and combined address mode will require you to delete your accounts(s) from your email client and begin the setup process from scratch.")
|
||||
title: qsTr("Enable split mode?")
|
||||
description: qsTr("Changing between split and combined address mode will require you to delete your account(s) from your email client and begin the setup process from scratch.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
|
||||
@ -632,7 +643,6 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
target: (root && root.enableSplitMode && root.enableSplitMode.user ) ? root.enableSplitMode.user : null
|
||||
onToggleSplitModeFinished: {
|
||||
@ -664,7 +674,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification disableLocalCache: Notification {
|
||||
text: qsTr("Disable local cache?")
|
||||
title: qsTr("Disable local cache?")
|
||||
description: qsTr("This action will clear your local cache, including locally stored messages. Bridge will restart.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
@ -676,7 +686,6 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
target: root.backend
|
||||
onChangeLocalCacheFinished: {
|
||||
@ -708,7 +717,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification enableLocalCache: Notification {
|
||||
text: qsTr("Enable local cache?")
|
||||
title: qsTr("Enable local cache")
|
||||
description: qsTr("Bridge will restart.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
@ -723,7 +732,6 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
target: root.backend
|
||||
onChangeLocalCacheFinished: {
|
||||
@ -755,7 +763,7 @@ QtObject {
|
||||
}
|
||||
|
||||
property Notification resetBridge: Notification {
|
||||
text: qsTr("Reset Bridge?")
|
||||
title: qsTr("Reset Bridge?")
|
||||
description: qsTr("This will clear your accounts, preferences, and cached data. You will need to reconfigure your email client. Bridge will automatically restart.")
|
||||
type: Notification.NotificationType.Warning
|
||||
group: Notifications.Group.Configuration | Notifications.Group.Dialogs
|
||||
@ -769,7 +777,6 @@ QtObject {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
target: root.backend
|
||||
onResetFinished: {
|
||||
|
||||
@ -56,22 +56,22 @@ Item {
|
||||
}
|
||||
|
||||
image.source = topmost.icon
|
||||
label.text = topmost.text
|
||||
label.text = topmost.brief
|
||||
|
||||
switch (topmost.type) {
|
||||
case Notification.NotificationType.Danger:
|
||||
case Notification.NotificationType.Danger:
|
||||
image.color = root.colorScheme.signal_danger
|
||||
label.color = root.colorScheme.signal_danger
|
||||
break;
|
||||
case Notification.NotificationType.Warning:
|
||||
case Notification.NotificationType.Warning:
|
||||
image.color = root.colorScheme.signal_warning
|
||||
label.color = root.colorScheme.signal_warning
|
||||
break;
|
||||
case Notification.NotificationType.Success:
|
||||
case Notification.NotificationType.Success:
|
||||
image.color = root.colorScheme.signal_success
|
||||
label.color = root.colorScheme.signal_success
|
||||
break;
|
||||
case Notification.NotificationType.Info:
|
||||
case Notification.NotificationType.Info:
|
||||
image.color = root.colorScheme.signal_info
|
||||
label.color = root.colorScheme.signal_info
|
||||
break;
|
||||
|
||||
@ -128,7 +128,7 @@ Window {
|
||||
Layout.topMargin: 12
|
||||
Layout.bottomMargin: 12
|
||||
|
||||
visible: (statusItem.activeNotification && statusItem.activeNotification.action) ? true : false
|
||||
visible: statusItem.activeNotification && statusItem.activeNotification.action.length > 0
|
||||
action: statusItem.activeNotification && statusItem.activeNotification.action.length > 0 ? statusItem.activeNotification.action[0] : null
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build build_qt
|
||||
// +build build_qt
|
||||
|
||||
// Package qt provides communication between Qt/QML frontend and Go backend
|
||||
@ -23,12 +24,18 @@ package qt
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
)
|
||||
|
||||
func (f *FrontendQt) watchEvents() {
|
||||
f.WaitUntilFrontendIsReady()
|
||||
|
||||
// First we check bridge global errors for any error that should be shown on GUI.
|
||||
if f.bridge.HasError(bridge.ErrLocalCacheUnavailable) {
|
||||
f.qml.CacheUnavailable()
|
||||
}
|
||||
|
||||
errorCh := f.eventListener.ProvideChannel(events.ErrorEvent)
|
||||
credentialsErrorCh := f.eventListener.ProvideChannel(events.CredentialsErrorEvent)
|
||||
noActiveKeyForRecipientCh := f.eventListener.ProvideChannel(events.NoActiveKeyForRecipientEvent)
|
||||
|
||||
@ -86,6 +86,7 @@ type Bridger interface {
|
||||
SetUpdateChannel(updater.UpdateChannel)
|
||||
GetKeychainApp() string
|
||||
SetKeychainApp(keychain string)
|
||||
HasError(err error) bool
|
||||
}
|
||||
|
||||
type bridgeWrap struct {
|
||||
|
||||
@ -39,6 +39,7 @@ import (
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/config/settings"
|
||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||
"github.com/ProtonMail/proton-bridge/internal/users"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
"github.com/emersion/go-imap"
|
||||
goIMAPBackend "github.com/emersion/go-imap/backend"
|
||||
@ -168,6 +169,10 @@ func (ib *imapBackend) Login(_ *imap.ConnInfo, username, password string) (goIMA
|
||||
// Called from go-imap in goroutines - we need to handle panics for each function.
|
||||
defer ib.panicHandler.HandlePanic()
|
||||
|
||||
if ib.bridge.HasError(bridge.ErrLocalCacheUnavailable) {
|
||||
return nil, users.ErrLoggedOutUser
|
||||
}
|
||||
|
||||
imapUser, err := ib.getUser(username)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Cannot get user")
|
||||
|
||||
@ -30,6 +30,7 @@ type cacheProvider interface {
|
||||
|
||||
type bridger interface {
|
||||
GetUser(query string) (bridgeUser, error)
|
||||
HasError(err error) bool
|
||||
}
|
||||
|
||||
type bridgeUser interface {
|
||||
|
||||
@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/bridge"
|
||||
"github.com/ProtonMail/proton-bridge/internal/config/settings"
|
||||
"github.com/ProtonMail/proton-bridge/internal/users"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/confirmer"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/listener"
|
||||
goSMTPBackend "github.com/emersion/go-smtp"
|
||||
@ -77,6 +78,11 @@ func newSMTPBackend(
|
||||
func (sb *smtpBackend) Login(_ *goSMTPBackend.ConnectionState, username, password string) (goSMTPBackend.Session, error) {
|
||||
// Called from go-smtp in goroutines - we need to handle panics for each function.
|
||||
defer sb.panicHandler.HandlePanic()
|
||||
|
||||
if sb.bridge.HasError(bridge.ErrLocalCacheUnavailable) {
|
||||
return nil, users.ErrLoggedOutUser
|
||||
}
|
||||
|
||||
username = strings.ToLower(username)
|
||||
|
||||
user, err := sb.bridge.GetUser(username)
|
||||
|
||||
@ -25,6 +25,7 @@ import (
|
||||
|
||||
type bridger interface {
|
||||
GetUser(query string) (bridgeUser, error)
|
||||
HasError(err error) bool
|
||||
}
|
||||
|
||||
type bridgeUser interface {
|
||||
|
||||
Reference in New Issue
Block a user