diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml index 4f567e20..d3204b9a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml @@ -48,6 +48,8 @@ QtObject { property var all: [ root.noInternet, + root.portIssueIMAP, + root.portIssueSMTP, root.updateManualReady, root.updateManualRestartNeeded, root.updateManualError, @@ -98,6 +100,38 @@ QtObject { } } + property Notification portIssueIMAP: Notification { + description: qsTr("The IMAP server could not be started. Please check or change the IMAP port and restart the application.") + brief: qsTr("IMAP port error") + icon: "./icons/ic-alert.svg" + type: Notification.NotificationType.Danger + group: Notifications.Group.Connection + + Connections { + target: Backend + + function onPortIssueIMAP() { + root.portIssueIMAP.active = true + } + } + } + + property Notification portIssueSMTP: Notification { + description: qsTr("The SMTP server could not be started. Please check or change the SMTP port and restart the application.") + brief: qsTr("SMTP port error") + icon: "./icons/ic-alert.svg" + type: Notification.NotificationType.Danger + group: Notifications.Group.Connection + + Connections { + target: Backend + + function onPortIssueSMTP() { + root.portIssueSMTP.active = true + } + } + } + // Updates property Notification updateManualReady: Notification { title: qsTr("Update to Bridge %1").arg(data ? data.version : "") diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 88417155..e2548b4b 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -50,6 +50,8 @@ type Service struct { // nolint:structcheck listener net.Listener eventStreamCh chan *StreamEvent eventStreamDoneCh chan struct{} + eventQueue []*StreamEvent + eventQueueMutex sync.Mutex panicHandler types.PanicHandler eventListener listener.Listener diff --git a/internal/frontend/grpc/service_stream.go b/internal/frontend/grpc/service_stream.go index 067131e1..600d160e 100644 --- a/internal/frontend/grpc/service_stream.go +++ b/internal/frontend/grpc/service_stream.go @@ -20,7 +20,6 @@ package grpc import ( "context" - "github.com/pkg/errors" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" @@ -47,6 +46,18 @@ func (s *Service) RunEventStream(request *EventStreamRequest, server Bridge_RunE s.eventStreamDoneCh = nil }() + // if events occurred before streaming started, they've been queued. Now that the stream channel is available + // we can flush the queued + go func() { + s.eventQueueMutex.Lock() + defer s.eventQueueMutex.Unlock() + for _, event := range s.eventQueue { + s.eventStreamCh <- event + } + + s.eventQueue = nil + }() + for { select { case <-s.eventStreamDoneCh: @@ -76,8 +87,13 @@ func (s *Service) StopEventStream(_ context.Context, _ *emptypb.Empty) (*emptypb // SendEvent sends an event to the via the gRPC event stream. func (s *Service) SendEvent(event *StreamEvent) error { + s.eventQueueMutex.Lock() + defer s.eventQueueMutex.Unlock() + if s.eventStreamCh == nil { - return errors.New("gRPC service is not streaming") + // nobody is connected to the event stream, we queue events + s.eventQueue = append(s.eventQueue, event) + return nil } s.eventStreamCh <- event