diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2ecfa17c..8a6775db 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -143,3 +143,56 @@ linting: - apk update && apk add clang make git script: - make lint + +appimage-amd64: + stage: build + image: appimagecrafters/appimage-builder + tags: [docker] + before_script: + # app build requirements + - echo 'deb http://archive.neon.kde.org/user/ bionic main' > /etc/apt/sources.list.d/neon.list + - wget -qO - https://archive.neon.kde.org/public.key | apt-key add - + - apt-get update + - apt-get install -y git wget curl + + # update appimage-builder (optional) + - pip3 install --upgrade git+https://www.opencode.net/azubieta/appimagecraft.git + + - apt-get install -y qt5-default qtdeclarative5-dev qttools5-dev qtscript5-dev qtquickcontrols2-5-dev qtmultimedia5-dev libqt5svg5-dev liblmdb-dev libssl-dev git ninja-build qt5keychain-dev libgtest-dev ccache + - wget https://github.com/Kitware/CMake/releases/download/v3.19.0/cmake-3.19.0-Linux-x86_64.sh && sh cmake-3.19.0-Linux-x86_64.sh --skip-license --prefix=/usr/local + - /usr/sbin/update-ccache-symlinks + script: + - export PATH="/usr/local/bin/:/usr/lib/ccache:${PATH}" + - export CMAKE_BUILD_PARALLEL_LEVEL=$(cat /proc/cpuinfo | awk '/^processor/{print $3}' | wc -l) + - cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -GNinja + -DHUNTER_ROOT=".hunter" + -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF + -DHUNTER_CONFIGURATION_TYPES=Release + -DUSE_BUNDLED_BOOST=ON + -DUSE_BUNDLED_SPDLOG=ON + -DUSE_BUNDLED_OLM=ON + -DUSE_BUNDLED_GTEST=OFF + -DUSE_BUNDLED_CMARK=ON + -DUSE_BUNDLED_JSON=ON + -DUSE_BUNDLED_OPENSSL=OFF + -DUSE_BUNDLED_MTXCLIENT=ON + -DUSE_BUNDLED_LMDB=OFF + -DUSE_BUNDLED_LMDBXX=ON + -DUSE_BUNDLED_TWEENY=ON + -DUSE_BUNDLED_QTKEYCHAIN=OFF + - DESTDIR=`pwd`/AppDir ninja -C build install/local + - DESTDIR=`pwd`/AppDir ninja -C build _deps/cmark-build/src/install + - mkdir -p AppDir/usr/lib/x86_64-linux-gnu AppDir/lib/x86_64-linux-gnu + - appimage-builder --skip-test + after_script: + - bash ./.ci/upload-nightly-gitlab.sh nheko-latest-x86_64.AppImage + artifacts: + paths: + - 'nheko-latest-x86_64.AppImage' + expire_in: 1 week + expose_as: 'appimage-amd64' + cache: + key: "$CI_JOB_NAME" + paths: + - .hunter/ + - .ccache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 935e7c6f..00000000 --- a/.travis.yml +++ /dev/null @@ -1,99 +0,0 @@ -language: cpp -sudo: required -dist: xenial - -notifications: - webhooks: - urls: - - https://scalar.vector.im/api/neb/services/hooks/dHJhdmlzLWNpLyU0MHJlZF9za3klM0FuaGVrby5pbS8lMjFVYkNtSWxHVEhOSWdJUlpjcHQlM0FuaGVrby5pbQ - on_success: always - on_failure: always - on_start: never - email: false - -cache: - directories: - - .hunter - -matrix: - include: - - os: linux - compiler: gcc-7 - env: - - CXX=g++-7 - - CC=gcc-7 - - QT_PKG=512 - - DEPLOYMENT=1 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - sourceline: 'ppa:beineri/opt-qt-5.12.6-xenial' - packages: - - g++-7 - - ninja-build - - qt512base - - qt512tools - - qt512svg - - qt512multimedia - - qt512quickcontrols2 - - qt512graphicaleffects - - liblmdb-dev - - libgl1-mesa-dev # needed for missing gl.h - - os: linux - compiler: clang-6 - env: - - CXX=clang++-6.0 - - CC=clang-6.0 - - QT_PKG=510 - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-6.0 - - sourceline: 'ppa:beineri/opt-qt-5.10.1-xenial' - packages: - - clang++-6.0 - - g++-7 - - ninja-build - - qt510base - - qt510tools - - qt510svg - - qt510multimedia - - qt510quickcontrols2 - - qt510graphicaleffects - - liblmdb-dev - - libgl1-mesa-dev # needed for missing gl.h - -before_install: - # Use TRAVIS_TAG if defined, or the short commit SHA otherwise - - export VERSION=${TRAVIS_TAG:-$(git rev-parse --short HEAD)} -install: - - ./.ci/install.sh - - export PATH=/usr/local/bin:${PATH} - -script: - - ./.ci/script.sh - - sed -i -e "s/VERSION_NAME_VALUE/${VERSION}/g" ./.ci/bintray-release.json || true - - cp ./.ci/bintray-release.json . -deploy: -- provider: script - script: ./.ci/upload-nightly.sh - skip_cleanup: true - on: - condition: "$DEPLOYMENT == 1" - repo: Nheko-Reborn/nheko - tags: false - all_branches: true -- skip_cleanup: true - overwrite: true - provider: releases - api_key: - secure: "rDFG4DIwIG+A9R8seQ3SIXfWOWhJgJHlNQHtAsnfRrPOSIpI7kMebHLDO5sBPNaJ+9MH9acVTJZOabVLf0DdPqRsDUw/PN28aiiqbaH9+zAGOTxahaQ222Gz/ROf/iXvDoTDUnUzURqQUA0YlHy89Z1CnO7TKwlsYhA5A8n0biG7d8i7vQayvwYXfxlk7CouK+Y86ana4r54j1emGRg97p7BOhORibg54ZD520hN0Iif7EJM2hQDTWKZzTDdBt3mF1kBr7cBbuBHWuvE+eIFO3F3yi+u7ggHzw5FaAv245N4fhkpYUl/mSbhLrQG2NOnkglFCpQ2lLd6mWdXHwUNrxN/j+UPewmLg7CymY25zkiL43deDsT8KmpzYalmdaevCqEaX2VehuBzblmH4Re8wnXqBrab14fq0TNDfPqC+NKxy75mdxszbKBC55nTlTB+hsox43dvfvyXDSON4qAzwe9Q/tfp8mL2mehcM868vhw5cbNIskKT8SrhMwmA+sxoqnqLsmAjNVJVTgg6ppbMhjNMOBTndblRHfH6bxsgpTXPtnzC17o9Mw1WgF63eOWNYBEj2wW5ZvWX95Gvg5YzvsF178ipHZDqZfA62ShB3b89fcqN5SOxBsE8UYoHjQIHxQdWeKv23iFwmT8fWAOD8sKDcRyz0WCgidZ1/RjLqsU=" - file_glob: true - file: - - nheko-${VERSION}-x86_64.AppImage - on: - condition: "$TRAVIS_OS_NAME == linux && $DEPLOYMENT == 1" - repo: Nheko-Reborn/nheko - tags: true diff --git a/AppImageBuilder.yml b/AppImageBuilder.yml new file mode 100644 index 00000000..7b263058 --- /dev/null +++ b/AppImageBuilder.yml @@ -0,0 +1,122 @@ +# appimage-builder recipe see https://appimage-builder.readthedocs.io for details +version: 1 +AppDir: + path: ./AppDir + app_info: + id: nheko + name: nheko + icon: nheko + version: latest + exec: usr/bin/nheko + exec_args: $@ + runtime: + env: + APPDIR_LIBRARY_PATH: $APPDIR/usr/lib/x86_64-linux-gnu:$APPDIR/usr/lib/x86_64-linux-gnu/gstreamer-1.0:$APPDIR/usr/lib/x86_64-linux-gnu/gconv:$APPDIR/lib/x86_64-linux-gnu:$APPDIR/usr/lib/x86_64-linux-gnu/pulseaudio + apt: + arch: amd64 + allow_unauthenticated: true + sources: + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic main restricted + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic-updates main restricted + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic universe + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic-updates universe + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic multiverse + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic-updates multiverse + - sourceline: deb http://de.archive.ubuntu.com/ubuntu/ bionic-backports main restricted + universe multiverse + - sourceline: deb http://security.ubuntu.com/ubuntu bionic-security main restricted + - sourceline: deb http://security.ubuntu.com/ubuntu bionic-security universe + - sourceline: deb http://security.ubuntu.com/ubuntu bionic-security multiverse + - sourceline: deb http://archive.neon.kde.org/user/ bionic main + include: + - gstreamer1.0-libav + - gstreamer1.0-plugins-bad + - gstreamer1.0-plugins-base + - gstreamer1.0-plugins-good + - gstreamer1.0-pulseaudio + - gstreamer1.0-x + - kimageformat-plugins + - libbs2b0 + - libbz2-1.0 + - libelf1 + - libexpat1 + - libhogweed4 + - libjpeg-turbo8 + - libkf5archive5 + - libllvm10 + - liblmdb0 + - liblz4-1 + - libnorm1 + - libnss-mdns + - libopenexr22 + - libpcre3 + - libqt5keychain1 + - libqt5multimedia5-plugins + - libqt5multimediagsttools5 + - libqt5multimediawidgets5 + - libqt5quickcontrols2-5 + - libqt5quicktemplates2-5 + - libqt5quickwidgets5 + - libqt5svg5 + - librubberband2 + - libsensors4 + - libsm6 + - libsnappy1v5 + - libsystemd0 + - libwayland-server0 + - libx264-152 + - libxau6 + - libxcb-render-util0 + - libxcb-sync1 + - libxcb-xinerama0 + - libxcb-xkb1 + - libxcursor1 + - libxdmcp6 + - libxext6 + - libxfixes3 + - libxrender1 + - libxshmfence1 + - libxv1 + - libxxf86vm1 + - libzstd1 + - qml-module-qtgraphicaleffects + - qml-module-qtmultimedia + - qml-module-qtquick-controls2 + - qml-module-qtquick-layouts + - qml-module-qtquick-templates2 + - qml-module-qtquick-window2 + - qml-module-qtquick2 + - qt5-image-formats-plugins + exclude: [] + files: + exclude: + - usr/share/man + - usr/share/doc/*/README.* + - usr/share/doc/*/changelog.* + - usr/share/doc/*/NEWS.* + - usr/share/doc/*/TODO.* + test: + fedora: + image: appimagecrafters/tests-env:fedora-30 + command: ./AppRun + use_host_x: true + debian: + image: appimagecrafters/tests-env:debian-stable + command: ./AppRun + use_host_x: true + arch: + image: appimagecrafters/tests-env:archlinux-latest + command: ./AppRun + use_host_x: true + centos: + image: appimagecrafters/tests-env:centos-7 + command: ./AppRun + use_host_x: true + ubuntu: + image: appimagecrafters/tests-env:ubuntu-xenial + command: ./AppRun + use_host_x: true +AppImage: + arch: x86_64 + update-information: None + sign-key: None diff --git a/src/Cache.cpp b/src/Cache.cpp index 5d11a178..dac0b23a 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp @@ -167,13 +167,14 @@ Cache::Cache(const QString &userId, QObject *parent) void Cache::setup() { - UserSettings settings; + auto settings = UserSettings::instance(); nhlog::db()->debug("setting up cache"); cacheDirectory_ = QString("%1/%2%3") .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) - .arg(QString::fromUtf8(localUserId_.toUtf8().toHex())).arg(QString::fromUtf8(settings.profile().toUtf8().toHex())); + .arg(QString::fromUtf8(localUserId_.toUtf8().toHex())) + .arg(QString::fromUtf8(settings->profile().toUtf8().toHex())); bool isInitial = !QFile::exists(cacheDirectory_); @@ -186,7 +187,9 @@ Cache::setup() if (!QDir().mkpath(cacheDirectory_)) { throw std::runtime_error( - ("Unable to create state directory:" + cacheDirectory_).toStdString().c_str()); + ("Unable to create state directory:" + cacheDirectory_) + .toStdString() + .c_str()); } } @@ -575,14 +578,14 @@ Cache::restoreOlmAccount() void Cache::storeSecret(const std::string &name, const std::string &secret) { - UserSettings settings; + auto settings = UserSettings::instance(); QKeychain::WritePasswordJob job(QCoreApplication::applicationName()); job.setAutoDelete(false); job.setInsecureFallback(true); - job.setKey( - "matrix." + - QString(QCryptographicHash::hash(settings.profile().toUtf8(), QCryptographicHash::Sha256)) + - "." + name.c_str()); + 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); @@ -600,14 +603,14 @@ Cache::storeSecret(const std::string &name, const std::string &secret) void Cache::deleteSecret(const std::string &name) { - UserSettings settings; + auto settings = UserSettings::instance(); QKeychain::DeletePasswordJob job(QCoreApplication::applicationName()); job.setAutoDelete(false); job.setInsecureFallback(true); - job.setKey( - "matrix." + - QString(QCryptographicHash::hash(settings.profile().toUtf8(), QCryptographicHash::Sha256)) + - "." + name.c_str()); + 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(); @@ -619,14 +622,14 @@ Cache::deleteSecret(const std::string &name) std::optional Cache::secret(const std::string &name) { - UserSettings settings; + auto settings = UserSettings::instance(); QKeychain::ReadPasswordJob job(QCoreApplication::applicationName()); job.setAutoDelete(false); job.setInsecureFallback(true); - job.setKey( - "matrix." + - QString(QCryptographicHash::hash(settings.profile().toUtf8(), QCryptographicHash::Sha256)) + - "." + name.c_str()); + 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 bc7b5223..77269008 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -56,8 +56,8 @@ MainWindow *MainWindow::instance_ = nullptr; MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), - userSettings_{QSharedPointer{new UserSettings}} + : QMainWindow(parent) + , userSettings_{UserSettings::instance()} { setWindowTitle(0); setObjectName("MainWindow"); diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 55f666c1..4ca3be49 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -50,10 +50,30 @@ #include "config/nheko.h" -UserSettings::UserSettings() { load(); } +QSharedPointer UserSettings::instance_; + +UserSettings::UserSettings() +{ + connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [this]() { + instance_.clear(); + }); +} + +QSharedPointer +UserSettings::instance() +{ + return instance_; +} void -UserSettings::load() +UserSettings::initialize(std::optional profile) +{ + instance_.reset(new UserSettings()); + instance_->load(profile); +} + +void +UserSettings::load(std::optional profile) { QSettings settings; tray_ = settings.value("user/window/tray", false).toBool(); @@ -89,7 +109,11 @@ 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(); + + if (profile) + profile_ = *profile; + else + profile_ = settings.value("user/currentProfile", "").toString(); QString prefix = (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; @@ -527,6 +551,8 @@ UserSettings::save() settings.setValue("use_stun_server", useStunServer_); settings.setValue("currentProfile", profile_); + settings.endGroup(); // user + QString prefix = (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : ""; settings.setValue(prefix + "auth/access_token", accessToken_); @@ -534,8 +560,6 @@ UserSettings::save() settings.setValue(prefix + "auth/user_id", userId_); settings.setValue(prefix + "auth/device_id", deviceId_); - settings.endGroup(); // user - settings.sync(); } diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index dd1e26d9..af73202e 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -91,9 +91,12 @@ class UserSettings : public QObject Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged) Q_PROPERTY(QString homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) -public: UserSettings(); +public: + static QSharedPointer instance(); + static void initialize(std::optional profile); + enum class Presence { AutomaticPresence, @@ -104,7 +107,7 @@ public: Q_ENUM(Presence) void save(); - void load(); + void load(std::optional profile); void applyTheme(); void setTheme(QString theme); void setMessageHoverHighlight(bool state); @@ -252,6 +255,8 @@ private: QString accessToken_; QString deviceId_; QString homeserver_; + + static QSharedPointer instance_; }; class HorizontalLine : public QFrame diff --git a/src/main.cpp b/src/main.cpp index 58bdda34..a60c66c4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -196,17 +196,19 @@ main(int argc, char *argv[]) std::exit(1); } - UserSettings settings; - if (parser.isSet(configName)) - settings.setProfile(parser.value(configName)); + UserSettings::initialize(parser.value(configName)); + else + UserSettings::initialize(std::nullopt); + + auto settings = UserSettings::instance().toWeakRef(); QFont font; - QString userFontFamily = settings.font(); + QString userFontFamily = settings.lock()->font(); if (!userFontFamily.isEmpty()) { font.setFamily(userFontFamily); } - font.setPointSizeF(settings.fontSize()); + font.setPointSizeF(settings.lock()->fontSize()); app.setFont(font); @@ -226,7 +228,7 @@ main(int argc, char *argv[]) // Move the MainWindow to the center w.move(screenCenter(w.width(), w.height())); - if (!settings.startInTray() && !settings.tray()) + if (!settings.lock()->startInTray() && !settings.lock()->tray()) w.show(); QObject::connect(&app, &QApplication::aboutToQuit, &w, [&w]() {