summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp44
-rw-r--r--src/MainWindow.cpp41
-rw-r--r--src/MainWindow.h4
-rw-r--r--src/UserSettingsPage.cpp72
-rw-r--r--src/UserSettingsPage.h28
-rw-r--r--src/main.cpp64
6 files changed, 179 insertions, 74 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp

index 674b5793..8ea44e13 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp
@@ -21,6 +21,7 @@ #include <QByteArray> #include <QCoreApplication> +#include <QCryptographicHash> #include <QFile> #include <QHash> #include <QMap> @@ -41,6 +42,7 @@ #include "Logging.h" #include "MatrixClient.h" #include "Olm.h" +#include "UserSettingsPage.h" #include "Utils.h" //! Should be changed when a breaking change occurs in the cache format. @@ -165,17 +167,15 @@ Cache::Cache(const QString &userId, QObject *parent) void Cache::setup() { - nhlog::db()->debug("setting up cache"); + UserSettings settings; - auto statePath = QString("%1/%2") - .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) - .arg(QString::fromUtf8(localUserId_.toUtf8().toHex())); + nhlog::db()->debug("setting up cache"); - cacheDirectory_ = QString("%1/%2") + cacheDirectory_ = QString("%1/%2%3") .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) - .arg(QString::fromUtf8(localUserId_.toUtf8().toHex())); + .arg(QString::fromUtf8(localUserId_.toUtf8().toHex())).arg(QString::fromUtf8(settings.profile().toUtf8().toHex())); - bool isInitial = !QFile::exists(statePath); + bool isInitial = !QFile::exists(cacheDirectory_); env_ = lmdb::env::create(); env_.set_mapsize(DB_SIZE); @@ -184,9 +184,9 @@ Cache::setup() if (isInitial) { nhlog::db()->info("initializing LMDB"); - if (!QDir().mkpath(statePath)) { + if (!QDir().mkpath(cacheDirectory_)) { throw std::runtime_error( - ("Unable to create state directory:" + statePath).toStdString().c_str()); + ("Unable to create state directory:" + cacheDirectory_).toStdString().c_str()); } } @@ -194,7 +194,7 @@ Cache::setup() // NOTE(Nico): We may want to use (MDB_MAPASYNC | MDB_WRITEMAP) in the future, but // it can really mess up our database, so we shouldn't. For now, hopefully // NOMETASYNC is fast enough. - env_.open(statePath.toStdString().c_str(), MDB_NOMETASYNC | MDB_NOSYNC); + env_.open(cacheDirectory_.toStdString().c_str(), MDB_NOMETASYNC | MDB_NOSYNC); } catch (const lmdb::error &e) { if (e.code() != MDB_VERSION_MISMATCH && e.code() != MDB_INVALID) { throw std::runtime_error("LMDB initialization failed" + @@ -203,15 +203,14 @@ Cache::setup() nhlog::db()->warn("resetting cache due to LMDB version mismatch: {}", e.what()); - QDir stateDir(statePath); + QDir stateDir(cacheDirectory_); for (const auto &file : stateDir.entryList(QDir::NoDotAndDotDot)) { if (!stateDir.remove(file)) throw std::runtime_error( ("Unable to delete file " + file).toStdString().c_str()); } - - env_.open(statePath.toStdString().c_str()); + env_.open(cacheDirectory_.toStdString().c_str()); } auto txn = lmdb::txn::begin(env_); @@ -513,7 +512,6 @@ Cache::getLatestOlmSession(const std::string &curve25519) auto db = getOlmSessionsDb(txn, curve25519); std::string session_id, pickled_session; - std::vector<std::string> res; std::optional<StoredOlmSession> currentNewest; @@ -577,10 +575,14 @@ Cache::restoreOlmAccount() void Cache::storeSecret(const std::string &name, const std::string &secret) { + UserSettings settings; QKeychain::WritePasswordJob job(QCoreApplication::applicationName()); job.setAutoDelete(false); job.setInsecureFallback(true); - job.setKey(QString::fromStdString(name)); + job.setKey( + "matrix." + + QString(QCryptographicHash::hash(settings.profile().toUtf8(), QCryptographicHash::Sha256)) + + "." + name.c_str()); job.setTextData(QString::fromStdString(secret)); QEventLoop loop; job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); @@ -598,10 +600,14 @@ Cache::storeSecret(const std::string &name, const std::string &secret) void Cache::deleteSecret(const std::string &name) { + UserSettings settings; QKeychain::DeletePasswordJob job(QCoreApplication::applicationName()); job.setAutoDelete(false); job.setInsecureFallback(true); - job.setKey(QString::fromStdString(name)); + job.setKey( + "matrix." + + QString(QCryptographicHash::hash(settings.profile().toUtf8(), QCryptographicHash::Sha256)) + + "." + name.c_str()); QEventLoop loop; job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); @@ -613,10 +619,14 @@ Cache::deleteSecret(const std::string &name) std::optional<std::string> Cache::secret(const std::string &name) { + UserSettings settings; QKeychain::ReadPasswordJob job(QCoreApplication::applicationName()); job.setAutoDelete(false); job.setInsecureFallback(true); - job.setKey(QString::fromStdString(name)); + job.setKey( + "matrix." + + QString(QCryptographicHash::hash(settings.profile().toUtf8(), QCryptographicHash::Sha256)) + + "." + name.c_str()); QEventLoop loop; job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit); job.start(); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index d056aca6..ffd0e30b 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp
@@ -55,9 +55,9 @@ MainWindow *MainWindow::instance_ = nullptr; -MainWindow::MainWindow(const QString profile, QWidget *parent) - : QMainWindow(parent) - , profile_{profile} +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), + userSettings_{QSharedPointer<UserSettings>{new UserSettings}} { setWindowTitle(0); setObjectName("MainWindow"); @@ -70,8 +70,7 @@ MainWindow::MainWindow(const QString profile, QWidget *parent) font.setStyleStrategy(QFont::PreferAntialias); setFont(font); - userSettings_ = QSharedPointer<UserSettings>(new UserSettings); - trayIcon_ = new TrayIcon(":/logos/nheko.svg", this); + trayIcon_ = new TrayIcon(":/logos/nheko.svg", this); welcome_page_ = new WelcomePage(this); login_page_ = new LoginPage(this); @@ -150,15 +149,13 @@ MainWindow::MainWindow(const QString profile, QWidget *parent) chat_page_->showQuickSwitcher(); }); - QSettings settings; - trayIcon_->setVisible(userSettings_->tray()); if (hasActiveUser()) { - QString token = settings.value("auth/access_token").toString(); - QString home_server = settings.value("auth/home_server").toString(); - QString user_id = settings.value("auth/user_id").toString(); - QString device_id = settings.value("auth/device_id").toString(); + QString token = userSettings_->accessToken(); + QString home_server = userSettings_->homeserver(); + QString user_id = userSettings_->userId(); + QString device_id = userSettings_->deviceId(); http::client()->set_access_token(token.toStdString()); http::client()->set_server(home_server.toStdString()); @@ -184,8 +181,9 @@ void MainWindow::setWindowTitle(int notificationCount) { QString name = "nheko"; - if (!profile_.isEmpty()) - name += " | " + profile_; + + if (!userSettings_.data()->profile().isEmpty()) + name += " | " + userSettings_.data()->profile(); if (notificationCount > 0) { name.append(QString{" (%1)"}.arg(notificationCount)); } @@ -279,11 +277,10 @@ MainWindow::showChatPage() std::to_string(http::client()->port())); auto token = QString::fromStdString(http::client()->access_token()); - QSettings settings; - settings.setValue("auth/access_token", token); - settings.setValue("auth/home_server", homeserver); - settings.setValue("auth/user_id", userid); - settings.setValue("auth/device_id", device_id); + userSettings_.data()->setUserId(userid); + userSettings_.data()->setAccessToken(token); + userSettings_.data()->setDeviceId(device_id); + userSettings_.data()->setHomeserver(homeserver); showOverlayProgressBar(); @@ -341,9 +338,13 @@ bool MainWindow::hasActiveUser() { QSettings settings; + QString prefix; + if (userSettings_->profile() != "") + prefix = "profile/" + userSettings_->profile() + "/"; - return settings.contains("auth/access_token") && settings.contains("auth/home_server") && - settings.contains("auth/user_id"); + return settings.contains(prefix + "auth/access_token") && + settings.contains(prefix + "auth/home_server") && + settings.contains(prefix + "auth/user_id"); } void diff --git a/src/MainWindow.h b/src/MainWindow.h
index 2f9ff897..0915a849 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h
@@ -62,7 +62,7 @@ class MainWindow : public QMainWindow Q_OBJECT public: - explicit MainWindow(const QString name, QWidget *parent = nullptr); + explicit MainWindow(QWidget *parent = nullptr); static MainWindow *instance() { return instance_; }; void saveCurrentWindowSize(); @@ -149,6 +149,4 @@ private: LoadingIndicator *spinner_ = nullptr; JdenticonInterface *jdenticonInteface_ = nullptr; - - QString profile_; }; diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index 708fb7fd..55f666c1 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp
@@ -89,6 +89,14 @@ UserSettings::load() cameraResolution_ = settings.value("user/camera_resolution", QString()).toString(); cameraFrameRate_ = settings.value("user/camera_frame_rate", QString()).toString(); useStunServer_ = settings.value("user/use_stun_server", false).toBool(); + profile_ = settings.value("user/currentProfile", "").toString(); + + QString prefix = + (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; + accessToken_ = settings.value(prefix + "auth/access_token", "").toString(); + homeserver_ = settings.value(prefix + "auth/home_server", "").toString(); + userId_ = settings.value(prefix + "auth/user_id", "").toString(); + deviceId_ = settings.value(prefix + "auth/device_id", "").toString(); applyTheme(); } @@ -373,6 +381,56 @@ UserSettings::setCameraFrameRate(QString frameRate) } void +UserSettings::setProfile(QString profile) +{ + if (profile == profile_) + return; + profile_ = profile; + emit profileChanged(profile_); + save(); +} + +void +UserSettings::setUserId(QString userId) +{ + if (userId == userId_) + return; + userId_ = userId; + emit userIdChanged(userId_); + save(); +} + +void +UserSettings::setAccessToken(QString accessToken) +{ + if (accessToken == accessToken_) + return; + accessToken_ = accessToken; + emit accessTokenChanged(accessToken_); + save(); +} + +void +UserSettings::setDeviceId(QString deviceId) +{ + if (deviceId == deviceId_) + return; + deviceId_ = deviceId; + emit deviceIdChanged(deviceId_); + save(); +} + +void +UserSettings::setHomeserver(QString homeserver) +{ + if (homeserver == homeserver_) + return; + homeserver_ = homeserver; + emit homeserverChanged(homeserver_); + save(); +} + +void UserSettings::applyTheme() { QFile stylefile; @@ -436,14 +494,14 @@ UserSettings::save() settings.beginGroup("window"); settings.setValue("tray", tray_); settings.setValue("start_in_tray", startInTray_); - settings.endGroup(); + settings.endGroup(); // window settings.beginGroup("timeline"); settings.setValue("buttons", buttonsInTimeline_); settings.setValue("message_hover_highlight", messageHoverHighlight_); settings.setValue("enlarge_emoji_only_msg", enlargeEmojiOnlyMessages_); settings.setValue("max_width", timelineMaxWidth_); - settings.endGroup(); + settings.endGroup(); // timeline settings.setValue("avatar_circles", avatarCircles_); settings.setValue("decrypt_sidebar", decryptSidebar_); @@ -467,8 +525,16 @@ UserSettings::save() settings.setValue("camera_resolution", cameraResolution_); settings.setValue("camera_frame_rate", cameraFrameRate_); settings.setValue("use_stun_server", useStunServer_); + settings.setValue("currentProfile", profile_); + + QString prefix = + (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; + settings.setValue(prefix + "auth/access_token", accessToken_); + settings.setValue(prefix + "auth/home_server", homeserver_); + settings.setValue(prefix + "auth/user_id", userId_); + settings.setValue(prefix + "auth/device_id", deviceId_); - settings.endGroup(); + settings.endGroup(); // user settings.sync(); } diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index c699fd59..dd1e26d9 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h
@@ -84,6 +84,12 @@ class UserSettings : public QObject bool useStunServer READ useStunServer WRITE setUseStunServer NOTIFY useStunServerChanged) Q_PROPERTY(bool shareKeysWithTrustedUsers READ shareKeysWithTrustedUsers WRITE setShareKeysWithTrustedUsers NOTIFY shareKeysWithTrustedUsersChanged) + Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged) + Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged) + Q_PROPERTY( + QString accessToken READ accessToken WRITE setAccessToken NOTIFY accessTokenChanged) + Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged) + Q_PROPERTY(QString homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) public: UserSettings(); @@ -95,7 +101,7 @@ public: Unavailable, Offline, }; - Q_ENUM(Presence); + Q_ENUM(Presence) void save(); void load(); @@ -128,6 +134,11 @@ public: void setCameraFrameRate(QString frameRate); void setUseStunServer(bool state); void setShareKeysWithTrustedUsers(bool state); + void setProfile(QString profile); + void setUserId(QString userId); + void setAccessToken(QString accessToken); + void setDeviceId(QString deviceId); + void setHomeserver(QString homeserver); QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; } bool messageHoverHighlight() const { return messageHoverHighlight_; } @@ -161,6 +172,11 @@ public: QString cameraFrameRate() const { return cameraFrameRate_; } bool useStunServer() const { return useStunServer_; } bool shareKeysWithTrustedUsers() const { return shareKeysWithTrustedUsers_; } + QString profile() const { return profile_; } + QString userId() const { return userId_; } + QString accessToken() const { return accessToken_; } + QString deviceId() const { return deviceId_; } + QString homeserver() const { return homeserver_; } signals: void groupViewStateChanged(bool state); @@ -191,6 +207,11 @@ signals: void cameraFrameRateChanged(QString frameRate); void useStunServerChanged(bool state); void shareKeysWithTrustedUsersChanged(bool state); + void profileChanged(QString profile); + void userIdChanged(QString userId); + void accessTokenChanged(QString accessToken); + void deviceIdChanged(QString deviceId); + void homeserverChanged(QString homeserver); private: // Default to system theme if QT_QPA_PLATFORMTHEME var is set. @@ -226,6 +247,11 @@ private: QString cameraResolution_; QString cameraFrameRate_; bool useStunServer_; + QString profile_; + QString userId_; + QString accessToken_; + QString deviceId_; + QString homeserver_; }; class HorizontalLine : public QFrame diff --git a/src/main.cpp b/src/main.cpp
index 5eeebb82..58bdda34 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -107,29 +107,7 @@ main(int argc, char *argv[]) // needed for settings so need to register before any settings are read to prevent warnings qRegisterMetaType<UserSettings::Presence>(); - // This is some hacky programming, but it's necessary (AFAIK?) to get the unique config name - // parsed before the app name is set. - QString appName{"nheko"}; - for (int i = 0; i < argc; ++i) { - if (QString{argv[i]}.startsWith("--profile=")) { - QString q{argv[i]}; - q.remove("--profile="); - appName += "-" + q; - } else if (QString{argv[i]}.startsWith("--p=")) { - QString q{argv[i]}; - q.remove("-p="); - appName += "-" + q; - } else if (QString{argv[i]} == "--profile" || QString{argv[i]} == "-p") { - if (i < argc - 1) // if i is less than argc - 1, we still have a parameter - // left to process as the name - { - ++i; // the next arg is the name, so increment - appName += "-" + QString{argv[i]}; - } - } - } - - QCoreApplication::setApplicationName(appName); + QCoreApplication::setApplicationName("nheko"); QCoreApplication::setApplicationVersion(nheko::version); QCoreApplication::setOrganizationName("nheko"); QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); @@ -147,12 +125,36 @@ main(int argc, char *argv[]) } #endif + // This is some hacky programming, but it's necessary (AFAIK?) to get the unique config name + // parsed before the SingleApplication userdata is set. + QString userdata{""}; + for (int i = 0; i < argc; ++i) { + if (QString{argv[i]}.startsWith("--profile=")) { + QString q{argv[i]}; + q.remove("--profile="); + userdata = q; + } else if (QString{argv[i]}.startsWith("--p=")) { + QString q{argv[i]}; + q.remove("-p="); + userdata = q; + } else if (QString{argv[i]} == "--profile" || QString{argv[i]} == "-p") { + if (i < argc - 1) // if i is less than argc - 1, we still have a parameter + // left to process as the name + { + ++i; // the next arg is the name, so increment + userdata = QString{argv[i]}; + } + } + } + SingleApplication app(argc, argv, false, SingleApplication::Mode::User | SingleApplication::Mode::ExcludeAppPath | - SingleApplication::Mode::ExcludeAppVersion); + SingleApplication::Mode::ExcludeAppVersion, + 100, + userdata); QCommandLineParser parser; parser.addHelpOption(); @@ -194,14 +196,17 @@ main(int argc, char *argv[]) std::exit(1); } - QSettings settings; + UserSettings settings; + + if (parser.isSet(configName)) + settings.setProfile(parser.value(configName)); QFont font; - QString userFontFamily = settings.value("user/font_family", "").toString(); + QString userFontFamily = settings.font(); if (!userFontFamily.isEmpty()) { font.setFamily(userFontFamily); } - font.setPointSizeF(settings.value("user/font_size", font.pointSizeF()).toDouble()); + font.setPointSizeF(settings.fontSize()); app.setFont(font); @@ -216,13 +221,12 @@ main(int argc, char *argv[]) appTranslator.load(QLocale(), "nheko", "_", ":/translations"); app.installTranslator(&appTranslator); - MainWindow w{(appName == "nheko" ? "" : appName.remove("nheko-"))}; + MainWindow w; // Move the MainWindow to the center w.move(screenCenter(w.width(), w.height())); - if (!settings.value("user/window/start_in_tray", false).toBool() || - !settings.value("user/window/tray", true).toBool()) + if (!settings.startInTray() && !settings.tray()) w.show(); QObject::connect(&app, &QApplication::aboutToQuit, &w, [&w]() {