mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-15 06:56:42 +00:00
feat(GODT-2261): sync progress in GUI.
This commit is contained in:
@ -49,6 +49,48 @@ qt_standard_project_setup()
|
|||||||
message(STATUS "Using Qt ${Qt6_VERSION}")
|
message(STATUS "Using Qt ${Qt6_VERSION}")
|
||||||
|
|
||||||
|
|
||||||
|
#*****************************************************************************************************************************************************
|
||||||
|
# bridgelib
|
||||||
|
#*****************************************************************************************************************************************************
|
||||||
|
find_program(GO_BIN "go")
|
||||||
|
if (NOT GO_BIN)
|
||||||
|
message(FATAL_ERROR "Could not location go compiler")
|
||||||
|
endif()
|
||||||
|
message(STATUS "go compiler is ${GO_BIN}")
|
||||||
|
|
||||||
|
if (APPLE) # set some env variable for go compiler on macOS. Note the CGO_ENABLED=1 is required when cross-compiling.
|
||||||
|
if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||||
|
set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=11.0" "GOARCH=arm64" "CGO_CFLAGS=\"-mmacosx-version-min=11.0\"" CGO_ENABLED=1 ${GO_BIN})
|
||||||
|
else ()
|
||||||
|
set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=10.15" "GOARCH=amd64" "CGO_CFLAGS=\"-mmacosx-version-min=10.15\"" CGO_ENABLED=1 ${GO_BIN})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(REAL_PATH "pkg/bridgelib" BRIDGELIB_DIR BASE_DIRECTORY "${BRIDGE_REPO_ROOT}")
|
||||||
|
message(STATUS "bridgelib folder is ${BRIDGELIB_DIR}")
|
||||||
|
|
||||||
|
set(BRIDGELIB_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
set(BRIDGELIB_BASE_NAME "bridgelib")
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.so")
|
||||||
|
endif()
|
||||||
|
if (APPLE)
|
||||||
|
set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dylib")
|
||||||
|
endif()
|
||||||
|
if (WIN32)
|
||||||
|
set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dll")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(BRIDGELIB_OUTPUT_PATH "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}")
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
bridgelib
|
||||||
|
COMMAND ${GO_BIN} build -o ${BRIDGELIB_OUTPUT_PATH} --buildmode c-shared
|
||||||
|
WORKING_DIRECTORY ${BRIDGELIB_DIR}
|
||||||
|
COMMENT "Compile bridgelib library"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#*****************************************************************************************************************************************************
|
#*****************************************************************************************************************************************************
|
||||||
# Source files and output
|
# Source files and output
|
||||||
#*****************************************************************************************************************************************************
|
#*****************************************************************************************************************************************************
|
||||||
@ -72,6 +114,8 @@ add_executable(bridge-gui-tester
|
|||||||
UserTable.cpp UserTable.h
|
UserTable.cpp UserTable.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_dependencies(bridge-gui-tester bridgelib)
|
||||||
|
|
||||||
target_precompile_headers(bridge-gui-tester PRIVATE Pch.h)
|
target_precompile_headers(bridge-gui-tester PRIVATE Pch.h)
|
||||||
target_include_directories(bridge-gui-tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(bridge-gui-tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
target_compile_definitions(bridge-gui-tester PRIVATE BRIDGE_APP_VERSION=\"${BRIDGE_APP_VERSION}\")
|
target_compile_definitions(bridge-gui-tester PRIVATE BRIDGE_APP_VERSION=\"${BRIDGE_APP_VERSION}\")
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "GRPCServerWorker.h"
|
#include "GRPCServerWorker.h"
|
||||||
#include "Cert.h"
|
#include "Cert.h"
|
||||||
#include "GRPCService.h"
|
#include "GRPCService.h"
|
||||||
|
#include <bridgepp/BridgeLib.h>
|
||||||
#include <bridgepp/Exception/Exception.h>
|
#include <bridgepp/Exception/Exception.h>
|
||||||
#include <bridgepp/GRPC/GRPCUtils.h>
|
#include <bridgepp/GRPC/GRPCUtils.h>
|
||||||
#include <bridgepp/GRPC/GRPCConfig.h>
|
#include <bridgepp/GRPC/GRPCConfig.h>
|
||||||
@ -33,7 +34,6 @@ using namespace grpc;
|
|||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
GRPCServerWorker::GRPCServerWorker(QObject *parent)
|
GRPCServerWorker::GRPCServerWorker(QObject *parent)
|
||||||
: Worker(parent) {
|
: Worker(parent) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ void GRPCServerWorker::run() {
|
|||||||
|
|
||||||
config.port = port;
|
config.port = port;
|
||||||
QString err;
|
QString err;
|
||||||
if (!config.save(grpcServerConfigPath(), &err)) {
|
if (!config.save(grpcServerConfigPath(bridgelib::userConfigDir()), &err)) {
|
||||||
throw Exception(QString("Could not save gRPC server config. %1").arg(err));
|
throw Exception(QString("Could not save gRPC server config. %1").arg(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -192,17 +192,6 @@ Status GRPCService::IsAllMailVisible(ServerContext *, Empty const *request, Bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
|
||||||
/// \param[out] response The response.
|
|
||||||
/// \return The status for the call.
|
|
||||||
//****************************************************************************************************************************************************
|
|
||||||
Status GRPCService::GoOs(ServerContext *, Empty const *, StringValue *response) {
|
|
||||||
app().log().debug(__FUNCTION__);
|
|
||||||
response->set_value(app().mainWindow().settingsTab().os().toStdString());
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
/// \return The status for the call.
|
/// \return The status for the call.
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
|
|||||||
@ -51,7 +51,6 @@ public: // member functions.
|
|||||||
grpc::Status IsBetaEnabled(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::BoolValue *response) override;
|
grpc::Status IsBetaEnabled(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::BoolValue *response) override;
|
||||||
grpc::Status SetIsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *response) override;
|
grpc::Status SetIsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *response) override;
|
||||||
grpc::Status IsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::Empty const *request, ::google::protobuf::BoolValue *response) override;
|
grpc::Status IsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::Empty const *request, ::google::protobuf::BoolValue *response) override;
|
||||||
grpc::Status GoOs(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override;
|
|
||||||
grpc::Status TriggerReset(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::Empty *) override;
|
grpc::Status TriggerReset(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::Empty *) override;
|
||||||
grpc::Status Version(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override;
|
grpc::Status Version(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override;
|
||||||
grpc::Status LogsPath(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override;
|
grpc::Status LogsPath(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override;
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "SettingsTab.h"
|
#include "SettingsTab.h"
|
||||||
#include "GRPCService.h"
|
#include "GRPCService.h"
|
||||||
|
#include <bridgepp/BridgeLib.h>
|
||||||
#include <bridgepp/GRPC/EventFactory.h>
|
#include <bridgepp/GRPC/EventFactory.h>
|
||||||
#include <bridgepp/BridgeUtils.h>
|
#include <bridgepp/BridgeUtils.h>
|
||||||
|
|
||||||
@ -438,7 +439,7 @@ void SettingsTab::resetUI() {
|
|||||||
this->setClientPlatform("Unknown");
|
this->setClientPlatform("Unknown");
|
||||||
|
|
||||||
ui_.editVersion->setText(BRIDGE_APP_VERSION);
|
ui_.editVersion->setText(BRIDGE_APP_VERSION);
|
||||||
ui_.comboOS->setCurrentText(bridgepp::goos());
|
ui_.comboOS->setCurrentText(bridgelib::goos());
|
||||||
ui_.editCurrentEmailClient->setText("Thunderbird/102.0.3");
|
ui_.editCurrentEmailClient->setText("Thunderbird/102.0.3");
|
||||||
ui_.checkShowOnStartup->setChecked(true);
|
ui_.checkShowOnStartup->setChecked(true);
|
||||||
ui_.checkShowSplashScreen->setChecked(false);
|
ui_.checkShowSplashScreen->setChecked(false);
|
||||||
|
|||||||
@ -55,6 +55,8 @@ UsersTab::UsersTab(QWidget *parent)
|
|||||||
connect(ui_.buttonImapLoginFailed, &QPushButton::clicked, this, &UsersTab::onSendIMAPLoginFailedEvent);
|
connect(ui_.buttonImapLoginFailed, &QPushButton::clicked, this, &UsersTab::onSendIMAPLoginFailedEvent);
|
||||||
connect(ui_.buttonUsedBytesChanged, &QPushButton::clicked, this, &UsersTab::onSendUsedBytesChangedEvent);
|
connect(ui_.buttonUsedBytesChanged, &QPushButton::clicked, this, &UsersTab::onSendUsedBytesChangedEvent);
|
||||||
connect(ui_.checkUsernamePasswordError, &QCheckBox::toggled, this, &UsersTab::updateGUIState);
|
connect(ui_.checkUsernamePasswordError, &QCheckBox::toggled, this, &UsersTab::updateGUIState);
|
||||||
|
connect(ui_.checkSync, &QCheckBox::toggled, this, &UsersTab::onCheckSyncToggled);
|
||||||
|
connect(ui_.sliderSync, &QSlider::valueChanged, this, &UsersTab::onSliderSyncValueChanged);
|
||||||
|
|
||||||
users_.append(randomUser());
|
users_.append(randomUser());
|
||||||
|
|
||||||
@ -217,9 +219,19 @@ void UsersTab::updateGUIState() {
|
|||||||
ui_.groupBoxUsedSpace->setEnabled(hasSelectedUser && (UserState::Connected == state));
|
ui_.groupBoxUsedSpace->setEnabled(hasSelectedUser && (UserState::Connected == state));
|
||||||
ui_.editUsernamePasswordError->setEnabled(ui_.checkUsernamePasswordError->isChecked());
|
ui_.editUsernamePasswordError->setEnabled(ui_.checkUsernamePasswordError->isChecked());
|
||||||
ui_.spinUsedBytes->setValue(user ? user->usedBytes() : 0.0);
|
ui_.spinUsedBytes->setValue(user ? user->usedBytes() : 0.0);
|
||||||
|
ui_.groupboxSync->setEnabled(user.get());
|
||||||
|
|
||||||
if (user)
|
if (user)
|
||||||
ui_.editIMAPLoginFailedUsername->setText(user->primaryEmailOrUsername());
|
ui_.editIMAPLoginFailedUsername->setText(user->primaryEmailOrUsername());
|
||||||
|
|
||||||
|
QSignalBlocker b(ui_.checkSync);
|
||||||
|
bool const syncing = user && user->isSyncing();
|
||||||
|
ui_.checkSync->setChecked(syncing);
|
||||||
|
b = QSignalBlocker(ui_.sliderSync);
|
||||||
|
ui_.sliderSync->setEnabled(syncing);
|
||||||
|
qint32 const progressPercent = syncing ? qint32(user->syncProgress() * 100.0f) : 0;
|
||||||
|
ui_.sliderSync->setValue(progressPercent);
|
||||||
|
ui_.labelSync->setText(syncing ? QString("%1%").arg(progressPercent) : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -398,3 +410,44 @@ void UsersTab::configureUserAppleMail(QString const &userID, QString const &addr
|
|||||||
app().log().info(QString("Apple mail configuration was requested for user %1, address %2").arg(userID, address));
|
app().log().info(QString("Apple mail configuration was requested for user %1, address %2").arg(userID, address));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] checked Is the sync checkbox checked?
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void UsersTab::onCheckSyncToggled(bool checked) {
|
||||||
|
SPUser const user = this->selectedUser();
|
||||||
|
if ((!user) || (user->isSyncing() == checked)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
user->setIsSyncing(checked);
|
||||||
|
user->setSyncProgress(0.0);
|
||||||
|
GRPCService &grpc = app().grpc();
|
||||||
|
|
||||||
|
// we do not apply delay for these event.
|
||||||
|
if (checked) {
|
||||||
|
grpc.sendEvent(newSyncStartedEvent(user->id()));
|
||||||
|
grpc.sendEvent(newSyncProgressEvent(user->id(), 0.0, 1, 1));
|
||||||
|
} else {
|
||||||
|
grpc.sendEvent(newSyncFinishedEvent(user->id()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->updateGUIState();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] value The value for the slider.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void UsersTab::onSliderSyncValueChanged(int value) {
|
||||||
|
SPUser const user = this->selectedUser();
|
||||||
|
if ((!user) || (!user->isSyncing()) || user->syncProgress() == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double const progress = value / 100.0;
|
||||||
|
user->setSyncProgress(progress);
|
||||||
|
app().grpc().sendEvent(newSyncProgressEvent(user->id(), progress, 1, 1)); // we do not simulate elapsed & remaining.
|
||||||
|
this->updateGUIState();
|
||||||
|
}
|
||||||
|
|||||||
@ -54,7 +54,6 @@ public slots:
|
|||||||
void logoutUser(QString const &userID); ///< slot for the logging out of a user.
|
void logoutUser(QString const &userID); ///< slot for the logging out of a user.
|
||||||
void removeUser(QString const &userID); ///< Slot for the removal of a user.
|
void removeUser(QString const &userID); ///< Slot for the removal of a user.
|
||||||
void configureUserAppleMail(QString const &userID, QString const &address); ///< Slot for the configuration of Apple mail.
|
void configureUserAppleMail(QString const &userID, QString const &address); ///< Slot for the configuration of Apple mail.
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onAddUserButton(); ///< Add a user to the user list.
|
void onAddUserButton(); ///< Add a user to the user list.
|
||||||
void onEditUserButton(); ///< Edit the currently selected user.
|
void onEditUserButton(); ///< Edit the currently selected user.
|
||||||
@ -63,6 +62,8 @@ private slots:
|
|||||||
void onSendUserBadEvent(); ///< Slot for the 'Send Bad Event Error' button.
|
void onSendUserBadEvent(); ///< Slot for the 'Send Bad Event Error' button.
|
||||||
void onSendUsedBytesChangedEvent(); ///< Slot for the 'Send Used Bytes Changed Event' button.
|
void onSendUsedBytesChangedEvent(); ///< Slot for the 'Send Used Bytes Changed Event' button.
|
||||||
void onSendIMAPLoginFailedEvent(); ///< Slot for the 'Send IMAP Login failure Event' button.
|
void onSendIMAPLoginFailedEvent(); ///< Slot for the 'Send IMAP Login failure Event' button.
|
||||||
|
void onCheckSyncToggled(bool checked); ///< Slot for the 'Synchronizing' check box.
|
||||||
|
void onSliderSyncValueChanged(int value); ///< Slot for the sync 'Progress' slider.
|
||||||
void updateGUIState(); ///< Update the GUI state.
|
void updateGUIState(); ///< Update the GUI state.
|
||||||
|
|
||||||
private: // member functions.
|
private: // member functions.
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1225</width>
|
<width>1221</width>
|
||||||
<height>717</height>
|
<height>894</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -66,6 +66,52 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupboxSync">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Sync</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,0">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkSync">
|
||||||
|
<property name="text">
|
||||||
|
<string>Synchronizing</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labelSync">
|
||||||
|
<property name="text">
|
||||||
|
<string>0%</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="sliderSync">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickInterval">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBoxBadEvent">
|
<widget class="QGroupBox" name="groupBoxBadEvent">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "AppController.h"
|
#include "AppController.h"
|
||||||
#include "GRPCServerWorker.h"
|
#include "GRPCServerWorker.h"
|
||||||
|
#include <bridgepp/BridgeLib.h>
|
||||||
#include <bridgepp/Exception/Exception.h>
|
#include <bridgepp/Exception/Exception.h>
|
||||||
#include <bridgepp/Worker/Overseer.h>
|
#include <bridgepp/Worker/Overseer.h>
|
||||||
|
|
||||||
@ -54,6 +55,8 @@ int main(int argc, char **argv) {
|
|||||||
QApplication::setOrganizationDomain("proton.ch");
|
QApplication::setOrganizationDomain("proton.ch");
|
||||||
QApplication::setQuitOnLastWindowClosed(true);
|
QApplication::setQuitOnLastWindowClosed(true);
|
||||||
|
|
||||||
|
bridgelib::loadLibrary();
|
||||||
|
|
||||||
Log &log = app().log();
|
Log &log = app().log();
|
||||||
log.setEchoInConsole(true);
|
log.setEchoInConsole(true);
|
||||||
log.setLevel(Log::Level::Debug);
|
log.setLevel(Log::Level::Debug);
|
||||||
@ -85,7 +88,10 @@ int main(int argc, char **argv) {
|
|||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
catch (Exception const &e) {
|
catch (Exception const &e) {
|
||||||
QTextStream(stderr) << QString("A fatal error occurred: %1\n").arg(e.qwhat());
|
QString message = e.qwhat();
|
||||||
|
if (!e.details().isEmpty())
|
||||||
|
message += "\n\nDetails:\n" + e.details();
|
||||||
|
QTextStream(stderr) << QString("A fatal error occurred: %1\n").arg(message);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -152,10 +152,9 @@ add_executable(bridge-gui
|
|||||||
Resources.qrc
|
Resources.qrc
|
||||||
AppController.cpp AppController.h
|
AppController.cpp AppController.h
|
||||||
BridgeApp.cpp BridgeApp.h
|
BridgeApp.cpp BridgeApp.h
|
||||||
BridgeLib.cpp BridgeLib.h
|
|
||||||
CommandLine.cpp CommandLine.h
|
CommandLine.cpp CommandLine.h
|
||||||
EventStreamWorker.cpp EventStreamWorker.h
|
EventStreamWorker.cpp EventStreamWorker.h
|
||||||
Log.cpp Log.h
|
LogUtils.cpp LogUtils.h
|
||||||
main.cpp
|
main.cpp
|
||||||
Pch.h
|
Pch.h
|
||||||
QMLBackend.cpp QMLBackend.h
|
QMLBackend.cpp QMLBackend.h
|
||||||
|
|||||||
@ -16,9 +16,9 @@
|
|||||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
#include "Log.h"
|
#include "LogUtils.h"
|
||||||
#include "BridgeLib.h"
|
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
#include <bridgepp/BridgeLib.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace bridgepp;
|
using namespace bridgepp;
|
||||||
@ -16,8 +16,8 @@
|
|||||||
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
// along with Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
#ifndef BRIDGE_GUI_LOG_H
|
#ifndef BRIDGE_GUI_LOG_UTILS_H
|
||||||
#define BRIDGE_GUI_LOG_H
|
#define BRIDGE_GUI_LOG_UTILS_H
|
||||||
|
|
||||||
|
|
||||||
#include <bridgepp/Log/Log.h>
|
#include <bridgepp/Log/Log.h>
|
||||||
@ -26,4 +26,4 @@
|
|||||||
bridgepp::Log &initLog(); ///< Initialize the application log.
|
bridgepp::Log &initLog(); ///< Initialize the application log.
|
||||||
|
|
||||||
|
|
||||||
#endif //BRIDGE_GUI_LOG_H
|
#endif //BRIDGE_GUI_LOG_UTILS_H
|
||||||
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
#include "QMLBackend.h"
|
#include "QMLBackend.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
#include "BridgeLib.h"
|
|
||||||
#include "EventStreamWorker.h"
|
#include "EventStreamWorker.h"
|
||||||
|
#include <bridgepp/BridgeLib.h>
|
||||||
#include <bridgepp/GRPC/GRPCClient.h>
|
#include <bridgepp/GRPC/GRPCClient.h>
|
||||||
#include <bridgepp/Exception/Exception.h>
|
#include <bridgepp/Exception/Exception.h>
|
||||||
#include <bridgepp/Worker/Overseer.h>
|
#include <bridgepp/Worker/Overseer.h>
|
||||||
|
|||||||
@ -17,12 +17,8 @@
|
|||||||
|
|
||||||
#include "SentryUtils.h"
|
#include "SentryUtils.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
#include "BridgeLib.h"
|
#include <bridgepp/BridgeLib.h>
|
||||||
#include <bridgepp/BridgeUtils.h>
|
#include <bridgepp/BridgeUtils.h>
|
||||||
#include <QByteArray>
|
|
||||||
#include <QCryptographicHash>
|
|
||||||
#include <QString>
|
|
||||||
#include <QSysInfo>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace bridgepp;
|
using namespace bridgepp;
|
||||||
|
|||||||
@ -39,6 +39,9 @@ void UserList::connectGRPCEvents() const {
|
|||||||
connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged);
|
connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged);
|
||||||
connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished);
|
connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished);
|
||||||
connect(&client, &GRPCClient::usedBytesChanged, this, &UserList::onUsedBytesChanged);
|
connect(&client, &GRPCClient::usedBytesChanged, this, &UserList::onUsedBytesChanged);
|
||||||
|
connect(&client, &GRPCClient::syncStarted, this, &UserList::onSyncStarted);
|
||||||
|
connect(&client, &GRPCClient::syncFinished, this, &UserList::onSyncFinished);
|
||||||
|
connect(&client, &GRPCClient::syncProgress, this, &UserList::onSyncProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -251,3 +254,47 @@ void UserList::onUsedBytesChanged(QString const &userID, qint64 usedBytes) {
|
|||||||
}
|
}
|
||||||
users_[index]->setUsedBytes(usedBytes);
|
users_[index]->setUsedBytes(usedBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] userID The userID.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void UserList::onSyncStarted(QString const &userID) {
|
||||||
|
int const index = this->rowOfUserID(userID);
|
||||||
|
if (index < 0) {
|
||||||
|
app().log().error(QString("Received onSyncStarted event for unknown userID %1").arg(userID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
users_[index]->setIsSyncing(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] userID The userID.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void UserList::onSyncFinished(QString const &userID) {
|
||||||
|
int const index = this->rowOfUserID(userID);
|
||||||
|
if (index < 0) {
|
||||||
|
app().log().error(QString("Received onSyncFinished event for unknown userID %1").arg(userID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
users_[index]->setIsSyncing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] userID The userID.
|
||||||
|
/// \param[in] progress The sync progress ratio.
|
||||||
|
/// \param[in] elapsedMs The elapsed sync time in milliseconds.
|
||||||
|
/// \param[in] remainingMs The remaining sync time in milliseconds.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void UserList::onSyncProgress(QString const &userID, double progress, float elapsedMs, float remainingMs) {
|
||||||
|
Q_UNUSED(elapsedMs)
|
||||||
|
Q_UNUSED(remainingMs)
|
||||||
|
int const index = this->rowOfUserID(userID);
|
||||||
|
if (index < 0) {
|
||||||
|
app().log().error(QString("Received onSyncFinished event for unknown userID %1").arg(userID));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
users_[index]->setSyncProgress(progress);
|
||||||
|
}
|
||||||
|
|||||||
@ -61,6 +61,9 @@ public slots: ///< handler for signals coming from the gRPC service
|
|||||||
void onUserChanged(QString const &userID);
|
void onUserChanged(QString const &userID);
|
||||||
void onToggleSplitModeFinished(QString const &userID);
|
void onToggleSplitModeFinished(QString const &userID);
|
||||||
void onUsedBytesChanged(QString const &userID, qint64 usedBytes); ///< Slot for usedBytesChanged events.
|
void onUsedBytesChanged(QString const &userID, qint64 usedBytes); ///< Slot for usedBytesChanged events.
|
||||||
|
void onSyncStarted(QString const &userID); ///< Slot for syncStarted events.
|
||||||
|
void onSyncFinished(QString const &userID); ///< Slot for syncFinished events.
|
||||||
|
void onSyncProgress(QString const &userID, double progress, float elapsedMs, float remainingMs); ///< Slot for syncFinished events.
|
||||||
|
|
||||||
private: // data members
|
private: // data members
|
||||||
QList<bridgepp::SPUser> users_; ///< The user list.
|
QList<bridgepp::SPUser> users_; ///< The user list.
|
||||||
|
|||||||
@ -18,12 +18,12 @@
|
|||||||
|
|
||||||
#include "Pch.h"
|
#include "Pch.h"
|
||||||
#include "BridgeApp.h"
|
#include "BridgeApp.h"
|
||||||
#include "BridgeLib.h"
|
|
||||||
#include "CommandLine.h"
|
#include "CommandLine.h"
|
||||||
#include "Log.h"
|
#include "LogUtils.h"
|
||||||
#include "QMLBackend.h"
|
#include "QMLBackend.h"
|
||||||
#include "SentryUtils.h"
|
#include "SentryUtils.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
#include <bridgepp/BridgeLib.h>
|
||||||
#include <bridgepp/BridgeUtils.h>
|
#include <bridgepp/BridgeUtils.h>
|
||||||
#include <bridgepp/Exception/Exception.h>
|
#include <bridgepp/Exception/Exception.h>
|
||||||
#include <bridgepp/FocusGRPC/FocusGRPCClient.h>
|
#include <bridgepp/FocusGRPC/FocusGRPCClient.h>
|
||||||
|
|||||||
@ -29,14 +29,19 @@ Item {
|
|||||||
|
|
||||||
property var _spacing: 12 * ProtonStyle.px
|
property var _spacing: 12 * ProtonStyle.px
|
||||||
|
|
||||||
property color usedSpaceColor : {
|
property color progressColor : {
|
||||||
if (!root.enabled) return root.colorScheme.text_weak
|
if (!root.enabled) return root.colorScheme.text_weak
|
||||||
if (root.type == AccountDelegate.SmallView) return root.colorScheme.text_weak
|
if (root.type == AccountDelegate.SmallView) return root.colorScheme.text_weak
|
||||||
if (root.usedFraction < .50) return root.colorScheme.signal_success
|
if (root.user && root.user.isSyncing) return root.colorScheme.text_weak
|
||||||
if (root.usedFraction < .75) return root.colorScheme.signal_warning
|
if (root.progressRatio < .50) return root.colorScheme.signal_success
|
||||||
|
if (root.progressRatio < .75) return root.colorScheme.signal_warning
|
||||||
return root.colorScheme.signal_danger
|
return root.colorScheme.signal_danger
|
||||||
}
|
}
|
||||||
property real usedFraction: root.user ? reasonableFraction(root.user.usedBytes, root.user.totalBytes) : 0
|
property real progressRatio: {
|
||||||
|
if (!root.user)
|
||||||
|
return 0
|
||||||
|
return root.user.isSyncing ? root.user.syncProgress : reasonableFraction(root.user.usedBytes, root.user.totalBytes)
|
||||||
|
}
|
||||||
property string totalSpace: root.spaceWithUnits(root.user ? root.reasonableBytes(root.user.totalBytes) : 0)
|
property string totalSpace: root.spaceWithUnits(root.user ? root.reasonableBytes(root.user.totalBytes) : 0)
|
||||||
property string usedSpace: root.spaceWithUnits(root.user ? root.reasonableBytes(root.user.usedBytes) : 0)
|
property string usedSpace: root.spaceWithUnits(root.user ? root.reasonableBytes(root.user.usedBytes) : 0)
|
||||||
|
|
||||||
@ -171,18 +176,21 @@ Item {
|
|||||||
case EUserState.Locked:
|
case EUserState.Locked:
|
||||||
return qsTr("Connecting") + dotsTimer.dots
|
return qsTr("Connecting") + dotsTimer.dots
|
||||||
case EUserState.Connected:
|
case EUserState.Connected:
|
||||||
return root.usedSpace
|
if (root.user.isSyncing)
|
||||||
|
return qsTr("Synchronizing (%1%)").arg(Math.floor(root.user.syncProgress * 100)) + dotsTimer.dots
|
||||||
|
else
|
||||||
|
return root.usedSpace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer { // dots animation while connecting. 1 sec cycle, roughly similar to the webmail loading page.
|
Timer { // dots animation while connecting & syncing.
|
||||||
id:dotsTimer
|
id:dotsTimer
|
||||||
property string dots: ""
|
property string dots: ""
|
||||||
interval: 250;
|
interval: 500;
|
||||||
repeat: true;
|
repeat: true;
|
||||||
running: (root.user != null) && (root.user.state === EUserState.Locked)
|
running: (root.user != null) && ((root.user.state === EUserState.Locked) || (root.user.isSyncing))
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
dots = dots + "."
|
dots += "."
|
||||||
if (dots.length > 3)
|
if (dots.length > 3)
|
||||||
dots = ""
|
dots = ""
|
||||||
}
|
}
|
||||||
@ -191,7 +199,7 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
color: root.usedSpaceColor
|
color: root.progressColor
|
||||||
type: {
|
type: {
|
||||||
switch (root.type) {
|
switch (root.type) {
|
||||||
case AccountDelegate.SmallView: return Label.Caption
|
case AccountDelegate.SmallView: return Label.Caption
|
||||||
@ -202,7 +210,7 @@ Item {
|
|||||||
|
|
||||||
Label {
|
Label {
|
||||||
colorScheme: root.colorScheme
|
colorScheme: root.colorScheme
|
||||||
text: root.user && root.user.state == EUserState.Connected ? " / " + root.totalSpace : ""
|
text: root.user && root.user.state == EUserState.Connected && !root.user.isSyncing ? " / " + root.totalSpace : ""
|
||||||
color: root.colorScheme.text_weak
|
color: root.colorScheme.text_weak
|
||||||
type: {
|
type: {
|
||||||
switch (root.type) {
|
switch (root.type) {
|
||||||
@ -213,26 +221,27 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item { implicitHeight: root.type == AccountDelegate.LargeView ? 3 * ProtonStyle.px : 0 }
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: storage_bar
|
id: progress_bar
|
||||||
visible: root.user ? root.type == AccountDelegate.LargeView : false
|
visible: root.user ? root.type == AccountDelegate.LargeView : false
|
||||||
width: 140 * ProtonStyle.px
|
width: 140 * ProtonStyle.px
|
||||||
height: 4 * ProtonStyle.px
|
height: 4 * ProtonStyle.px
|
||||||
radius: ProtonStyle.storage_bar_radius
|
radius: ProtonStyle.progress_bar_radius
|
||||||
color: root.colorScheme.border_weak
|
color: root.colorScheme.border_weak
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: storage_bar_filled
|
id: progress_bar_filled
|
||||||
radius: ProtonStyle.storage_bar_radius
|
radius: ProtonStyle.progress_bar_radius
|
||||||
color: root.usedSpaceColor
|
color: root.progressColor
|
||||||
visible: root.user ? parent.visible && (root.user.state == EUserState.Connected) : false
|
visible: root.user ? parent.visible && (root.user.state == EUserState.Connected): false
|
||||||
anchors {
|
anchors {
|
||||||
top : parent.top
|
top : parent.top
|
||||||
bottom : parent.bottom
|
bottom : parent.bottom
|
||||||
left : parent.left
|
left : parent.left
|
||||||
}
|
}
|
||||||
width: Math.min(1,Math.max(0.02,root.usedFraction)) * parent.width
|
width: Math.min(1,Math.max(0.02,root.progressRatio)) * parent.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -362,7 +362,7 @@ QtObject {
|
|||||||
property real banner_radius : 12 * root.px // px
|
property real banner_radius : 12 * root.px // px
|
||||||
property real dialog_radius : 12 * root.px // px
|
property real dialog_radius : 12 * root.px // px
|
||||||
property real card_radius : 12 * root.px // px
|
property real card_radius : 12 * root.px // px
|
||||||
property real storage_bar_radius : 3 * root.px // px
|
property real progress_bar_radius : 3 * root.px // px
|
||||||
property real tooltip_radius : 8 * root.px // px
|
property real tooltip_radius : 8 * root.px // px
|
||||||
|
|
||||||
property int heading_font_size: 28
|
property int heading_font_size: 28
|
||||||
|
|||||||
@ -135,6 +135,7 @@ add_custom_command(
|
|||||||
|
|
||||||
|
|
||||||
add_library(bridgepp
|
add_library(bridgepp
|
||||||
|
bridgepp/BridgeLib.cpp bridgepp/BridgeLib.h
|
||||||
bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h
|
bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h
|
||||||
bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp
|
bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp
|
||||||
bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h
|
bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h
|
||||||
|
|||||||
@ -601,6 +601,51 @@ SPStreamEvent newIMAPLoginFailedEvent(QString const &username) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] userID The userID.
|
||||||
|
/// \return The event.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
SPStreamEvent newSyncStartedEvent(QString const &userID) {
|
||||||
|
auto event = new grpc::SyncStartedEvent;
|
||||||
|
event->set_userid(userID.toStdString());
|
||||||
|
auto userEvent = new grpc::UserEvent;
|
||||||
|
userEvent->set_allocated_syncstartedevent(event);
|
||||||
|
return wrapUserEvent(userEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] userID The userID.
|
||||||
|
/// \return The event.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
SPStreamEvent newSyncFinishedEvent(QString const &userID) {
|
||||||
|
auto event = new grpc::SyncFinishedEvent;
|
||||||
|
event->set_userid(userID.toStdString());
|
||||||
|
auto userEvent = new grpc::UserEvent;
|
||||||
|
userEvent->set_allocated_syncfinishedevent(event);
|
||||||
|
return wrapUserEvent(userEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] userID The userID.
|
||||||
|
/// \param[in] progress The progress ratio.
|
||||||
|
/// \param[in] elapsedMs The elapsed time in milliseconds.
|
||||||
|
/// \param[in] remainingMs The remaining time in milliseconds.
|
||||||
|
/// \return The event.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
SPStreamEvent newSyncProgressEvent(QString const &userID, double progress, qint64 elapsedMs, qint64 remainingMs) {
|
||||||
|
auto event = new grpc::SyncProgressEvent;
|
||||||
|
event->set_userid(userID.toStdString());
|
||||||
|
event->set_progress(progress);
|
||||||
|
event->set_elapsedms(elapsedMs);
|
||||||
|
event->set_remainingms(remainingMs);
|
||||||
|
auto userEvent = new grpc::UserEvent;
|
||||||
|
userEvent->set_allocated_syncprogressevent(event);
|
||||||
|
return wrapUserEvent(userEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
/// \param[in] errorCode The error errorCode.
|
/// \param[in] errorCode The error errorCode.
|
||||||
/// \return The event.
|
/// \return The event.
|
||||||
|
|||||||
@ -80,6 +80,9 @@ SPStreamEvent newUserChangedEvent(QString const &userID); ///< Create a new User
|
|||||||
SPStreamEvent newUserBadEvent(QString const &userID, QString const& errorMessage); ///< Create a new UserBadEvent event.
|
SPStreamEvent newUserBadEvent(QString const &userID, QString const& errorMessage); ///< Create a new UserBadEvent event.
|
||||||
SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes); ///< Create a new UsedBytesChangedEvent event.
|
SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes); ///< Create a new UsedBytesChangedEvent event.
|
||||||
SPStreamEvent newIMAPLoginFailedEvent(QString const &username); ///< Create a new ImapLoginFailedEvent event.
|
SPStreamEvent newIMAPLoginFailedEvent(QString const &username); ///< Create a new ImapLoginFailedEvent event.
|
||||||
|
SPStreamEvent newSyncStartedEvent(QString const &userID); ///< Create a new SyncStarted event.
|
||||||
|
SPStreamEvent newSyncFinishedEvent(QString const &userID); ///< Create a new SyncFinished event.
|
||||||
|
SPStreamEvent newSyncProgressEvent(QString const &userID, double progress, qint64 elapsedMs, qint64 remainingMs); ///< Create a new SyncFinished event.
|
||||||
|
|
||||||
// Generic error event
|
// Generic error event
|
||||||
SPStreamEvent newGenericErrorEvent(grpc::ErrorCode errorCode); ///< Create a new GenericErrrorEvent event.
|
SPStreamEvent newGenericErrorEvent(grpc::ErrorCode errorCode); ///< Create a new GenericErrrorEvent event.
|
||||||
|
|||||||
@ -1380,6 +1380,28 @@ void GRPCClient::processUserEvent(UserEvent const &event) {
|
|||||||
emit imapLoginFailed(username);
|
emit imapLoginFailed(username);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case UserEvent::kSyncStartedEvent: {
|
||||||
|
SyncStartedEvent const &e = event.syncstartedevent();
|
||||||
|
QString const &userID = QString::fromStdString(e.userid());
|
||||||
|
this->logTrace(QString("User event received: SyncStarted (userID = %1).:").arg(userID));
|
||||||
|
emit syncStarted(userID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UserEvent::kSyncFinishedEvent: {
|
||||||
|
SyncFinishedEvent const &e = event.syncfinishedevent();
|
||||||
|
QString const &userID = QString::fromStdString(e.userid());
|
||||||
|
this->logTrace(QString("User event received: SyncFinished (userID = %1).:").arg(userID));
|
||||||
|
emit syncFinished(userID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UserEvent::kSyncProgressEvent: {
|
||||||
|
SyncProgressEvent const &e = event.syncprogressevent();
|
||||||
|
QString const &userID = QString::fromStdString(e.userid());
|
||||||
|
this->logTrace(QString("User event received SyncProgress (userID = %1, progress = %2, elapsedMs = %3, remainingMs = %4).").arg(userID)
|
||||||
|
.arg(e.progress()).arg(e.elapsedms()).arg(e.remainingms()));
|
||||||
|
emit syncProgress(userID, e.progress(), e.elapsedms(), e.remainingms());
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
this->logError("Unknown User event received.");
|
this->logError("Unknown User event received.");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -181,6 +181,9 @@ signals:
|
|||||||
void userBadEvent(QString const &userID, QString const& errorMessage);
|
void userBadEvent(QString const &userID, QString const& errorMessage);
|
||||||
void usedBytesChanged(QString const &userID, qint64 usedBytes);
|
void usedBytesChanged(QString const &userID, qint64 usedBytes);
|
||||||
void imapLoginFailed(QString const& username);
|
void imapLoginFailed(QString const& username);
|
||||||
|
void syncStarted(QString const &userID);
|
||||||
|
void syncFinished(QString const &userID);
|
||||||
|
void syncProgress(QString const &userID, double progress, qint64 elapsedMs, qint64 remainingMs);
|
||||||
|
|
||||||
public: // keychain related calls
|
public: // keychain related calls
|
||||||
grpc::Status availableKeychains(QStringList &outKeychains);
|
grpc::Status availableKeychains(QStringList &outKeychains);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -294,6 +294,48 @@ void User::setTotalBytes(float totalBytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \return true iff a sync is in progress.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
bool User::isSyncing() const {
|
||||||
|
return isSyncing_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] syncing The new value for the sync state.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void User::setIsSyncing(bool syncing) {
|
||||||
|
if (isSyncing_ == syncing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSyncing_ = syncing;
|
||||||
|
emit isSyncingChanged(syncing);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \return The sync progress ratio
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
float User::syncProgress() const {
|
||||||
|
return syncProgress_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
/// \param[in] progress The progress ratio.
|
||||||
|
//****************************************************************************************************************************************************
|
||||||
|
void User::setSyncProgress(float progress) {
|
||||||
|
if (qAbs(syncProgress_ - progress) < 0.00001) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
syncProgress_ = progress;
|
||||||
|
emit syncProgressChanged(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//****************************************************************************************************************************************************
|
//****************************************************************************************************************************************************
|
||||||
/// \param[in] state The user state.
|
/// \param[in] state The user state.
|
||||||
/// \return A string describing the state.
|
/// \return A string describing the state.
|
||||||
|
|||||||
@ -101,6 +101,8 @@ public:
|
|||||||
Q_PROPERTY(bool splitMode READ splitMode WRITE setSplitMode NOTIFY splitModeChanged)
|
Q_PROPERTY(bool splitMode READ splitMode WRITE setSplitMode NOTIFY splitModeChanged)
|
||||||
Q_PROPERTY(float usedBytes READ usedBytes WRITE setUsedBytes NOTIFY usedBytesChanged)
|
Q_PROPERTY(float usedBytes READ usedBytes WRITE setUsedBytes NOTIFY usedBytesChanged)
|
||||||
Q_PROPERTY(float totalBytes READ totalBytes WRITE setTotalBytes NOTIFY totalBytesChanged)
|
Q_PROPERTY(float totalBytes READ totalBytes WRITE setTotalBytes NOTIFY totalBytesChanged)
|
||||||
|
Q_PROPERTY(bool isSyncing READ isSyncing WRITE setIsSyncing NOTIFY isSyncingChanged)
|
||||||
|
Q_PROPERTY(float syncProgress READ syncProgress WRITE setSyncProgress NOTIFY syncProgressChanged)
|
||||||
|
|
||||||
QString id() const;
|
QString id() const;
|
||||||
void setID(QString const &id);
|
void setID(QString const &id);
|
||||||
@ -120,6 +122,10 @@ public:
|
|||||||
void setUsedBytes(float usedBytes);
|
void setUsedBytes(float usedBytes);
|
||||||
float totalBytes() const;
|
float totalBytes() const;
|
||||||
void setTotalBytes(float totalBytes);
|
void setTotalBytes(float totalBytes);
|
||||||
|
bool isSyncing() const;
|
||||||
|
void setIsSyncing(bool syncing);
|
||||||
|
float syncProgress() const;
|
||||||
|
void setSyncProgress(float progress);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// signals used for Qt properties
|
// signals used for Qt properties
|
||||||
@ -134,6 +140,8 @@ signals:
|
|||||||
void usedBytesChanged(float byteCount);
|
void usedBytesChanged(float byteCount);
|
||||||
void totalBytesChanged(float byteCount);
|
void totalBytesChanged(float byteCount);
|
||||||
void toggleSplitModeFinished();
|
void toggleSplitModeFinished();
|
||||||
|
void isSyncingChanged(bool syncing);
|
||||||
|
void syncProgressChanged(float syncProgress);
|
||||||
|
|
||||||
private: // member functions.
|
private: // member functions.
|
||||||
User(QObject *parent); ///< Default constructor.
|
User(QObject *parent); ///< Default constructor.
|
||||||
@ -149,6 +157,8 @@ private: // data members.
|
|||||||
bool splitMode_ { false }; ///< Is split mode active.
|
bool splitMode_ { false }; ///< Is split mode active.
|
||||||
float usedBytes_ { 0.0f }; ///< The storage used by the user.
|
float usedBytes_ { 0.0f }; ///< The storage used by the user.
|
||||||
float totalBytes_ { 1.0f }; ///< The storage quota of the user.
|
float totalBytes_ { 1.0f }; ///< The storage quota of the user.
|
||||||
|
bool isSyncing_ { false }; ///< Is a sync in progress for the user.
|
||||||
|
float syncProgress_ { 0.0f }; ///< The sync progress.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -449,6 +449,9 @@ message UserEvent {
|
|||||||
UserBadEvent userBadEvent = 4;
|
UserBadEvent userBadEvent = 4;
|
||||||
UsedBytesChangedEvent usedBytesChangedEvent = 5;
|
UsedBytesChangedEvent usedBytesChangedEvent = 5;
|
||||||
ImapLoginFailedEvent imapLoginFailedEvent = 6;
|
ImapLoginFailedEvent imapLoginFailedEvent = 6;
|
||||||
|
SyncStartedEvent syncStartedEvent = 7;
|
||||||
|
SyncFinishedEvent syncFinishedEvent = 8;
|
||||||
|
SyncProgressEvent syncProgressEvent = 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -478,6 +481,21 @@ message ImapLoginFailedEvent {
|
|||||||
string username = 1;
|
string username = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SyncStartedEvent {
|
||||||
|
string userID = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SyncFinishedEvent {
|
||||||
|
string userID = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SyncProgressEvent {
|
||||||
|
string userID = 1;
|
||||||
|
double progress = 2;
|
||||||
|
int64 elapsedMs = 3;
|
||||||
|
int64 remainingMs = 4;
|
||||||
|
}
|
||||||
|
|
||||||
//**********************************************************
|
//**********************************************************
|
||||||
// Generic errors
|
// Generic errors
|
||||||
//**********************************************************
|
//**********************************************************
|
||||||
|
|||||||
@ -185,6 +185,23 @@ func newIMAPLoginFailedEvent(username string) *StreamEvent {
|
|||||||
return userEvent(&UserEvent{Event: &UserEvent_ImapLoginFailedEvent{ImapLoginFailedEvent: &ImapLoginFailedEvent{Username: username}}})
|
return userEvent(&UserEvent{Event: &UserEvent_ImapLoginFailedEvent{ImapLoginFailedEvent: &ImapLoginFailedEvent{Username: username}}})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewSyncStartedEvent(userID string) *StreamEvent {
|
||||||
|
return userEvent(&UserEvent{Event: &UserEvent_SyncStartedEvent{SyncStartedEvent: &SyncStartedEvent{UserID: userID}}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncFinishedEvent(userID string) *StreamEvent {
|
||||||
|
return userEvent(&UserEvent{Event: &UserEvent_SyncFinishedEvent{SyncFinishedEvent: &SyncFinishedEvent{UserID: userID}}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSyncProgressEvent(userID string, progress float64, elapsedMs, remainingMs int64) *StreamEvent {
|
||||||
|
return userEvent(&UserEvent{Event: &UserEvent_SyncProgressEvent{SyncProgressEvent: &SyncProgressEvent{
|
||||||
|
UserID: userID,
|
||||||
|
Progress: progress,
|
||||||
|
ElapsedMs: elapsedMs,
|
||||||
|
RemainingMs: remainingMs,
|
||||||
|
}}})
|
||||||
|
}
|
||||||
|
|
||||||
func NewGenericErrorEvent(errorCode ErrorCode) *StreamEvent {
|
func NewGenericErrorEvent(errorCode ErrorCode) *StreamEvent {
|
||||||
return genericErrorEvent(&GenericErrorEvent{Code: errorCode})
|
return genericErrorEvent(&GenericErrorEvent{Code: errorCode})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -323,6 +323,15 @@ func (s *Service) watchEvents() {
|
|||||||
case events.UserBadEvent:
|
case events.UserBadEvent:
|
||||||
_ = s.SendEvent(NewUserBadEvent(event.UserID, event.Error.Error()))
|
_ = s.SendEvent(NewUserBadEvent(event.UserID, event.Error.Error()))
|
||||||
|
|
||||||
|
case events.SyncStarted:
|
||||||
|
_ = s.SendEvent(NewSyncStartedEvent(event.UserID))
|
||||||
|
|
||||||
|
case events.SyncFinished:
|
||||||
|
_ = s.SendEvent(NewSyncFinishedEvent(event.UserID))
|
||||||
|
|
||||||
|
case events.SyncProgress:
|
||||||
|
_ = s.SendEvent(NewSyncProgressEvent(event.UserID, event.Progress, event.Elapsed.Milliseconds(), event.Remaining.Milliseconds()))
|
||||||
|
|
||||||
case events.UpdateLatest:
|
case events.UpdateLatest:
|
||||||
safe.RLock(func() {
|
safe.RLock(func() {
|
||||||
s.latest = event.Version
|
s.latest = event.Version
|
||||||
|
|||||||
Reference in New Issue
Block a user