Merge branch 'master' into windowsIconFix
20
.ci/linux/deploy.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
mkdir -p appdir
|
||||
cp build/nheko appdir/
|
||||
cp resources/nheko.desktop appdir/
|
||||
cp resources/nheko*.png appdir/
|
||||
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
chmod a+x linuxdeployqt*.AppImage
|
||||
|
||||
unset QTDIR
|
||||
unset QT_PLUGIN_PATH
|
||||
unset LD_LIBRARY_PATH
|
||||
|
||||
./linuxdeployqt*.AppImage ./appdir/*.desktop -bundle-non-qt-libs
|
||||
./linuxdeployqt*.AppImage ./appdir/*.desktop -appimage
|
||||
|
||||
chmod +x nheko-x86_64.AppImage
|
13
.ci/macos/deploy.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
# Add Qt binaries to path
|
||||
PATH=/usr/local/opt/qt/bin/:${PATH}
|
||||
|
||||
cp -fp ./build/nheko dist/MacOS/Nheko.app/Contents/MacOS
|
||||
|
||||
sudo macdeployqt dist/MacOS/Nheko.app -dmg
|
||||
user=$(id -nu)
|
||||
sudo chown ${user} dist/MacOS/Nheko.dmg
|
||||
mv dist/MacOS/Nheko.dmg .
|
@ -1,13 +1,14 @@
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: Cpp11
|
||||
AccessModifierOffset: -8
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: true
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
BasedOnStyle: Mozilla
|
||||
BreakBeforeBraces: Linux
|
||||
ColumnLimit: 100
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 8
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
PointerAlignment: Right
|
||||
Cpp11BracedListStyle: true
|
||||
|
20
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<!--
|
||||
If you want to request a feature or ask a question, feel free to remove all the irrelevant text.
|
||||
-->
|
||||
|
||||
### System:
|
||||
|
||||
- Nheko commit/version:
|
||||
- Operating System:
|
||||
- Qt version:
|
||||
- C++ compiler:
|
||||
- Desktop Environment: <!-- for Linux -->
|
||||
|
||||
### Actual behavior
|
||||
|
||||
### Expected behavior
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!-- If the program crashed. -->
|
||||
### Debugger traceback
|
26
.travis.yml
@ -25,5 +25,29 @@ before_script:
|
||||
- cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Release
|
||||
script:
|
||||
- make -C build -j2
|
||||
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/run-tests.sh; fi
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then make lint; fi
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then ./.ci/macos/deploy.sh; fi
|
||||
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/run-tests.sh; fi
|
||||
- if [ $TRAVIS_OS_NAME == linux ]; then ./.ci/linux/deploy.sh; fi
|
||||
|
||||
deploy:
|
||||
- skip_cleanup: true
|
||||
overwrite: true
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: oprXzESukFiXBeF2BXkXUlegsAQc95Ub4kc/OkoNFaYBvqpA+IGpWHmHCx5JPny/OT3Kc2Urpe2JUeGSWDHZ7UCKDjH+NzGP3uN82fHh/HiszG/Srw7+hWEHm1ve+gMK9GS8pr+yUsUrPP0UfVXlPoI4pBWa4zGi2Ndb/SqvjCgIHFLtGyoBo6CydKQ/AyWiXSMKDfJL+Dx4JLIPP4RTCBJy8ZrZ8m/a5Tgy4Ij6+djjrgYCZCEhGxSYw7xDIT/9SV8g9NkrbisqBDrILzAH8Yhe4XMRMXo88OAxV5+Vb9Rw1hrqczez6lpFDbJetv8MjofND+pSoAFwtjaL1wTFK9Ud6w4O9AuHlEQH9cGVdvsxFcosRwJVh58x51JM9ptoktqhx/HHJBTuCHCYYlHwtRwbwqnMYdLzKZG5FnujT8DG+9mcva1fL6tzW/XD505VPMWwXFC/2/pvolgAkTFFXYSALAwZlK3IgoXU8Gok/3B4iHofzQsFf6Yq3BI/88x7tVASUqiYhoKrO50+gb6pNIRCyWgGUiBEVXBp6Ziq3ORQPyQJg7i9HHUGTUu74yvGLHWLwjNQzZP/hxJZK3VlJxzyXntdOxiJc8iOzNrU+rPKBAlAaE6bQDOoniIysEgdD5BXHTLFzPvts4P1n2Ckor5/rNJ+qXR8GU+/y7e1GKU=
|
||||
file: nheko-x86_64.AppImage
|
||||
on:
|
||||
condition: $TRAVIS_OS_NAME == linux
|
||||
repo: mujx/nheko
|
||||
tags: true
|
||||
- skip_cleanup: true
|
||||
overwrite: true
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: oprXzESukFiXBeF2BXkXUlegsAQc95Ub4kc/OkoNFaYBvqpA+IGpWHmHCx5JPny/OT3Kc2Urpe2JUeGSWDHZ7UCKDjH+NzGP3uN82fHh/HiszG/Srw7+hWEHm1ve+gMK9GS8pr+yUsUrPP0UfVXlPoI4pBWa4zGi2Ndb/SqvjCgIHFLtGyoBo6CydKQ/AyWiXSMKDfJL+Dx4JLIPP4RTCBJy8ZrZ8m/a5Tgy4Ij6+djjrgYCZCEhGxSYw7xDIT/9SV8g9NkrbisqBDrILzAH8Yhe4XMRMXo88OAxV5+Vb9Rw1hrqczez6lpFDbJetv8MjofND+pSoAFwtjaL1wTFK9Ud6w4O9AuHlEQH9cGVdvsxFcosRwJVh58x51JM9ptoktqhx/HHJBTuCHCYYlHwtRwbwqnMYdLzKZG5FnujT8DG+9mcva1fL6tzW/XD505VPMWwXFC/2/pvolgAkTFFXYSALAwZlK3IgoXU8Gok/3B4iHofzQsFf6Yq3BI/88x7tVASUqiYhoKrO50+gb6pNIRCyWgGUiBEVXBp6Ziq3ORQPyQJg7i9HHUGTUu74yvGLHWLwjNQzZP/hxJZK3VlJxzyXntdOxiJc8iOzNrU+rPKBAlAaE6bQDOoniIysEgdD5BXHTLFzPvts4P1n2Ckor5/rNJ+qXR8GU+/y7e1GKU=
|
||||
file: Nheko.dmg
|
||||
on:
|
||||
condition: $TRAVIS_OS_NAME == osx
|
||||
repo: mujx/nheko
|
||||
tags: true
|
||||
|
@ -56,6 +56,7 @@ endif()
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
find_package(Qt5LinguistTools REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
|
||||
if (APPLE)
|
||||
find_package(Qt5MacExtras REQUIRED)
|
||||
@ -140,8 +141,8 @@ endif()
|
||||
#
|
||||
set(SRC_FILES
|
||||
src/AvatarProvider.cc
|
||||
src/ChatPage.cc
|
||||
src/Cache.cc
|
||||
src/ChatPage.cc
|
||||
src/Deserializable.cc
|
||||
src/EmojiCategory.cc
|
||||
src/EmojiItemDelegate.cc
|
||||
@ -150,9 +151,6 @@ set(SRC_FILES
|
||||
src/EmojiProvider.cc
|
||||
src/ImageItem.cc
|
||||
src/ImageOverlayDialog.cc
|
||||
src/TimelineItem.cc
|
||||
src/TimelineView.cc
|
||||
src/TimelineViewManager.cc
|
||||
src/InputValidator.cc
|
||||
src/JoinRoomDialog.cc
|
||||
src/LeaveRoomDialog.cc
|
||||
@ -162,34 +160,44 @@ set(SRC_FILES
|
||||
src/MainWindow.cc
|
||||
src/MatrixClient.cc
|
||||
src/Profile.cc
|
||||
src/RoomInfoListItem.cc
|
||||
src/RoomMessages.cc
|
||||
src/RoomList.cc
|
||||
src/RoomState.cc
|
||||
src/QuickSwitcher.cc
|
||||
src/Register.cc
|
||||
src/RegisterPage.cc
|
||||
src/RoomInfoListItem.cc
|
||||
src/RoomList.cc
|
||||
src/RoomMessages.cc
|
||||
src/RoomState.cc
|
||||
src/SideBarActions.cc
|
||||
src/UserSettingsPage.cc
|
||||
src/Splitter.cc
|
||||
src/Sync.cc
|
||||
src/TextInputWidget.cc
|
||||
src/TrayIcon.cc
|
||||
src/TimelineItem.cc
|
||||
src/TimelineView.cc
|
||||
src/TimelineViewManager.cc
|
||||
src/TopRoomBar.cc
|
||||
src/TrayIcon.cc
|
||||
src/TypingDisplay.cc
|
||||
src/UserInfoWidget.cc
|
||||
src/Versions.cc
|
||||
src/WelcomePage.cc
|
||||
src/QuickSwitcher.cc
|
||||
src/main.cc
|
||||
|
||||
src/ui/Avatar.cc
|
||||
src/ui/Badge.cc
|
||||
src/ui/LoadingIndicator.cc
|
||||
src/ui/FlatButton.cc
|
||||
src/ui/FloatingButton.cc
|
||||
src/ui/Label.cc
|
||||
src/ui/OverlayModal.cc
|
||||
src/ui/ScrollBar.cc
|
||||
src/ui/SnackBar.cc
|
||||
src/ui/RaisedButton.cc
|
||||
src/ui/Ripple.cc
|
||||
src/ui/RippleOverlay.cc
|
||||
src/ui/OverlayWidget.cc
|
||||
src/ui/TextField.cc
|
||||
src/ui/ToggleButton.cc
|
||||
src/ui/Theme.cc
|
||||
src/ui/ThemeManager.cc
|
||||
)
|
||||
@ -234,38 +242,45 @@ qt5_wrap_cpp(MOC_HEADERS
|
||||
include/EmojiItemDelegate.h
|
||||
include/EmojiPanel.h
|
||||
include/EmojiPickButton.h
|
||||
include/ui/FloatingButton.h
|
||||
include/ImageItem.h
|
||||
include/ImageOverlayDialog.h
|
||||
include/JoinRoomDialog.h
|
||||
include/TimelineItem.h
|
||||
include/TimelineView.h
|
||||
include/TimelineViewManager.h
|
||||
include/LeaveRoomDialog.h
|
||||
include/LoginPage.h
|
||||
include/LogoutDialog.h
|
||||
include/MainWindow.h
|
||||
include/MatrixClient.h
|
||||
include/QuickSwitcher.h
|
||||
include/RegisterPage.h
|
||||
include/RoomInfoListItem.h
|
||||
include/RoomList.h
|
||||
include/SideBarActions.h
|
||||
include/UserSettingsPage.h
|
||||
include/Splitter.h
|
||||
include/UserInfoWidget.h
|
||||
include/TextInputWidget.h
|
||||
include/TimelineItem.h
|
||||
include/TimelineView.h
|
||||
include/TimelineViewManager.h
|
||||
include/TopRoomBar.h
|
||||
include/TrayIcon.h
|
||||
include/TextInputWidget.h
|
||||
include/QuickSwitcher.h
|
||||
include/TypingDisplay.h
|
||||
include/UserInfoWidget.h
|
||||
include/WelcomePage.h
|
||||
|
||||
include/ui/Avatar.h
|
||||
include/ui/Badge.h
|
||||
include/ui/LoadingIndicator.h
|
||||
include/ui/FlatButton.h
|
||||
include/ui/Label.h
|
||||
include/ui/OverlayWidget.h
|
||||
include/ui/ScrollBar.h
|
||||
include/ui/SnackBar.h
|
||||
include/ui/RaisedButton.h
|
||||
include/ui/Ripple.h
|
||||
include/ui/RippleOverlay.h
|
||||
include/ui/TextField.h
|
||||
include/ui/ToggleButton.h
|
||||
include/ui/Theme.h
|
||||
include/ui/ThemeManager.h
|
||||
)
|
||||
@ -297,9 +312,6 @@ add_library(matrix_events ${MATRIX_EVENTS} src/Deserializable.cc)
|
||||
target_link_libraries(matrix_events Qt5::Core)
|
||||
|
||||
if (BUILD_TESTS)
|
||||
#
|
||||
# Build tests.
|
||||
#
|
||||
enable_testing()
|
||||
|
||||
find_package(GTest REQUIRED)
|
||||
@ -317,16 +329,13 @@ if (BUILD_TESTS)
|
||||
add_test(MatrixEvents events_test)
|
||||
add_test(MatrixEventCollection event_collection_test)
|
||||
add_test(MatrixMessageEvents message_events)
|
||||
else()
|
||||
#
|
||||
# Build the executable.
|
||||
#
|
||||
if(APPVEYOR_BUILD)
|
||||
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network lmdb)
|
||||
else()
|
||||
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network ${LMDB_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(APPVEYOR_BUILD)
|
||||
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network Qt5::Concurrent lmdb)
|
||||
else()
|
||||
set (NHEKO_LIBS matrix_events Qt5::Widgets Qt5::Network Qt5::Concurrent ${LMDB_LIBRARY})
|
||||
endif()
|
||||
set (NHEKO_DEPS ${SRC_FILES} ${UI_HEADERS} ${MOC_HEADERS} ${QRC} ${LANG_QRC} ${QM_SRC} ${META_FILES_TO_INCLUDE})
|
||||
|
||||
if(APPLE)
|
||||
|
5
Makefile
@ -9,7 +9,7 @@ debug:
|
||||
@cmake --build build
|
||||
|
||||
release-debug:
|
||||
@cmake -DBUILD_TESTS=OFF -H. -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
@cmake -DBUILD_TESTS=OFF -H. -GNinja -Bbuild -DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
@cmake --build build
|
||||
|
||||
test:
|
||||
@ -17,6 +17,9 @@ test:
|
||||
@cmake --build build
|
||||
@cd build && GTEST_COLOR=1 ctest --verbose
|
||||
|
||||
linux-appimage:
|
||||
@./.ci/linux/deploy.sh
|
||||
|
||||
app: release-debug $(APP_TEMPLATE)
|
||||
@cp -fp ./build/$(APP_NAME) $(APP_TEMPLATE)/Contents/MacOS
|
||||
@echo "Created '$(APP_NAME).app' in '$(APP_TEMPLATE)'"
|
||||
|
29
README.md
@ -12,25 +12,33 @@ feels more like a mainstream chat app ([Riot], Telegram etc) and less like an IR
|
||||
### Features
|
||||
|
||||
Most of the features you would expect from a chat application are missing right now
|
||||
but you can of course receive and send messages in the rooms that you are a member of.
|
||||
but we are getting close to a more feature complete client.
|
||||
Specifically there is support for:
|
||||
- Joining & leaving rooms
|
||||
- Sending & receiving images and emoji.
|
||||
- Typing notifications.
|
||||
|
||||
### Installation
|
||||
|
||||
There are pre-built nigtly releases [here](https://github.com/mujx/nheko/releases/tag/nightly) for Linux ([AppImage](https://appimage.org/)), Mac and Windows.
|
||||
|
||||
#### Arch Linux
|
||||
```bash
|
||||
pacaur -S nheko-git
|
||||
```
|
||||
|
||||
#### Fedora
|
||||
```bash
|
||||
sudo dnf copr enable xvitaly/matrix
|
||||
sudo dnf install nheko
|
||||
```
|
||||
|
||||
#### Gentoo Linux
|
||||
```bash
|
||||
sudo layman -a matrix
|
||||
sudo emerge -a nheko
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
You can find a NSIS installer [here](https://ci.appveyor.com/project/mujx/nheko/branch/master/artifacts).
|
||||
|
||||
### Build Requirements
|
||||
|
||||
- Qt5 (5.7 or greater). Qt 5.7 adds support for color font rendering with
|
||||
@ -95,15 +103,7 @@ make -C build
|
||||
|
||||
The `nheko` binary will be located in the `build` directory.
|
||||
|
||||
##### MacOS
|
||||
|
||||
You can create an app bundle with `make app`. The output will be located at
|
||||
`dist/MacOS/Nheko.app` which can be copied to `/Applications/Nheko.app`.
|
||||
|
||||
You can also create a disk image with `make dmg`. The output will be located at
|
||||
`dist/MacOS/Nheko.dmg`
|
||||
|
||||
##### Nix
|
||||
#### Nix
|
||||
|
||||
Download the repo as mentioned above and run
|
||||
|
||||
@ -129,6 +129,7 @@ Here is a screen shot to get a feel for the UI, but things will probably change.
|
||||
### Third party
|
||||
|
||||
- [Emoji One](http://emojione.com)
|
||||
- [Font Awesome](http://fontawesome.io/)
|
||||
- [Open Sans](https://fonts.google.com/specimen/Open+Sans)
|
||||
|
||||
[Matrix]:https://matrix.org
|
||||
|
11
appveyor.yml
@ -92,6 +92,17 @@ after_build:
|
||||
- set PATH=%BUILD%\tools\bin;%PATH%
|
||||
- binarycreator.exe -f -c installer\config\config.xml -p installer\packages %DIST%-installer.exe
|
||||
|
||||
deploy:
|
||||
description: "Development builds"
|
||||
provider: GitHub
|
||||
auth_token:
|
||||
secure: YqB7hcM+4482eSHhtVR7ZA7N7lE78y8BC897/7UDTBQd+NWdWFW/6S+oKDie9TT7
|
||||
artifact: nheko_setup.exe
|
||||
force_update: true
|
||||
prerelease: true
|
||||
on:
|
||||
appveyor_repo_tag: true
|
||||
|
||||
artifacts:
|
||||
- path: nheko_win_64.zip
|
||||
- path: NhekoRelease\nheko.exe
|
||||
|
@ -18,12 +18,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <QImage>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QUrl>
|
||||
|
||||
#include "MatrixClient.h"
|
||||
#include "TimelineItem.h"
|
||||
class MatrixClient;
|
||||
class TimelineItem;
|
||||
|
||||
struct AvatarData
|
||||
{
|
||||
QImage img;
|
||||
QUrl url;
|
||||
};
|
||||
|
||||
class AvatarProvider : public QObject
|
||||
{
|
||||
@ -40,8 +45,8 @@ private:
|
||||
static void updateAvatar(const QString &uid, const QImage &img);
|
||||
|
||||
static QSharedPointer<MatrixClient> client_;
|
||||
static QMap<QString, QList<TimelineItem *>> toBeResolved_;
|
||||
|
||||
static QMap<QString, QImage> userAvatars_;
|
||||
static QMap<QString, QUrl> avatarUrls_;
|
||||
using UserID = QString;
|
||||
static QMap<UserID, AvatarData> avatars_;
|
||||
static QMap<UserID, QList<TimelineItem *>> toBeResolved_;
|
||||
};
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <QDir>
|
||||
#include <lmdb++.h>
|
||||
|
||||
#include "RoomState.h"
|
||||
class RoomState;
|
||||
|
||||
class Cache
|
||||
{
|
||||
@ -33,11 +33,11 @@ public:
|
||||
QString nextBatchToken() const;
|
||||
QMap<QString, RoomState> states();
|
||||
|
||||
inline void deleteData();
|
||||
inline void unmount();
|
||||
inline QString memberDbName(const QString &roomid);
|
||||
void deleteData();
|
||||
void unmount() { isMounted_ = false; };
|
||||
|
||||
void removeRoom(const QString &roomid);
|
||||
void setup();
|
||||
|
||||
private:
|
||||
void setNextBatchToken(lmdb::txn &txn, const QString &token);
|
||||
@ -52,22 +52,3 @@ private:
|
||||
QString userId_;
|
||||
QString cacheDirectory_;
|
||||
};
|
||||
|
||||
inline void
|
||||
Cache::unmount()
|
||||
{
|
||||
isMounted_ = false;
|
||||
}
|
||||
|
||||
inline QString
|
||||
Cache::memberDbName(const QString &roomid)
|
||||
{
|
||||
return QString("m.%1").arg(roomid);
|
||||
}
|
||||
|
||||
inline void
|
||||
Cache::deleteData()
|
||||
{
|
||||
if (!cacheDirectory_.isEmpty())
|
||||
QDir(cacheDirectory_).removeRecursively();
|
||||
}
|
||||
|
@ -17,21 +17,37 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QMap>
|
||||
#include <QPixmap>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Cache.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "QuickSwitcher.h"
|
||||
#include "RoomList.h"
|
||||
#include "RoomSettings.h"
|
||||
#include "RoomState.h"
|
||||
#include "Splitter.h"
|
||||
#include "TextInputWidget.h"
|
||||
#include "TimelineViewManager.h"
|
||||
#include "TopRoomBar.h"
|
||||
#include "UserInfoWidget.h"
|
||||
#include "MemberEventContent.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "StateEvent.h"
|
||||
|
||||
class Cache;
|
||||
class MatrixClient;
|
||||
class OverlayModal;
|
||||
class QuickSwitcher;
|
||||
class RoomList;
|
||||
class RoomSettings;
|
||||
class RoomState;
|
||||
class SideBarActions;
|
||||
class Splitter;
|
||||
class SyncResponse;
|
||||
class TextInputWidget;
|
||||
class TimelineViewManager;
|
||||
class TopRoomBar;
|
||||
class TypingDisplay;
|
||||
class UserInfoWidget;
|
||||
class JoinedRoom;
|
||||
class LeftRoom;
|
||||
|
||||
constexpr int CONSENSUS_TIMEOUT = 1000;
|
||||
constexpr int SHOW_CONTENT_TIMEOUT = 3000;
|
||||
constexpr int TYPING_REFRESH_TIMEOUT = 10000;
|
||||
|
||||
class ChatPage : public QWidget
|
||||
{
|
||||
@ -43,12 +59,16 @@ public:
|
||||
|
||||
// Initialize all the components of the UI.
|
||||
void bootstrap(QString userid, QString homeserver, QString token);
|
||||
void showQuickSwitcher();
|
||||
|
||||
signals:
|
||||
void contentLoaded();
|
||||
void close();
|
||||
void changeWindowTitle(const QString &msg);
|
||||
void unreadMessages(int count);
|
||||
void showNotification(const QString &msg);
|
||||
void showLoginPage(const QString &msg);
|
||||
void showUserSettingsPage();
|
||||
|
||||
private slots:
|
||||
void showUnreadMessageNotification(int count);
|
||||
@ -59,18 +79,32 @@ private slots:
|
||||
void syncCompleted(const SyncResponse &response);
|
||||
void syncFailed(const QString &msg);
|
||||
void changeTopRoomInfo(const QString &room_id);
|
||||
void startSync();
|
||||
void logout();
|
||||
void addRoom(const QString &room_id);
|
||||
void removeRoom(const QString &room_id);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private:
|
||||
void updateDisplayNames(const RoomState &state);
|
||||
using UserID = QString;
|
||||
using RoomStates = QMap<UserID, RoomState>;
|
||||
using JoinedRooms = QMap<UserID, JoinedRoom>;
|
||||
using LeftRooms = QMap<UserID, LeftRoom>;
|
||||
using Membership = matrix::events::StateEvent<matrix::events::MemberEventContent>;
|
||||
using Memberships = QMap<UserID, Membership>;
|
||||
|
||||
void removeLeftRooms(const LeftRooms &rooms);
|
||||
void updateJoinedRooms(const JoinedRooms &rooms);
|
||||
|
||||
Memberships getMemberships(const QJsonArray &events) const;
|
||||
RoomStates generateMembershipDifference(const JoinedRooms &rooms,
|
||||
const RoomStates &states) const;
|
||||
|
||||
void updateTypingUsers(const QString &roomid, const QList<QString> &user_ids);
|
||||
void updateUserMetadata(const QJsonArray &events);
|
||||
void updateUserDisplayName(const Membership &event);
|
||||
void updateUserAvatarUrl(const Membership &event);
|
||||
void loadStateFromCache();
|
||||
void showQuickSwitcher();
|
||||
void deleteConfigs();
|
||||
void resetUI();
|
||||
|
||||
QHBoxLayout *topLayout_;
|
||||
Splitter *splitter;
|
||||
@ -89,12 +123,15 @@ private:
|
||||
|
||||
RoomList *room_list_;
|
||||
TimelineViewManager *view_manager_;
|
||||
SideBarActions *sidebarActions_;
|
||||
|
||||
TopRoomBar *top_bar_;
|
||||
TextInputWidget *text_input_;
|
||||
TypingDisplay *typingDisplay_;
|
||||
|
||||
QTimer *sync_timer_;
|
||||
int sync_interval_;
|
||||
// Safety net if consensus is not possible or too slow.
|
||||
QTimer *showContentTimer_;
|
||||
QTimer *consensusTimer_;
|
||||
|
||||
QString current_room_;
|
||||
QMap<QString, QPixmap> room_avatars_;
|
||||
@ -104,12 +141,20 @@ private:
|
||||
QMap<QString, RoomState> state_manager_;
|
||||
QMap<QString, QSharedPointer<RoomSettings>> settingsManager_;
|
||||
|
||||
QuickSwitcher *quickSwitcher_ = nullptr;
|
||||
OverlayModal *quickSwitcherModal_ = nullptr;
|
||||
// Keeps track of the users currently typing on each room.
|
||||
QMap<QString, QList<QString>> typingUsers_;
|
||||
QTimer *typingRefresher_;
|
||||
|
||||
QSharedPointer<QuickSwitcher> quickSwitcher_;
|
||||
QSharedPointer<OverlayModal> quickSwitcherModal_;
|
||||
|
||||
// Matrix Client API provider.
|
||||
QSharedPointer<MatrixClient> client_;
|
||||
|
||||
// LMDB wrapper.
|
||||
QSharedPointer<Cache> cache_;
|
||||
|
||||
// If the number of failures exceeds a certain threshold we
|
||||
// return to the login page.
|
||||
int initialSyncFailures = 0;
|
||||
};
|
||||
|
@ -4,70 +4,70 @@
|
||||
//
|
||||
// Font sizes are in pixels.
|
||||
|
||||
namespace conf
|
||||
{
|
||||
namespace conf {
|
||||
// Global settings.
|
||||
static const int fontSize = 12;
|
||||
static const int emojiSize = 14;
|
||||
static const int headerFontSize = 21;
|
||||
static constexpr int fontSize = 12;
|
||||
static constexpr int textInputFontSize = 14;
|
||||
static constexpr int emojiSize = 14;
|
||||
static constexpr int headerFontSize = 21;
|
||||
static constexpr int typingNotificationFontSize = 11;
|
||||
|
||||
// Window geometry.
|
||||
namespace window
|
||||
{
|
||||
static const int height = 600;
|
||||
static const int width = 1066;
|
||||
namespace window {
|
||||
static constexpr int height = 600;
|
||||
static constexpr int width = 1066;
|
||||
|
||||
static const int minHeight = 600;
|
||||
static const int minWidth = 950;
|
||||
static constexpr int minHeight = height;
|
||||
static constexpr int minWidth = 950;
|
||||
} // namespace window
|
||||
|
||||
namespace textInput {
|
||||
static constexpr int height = 50;
|
||||
}
|
||||
|
||||
namespace sidebarActions {
|
||||
static constexpr int height = textInput::height;
|
||||
static constexpr int iconSize = 28;
|
||||
}
|
||||
|
||||
// Button settings.
|
||||
namespace btn
|
||||
{
|
||||
static const int fontSize = 20;
|
||||
static const int cornerRadius = 3;
|
||||
}
|
||||
namespace btn {
|
||||
static constexpr int fontSize = 20;
|
||||
static constexpr int cornerRadius = 3;
|
||||
} // namespace btn
|
||||
|
||||
// RoomList specific.
|
||||
namespace roomlist
|
||||
{
|
||||
namespace fonts
|
||||
{
|
||||
static const int heading = 13;
|
||||
static const int badge = 10;
|
||||
static const int bubble = 20;
|
||||
namespace roomlist {
|
||||
namespace fonts {
|
||||
static constexpr int heading = 13;
|
||||
static constexpr int badge = 10;
|
||||
static constexpr int bubble = 20;
|
||||
} // namespace fonts
|
||||
} // namespace roomlist
|
||||
|
||||
namespace userInfoWidget
|
||||
{
|
||||
namespace fonts
|
||||
{
|
||||
static const int displayName = 16;
|
||||
static const int userid = 14;
|
||||
namespace userInfoWidget {
|
||||
namespace fonts {
|
||||
static constexpr int displayName = 16;
|
||||
static constexpr int userid = 14;
|
||||
} // namespace fonts
|
||||
} // namespace userInfoWidget
|
||||
|
||||
namespace topRoomBar
|
||||
{
|
||||
namespace fonts
|
||||
{
|
||||
static const int roomName = 15;
|
||||
static const int roomDescription = 13;
|
||||
namespace topRoomBar {
|
||||
namespace fonts {
|
||||
static constexpr int roomName = 15;
|
||||
static constexpr int roomDescription = 13;
|
||||
} // namespace fonts
|
||||
} // namespace topRoomBar
|
||||
|
||||
namespace timeline
|
||||
{
|
||||
static const int msgMargin = 11;
|
||||
static const int avatarSize = 36;
|
||||
static const int headerSpacing = 5;
|
||||
static const int headerLeftMargin = 15;
|
||||
namespace timeline {
|
||||
static constexpr int msgMargin = 11;
|
||||
static constexpr int avatarSize = 36;
|
||||
static constexpr int headerSpacing = 5;
|
||||
static constexpr int headerLeftMargin = 15;
|
||||
|
||||
namespace fonts
|
||||
{
|
||||
static const int timestamp = 9;
|
||||
}
|
||||
}
|
||||
namespace fonts {
|
||||
static constexpr int timestamp = 9;
|
||||
} // namespace fonts
|
||||
} // namespace timeline
|
||||
|
||||
} // namespace conf
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
|
||||
class DeserializationException : public std::exception
|
||||
{
|
||||
|
@ -17,15 +17,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QListView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "EmojiItemDelegate.h"
|
||||
#include "EmojiProvider.h"
|
||||
|
||||
class EmojiProvider;
|
||||
|
||||
class EmojiCategory : public QWidget
|
||||
{
|
||||
@ -39,7 +38,10 @@ signals:
|
||||
void emojiSelected(const QString &emoji);
|
||||
|
||||
private slots:
|
||||
inline void clickIndex(const QModelIndex &);
|
||||
void clickIndex(const QModelIndex &index)
|
||||
{
|
||||
emit emojiSelected(index.data(Qt::UserRole).toString());
|
||||
};
|
||||
|
||||
private:
|
||||
QVBoxLayout *mainLayout_;
|
||||
@ -52,9 +54,3 @@ private:
|
||||
|
||||
QLabel *category_;
|
||||
};
|
||||
|
||||
inline void
|
||||
EmojiCategory::clickIndex(const QModelIndex &index)
|
||||
{
|
||||
emit emojiSelected(index.data(Qt::UserRole).toString());
|
||||
}
|
||||
|
@ -20,11 +20,11 @@
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QScrollArea>
|
||||
#include <QWidget>
|
||||
|
||||
#include "EmojiCategory.h"
|
||||
#include "EmojiProvider.h"
|
||||
|
||||
class EmojiCategory;
|
||||
|
||||
class EmojiPanel : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -20,9 +20,10 @@
|
||||
#include <QEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include "EmojiPanel.h"
|
||||
#include "FlatButton.h"
|
||||
|
||||
class EmojiPanel;
|
||||
|
||||
class EmojiPickButton : public FlatButton
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -43,5 +44,5 @@ private:
|
||||
// Horizontal distance from panel's bottom right corner.
|
||||
int horizontal_distance_ = 70;
|
||||
|
||||
EmojiPanel *panel_;
|
||||
QSharedPointer<EmojiPanel> panel_;
|
||||
};
|
||||
|
@ -17,11 +17,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFile>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
|
||||
struct Emoji {
|
||||
struct Emoji
|
||||
{
|
||||
// Unicode code.
|
||||
QString unicode;
|
||||
// Keyboard shortcut e.g :emoji:
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "Image.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "MessageEvent.h"
|
||||
|
||||
namespace events = matrix::events;
|
||||
namespace msgs = matrix::events::messages;
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QRegExp>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
class InputValidator
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <QFrame>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "FlatButton.h"
|
||||
class FlatButton;
|
||||
|
||||
class JoinRoomDialog : public QFrame
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
#include "FlatButton.h"
|
||||
class FlatButton;
|
||||
|
||||
class LeaveRoomDialog : public QFrame
|
||||
{
|
||||
|
@ -29,55 +29,25 @@ public:
|
||||
|
||||
QByteArray serialize() noexcept;
|
||||
|
||||
inline void setPassword(QString password);
|
||||
inline void setUser(QString username);
|
||||
void setPassword(QString password) { password_ = password; };
|
||||
void setUser(QString username) { user_ = username; };
|
||||
|
||||
private:
|
||||
QString user_;
|
||||
QString password_;
|
||||
};
|
||||
|
||||
inline void
|
||||
LoginRequest::setPassword(QString password)
|
||||
{
|
||||
password_ = password;
|
||||
}
|
||||
|
||||
inline void
|
||||
LoginRequest::setUser(QString username)
|
||||
{
|
||||
user_ = username;
|
||||
}
|
||||
|
||||
class LoginResponse : public Deserializable
|
||||
{
|
||||
public:
|
||||
void deserialize(const QJsonDocument &data) override;
|
||||
|
||||
inline QString getAccessToken();
|
||||
inline QString getHomeServer();
|
||||
inline QString getUserId();
|
||||
QString getAccessToken() { return access_token_; };
|
||||
QString getHomeServer() { return home_server_; };
|
||||
QString getUserId() { return user_id_; };
|
||||
|
||||
private:
|
||||
QString access_token_;
|
||||
QString home_server_;
|
||||
QString user_id_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
LoginResponse::getAccessToken()
|
||||
{
|
||||
return access_token_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
LoginResponse::getHomeServer()
|
||||
{
|
||||
return home_server_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
LoginResponse::getUserId()
|
||||
{
|
||||
return user_id_;
|
||||
}
|
||||
|
@ -17,18 +17,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QSharedPointer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "FlatButton.h"
|
||||
#include "LoadingIndicator.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "OverlayModal.h"
|
||||
#include "RaisedButton.h"
|
||||
#include "TextField.h"
|
||||
class FlatButton;
|
||||
class LoadingIndicator;
|
||||
class MatrixClient;
|
||||
class OverlayModal;
|
||||
class RaisedButton;
|
||||
class TextField;
|
||||
|
||||
class LoginPage : public QWidget
|
||||
{
|
||||
@ -43,6 +42,10 @@ public:
|
||||
signals:
|
||||
void backButtonClicked();
|
||||
|
||||
public slots:
|
||||
// Displays errors produced during the login.
|
||||
void loginError(QString error_message);
|
||||
|
||||
private slots:
|
||||
// Callback for the back button.
|
||||
void onBackButtonClicked();
|
||||
@ -56,9 +59,6 @@ private slots:
|
||||
// Callback for probing the manually entered server
|
||||
void onServerAddressEntered();
|
||||
|
||||
// Displays errors produced during the login.
|
||||
void loginError(QString error_message);
|
||||
|
||||
// Callback for errors produced during server probing
|
||||
void versionError(QString error_message);
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
#include "FlatButton.h"
|
||||
class FlatButton;
|
||||
|
||||
class LogoutDialog : public QFrame
|
||||
{
|
||||
|
@ -19,15 +19,20 @@
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSharedPointer>
|
||||
#include <QStackedWidget>
|
||||
#include <QSystemTrayIcon>
|
||||
|
||||
#include "ChatPage.h"
|
||||
#include "LoadingIndicator.h"
|
||||
#include "LoginPage.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "OverlayModal.h"
|
||||
#include "RegisterPage.h"
|
||||
#include "TrayIcon.h"
|
||||
#include "WelcomePage.h"
|
||||
class ChatPage;
|
||||
class LoadingIndicator;
|
||||
class LoginPage;
|
||||
class MatrixClient;
|
||||
class OverlayModal;
|
||||
class RegisterPage;
|
||||
class SnackBar;
|
||||
class TrayIcon;
|
||||
class UserSettingsPage;
|
||||
class UserSettings;
|
||||
class WelcomePage;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
@ -55,6 +60,7 @@ private slots:
|
||||
|
||||
// Show the register page in the main window.
|
||||
void showRegisterPage();
|
||||
void showUserSettingsPage();
|
||||
|
||||
// Show the chat page and start communicating with the given access token.
|
||||
void showChatPage(QString user_id, QString home_server, QString token);
|
||||
@ -81,14 +87,19 @@ private:
|
||||
|
||||
// The main chat area.
|
||||
ChatPage *chat_page_;
|
||||
UserSettingsPage *userSettingsPage_;
|
||||
QSharedPointer<UserSettings> userSettings_;
|
||||
|
||||
// Used to hide undefined states between page transitions.
|
||||
OverlayModal *progress_modal_;
|
||||
LoadingIndicator *spinner_;
|
||||
QSharedPointer<OverlayModal> progressModal_;
|
||||
QSharedPointer<LoadingIndicator> spinner_;
|
||||
|
||||
// Matrix Client API provider.
|
||||
QSharedPointer<MatrixClient> client_;
|
||||
|
||||
// Tray icon that shows the unread message count.
|
||||
TrayIcon *trayIcon_;
|
||||
|
||||
// Notifications display.
|
||||
QSharedPointer<SnackBar> snackBar_;
|
||||
};
|
||||
|
@ -17,12 +17,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QUrl>
|
||||
|
||||
#include "MessageEvent.h"
|
||||
#include "Profile.h"
|
||||
#include "RoomMessages.h"
|
||||
#include "Sync.h"
|
||||
|
||||
class SyncResponse;
|
||||
class Profile;
|
||||
class RoomMessages;
|
||||
|
||||
/*
|
||||
* MatrixClient provides the high level API to communicate with
|
||||
@ -50,14 +52,16 @@ public:
|
||||
void fetchUserAvatar(const QString &userId, const QUrl &avatarUrl);
|
||||
void fetchOwnAvatar(const QUrl &avatar_url);
|
||||
void downloadImage(const QString &event_id, const QUrl &url);
|
||||
void messages(const QString &room_id, const QString &from_token, int limit = 20) noexcept;
|
||||
void messages(const QString &room_id, const QString &from_token, int limit = 30) noexcept;
|
||||
void uploadImage(const QString &roomid, const QString &filename);
|
||||
void joinRoom(const QString &roomIdOrAlias);
|
||||
void leaveRoom(const QString &roomId);
|
||||
void sendTypingNotification(const QString &roomid, int timeoutInMillis = 20000);
|
||||
void removeTypingNotification(const QString &roomid);
|
||||
|
||||
inline QUrl getHomeServer();
|
||||
inline int transactionId();
|
||||
inline void incrementTransactionId();
|
||||
QUrl getHomeServer() { return server_; };
|
||||
int transactionId() { return txn_id_; };
|
||||
void incrementTransactionId() { txn_id_ += 1; };
|
||||
|
||||
void reset() noexcept;
|
||||
|
||||
@ -65,9 +69,12 @@ public slots:
|
||||
void getOwnProfile() noexcept;
|
||||
void logout() noexcept;
|
||||
|
||||
inline void setServer(const QString &server);
|
||||
inline void setAccessToken(const QString &token);
|
||||
inline void setNextBatchToken(const QString &next_batch);
|
||||
void setServer(const QString &server)
|
||||
{
|
||||
server_ = QUrl(QString("https://%1").arg(server));
|
||||
};
|
||||
void setAccessToken(const QString &token) { token_ = token; };
|
||||
void setNextBatchToken(const QString &next_batch) { next_batch_ = next_batch; };
|
||||
|
||||
signals:
|
||||
void loginError(const QString &error);
|
||||
@ -91,56 +98,17 @@ signals:
|
||||
// Returned profile data for the user's account.
|
||||
void getOwnProfileResponse(const QUrl &avatar_url, const QString &display_name);
|
||||
void initialSyncCompleted(const SyncResponse &response);
|
||||
void initialSyncFailed(const QString &msg);
|
||||
void syncCompleted(const SyncResponse &response);
|
||||
void syncFailed(const QString &msg);
|
||||
void joinFailed(const QString &msg);
|
||||
void messageSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||
void emoteSent(const QString &event_id, const QString &roomid, const int txn_id);
|
||||
void messagesRetrieved(const QString &room_id, const RoomMessages &msgs);
|
||||
void joinedRoom(const QString &room_id);
|
||||
void leftRoom(const QString &room_id);
|
||||
|
||||
private slots:
|
||||
void onResponse(QNetworkReply *reply);
|
||||
|
||||
private:
|
||||
enum class Endpoint {
|
||||
GetOwnAvatar,
|
||||
GetOwnProfile,
|
||||
GetProfile,
|
||||
Image,
|
||||
InitialSync,
|
||||
ImageUpload,
|
||||
Login,
|
||||
Logout,
|
||||
Messages,
|
||||
Register,
|
||||
RoomAvatar,
|
||||
SendRoomMessage,
|
||||
Sync,
|
||||
UserAvatar,
|
||||
Versions,
|
||||
JoinRoom,
|
||||
LeaveRoom,
|
||||
};
|
||||
|
||||
// Response handlers.
|
||||
void onGetOwnAvatarResponse(QNetworkReply *reply);
|
||||
void onGetOwnProfileResponse(QNetworkReply *reply);
|
||||
void onImageResponse(QNetworkReply *reply);
|
||||
void onInitialSyncResponse(QNetworkReply *reply);
|
||||
void onImageUploadResponse(QNetworkReply *reply);
|
||||
void onLoginResponse(QNetworkReply *reply);
|
||||
void onLogoutResponse(QNetworkReply *reply);
|
||||
void onMessagesResponse(QNetworkReply *reply);
|
||||
void onRegisterResponse(QNetworkReply *reply);
|
||||
void onRoomAvatarResponse(QNetworkReply *reply);
|
||||
void onSendRoomMessage(QNetworkReply *reply);
|
||||
void onSyncResponse(QNetworkReply *reply);
|
||||
void onUserAvatarResponse(QNetworkReply *reply);
|
||||
void onVersionsResponse(QNetworkReply *reply);
|
||||
void onJoinRoomResponse(QNetworkReply *reply);
|
||||
void onLeaveRoomResponse(QNetworkReply *reply);
|
||||
|
||||
// Client API prefix.
|
||||
QString clientApiUrl_;
|
||||
|
||||
@ -159,39 +127,3 @@ private:
|
||||
// Token to be used for the next sync.
|
||||
QString next_batch_;
|
||||
};
|
||||
|
||||
inline QUrl
|
||||
MatrixClient::getHomeServer()
|
||||
{
|
||||
return server_;
|
||||
}
|
||||
|
||||
inline int
|
||||
MatrixClient::transactionId()
|
||||
{
|
||||
return txn_id_;
|
||||
}
|
||||
|
||||
inline void
|
||||
MatrixClient::setServer(const QString &server)
|
||||
{
|
||||
server_ = QUrl(QString("https://%1").arg(server));
|
||||
}
|
||||
|
||||
inline void
|
||||
MatrixClient::setAccessToken(const QString &token)
|
||||
{
|
||||
token_ = token;
|
||||
}
|
||||
|
||||
inline void
|
||||
MatrixClient::setNextBatchToken(const QString &next_batch)
|
||||
{
|
||||
next_batch_ = next_batch;
|
||||
}
|
||||
|
||||
inline void
|
||||
MatrixClient::incrementTransactionId()
|
||||
{
|
||||
txn_id_ += 1;
|
||||
}
|
||||
|
@ -20,29 +20,17 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QUrl>
|
||||
|
||||
#include "Deserializable.h"
|
||||
class Deserializable;
|
||||
|
||||
class ProfileResponse : public Deserializable
|
||||
{
|
||||
public:
|
||||
void deserialize(const QJsonDocument &data) override;
|
||||
|
||||
inline QUrl getAvatarUrl();
|
||||
inline QString getDisplayName();
|
||||
QUrl getAvatarUrl() { return avatar_url_; };
|
||||
QString getDisplayName() { return display_name_; };
|
||||
|
||||
private:
|
||||
QUrl avatar_url_;
|
||||
QString display_name_;
|
||||
};
|
||||
|
||||
inline QUrl
|
||||
ProfileResponse::getAvatarUrl()
|
||||
{
|
||||
return avatar_url_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
ProfileResponse::getDisplayName()
|
||||
{
|
||||
return display_name_;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
|
||||
#include "Deserializable.h"
|
||||
class Deserializable;
|
||||
|
||||
class RegisterRequest
|
||||
{
|
||||
@ -29,55 +29,25 @@ public:
|
||||
|
||||
QByteArray serialize() noexcept;
|
||||
|
||||
inline void setPassword(QString password);
|
||||
inline void setUser(QString username);
|
||||
void setPassword(QString password) { password_ = password; };
|
||||
void setUser(QString username) { user_ = username; };
|
||||
|
||||
private:
|
||||
QString user_;
|
||||
QString password_;
|
||||
};
|
||||
|
||||
inline void
|
||||
RegisterRequest::setPassword(QString password)
|
||||
{
|
||||
password_ = password;
|
||||
}
|
||||
|
||||
inline void
|
||||
RegisterRequest::setUser(QString username)
|
||||
{
|
||||
user_ = username;
|
||||
}
|
||||
|
||||
class RegisterResponse : public Deserializable
|
||||
{
|
||||
public:
|
||||
void deserialize(const QJsonDocument &data) override;
|
||||
|
||||
inline QString getAccessToken();
|
||||
inline QString getHomeServer();
|
||||
inline QString getUserId();
|
||||
QString getAccessToken() { return access_token_; };
|
||||
QString getHomeServer() { return home_server_; };
|
||||
QString getUserId() { return user_id_; };
|
||||
|
||||
private:
|
||||
QString access_token_;
|
||||
QString home_server_;
|
||||
QString user_id_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
RegisterResponse::getAccessToken()
|
||||
{
|
||||
return access_token_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
RegisterResponse::getHomeServer()
|
||||
{
|
||||
return home_server_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
RegisterResponse::getUserId()
|
||||
{
|
||||
return user_id_;
|
||||
}
|
||||
|
@ -17,17 +17,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QSharedPointer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "FlatButton.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "RaisedButton.h"
|
||||
#include "TextField.h"
|
||||
class Avatar;
|
||||
class FlatButton;
|
||||
class MatrixClient;
|
||||
class RaisedButton;
|
||||
class TextField;
|
||||
|
||||
class RegisterPage : public QWidget
|
||||
{
|
||||
|
@ -21,12 +21,14 @@
|
||||
#include <QSharedPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Menu.h"
|
||||
#include "RippleOverlay.h"
|
||||
#include "RoomSettings.h"
|
||||
#include "RoomState.h"
|
||||
|
||||
struct DescInfo {
|
||||
class Menu;
|
||||
class RippleOverlay;
|
||||
class RoomSettings;
|
||||
|
||||
struct DescInfo
|
||||
{
|
||||
QString username;
|
||||
QString userid;
|
||||
QString body;
|
||||
@ -49,11 +51,12 @@ public:
|
||||
void clearUnreadMessageCount();
|
||||
void setState(const RoomState &state);
|
||||
|
||||
inline bool isPressed() const;
|
||||
inline RoomState state() const;
|
||||
inline void setAvatar(const QImage &avatar_image);
|
||||
inline int unreadMessageCount() const;
|
||||
inline void setDescriptionMessage(const DescInfo &info);
|
||||
bool isPressed() const { return isPressed_; };
|
||||
RoomState state() const { return state_; };
|
||||
int unreadMessageCount() const { return unreadMsgCount_; };
|
||||
|
||||
void setAvatar(const QImage &avatar_image);
|
||||
void setDescriptionMessage(const DescInfo &info);
|
||||
|
||||
signals:
|
||||
void clicked(const QString &room_id);
|
||||
@ -96,36 +99,3 @@ private:
|
||||
int maxHeight_;
|
||||
int unreadMsgCount_ = 0;
|
||||
};
|
||||
|
||||
inline int
|
||||
RoomInfoListItem::unreadMessageCount() const
|
||||
{
|
||||
return unreadMsgCount_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
RoomInfoListItem::isPressed() const
|
||||
{
|
||||
return isPressed_;
|
||||
}
|
||||
|
||||
inline RoomState
|
||||
RoomInfoListItem::state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
inline void
|
||||
RoomInfoListItem::setAvatar(const QImage &img)
|
||||
{
|
||||
roomAvatar_ = QPixmap::fromImage(
|
||||
img.scaled(IconSize, IconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
RoomInfoListItem::setDescriptionMessage(const DescInfo &info)
|
||||
{
|
||||
lastMsgInfo_ = info;
|
||||
update();
|
||||
}
|
||||
|
@ -17,19 +17,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QSharedPointer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "JoinRoomDialog.h"
|
||||
#include "LeaveRoomDialog.h"
|
||||
#include "MatrixClient.h"
|
||||
#include "OverlayModal.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "RoomState.h"
|
||||
#include "Sync.h"
|
||||
class JoinRoomDialog;
|
||||
class LeaveRoomDialog;
|
||||
class MatrixClient;
|
||||
class OverlayModal;
|
||||
class RoomInfoListItem;
|
||||
class RoomSettings;
|
||||
class RoomState;
|
||||
class Sync;
|
||||
struct DescInfo;
|
||||
|
||||
class RoomList : public QWidget
|
||||
{
|
||||
@ -76,8 +79,8 @@ private:
|
||||
OverlayModal *joinRoomModal_;
|
||||
JoinRoomDialog *joinRoomDialog_;
|
||||
|
||||
OverlayModal *leaveRoomModal;
|
||||
LeaveRoomDialog *leaveRoomDialog_;
|
||||
QSharedPointer<OverlayModal> leaveRoomModal_;
|
||||
QSharedPointer<LeaveRoomDialog> leaveRoomDialog_;
|
||||
|
||||
QMap<QString, QSharedPointer<RoomInfoListItem>> rooms_;
|
||||
|
||||
|
@ -27,30 +27,12 @@ class RoomMessages : public Deserializable
|
||||
public:
|
||||
void deserialize(const QJsonDocument &data) override;
|
||||
|
||||
inline QString start() const;
|
||||
inline QString end() const;
|
||||
inline QJsonArray chunk() const;
|
||||
QString start() const { return start_; };
|
||||
QString end() const { return end_; };
|
||||
QJsonArray chunk() const { return chunk_; };
|
||||
|
||||
private:
|
||||
QString start_;
|
||||
QString end_;
|
||||
QJsonArray chunk_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
RoomMessages::start() const
|
||||
{
|
||||
return start_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
RoomMessages::end() const
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
||||
inline QJsonArray
|
||||
RoomMessages::chunk() const
|
||||
{
|
||||
return chunk_;
|
||||
}
|
||||
|
@ -35,10 +35,7 @@ public:
|
||||
settings.setValue(path_, isNotificationsEnabled_);
|
||||
};
|
||||
|
||||
bool isNotificationsEnabled()
|
||||
{
|
||||
return isNotificationsEnabled_;
|
||||
};
|
||||
bool isNotificationsEnabled() { return isNotificationsEnabled_; };
|
||||
|
||||
void toggleNotifications()
|
||||
{
|
||||
|
@ -41,6 +41,9 @@ namespace events = matrix::events;
|
||||
class RoomState
|
||||
{
|
||||
public:
|
||||
RoomState();
|
||||
RoomState(const QJsonArray &events);
|
||||
|
||||
// Calculate room data that are not immediatly accessible. Like room name and
|
||||
// avatar.
|
||||
//
|
||||
@ -49,9 +52,9 @@ public:
|
||||
void resolveAvatar();
|
||||
void parse(const QJsonObject &object);
|
||||
|
||||
inline QUrl getAvatar() const;
|
||||
inline QString getName() const;
|
||||
inline QString getTopic() const;
|
||||
QUrl getAvatar() const { return avatar_; };
|
||||
QString getName() const { return name_; };
|
||||
QString getTopic() const { return topic.content().topic().simplified(); };
|
||||
|
||||
void removeLeaveMemberships();
|
||||
void update(const RoomState &state);
|
||||
@ -71,7 +74,8 @@ public:
|
||||
events::StateEvent<events::TopicEventContent> topic;
|
||||
|
||||
// Contains the m.room.member events for all the joined users.
|
||||
QMap<QString, events::StateEvent<events::MemberEventContent>> memberships;
|
||||
using UserID = QString;
|
||||
QMap<UserID, events::StateEvent<events::MemberEventContent>> memberships;
|
||||
|
||||
private:
|
||||
QUrl avatar_;
|
||||
@ -81,21 +85,3 @@ private:
|
||||
// avatar event this should be empty.
|
||||
QString userAvatar_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
RoomState::getTopic() const
|
||||
{
|
||||
return topic.content().topic().simplified();
|
||||
}
|
||||
|
||||
inline QString
|
||||
RoomState::getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
inline QUrl
|
||||
RoomState::getAvatar() const
|
||||
{
|
||||
return avatar_;
|
||||
}
|
||||
|
29
include/SideBarActions.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QResizeEvent>
|
||||
#include <QWidget>
|
||||
|
||||
#include "FlatButton.h"
|
||||
|
||||
class SideBarActions : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SideBarActions(QWidget *parent = nullptr);
|
||||
~SideBarActions();
|
||||
|
||||
signals:
|
||||
void showSettings();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
private:
|
||||
QHBoxLayout *layout_;
|
||||
|
||||
FlatButton *settingsBtn_;
|
||||
FlatButton *createRoomBtn_;
|
||||
FlatButton *joinRoomBtn_;
|
||||
};
|
159
include/Sync.h
@ -18,24 +18,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
class Event : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QJsonObject content() const;
|
||||
inline QJsonObject unsigned_content() const;
|
||||
QJsonObject content() const { return content_; };
|
||||
QJsonObject unsigned_content() const { return unsigned_; };
|
||||
|
||||
inline QString sender() const;
|
||||
inline QString state_key() const;
|
||||
inline QString type() const;
|
||||
inline QString eventId() const;
|
||||
QString sender() const { return sender_; };
|
||||
QString state_key() const { return state_key_; };
|
||||
QString type() const { return type_; };
|
||||
QString eventId() const { return event_id_; };
|
||||
|
||||
inline uint64_t timestamp() const;
|
||||
uint64_t timestamp() const { return origin_server_ts_; };
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
|
||||
@ -51,70 +49,22 @@ private:
|
||||
uint64_t origin_server_ts_;
|
||||
};
|
||||
|
||||
inline QJsonObject
|
||||
Event::content() const
|
||||
{
|
||||
return content_;
|
||||
}
|
||||
|
||||
inline QJsonObject
|
||||
Event::unsigned_content() const
|
||||
{
|
||||
return unsigned_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
Event::sender() const
|
||||
{
|
||||
return sender_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
Event::state_key() const
|
||||
{
|
||||
return state_key_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
Event::type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
Event::eventId() const
|
||||
{
|
||||
return event_id_;
|
||||
}
|
||||
|
||||
inline uint64_t
|
||||
Event::timestamp() const
|
||||
{
|
||||
return origin_server_ts_;
|
||||
}
|
||||
|
||||
class State : public Deserializable
|
||||
{
|
||||
public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
inline QJsonArray events() const;
|
||||
QJsonArray events() const { return events_; };
|
||||
|
||||
private:
|
||||
QJsonArray events_;
|
||||
};
|
||||
|
||||
inline QJsonArray
|
||||
State::events() const
|
||||
{
|
||||
return events_;
|
||||
}
|
||||
|
||||
class Timeline : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QJsonArray events() const;
|
||||
inline QString previousBatch() const;
|
||||
inline bool limited() const;
|
||||
QJsonArray events() const { return events_; };
|
||||
QString previousBatch() const { return prev_batch_; };
|
||||
bool limited() const { return limited_; };
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
|
||||
@ -124,58 +74,29 @@ private:
|
||||
bool limited_;
|
||||
};
|
||||
|
||||
inline QJsonArray
|
||||
Timeline::events() const
|
||||
{
|
||||
return events_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
Timeline::previousBatch() const
|
||||
{
|
||||
return prev_batch_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
Timeline::limited() const
|
||||
{
|
||||
return limited_;
|
||||
}
|
||||
|
||||
// TODO: Add support for ehpmeral, account_data, undread_notifications
|
||||
// TODO: Add support for account_data, undread_notifications
|
||||
class JoinedRoom : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline State state() const;
|
||||
inline Timeline timeline() const;
|
||||
State state() const { return state_; };
|
||||
Timeline timeline() const { return timeline_; };
|
||||
QList<QString> typingUserIDs() const { return typingUserIDs_; };
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
|
||||
private:
|
||||
State state_;
|
||||
Timeline timeline_;
|
||||
/* Ephemeral ephemeral_; */
|
||||
QList<QString> typingUserIDs_;
|
||||
/* AccountData account_data_; */
|
||||
/* UnreadNotifications unread_notifications_; */
|
||||
};
|
||||
|
||||
inline State
|
||||
JoinedRoom::state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
inline Timeline
|
||||
JoinedRoom::timeline() const
|
||||
{
|
||||
return timeline_;
|
||||
}
|
||||
|
||||
class LeftRoom : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline State state() const;
|
||||
inline Timeline timeline() const;
|
||||
State state() const { return state_; };
|
||||
Timeline timeline() const { return timeline_; };
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
|
||||
@ -184,24 +105,12 @@ private:
|
||||
Timeline timeline_;
|
||||
};
|
||||
|
||||
inline State
|
||||
LeftRoom::state() const
|
||||
{
|
||||
return state_;
|
||||
}
|
||||
|
||||
inline Timeline
|
||||
LeftRoom::timeline() const
|
||||
{
|
||||
return timeline_;
|
||||
}
|
||||
|
||||
// TODO: Add support for invited and left rooms.
|
||||
class Rooms : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QMap<QString, JoinedRoom> join() const;
|
||||
inline QMap<QString, LeftRoom> leave() const;
|
||||
QMap<QString, JoinedRoom> join() const { return join_; };
|
||||
QMap<QString, LeftRoom> leave() const { return leave_; };
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
|
||||
private:
|
||||
@ -209,38 +118,14 @@ private:
|
||||
QMap<QString, LeftRoom> leave_;
|
||||
};
|
||||
|
||||
inline QMap<QString, JoinedRoom>
|
||||
Rooms::join() const
|
||||
{
|
||||
return join_;
|
||||
}
|
||||
|
||||
inline QMap<QString, LeftRoom>
|
||||
Rooms::leave() const
|
||||
{
|
||||
return leave_;
|
||||
}
|
||||
|
||||
class SyncResponse : public Deserializable
|
||||
{
|
||||
public:
|
||||
void deserialize(const QJsonDocument &data) override;
|
||||
inline QString nextBatch() const;
|
||||
inline Rooms rooms() const;
|
||||
QString nextBatch() const { return next_batch_; };
|
||||
Rooms rooms() const { return rooms_; };
|
||||
|
||||
private:
|
||||
QString next_batch_;
|
||||
Rooms rooms_;
|
||||
};
|
||||
|
||||
inline Rooms
|
||||
SyncResponse::rooms() const
|
||||
{
|
||||
return rooms_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
SyncResponse::nextBatch() const
|
||||
{
|
||||
return next_batch_;
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPaintEvent>
|
||||
#include <QTextEdit>
|
||||
@ -29,17 +31,36 @@
|
||||
|
||||
namespace msgs = matrix::events::messages;
|
||||
|
||||
static const QString EMOTE_COMMAND("/me ");
|
||||
|
||||
class FilteredTextEdit : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FilteredTextEdit(QWidget *parent = nullptr);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
|
||||
void stopTyping();
|
||||
|
||||
QSize sizeHint() const override;
|
||||
QSize minimumSizeHint() const override;
|
||||
|
||||
void submit();
|
||||
|
||||
signals:
|
||||
void enterPressed();
|
||||
void startedTyping();
|
||||
void stoppedTyping();
|
||||
void message(QString);
|
||||
void command(QString name, QString args);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
private:
|
||||
std::deque<QString> true_history_, working_history_;
|
||||
size_t history_index_;
|
||||
QTimer *typingTimer_;
|
||||
|
||||
void textChanged();
|
||||
void afterCompletion(int);
|
||||
};
|
||||
|
||||
class TextInputWidget : public QFrame
|
||||
@ -50,11 +71,12 @@ public:
|
||||
TextInputWidget(QWidget *parent = 0);
|
||||
~TextInputWidget();
|
||||
|
||||
void stopTyping();
|
||||
|
||||
public slots:
|
||||
void onSendButtonClicked();
|
||||
void openFileSelection();
|
||||
void hideUploadSpinner();
|
||||
inline void focusLineEdit();
|
||||
void focusLineEdit() { input_->setFocus(); };
|
||||
|
||||
private slots:
|
||||
void addSelectedEmoji(const QString &emoji);
|
||||
@ -63,10 +85,17 @@ signals:
|
||||
void sendTextMessage(QString msg);
|
||||
void sendEmoteMessage(QString msg);
|
||||
void uploadImage(QString filename);
|
||||
void sendJoinRoomRequest(const QString &room);
|
||||
|
||||
void startedTyping();
|
||||
void stoppedTyping();
|
||||
|
||||
protected:
|
||||
void focusInEvent(QFocusEvent *event);
|
||||
|
||||
private:
|
||||
void showUploadSpinner();
|
||||
QString parseEmoteCommand(const QString &cmd);
|
||||
void command(QString name, QString args);
|
||||
|
||||
QHBoxLayout *topLayout_;
|
||||
FilteredTextEdit *input_;
|
||||
@ -77,9 +106,3 @@ private:
|
||||
FlatButton *sendMessageBtn_;
|
||||
EmojiPickButton *emojiBtn_;
|
||||
};
|
||||
|
||||
inline void
|
||||
TextInputWidget::focusLineEdit()
|
||||
{
|
||||
input_->setFocus();
|
||||
}
|
||||
|
@ -19,12 +19,7 @@
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QWidget>
|
||||
|
||||
#include "ImageItem.h"
|
||||
#include "Sync.h"
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "Emote.h"
|
||||
#include "Image.h"
|
||||
#include "MessageEvent.h"
|
||||
@ -32,6 +27,9 @@
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Text.h"
|
||||
|
||||
class ImageItem;
|
||||
class Avatar;
|
||||
|
||||
namespace events = matrix::events;
|
||||
namespace msgs = matrix::events::messages;
|
||||
|
||||
@ -65,7 +63,7 @@ public:
|
||||
QWidget *parent);
|
||||
|
||||
void setUserAvatar(const QImage &pixmap);
|
||||
inline DescInfo descriptionMessage() const;
|
||||
DescInfo descriptionMessage() const { return descriptionMsg_; };
|
||||
|
||||
~TimelineItem();
|
||||
|
||||
@ -98,9 +96,3 @@ private:
|
||||
QLabel *userName_;
|
||||
QLabel *body_;
|
||||
};
|
||||
|
||||
inline DescInfo
|
||||
TimelineItem::descriptionMessage() const
|
||||
{
|
||||
return descriptionMsg_;
|
||||
}
|
||||
|
@ -17,29 +17,31 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLayout>
|
||||
#include <QList>
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "ScrollBar.h"
|
||||
#include "Sync.h"
|
||||
#include "TimelineItem.h"
|
||||
|
||||
#include "Emote.h"
|
||||
#include "Image.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "Notice.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Text.h"
|
||||
|
||||
class FloatingButton;
|
||||
class MatrixClient;
|
||||
class RoomMessages;
|
||||
class ScrollBar;
|
||||
class Timeline;
|
||||
class TimelineItem;
|
||||
struct DescInfo;
|
||||
|
||||
namespace msgs = matrix::events::messages;
|
||||
namespace events = matrix::events;
|
||||
|
||||
// Contains info about a message shown in the history view
|
||||
// but not yet confirmed by the homeserver through sync.
|
||||
struct PendingMessage {
|
||||
struct PendingMessage
|
||||
{
|
||||
int txn_id;
|
||||
QString body;
|
||||
QString event_id;
|
||||
@ -50,12 +52,12 @@ struct PendingMessage {
|
||||
, body(body)
|
||||
, event_id(event_id)
|
||||
, widget(widget)
|
||||
{
|
||||
}
|
||||
{}
|
||||
};
|
||||
|
||||
// In which place new TimelineItems should be inserted.
|
||||
enum class TimelineDirection {
|
||||
enum class TimelineDirection
|
||||
{
|
||||
Top,
|
||||
Bottom,
|
||||
};
|
||||
@ -97,6 +99,9 @@ public slots:
|
||||
// Add old events at the top of the timeline.
|
||||
void addBackwardsEvents(const QString &room_id, const RoomMessages &msgs);
|
||||
|
||||
// Whether or not the initial batch has been loaded.
|
||||
bool hasLoaded() { return scroll_layout_->count() > 1 || isTimelineFinished; };
|
||||
|
||||
signals:
|
||||
void updateLastTimelineMessage(const QString &user, const DescInfo &info);
|
||||
|
||||
@ -116,7 +121,7 @@ private:
|
||||
const QString &userid);
|
||||
void removePendingMessage(const QString &eventid, const QString &body);
|
||||
|
||||
inline bool isDuplicate(const QString &event_id);
|
||||
bool isDuplicate(const QString &event_id) { return eventIds_.contains(event_id); };
|
||||
|
||||
// Return nullptr if the event couldn't be parsed.
|
||||
TimelineItem *parseMessageEvent(const QJsonObject &event, TimelineDirection direction);
|
||||
@ -137,12 +142,11 @@ private:
|
||||
bool isPaginationInProgress_ = false;
|
||||
|
||||
// Keeps track whether or not the user has visited the view.
|
||||
bool isInitialized = false;
|
||||
bool isTimelineFinished = false;
|
||||
bool isInitialSync = true;
|
||||
bool isPaginationScrollPending_ = false;
|
||||
bool isInitialized = false;
|
||||
bool isTimelineFinished = false;
|
||||
bool isInitialSync = true;
|
||||
|
||||
const int SCROLL_BAR_GAP = 400;
|
||||
const int SCROLL_BAR_GAP = 200;
|
||||
|
||||
QTimer *paginationTimer_;
|
||||
|
||||
@ -152,14 +156,12 @@ private:
|
||||
int oldPosition_;
|
||||
int oldHeight_;
|
||||
|
||||
FloatingButton *scrollDownBtn_;
|
||||
|
||||
TimelineDirection lastMessageDirection_;
|
||||
|
||||
// The events currently rendered. Used for duplicate detection.
|
||||
QMap<QString, bool> eventIds_;
|
||||
QList<PendingMessage> pending_msgs_;
|
||||
QSharedPointer<MatrixClient> client_;
|
||||
};
|
||||
|
||||
inline bool
|
||||
TimelineView::isDuplicate(const QString &event_id)
|
||||
{
|
||||
return eventIds_.contains(event_id);
|
||||
}
|
||||
|
@ -17,16 +17,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
#include <QSharedPointer>
|
||||
#include <QStackedWidget>
|
||||
#include <QWidget>
|
||||
|
||||
#include "MatrixClient.h"
|
||||
#include "MessageEvent.h"
|
||||
#include "RoomInfoListItem.h"
|
||||
#include "Sync.h"
|
||||
#include "TimelineView.h"
|
||||
class JoinedRoom;
|
||||
class MatrixClient;
|
||||
class RoomInfoListItem;
|
||||
class Rooms;
|
||||
class TimelineView;
|
||||
struct DescInfo;
|
||||
|
||||
class TimelineViewManager : public QStackedWidget
|
||||
{
|
||||
@ -47,6 +47,9 @@ public:
|
||||
void sync(const Rooms &rooms);
|
||||
void clearAll();
|
||||
|
||||
// Check if all the timelines have been loaded.
|
||||
bool hasLoaded() const;
|
||||
|
||||
static QString chooseRandomColor();
|
||||
static QString displayName(const QString &userid);
|
||||
|
||||
|
@ -18,21 +18,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QIcon>
|
||||
#include <QImage>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QPaintEvent>
|
||||
#include <QSharedPointer>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "FlatButton.h"
|
||||
#include "LeaveRoomDialog.h"
|
||||
#include "Menu.h"
|
||||
#include "OverlayModal.h"
|
||||
#include "RoomSettings.h"
|
||||
class Avatar;
|
||||
class FlatButton;
|
||||
class Label;
|
||||
class LeaveRoomDialog;
|
||||
class Menu;
|
||||
class OverlayModal;
|
||||
class RoomSettings;
|
||||
|
||||
static const QString URL_HTML = "<a href=\"\\1\" style=\"color: #333333\">\\1</a>";
|
||||
static const QRegExp URL_REGEX("((?:https?|ftp)://\\S+)");
|
||||
@ -44,10 +44,10 @@ public:
|
||||
TopRoomBar(QWidget *parent = 0);
|
||||
~TopRoomBar();
|
||||
|
||||
inline void updateRoomAvatar(const QImage &avatar_image);
|
||||
inline void updateRoomAvatar(const QIcon &icon);
|
||||
inline void updateRoomName(const QString &name);
|
||||
inline void updateRoomTopic(QString topic);
|
||||
void updateRoomAvatar(const QImage &avatar_image);
|
||||
void updateRoomAvatar(const QIcon &icon);
|
||||
void updateRoomName(const QString &name);
|
||||
void updateRoomTopic(QString topic);
|
||||
void updateRoomAvatarFromName(const QString &name);
|
||||
void setRoomSettings(QSharedPointer<RoomSettings> settings);
|
||||
|
||||
@ -58,6 +58,7 @@ signals:
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void closeLeaveRoomDialog(bool leaving);
|
||||
@ -67,7 +68,7 @@ private:
|
||||
QVBoxLayout *textLayout_;
|
||||
|
||||
QLabel *nameLabel_;
|
||||
QLabel *topicLabel_;
|
||||
Label *topicLabel_;
|
||||
|
||||
QSharedPointer<RoomSettings> roomSettings_;
|
||||
|
||||
@ -77,45 +78,13 @@ private:
|
||||
|
||||
FlatButton *settingsBtn_;
|
||||
|
||||
OverlayModal *leaveRoomModal;
|
||||
LeaveRoomDialog *leaveRoomDialog_;
|
||||
QSharedPointer<OverlayModal> leaveRoomModal_;
|
||||
QSharedPointer<LeaveRoomDialog> leaveRoomDialog_;
|
||||
|
||||
Avatar *avatar_;
|
||||
|
||||
int buttonSize_;
|
||||
|
||||
QString roomName_;
|
||||
QString roomTopic_;
|
||||
};
|
||||
|
||||
inline void
|
||||
TopRoomBar::updateRoomAvatar(const QImage &avatar_image)
|
||||
{
|
||||
avatar_->setImage(avatar_image);
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
TopRoomBar::updateRoomAvatar(const QIcon &icon)
|
||||
{
|
||||
avatar_->setIcon(icon);
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
TopRoomBar::updateRoomName(const QString &name)
|
||||
{
|
||||
QString elidedText =
|
||||
QFontMetrics(nameLabel_->font()).elidedText(name, Qt::ElideRight, width() * 0.8);
|
||||
nameLabel_->setText(elidedText);
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
TopRoomBar::updateRoomTopic(QString topic)
|
||||
{
|
||||
topic.replace(URL_REGEX, URL_HTML);
|
||||
|
||||
QString elidedText =
|
||||
QFontMetrics(topicLabel_->font()).elidedText(topic, Qt::ElideRight, width() * 0.6);
|
||||
|
||||
topicLabel_->setText(topic);
|
||||
update();
|
||||
}
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <QAction>
|
||||
#include <QIcon>
|
||||
#include <QIconEngine>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QRect>
|
||||
#include <QSystemTrayIcon>
|
||||
|
21
include/TypingDisplay.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPaintEvent>
|
||||
#include <QWidget>
|
||||
|
||||
class TypingDisplay : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TypingDisplay(QWidget *parent = nullptr);
|
||||
|
||||
void setUsers(const QStringList &user_ids);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
QString text_;
|
||||
int leftPadding_;
|
||||
};
|
@ -17,15 +17,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "FlatButton.h"
|
||||
#include "LogoutDialog.h"
|
||||
#include "OverlayModal.h"
|
||||
class Avatar;
|
||||
class FlatButton;
|
||||
class LogoutDialog;
|
||||
class OverlayModal;
|
||||
|
||||
class UserInfoWidget : public QWidget
|
||||
{
|
||||
@ -68,8 +66,8 @@ private:
|
||||
|
||||
QImage avatar_image_;
|
||||
|
||||
OverlayModal *logoutModal_;
|
||||
LogoutDialog *logoutDialog_;
|
||||
QSharedPointer<OverlayModal> logoutModal_;
|
||||
QSharedPointer<LogoutDialog> logoutDialog_;
|
||||
|
||||
int logoutButtonSize_;
|
||||
};
|
||||
|
81
include/UserSettingsPage.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* nheko Copyright (C) 2017 Konstantinos Sideris <siderisk@auth.gr>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFrame>
|
||||
#include <QLayout>
|
||||
#include <QSharedPointer>
|
||||
#include <QWidget>
|
||||
|
||||
class Toggle;
|
||||
|
||||
constexpr int OptionMargin = 6;
|
||||
constexpr int LayoutSideMargin = 300;
|
||||
|
||||
class UserSettings
|
||||
{
|
||||
public:
|
||||
UserSettings();
|
||||
|
||||
void save();
|
||||
void load();
|
||||
void setTheme(QString theme) { theme_ = theme; }
|
||||
void setTray(bool state) { isTrayEnabled_ = state; }
|
||||
|
||||
QString theme() const { return !theme_.isEmpty() ? theme_ : "default"; }
|
||||
bool isTrayEnabled() const { return isTrayEnabled_; }
|
||||
|
||||
private:
|
||||
QString theme_;
|
||||
bool isTrayEnabled_;
|
||||
};
|
||||
|
||||
class HorizontalLine : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HorizontalLine(QWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
class UserSettingsPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
signals:
|
||||
void moveBack();
|
||||
void trayOptionChanged(bool value);
|
||||
|
||||
private:
|
||||
// Layouts
|
||||
QVBoxLayout *topLayout_;
|
||||
QHBoxLayout *topBarLayout_;
|
||||
|
||||
// Shared settings object.
|
||||
QSharedPointer<UserSettings> settings_;
|
||||
|
||||
Toggle *trayToggle_;
|
||||
QComboBox *themeCombo_;
|
||||
};
|
@ -20,7 +20,7 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QVector>
|
||||
|
||||
#include "Deserializable.h"
|
||||
class Deserializable;
|
||||
|
||||
class VersionsResponse : public Deserializable
|
||||
{
|
||||
@ -30,7 +30,8 @@ public:
|
||||
bool isVersionSupported(unsigned int major, unsigned int minor, unsigned int patch);
|
||||
|
||||
private:
|
||||
struct Version_ {
|
||||
struct Version_
|
||||
{
|
||||
unsigned int major_;
|
||||
unsigned int minor_;
|
||||
unsigned int patch_;
|
||||
|
@ -17,7 +17,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RaisedButton.h"
|
||||
#include <QWidget>
|
||||
|
||||
class RaisedButton;
|
||||
|
||||
class WelcomePage : public QWidget
|
||||
{
|
||||
|
@ -22,10 +22,8 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
class AliasesEventContent
|
||||
: public Deserializable
|
||||
, public Serializable
|
||||
@ -34,16 +32,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QList<QString> aliases() const;
|
||||
QList<QString> aliases() const { return aliases_; };
|
||||
|
||||
private:
|
||||
QList<QString> aliases_;
|
||||
};
|
||||
|
||||
inline QList<QString>
|
||||
AliasesEventContent::aliases() const
|
||||
{
|
||||
return aliases_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,10 +22,8 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
/*
|
||||
* A picture that is associated with the room.
|
||||
*/
|
||||
@ -38,16 +36,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QUrl url() const;
|
||||
QUrl url() const { return url_; };
|
||||
|
||||
private:
|
||||
QUrl url_;
|
||||
};
|
||||
|
||||
inline QUrl
|
||||
AvatarEventContent::url() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,10 +22,8 @@
|
||||
#include "CanonicalAliasEventContent.h"
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
/*
|
||||
* This event is used to inform the room about which alias should be considered
|
||||
* the canonical one. This could be for display purposes or as suggestion to
|
||||
@ -40,16 +38,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QString alias() const;
|
||||
QString alias() const { return alias_; };
|
||||
|
||||
private:
|
||||
QString alias_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
CanonicalAliasEventContent::alias() const
|
||||
{
|
||||
return alias_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
/*
|
||||
* This is the first event in a room and cannot be changed. It acts as the root
|
||||
* of all other events.
|
||||
@ -38,17 +36,12 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QString creator() const;
|
||||
QString creator() const { return creator_; };
|
||||
|
||||
private:
|
||||
// The user_id of the room creator. This is set by the homeserver.
|
||||
QString creator_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
CreateEventContent::creator() const
|
||||
{
|
||||
return creator_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,11 +22,10 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
enum class EventType
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
enum class EventType {
|
||||
/// m.room.aliases
|
||||
RoomAliases,
|
||||
/// m.room.avatar
|
||||
@ -67,8 +66,8 @@ class Event
|
||||
, public Serializable
|
||||
{
|
||||
public:
|
||||
inline Content content() const;
|
||||
inline EventType eventType() const;
|
||||
Content content() const;
|
||||
EventType eventType() const;
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
@ -21,11 +21,10 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
enum class HistoryVisibility
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
enum class HistoryVisibility {
|
||||
Invited,
|
||||
Joined,
|
||||
Shared,
|
||||
@ -37,7 +36,7 @@ class HistoryVisibilityEventContent
|
||||
, public Serializable
|
||||
{
|
||||
public:
|
||||
inline HistoryVisibility historyVisibility() const;
|
||||
HistoryVisibility historyVisibility() const { return history_visibility_; };
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
@ -46,10 +45,5 @@ private:
|
||||
HistoryVisibility history_visibility_;
|
||||
};
|
||||
|
||||
inline HistoryVisibility
|
||||
HistoryVisibilityEventContent::historyVisibility() const
|
||||
{
|
||||
return history_visibility_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -21,11 +21,10 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
enum class JoinRule
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
enum class JoinRule {
|
||||
// A user who wishes to join the room must first receive
|
||||
// an invite to the room from someone already inside of the room.
|
||||
Invite,
|
||||
@ -52,16 +51,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline JoinRule joinRule() const;
|
||||
JoinRule joinRule() const { return join_rule_; };
|
||||
|
||||
private:
|
||||
JoinRule join_rule_;
|
||||
};
|
||||
|
||||
inline JoinRule
|
||||
JoinRulesEventContent::joinRule() const
|
||||
{
|
||||
return join_rule_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,11 +22,10 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
enum class Membership
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
enum class Membership {
|
||||
// The user is banned.
|
||||
Ban,
|
||||
|
||||
@ -55,9 +54,9 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QUrl avatarUrl() const;
|
||||
inline QString displayName() const;
|
||||
inline Membership membershipState() const;
|
||||
QUrl avatarUrl() const { return avatar_url_; };
|
||||
QString displayName() const { return display_name_; };
|
||||
Membership membershipState() const { return membership_state_; };
|
||||
|
||||
private:
|
||||
QUrl avatar_url_;
|
||||
@ -65,22 +64,5 @@ private:
|
||||
Membership membership_state_;
|
||||
};
|
||||
|
||||
inline QUrl
|
||||
MemberEventContent::avatarUrl() const
|
||||
{
|
||||
return avatar_url_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
MemberEventContent::displayName() const
|
||||
{
|
||||
return display_name_;
|
||||
}
|
||||
|
||||
inline Membership
|
||||
MemberEventContent::membershipState() const
|
||||
{
|
||||
return membership_state_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -20,15 +20,13 @@
|
||||
#include "MessageEventContent.h"
|
||||
#include "RoomEvent.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
template<class MsgContent>
|
||||
class MessageEvent : public RoomEvent<MessageEventContent>
|
||||
{
|
||||
public:
|
||||
inline MsgContent msgContent() const;
|
||||
MsgContent msgContent() const;
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
|
||||
@ -52,9 +50,9 @@ MessageEvent<MsgContent>::deserialize(const QJsonValue &data)
|
||||
msg_content_.deserialize(data.toObject().value("content").toObject());
|
||||
}
|
||||
|
||||
namespace messages
|
||||
namespace messages {
|
||||
struct ThumbnailInfo
|
||||
{
|
||||
struct ThumbnailInfo {
|
||||
int h;
|
||||
int w;
|
||||
int size;
|
||||
|
@ -21,11 +21,10 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
enum class MessageEventType
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
enum class MessageEventType {
|
||||
// m.audio
|
||||
Audio,
|
||||
|
||||
@ -65,16 +64,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QString body() const;
|
||||
QString body() const { return body_; };
|
||||
|
||||
private:
|
||||
QString body_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
MessageEventContent::body() const
|
||||
{
|
||||
return body_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
/*
|
||||
* A human-friendly room name designed to be displayed to the end-user.
|
||||
*/
|
||||
@ -37,16 +35,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QString name() const;
|
||||
QString name() const { return name_; };
|
||||
|
||||
private:
|
||||
QString name_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
NameEventContent::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,11 +22,10 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
enum class PowerLevels
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
enum class PowerLevels {
|
||||
User = 0,
|
||||
Moderator = 50,
|
||||
Admin = 100,
|
||||
@ -44,14 +43,14 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline int banLevel() const;
|
||||
inline int inviteLevel() const;
|
||||
inline int kickLevel() const;
|
||||
inline int redactLevel() const;
|
||||
int banLevel() const { return ban_; };
|
||||
int inviteLevel() const { return invite_; };
|
||||
int kickLevel() const { return kick_; };
|
||||
int redactLevel() const { return redact_; };
|
||||
|
||||
inline int eventsDefaultLevel() const;
|
||||
inline int stateDefaultLevel() const;
|
||||
inline int usersDefaultLevel() const;
|
||||
int eventsDefaultLevel() const { return events_default_; };
|
||||
int stateDefaultLevel() const { return state_default_; };
|
||||
int usersDefaultLevel() const { return users_default_; };
|
||||
|
||||
int eventLevel(QString event_type) const;
|
||||
int userLevel(QString user_id) const;
|
||||
@ -70,46 +69,5 @@ private:
|
||||
QMap<QString, int> users_;
|
||||
};
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::banLevel() const
|
||||
{
|
||||
return ban_;
|
||||
}
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::inviteLevel() const
|
||||
{
|
||||
return invite_;
|
||||
}
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::kickLevel() const
|
||||
{
|
||||
return kick_;
|
||||
}
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::redactLevel() const
|
||||
{
|
||||
return redact_;
|
||||
}
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::eventsDefaultLevel() const
|
||||
{
|
||||
return events_default_;
|
||||
}
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::stateDefaultLevel() const
|
||||
{
|
||||
return state_default_;
|
||||
}
|
||||
|
||||
inline int
|
||||
PowerLevelsEventContent::usersDefaultLevel() const
|
||||
{
|
||||
return users_default_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,18 +22,16 @@
|
||||
|
||||
#include "Event.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
template<class Content>
|
||||
class RoomEvent : public Event<Content>
|
||||
{
|
||||
public:
|
||||
inline QString eventId() const;
|
||||
inline QString roomId() const;
|
||||
inline QString sender() const;
|
||||
inline uint64_t timestamp() const;
|
||||
QString eventId() const;
|
||||
QString roomId() const;
|
||||
QString sender() const;
|
||||
uint64_t timestamp() const;
|
||||
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
@ -21,16 +21,14 @@
|
||||
|
||||
#include "RoomEvent.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
template<class Content>
|
||||
class StateEvent : public RoomEvent<Content>
|
||||
{
|
||||
public:
|
||||
inline QString stateKey() const;
|
||||
inline Content previousContent() const;
|
||||
QString stateKey() const;
|
||||
Content previousContent() const;
|
||||
|
||||
void deserialize(const QJsonValue &data);
|
||||
QJsonObject serialize() const;
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
/*
|
||||
* A topic is a short message detailing what is currently being discussed in the
|
||||
* room.
|
||||
@ -38,16 +36,11 @@ public:
|
||||
void deserialize(const QJsonValue &data) override;
|
||||
QJsonObject serialize() const override;
|
||||
|
||||
inline QString topic() const;
|
||||
QString topic() const { return topic_; };
|
||||
|
||||
private:
|
||||
QString topic_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
TopicEventContent::topic() const
|
||||
{
|
||||
return topic_;
|
||||
}
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -21,13 +21,11 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
struct AudioInfo
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
struct AudioInfo {
|
||||
uint64_t duration;
|
||||
int size;
|
||||
|
||||
@ -37,8 +35,8 @@ struct AudioInfo {
|
||||
class Audio : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QString url() const;
|
||||
inline AudioInfo info() const;
|
||||
QString url() const { return url_; };
|
||||
AudioInfo info() const { return info_; };
|
||||
|
||||
void deserialize(const QJsonObject &object) override;
|
||||
|
||||
@ -47,18 +45,6 @@ private:
|
||||
AudioInfo info_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
Audio::url() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
|
||||
inline AudioInfo
|
||||
Audio::info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
} // namespace messages
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -21,12 +21,9 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
class Emote : public Deserializable
|
||||
{
|
||||
public:
|
||||
|
@ -22,13 +22,11 @@
|
||||
#include "Deserializable.h"
|
||||
#include "MessageEvent.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
struct FileInfo
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
struct FileInfo {
|
||||
int size;
|
||||
|
||||
QString mimetype;
|
||||
@ -39,10 +37,9 @@ struct FileInfo {
|
||||
class File : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QString url() const;
|
||||
inline QString filename() const;
|
||||
|
||||
inline FileInfo info() const;
|
||||
QString url() const { return url_; };
|
||||
QString filename() const { return filename_; };
|
||||
FileInfo info() const { return info_; };
|
||||
|
||||
void deserialize(const QJsonObject &object) override;
|
||||
|
||||
@ -53,24 +50,6 @@ private:
|
||||
FileInfo info_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
File::filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
|
||||
inline QString
|
||||
File::url() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
|
||||
inline FileInfo
|
||||
File::info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
} // namespace messages
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,13 +22,11 @@
|
||||
#include "Deserializable.h"
|
||||
#include "MessageEvent.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
struct ImageInfo
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
struct ImageInfo {
|
||||
int h;
|
||||
int w;
|
||||
int size;
|
||||
@ -41,8 +39,8 @@ struct ImageInfo {
|
||||
class Image : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QString url() const;
|
||||
inline ImageInfo info() const;
|
||||
QString url() const { return url_; };
|
||||
ImageInfo info() const { return info_; };
|
||||
|
||||
void deserialize(const QJsonObject &object) override;
|
||||
|
||||
@ -51,18 +49,6 @@ private:
|
||||
ImageInfo info_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
Image::url() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
|
||||
inline ImageInfo
|
||||
Image::info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
} // namespace messages
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -22,13 +22,11 @@
|
||||
#include "Deserializable.h"
|
||||
#include "MessageEvent.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
struct LocationInfo
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
struct LocationInfo {
|
||||
QString thumbnail_url;
|
||||
ThumbnailInfo thumbnail_info;
|
||||
};
|
||||
@ -36,8 +34,8 @@ struct LocationInfo {
|
||||
class Location : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QString geoUri() const;
|
||||
inline LocationInfo info() const;
|
||||
QString geoUri() const { return geo_uri_; };
|
||||
LocationInfo info() const { return info_; };
|
||||
|
||||
void deserialize(const QJsonObject &object) override;
|
||||
|
||||
@ -47,18 +45,6 @@ private:
|
||||
LocationInfo info_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
Location::geoUri() const
|
||||
{
|
||||
return geo_uri_;
|
||||
}
|
||||
|
||||
inline LocationInfo
|
||||
Location::info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
} // namespace messages
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -21,12 +21,9 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
class Notice : public Deserializable
|
||||
{
|
||||
public:
|
||||
|
@ -21,12 +21,9 @@
|
||||
|
||||
#include "Deserializable.h"
|
||||
|
||||
namespace matrix
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
class Text : public Deserializable
|
||||
{
|
||||
public:
|
||||
|
@ -22,13 +22,11 @@
|
||||
#include "Deserializable.h"
|
||||
#include "MessageEvent.h"
|
||||
|
||||
namespace matrix
|
||||
namespace matrix {
|
||||
namespace events {
|
||||
namespace messages {
|
||||
struct VideoInfo
|
||||
{
|
||||
namespace events
|
||||
{
|
||||
namespace messages
|
||||
{
|
||||
struct VideoInfo {
|
||||
int h;
|
||||
int w;
|
||||
int size;
|
||||
@ -42,8 +40,8 @@ struct VideoInfo {
|
||||
class Video : public Deserializable
|
||||
{
|
||||
public:
|
||||
inline QString url() const;
|
||||
inline VideoInfo info() const;
|
||||
QString url() const { return url_; };
|
||||
VideoInfo info() const { return info_; };
|
||||
|
||||
void deserialize(const QJsonObject &object) override;
|
||||
|
||||
@ -52,18 +50,6 @@ private:
|
||||
VideoInfo info_;
|
||||
};
|
||||
|
||||
inline QString
|
||||
Video::url() const
|
||||
{
|
||||
return url_;
|
||||
}
|
||||
|
||||
inline VideoInfo
|
||||
Video::info() const
|
||||
{
|
||||
return info_;
|
||||
}
|
||||
|
||||
} // namespace messages
|
||||
} // namespace events
|
||||
} // namespace matrix
|
||||
|
@ -5,9 +5,9 @@
|
||||
#include <QPushButton>
|
||||
#include <QStateMachine>
|
||||
|
||||
#include "RippleOverlay.h"
|
||||
#include "Theme.h"
|
||||
|
||||
class RippleOverlay;
|
||||
class FlatButton;
|
||||
|
||||
class FlatButtonStateMachine : public QStateMachine
|
||||
|
26
include/ui/FloatingButton.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "RaisedButton.h"
|
||||
|
||||
constexpr int DIAMETER = 40;
|
||||
constexpr int ICON_SIZE = 18;
|
||||
|
||||
constexpr int OFFSET_X = 30;
|
||||
constexpr int OFFSET_Y = 20;
|
||||
|
||||
class FloatingButton : public RaisedButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FloatingButton(const QIcon &icon, QWidget *parent = nullptr);
|
||||
|
||||
QSize sizeHint() const override { return QSize(DIAMETER, DIAMETER); };
|
||||
QRect buttonGeometry() const;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
};
|
26
include/ui/Label.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class Label : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
|
||||
explicit Label(const QString &text,
|
||||
QWidget *parent = Q_NULLPTR,
|
||||
Qt::WindowFlags f = Qt::WindowFlags());
|
||||
~Label() override {}
|
||||
|
||||
signals:
|
||||
void clicked(QMouseEvent *e);
|
||||
void pressed(QMouseEvent *e);
|
||||
void released(QMouseEvent *e);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *e) override;
|
||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||
|
||||
QPoint pressPosition_;
|
||||
};
|
@ -19,23 +19,11 @@ public:
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
QColor color()
|
||||
{
|
||||
return color_;
|
||||
}
|
||||
void setColor(QColor color)
|
||||
{
|
||||
color_ = color;
|
||||
}
|
||||
QColor color() { return color_; }
|
||||
void setColor(QColor color) { color_ = color; }
|
||||
|
||||
int interval()
|
||||
{
|
||||
return interval_;
|
||||
}
|
||||
void setInterval(int interval)
|
||||
{
|
||||
interval_ = interval;
|
||||
}
|
||||
int interval() { return interval_; }
|
||||
void setInterval(int interval) { interval_ = interval; }
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
|
81
include/ui/SnackBar.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QPaintEvent>
|
||||
#include <QStateMachine>
|
||||
#include <QTimer>
|
||||
|
||||
#include "OverlayWidget.h"
|
||||
|
||||
enum class SnackBarPosition
|
||||
{
|
||||
Bottom,
|
||||
Top,
|
||||
};
|
||||
|
||||
class SnackBar : public OverlayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SnackBar(QWidget *parent);
|
||||
~SnackBar();
|
||||
|
||||
inline void setBackgroundColor(const QColor &color);
|
||||
inline void setTextColor(const QColor &color);
|
||||
inline void setPosition(SnackBarPosition pos);
|
||||
|
||||
public slots:
|
||||
void showMessage(const QString &msg);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void onTimeout();
|
||||
void hideMessage();
|
||||
|
||||
private:
|
||||
void stopTimers();
|
||||
void start();
|
||||
|
||||
QColor bgColor_;
|
||||
QColor textColor_;
|
||||
|
||||
qreal bgOpacity_;
|
||||
qreal offset_;
|
||||
|
||||
QList<QString> messages_;
|
||||
|
||||
QTimer *showTimer_;
|
||||
QTimer *hideTimer_;
|
||||
|
||||
int duration_;
|
||||
int boxWidth_;
|
||||
int boxHeight_;
|
||||
int boxPadding_;
|
||||
|
||||
SnackBarPosition position_;
|
||||
};
|
||||
|
||||
inline void
|
||||
SnackBar::setPosition(SnackBarPosition pos)
|
||||
{
|
||||
position_ = pos;
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
SnackBar::setBackgroundColor(const QColor &color)
|
||||
{
|
||||
bgColor_ = color;
|
||||
update();
|
||||
}
|
||||
|
||||
inline void
|
||||
SnackBar::setTextColor(const QColor &color)
|
||||
{
|
||||
textColor_ = color;
|
||||
update();
|
||||
}
|
@ -4,12 +4,15 @@
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
|
||||
namespace ui
|
||||
namespace ui {
|
||||
enum class AvatarType
|
||||
{
|
||||
enum class AvatarType { Icon, Image, Letter };
|
||||
Icon,
|
||||
Image,
|
||||
Letter
|
||||
};
|
||||
|
||||
namespace sidebar
|
||||
{
|
||||
namespace sidebar {
|
||||
static const int SmallSize = 60;
|
||||
static const int NormalSize = 300;
|
||||
}
|
||||
@ -19,19 +22,47 @@ const int FontSize = 16;
|
||||
// Default avatar size. Width and height.
|
||||
const int AvatarSize = 40;
|
||||
|
||||
enum class ButtonPreset { FlatPreset, CheckablePreset };
|
||||
enum class ButtonPreset
|
||||
{
|
||||
FlatPreset,
|
||||
CheckablePreset
|
||||
};
|
||||
|
||||
enum class RippleStyle { CenteredRipple, PositionedRipple, NoRipple };
|
||||
enum class RippleStyle
|
||||
{
|
||||
CenteredRipple,
|
||||
PositionedRipple,
|
||||
NoRipple
|
||||
};
|
||||
|
||||
enum class OverlayStyle { NoOverlay, TintedOverlay, GrayOverlay };
|
||||
enum class OverlayStyle
|
||||
{
|
||||
NoOverlay,
|
||||
TintedOverlay,
|
||||
GrayOverlay
|
||||
};
|
||||
|
||||
enum class Role { Default, Primary, Secondary };
|
||||
enum class Role
|
||||
{
|
||||
Default,
|
||||
Primary,
|
||||
Secondary
|
||||
};
|
||||
|
||||
enum class ButtonIconPlacement { LeftIcon, RightIcon };
|
||||
enum class ButtonIconPlacement
|
||||
{
|
||||
LeftIcon,
|
||||
RightIcon
|
||||
};
|
||||
|
||||
enum class ProgressType { DeterminateProgress, IndeterminateProgress };
|
||||
enum class ProgressType
|
||||
{
|
||||
DeterminateProgress,
|
||||
IndeterminateProgress
|
||||
};
|
||||
|
||||
enum class Color {
|
||||
enum class Color
|
||||
{
|
||||
Black,
|
||||
BrightWhite,
|
||||
FadedWhite,
|
||||
|
110
include/ui/ToggleButton.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QColor>
|
||||
|
||||
class ToggleTrack;
|
||||
class ToggleThumb;
|
||||
|
||||
enum class Position
|
||||
{
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
|
||||
class Toggle : public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
|
||||
Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
|
||||
Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
|
||||
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||
|
||||
public:
|
||||
Toggle(QWidget *parent = nullptr);
|
||||
|
||||
void setState(bool isEnabled);
|
||||
|
||||
void setActiveColor(const QColor &color);
|
||||
void setDisabledColor(const QColor &color);
|
||||
void setInactiveColor(const QColor &color);
|
||||
void setTrackColor(const QColor &color);
|
||||
|
||||
QColor activeColor() const { return activeColor_; };
|
||||
QColor disabledColor() const { return disabledColor_; };
|
||||
QColor inactiveColor() const { return inactiveColor_; };
|
||||
QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
|
||||
|
||||
QSize sizeHint() const override { return QSize(64, 48); };
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void setupProperties();
|
||||
|
||||
ToggleTrack *track_;
|
||||
ToggleThumb *thumb_;
|
||||
|
||||
QColor disabledColor_;
|
||||
QColor activeColor_;
|
||||
QColor inactiveColor_;
|
||||
QColor trackColor_;
|
||||
};
|
||||
|
||||
class ToggleThumb : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
|
||||
|
||||
public:
|
||||
ToggleThumb(Toggle *parent);
|
||||
|
||||
Position shift() const { return position_; };
|
||||
qreal offset() const { return offset_; };
|
||||
QColor thumbColor() const { return thumbColor_; };
|
||||
|
||||
void setShift(Position position);
|
||||
void setThumbColor(const QColor &color)
|
||||
{
|
||||
thumbColor_ = color;
|
||||
update();
|
||||
};
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
void updateOffset();
|
||||
|
||||
Toggle *const toggle_;
|
||||
QColor thumbColor_;
|
||||
|
||||
Position position_;
|
||||
qreal offset_;
|
||||
};
|
||||
|
||||
class ToggleTrack : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
|
||||
|
||||
public:
|
||||
ToggleTrack(Toggle *parent);
|
||||
|
||||
void setTrackColor(const QColor &color);
|
||||
QColor trackColor() const { return trackColor_; };
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
private:
|
||||
Toggle *const toggle_;
|
||||
QColor trackColor_;
|
||||
};
|
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 952 B |
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 603 B |
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
enable-background="new 0 0 24 24"
|
||||
viewBox="0 0 24 24"
|
||||
height="24px"
|
||||
width="24px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Слой_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata4213"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4211" /><g
|
||||
id="g4205"><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path4207"
|
||||
d="M12,0C5.373,0,0,5.372,0,12c0,6.627,5.373,12,12,12c6.628,0,12-5.373,12-12C24,5.372,18.628,0,12,0 M21.949,11H17.05c0.224-2.527,1.232-4.773,1.968-6.113C20.634,6.481,21.712,8.618,21.949,11 M13,11V2.051 c1.623,0.162,3.13,0.719,4.432,1.564C16.574,5.106,15.276,7.835,15.04,11H13z M11,11H8.961C8.723,7.835,7.425,5.106,6.568,3.615 C7.871,2.77,9.377,2.213,11,2.051V11z M11,13v8.949c-1.623-0.162-3.129-0.718-4.432-1.564C7.425,18.893,8.723,16.164,8.961,13H11z M15.04,13c0.236,3.164,1.534,5.893,2.392,7.385c-1.302,0.847-2.809,1.402-4.432,1.564V13H15.04z M4.982,4.887 C5.718,6.227,6.726,8.473,6.951,11h-4.9C2.289,8.618,3.367,6.481,4.982,4.887 M2.051,13h4.9c-0.226,2.527-1.233,4.771-1.969,6.113 C3.367,17.52,2.289,15.383,2.051,13 M19.018,19.113c-0.735-1.342-1.744-3.586-1.968-6.113h4.899 C21.712,15.383,20.634,17.52,19.018,19.113"
|
||||
fill="#010202" /></g></svg>
|
Before Width: | Height: | Size: 1.7 KiB |
BIN
resources/icons/emoji-categories/activity@2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg2"
|
||||
viewBox="0 0 32 32"
|
||||
height="32"
|
||||
width="32"
|
||||
version="1.1">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<path
|
||||
id="path4"
|
||||
d="M14 8c0-1.105 0.895-2 2-2s2 0.895 2 2c0 1.105-0.895 2-2 2s-2-0.895-2-2zM16 0c-8.837 0-16 7.163-16 16s7.163 16 16 16 16-7.163 16-16-7.163-16-16-16zM16 26c-1.105 0-2-0.895-2-2s0.895-2 2-2c1.105 0 2 0.895 2 2s-0.895 2-2 2zM16 16c-3.59 0-6.5 2.91-6.5 6.5s2.91 6.5 6.5 6.5c-7.18 0-13-5.82-13-13s5.82-13 13-13c3.59 0 6.5 2.91 6.5 6.5s-2.91 6.5-6.5 6.5z" />
|
||||
</svg>
|
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 472 B After Width: | Height: | Size: 416 B |
@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
enable-background="new 0 0 24 24"
|
||||
viewBox="0 0 24 24"
|
||||
height="24px"
|
||||
width="24px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Слой_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata6641"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6639" /><g
|
||||
id="g6631"><polygon
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="polygon6633"
|
||||
points="0,0 6.084,24 8,24 1.916,0 "
|
||||
fill="#010202" /><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path6635"
|
||||
d="M21,5h-4l-1-4H4l3,12h3l1,4h2h11L21,5z M6.563,3h7.875l2,8H8.563L6.563,3z M15.395,13l-2.856,1.904 L12.063,13H15.395z M19,13l-1.5-6h1.938l2,8H16L19,13z"
|
||||
fill="#010202" /></g></svg>
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
resources/icons/emoji-categories/flags@2x.png
Normal file
After Width: | Height: | Size: 824 B |
Before Width: | Height: | Size: 599 B After Width: | Height: | Size: 537 B |
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
enable-background="new 0 0 24 24"
|
||||
viewBox="0 0 24 24"
|
||||
height="24px"
|
||||
width="24px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Слой_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata4164"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4162" /><g
|
||||
id="g4156"><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path4158"
|
||||
d="M17,4.978c-1.838,0-2.876,0.396-3.68,0.934c0.513-1.172,1.768-2.934,4.68-2.934c0.552,0,1-0.448,1-1 s-0.448-1-1-1c-2.921,0-4.629,1.365-5.547,2.512c-0.064,0.078-0.119,0.162-0.18,0.244c-0.543-1.896-1.475-3.711-3.066-3.711 C8.579,0.022,7.85,0.306,7,0.978C5.027,2.54,5.329,3.902,6.492,4.999C3.609,5.222,0,7.352,0,12.969c0,4.582,4.961,11.009,9,11.009 c1.975,0,2.371-0.486,3-1c0.629,0.514,1.025,1,3,1c4.039,0,9-6.418,9-11C24,7.025,19.945,4.978,17,4.978 M8.242,2.546 c0.641-0.508,0.943-0.523,0.965-0.523c0.426,0.169,0.975,1.405,1.357,3.055c-1.527-0.629-2.741-1.352-2.98-1.846 C7.643,3.12,7.825,2.876,8.242,2.546 M15,21.978c-1.08,0-1.21-0.109-1.559-0.402l-0.176-0.146 c-0.367-0.302-0.816-0.452-1.266-0.452s-0.898,0.15-1.266,0.452l-0.176,0.146C10.21,21.868,10.08,21.978,9,21.978 c-2.813,0-7-5.389-7-9.009c0-5.823,4.488-5.991,5-5.991c1.939,0,2.484,0.471,3.387,1.251c0.107,0.092,0.215,0.185,0.323,0.276 C11.083,8.82,11.541,8.978,12,8.978s0.917-0.157,1.29-0.473c0.108-0.092,0.216-0.185,0.323-0.276 c0.902-0.78,1.447-1.251,3.387-1.251c0.512,0,5,0.168,5,6C22,16.595,17.813,21.978,15,21.978"
|
||||
fill="#010202" /></g></svg>
|
Before Width: | Height: | Size: 1.9 KiB |
BIN
resources/icons/emoji-categories/foods@2x.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 725 B After Width: | Height: | Size: 667 B |
@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
enable-background="new 0 0 24 24"
|
||||
viewBox="0 0 24 24"
|
||||
height="24px"
|
||||
width="24px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Слой_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata6036"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6034" /><g
|
||||
id="g6024"><g
|
||||
id="g6578"><g
|
||||
id="g6583"><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path6028"
|
||||
d="M15.5,8C14.672,8,14,8.672,14,9.5s0.672,1.5,1.5,1.5S17,10.329,17,9.5S16.328,8,15.5,8"
|
||||
fill="#010202" /><g
|
||||
id="g6588"><path
|
||||
fill="#010202"
|
||||
d="M8.5,8C7.672,8,7,8.672,7,9.5S7.672,11,8.5,11S10,10.329,10,9.5S9.329,8,8.5,8"
|
||||
id="path6026"
|
||||
style="fill:#000000;fill-opacity:1" /><path
|
||||
fill="#010202"
|
||||
d="M18.933,0h-0.027c-0.97,0-2.138,0.787-3.018,1.497c-1.274-0.374-2.612-0.51-3.887-0.51 c-1.285,0-2.616,0.133-3.874,0.517C7.245,0.79,6.069,0,5.093,0H5.066C3.352,0,0.07,2.67,0.002,7.026 c-0.039,2.479,0.276,4.238,1.04,5.013c0.254,0.258,0.882,0.677,1.295,0.882c0.191,3.177,0.922,5.238,2.536,6.38 c0.897,0.637,2.187,0.949,3.2,1.102C8.04,20.6,8,20.795,8,21c0,1.773,2.35,3,4,3c1.648,0,4-1.227,4-3 c0-0.201-0.038-0.393-0.072-0.586c2.573-0.385,5.435-1.877,5.925-7.587c0.396-0.22,0.887-0.568,1.104-0.788 c0.763-0.774,1.079-2.534,1.04-5.013C23.929,2.67,20.646,0,18.933,0 M3.223,9.135c-0.237,0.281-0.837,1.155-0.884,1.238 c-0.15-0.41-0.368-1.349-0.337-3.291C2.053,3.801,4.48,2.11,5.093,2.051c0.256,0.015,0.731,0.27,1.265,0.646 c-1.11,1.171-2.275,2.915-2.352,5.125C3.873,8.368,3.608,8.68,3.223,9.135 M12,22c-0.901,0-1.954-0.693-2-1 c0-0.654,0.475-1.236,1-1.602V20c0,0.553,0.447,1,1,1s1-0.447,1-1v-0.602c0.524,0.365,1,0.947,1,1.602 C13.954,21.307,12.901,22,12,22 M15,18.52v0.02c-0.366-0.418-0.798-0.762-1.262-1.02c1.092-0.516,2.239-1.334,2.239-2.217 c0-1.842-1.781-2.195-3.977-2.195c-2.196,0-3.978,0.354-3.978,2.195c0,0.883,1.148,1.701,2.238,2.217 C9.799,17.777,9.368,18.121,9,18.539v-0.025c-1-0.076-2.182-0.281-2.973-0.842c-1.301-0.92-1.838-3.045-1.853-6.478 c0.008-0.014,0.016-0.028,0.023-0.041c0.496-0.826,1.49-1.45,1.804-3.102c0-2.047,1.357-3.631,2.362-4.522 C9.37,3.178,10.555,3,11.948,3c1.447,0,2.685,0.192,3.733,0.57c1,0.9,2.316,2.465,2.316,4.48c0.313,1.651,1.307,2.275,1.803,3.102 c0.035,0.058,0.068,0.117,0.102,0.178C19.843,17.297,17.953,18.34,15,18.52 M21.628,10.318c-0.037-0.065-0.074-0.13-0.113-0.195 c-0.233-0.387-0.502-0.706-0.739-0.987c-0.385-0.455-0.648-0.768-0.782-1.313c-0.076-2.209-1.241-3.954-2.353-5.124 c0.531-0.376,1.004-0.63,1.261-0.647c0.636,0.071,3.044,1.764,3.096,5.031C22.025,8.893,21.651,10.301,21.628,10.318"
|
||||
id="path6030"
|
||||
style="fill:#000000;fill-opacity:1" /></g></g></g></g></svg>
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
resources/icons/emoji-categories/nature@2x.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 606 B |
@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
enable-background="new 0 0 24 24"
|
||||
viewBox="0 0 24 24"
|
||||
height="24px"
|
||||
width="24px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Слой_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata4838"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4836" /><g
|
||||
id="g4820"><g
|
||||
id="g4822" /><g
|
||||
id="g4830"><g
|
||||
id="g5383"><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
d="M 12 0 C 7.029 0 3 4.029 3 9 C 3 12.120081 4.5888411 14.867862 7 16.482422 L 7 21 C 7 21 9.035 24 12 24 C 14.965 24 17 21 17 21 L 17 16.482422 C 19.411159 14.867862 21 12.120081 21 9 C 21 4.029 16.971 0 12 0 z M 12 2 C 15.86 2 19 5.141 19 9 C 19 12.859 15.86 16 12 16 C 8.14 16 5 12.859 5 9 C 5 5.141 8.14 2 12 2 z M 9 17.476562 C 9.9397054 17.809261 10.946226 18 12 18 C 13.053774 18 14.060295 17.809261 15 17.476562 L 15 18.310547 C 14.089581 18.746635 13.074971 19 12 19 C 10.925029 19 9.9104192 18.746635 9 18.310547 L 9 17.476562 z M 9.2363281 20.546875 C 10.108023 20.832252 11.032636 21 12 21 C 12.965197 21 13.887813 20.832689 14.757812 20.548828 C 14.155076 21.173162 13.152816 22 12 22 C 10.89775 22 9.8827458 21.211335 9.2363281 20.546875 z "
|
||||
id="path4824" /><path
|
||||
fill="#010202"
|
||||
d="M14.745,12.449h-0.004c-0.852-0.024-1.188-0.858-1.577-1.824c-0.421-1.061-0.703-1.561-1.182-1.566h-0.009 c-0.481,0-0.783,0.497-1.235,1.537c-0.436,0.982-0.801,1.811-1.636,1.791l-0.276-0.043c-0.565-0.171-0.853-0.691-1.284-1.794 c-0.125-0.313-0.202-0.632-0.27-0.913C7.221,9.424,7.145,9.107,7.077,9.003C7.067,9.004,7.039,9,6.99,9 C6.438,8.994,5.994,8.543,6,7.99C6.006,7.441,6.452,7,7,7h0.01c1.662,0.017,2.015,1.373,2.198,2.134 c0.486-0.981,1.304-2.058,2.797-2.075c1.531,0.018,2.28,1.153,2.731,2.141c0-0.002,0.001-0.006,0.002-0.008 C14.944,8.424,15.327,7,16.979,7h0.032C17.563,7.007,18.006,7.459,18,8.012C17.994,8.56,17.547,9,17,9h-0.011 c-0.149,0.076-0.256,0.474-0.319,0.709c-0.079,0.295-0.169,0.629-0.311,0.951C15.93,11.633,15.569,12.449,14.745,12.449"
|
||||
id="path4832" /></g></g></g></svg>
|
Before Width: | Height: | Size: 2.5 KiB |
BIN
resources/icons/emoji-categories/objects@2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 637 B After Width: | Height: | Size: 581 B |
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
enable-background="new 0 0 24 24"
|
||||
viewBox="0 0 24 24"
|
||||
height="24px"
|
||||
width="24px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Слой_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata7236"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7234" /><g
|
||||
id="g7222"><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path7224"
|
||||
d="M12,0C5.373,0,0,5.373,0,12s5.373,12,12,12s12-5.373,12-12S18.627,0,12,0 M12,22C6.486,22,2,17.514,2,12 S6.486,2,12,2s10,4.486,10,10S17.514,22,12,22"
|
||||
fill="#010202" /><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path7226"
|
||||
d="M8,7C6.895,7,6,7.895,6,9s0.895,2,2,2s2-0.895,2-2S9.105,7,8,7"
|
||||
fill="#010202" /><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path7228"
|
||||
d="M16,7c-1.105,0-2,0.895-2,2s0.895,2,2,2s2-0.895,2-2S17.105,7,16,7"
|
||||
fill="#010202" /><path
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="path7230"
|
||||
d="M15.232,15c-0.693,1.195-1.87,2-3.349,2c-1.477,0-2.655-0.805-3.347-2H15 M18,13H6c0,3.314,2.686,6,6,6 S18,16.314,18,13"
|
||||
fill="#010202" /></g></svg>
|
Before Width: | Height: | Size: 1.5 KiB |
BIN
resources/icons/emoji-categories/people@2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |