diff --git a/README.md b/README.md index 97f60d5f..e69de29b 100644 --- a/README.md +++ b/README.md @@ -1,33 +0,0 @@ -# harmonyqml - -[![PyPI downloads](http://pepy.tech/badge/harmonyqml)]( - http://pepy.tech/project/harmonyqml) -[![PyPI version](https://img.shields.io/pypi/v/harmonyqml.svg)]( - https://pypi.org/projects/harmonyqml) -[![PyPI pyversions](https://img.shields.io/pypi/pyversions/harmonyqml.svg)]( - https://pypi.python.org/pypi/harmonyqml) - - - - -## CLI examples - -```sh - $ harmonyqml -``` - -## Python package examples - -```python3 - >>> import harmonyqml - - >>> -``` - -## Installation - -Requires Python 3.6+, tested on GNU/Linux only. - -```sh - # pip3 install harmonyqml -``` diff --git a/TODO.md b/TODO.md index 0a1c2d14..14f42bec 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,6 @@ - Current focus - Merge login page + - Just import nio? - Refactoring - Migrate more JS functions to their own files / Implement in Python instead @@ -13,6 +14,8 @@ - Bug when resizing window being tiled (i3), can't figure it out - UI + - Leave room + - Forget room warning popup - Use HRowLayout and its totalSpacing wherever possible - Spacer component - One line label componant @@ -34,6 +37,8 @@ - Status message and presence - Client improvements + - HTTP/2 + - `retry_after_ms` when rate-limited - Direct chats category - On sync, check messages API, if a limited sync timeline was received - Markdown: don't turn #things into title (space), disable __ syntax @@ -46,11 +51,21 @@ - When inviting someone to direct chat, room is "Empty room" until accepted, it should be the peer's display name instead. - Keep an accounts order + - See `Qt.callLater()` potential usages + - Banner name color instead of bold - Missing nio support - - Forget room - Left room events - `org.matrix.room.preview_urls` event - `m.room.aliases` event - - Avatars - Support "Empty room (was ...)" after peer left + +- Waiting for approval/release + - nio avatars + - olm/olm-devel 0.3.1 in void repos + - html-sanitizer allowed attributes fix pypi release + +- Distribution + - Review setup.py, add dependencies + - REAMDE.md + - Remove initial test room switch diff --git a/harmonyqml/backend/client.py b/harmonyqml/backend/client.py index c9f5ed5f..36aea5cc 100644 --- a/harmonyqml/backend/client.py +++ b/harmonyqml/backend/client.py @@ -26,6 +26,8 @@ class Client(QObject): roomJoined = pyqtSignal(str) roomLeft = pyqtSignal([str, dict], [str]) + roomAboutToBeForgotten = pyqtSignal(str) + roomSyncPrevBatchTokenReceived = pyqtSignal(str, str) roomPastPrevBatchTokenReceived = pyqtSignal(str, str) roomEventReceived = pyqtSignal(str, str, dict) @@ -259,4 +261,5 @@ class Client(QObject): @pyqtSlot(str) @futurize() def forgetRoom(self, room_id: str) -> None: - raise NotImplementedError() + self.roomAboutToBeForgotten.emit(room_id) + return self.net.talk(self.nio.room_forget, room_id=room_id) diff --git a/harmonyqml/backend/client_manager.py b/harmonyqml/backend/client_manager.py index c39d21c7..05c537e7 100644 --- a/harmonyqml/backend/client_manager.py +++ b/harmonyqml/backend/client_manager.py @@ -25,7 +25,7 @@ _CONFIG_LOCK = threading.Lock() class ClientManager(QObject): clientAdded = pyqtSignal(Client) clientDeleted = pyqtSignal(str) - _clientsUpdate = pyqtSignal() + clientCountChanged = pyqtSignal(int) def __init__(self, backend: Backend) -> None: @@ -33,19 +33,25 @@ class ClientManager(QObject): self.backend = backend self._clients: Dict[str, Client] = {} - self.clientAdded.connect(self._clientsUpdate.emit) - self.clientDeleted.connect(self._clientsUpdate.emit) + func = lambda: self.clientCountChanged.emit(len(self.clients)) + self.clientAdded.connect(func) + self.clientDeleted.connect(func) def __repr__(self) -> str: return f"{type(self).__name__}(clients={self.clients!r})" - @pyqtProperty("QVariantMap", notify=_clientsUpdate) + @pyqtProperty("QVariantMap", notify=clientCountChanged) def clients(self): return self._clients + @pyqtProperty(int, notify=clientCountChanged) + def clientCount(self): + return len(self.clients) + + @pyqtSlot() def configLoad(self) -> None: for user_id, info in self.configAccounts().items(): diff --git a/harmonyqml/backend/network_manager.py b/harmonyqml/backend/network_manager.py index 9f4f1bad..d87044a6 100644 --- a/harmonyqml/backend/network_manager.py +++ b/harmonyqml/backend/network_manager.py @@ -114,6 +114,7 @@ class NetworkManager: nio_func: NioRequestFunc, *args, **kwargs) -> nr.Response: + with self._lock: retry = RetrySleeper() diff --git a/harmonyqml/backend/signal_manager.py b/harmonyqml/backend/signal_manager.py index 4d144b31..d1a7a25a 100644 --- a/harmonyqml/backend/signal_manager.py +++ b/harmonyqml/backend/signal_manager.py @@ -268,3 +268,11 @@ class SignalManager(QObject): self._events_in_transfer += 1 self._move_room(client.userId, room_id) + + + def onRoomAboutToBeForgotten(self, client: Client, room_id: str) -> None: + with self._lock: + rooms = self.backend.models.rooms[client.userId] + del rooms[rooms.indexWhere("roomId", room_id)] + + self.backend.models.roomEvents[room_id].clear() diff --git a/harmonyqml/components/Window.qml b/harmonyqml/components/Window.qml index f8f80c9b..6e084dea 100644 --- a/harmonyqml/components/Window.qml +++ b/harmonyqml/components/Window.qml @@ -9,7 +9,8 @@ ApplicationWindow { Loader { anchors.fill: parent - source: "UI.qml" + source: Backend.clientManager.clientCount < 1 ? + "pages/LoginPage.qml" : "pages/MainUI.qml" objectName: "UILoader" } } diff --git a/harmonyqml/components/base/HButton.qml b/harmonyqml/components/base/HButton.qml index cdb3b04e..b4e6c9c4 100644 --- a/harmonyqml/components/base/HButton.qml +++ b/harmonyqml/components/base/HButton.qml @@ -3,9 +3,73 @@ import QtQuick.Controls 2.2 import QtQuick.Layouts 1.4 Button { + property alias fontSize: buttonLabel.font.pixelSize + property color backgroundColor: "lightgray" + property alias overlayOpacity: buttonBackgroundOverlay.opacity property string iconName: "" + property bool circle: false id: button display: Button.TextBesideIcon - icon.source: "../../icons/" + iconName + ".svg" + + background: Rectangle { + id: buttonBackground + color: Qt.lighter(backgroundColor, checked ? 1.3 : 1.0) + radius: circle ? height : 0 + + Rectangle { + id: buttonBackgroundOverlay + anchors.fill: parent + radius: parent.radius + color: "black" + opacity: 0 + } + } + + contentItem: HRowLayout { + spacing: button.text && iconName ? 5 : 0 + + Component { + id: buttonIcon + Image { + cache: true + mipmap: true + source: "../../icons/" + iconName + ".svg" + fillMode: Image.PreserveAspectFit + width: button.text ? 20 : 24 + height: width + } + } + Loader { + sourceComponent: iconName ? buttonIcon : undefined + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + } + + HLabel { + id: buttonLabel + + text: button.text + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + elide: Text.ElideRight + maximumLineCount: 1 + Layout.maximumWidth: button.width - buttonIcon.width + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + propagateComposedEvents: true + + onEntered: overlayOpacity = checked ? 0 : 0.3 + onExited: overlayOpacity = 0 + onPressed: overlayOpacity += 0.3 + onReleased: { + if (checkable) { checked = ! checked } + overlayOpacity = checked ? 0 : 0.3 + } + } } diff --git a/harmonyqml/components/base/HLabel.qml b/harmonyqml/components/base/HLabel.qml index 46d1be6c..24f75647 100644 --- a/harmonyqml/components/base/HLabel.qml +++ b/harmonyqml/components/base/HLabel.qml @@ -1,12 +1,9 @@ import QtQuick 2.7 import QtQuick.Controls 2.0 +import "." Label { - property int bigSize: 24 - property int normalSize: 16 - property int smallSize: 12 - - font.family: "Roboto" - font.pixelSize: normalSize + font.family: HStyle.fontFamily.sans + font.pixelSize: HStyle.fontSize.normal textFormat: Text.PlainText } diff --git a/harmonyqml/components/base/HStyle.qml b/harmonyqml/components/base/HStyle.qml new file mode 100644 index 00000000..b144622e --- /dev/null +++ b/harmonyqml/components/base/HStyle.qml @@ -0,0 +1,22 @@ +pragma Singleton +import QtQuick 2.7 + +QtObject { + readonly property int foo: 3 + + readonly property QtObject fontSize: QtObject { + readonly property int smallest: 6 + readonly property int smaller: 8 + readonly property int small: 12 + readonly property int normal: 16 + readonly property int big: 24 + readonly property int bigger: 32 + readonly property int biggest: 48 + } + + readonly property QtObject fontFamily: QtObject { + readonly property string sans: "Roboto" + readonly property string serif: "Roboto Slab" + readonly property string mono: "Hack" + } +} diff --git a/harmonyqml/components/base/HTextField.qml b/harmonyqml/components/base/HTextField.qml new file mode 100644 index 00000000..098a9fd1 --- /dev/null +++ b/harmonyqml/components/base/HTextField.qml @@ -0,0 +1,9 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 + +TextField { + font.family: HStyle.fontFamily.sans + font.pixelSize: HStyle.fontSize.normal + + selectByMouse: true +} diff --git a/harmonyqml/components/base/qmldir b/harmonyqml/components/base/qmldir new file mode 100644 index 00000000..2c618068 --- /dev/null +++ b/harmonyqml/components/base/qmldir @@ -0,0 +1 @@ +singleton HStyle 1.0 HStyle.qml diff --git a/harmonyqml/components/chat/Banner.qml b/harmonyqml/components/chat/Banner.qml index cab0715c..ff1b5f9d 100644 --- a/harmonyqml/components/chat/Banner.qml +++ b/harmonyqml/components/chat/Banner.qml @@ -9,6 +9,8 @@ Rectangle { Layout.preferredHeight: 32 color: "#BBB" + signal buttonClicked(string signalId) + property alias avatarName: bannerAvatar.name property alias avatarSource: bannerAvatar.imageSource property alias labelText: bannerLabel.text @@ -77,8 +79,6 @@ Rectangle { text: modelData.text iconName: modelData.iconName - icon.color: modelData.iconColor - icon.width: 32 display: bannerButtons.displayMode onClicked: { @@ -87,14 +87,20 @@ Rectangle { iconName = "hourglass" alreadyClicked = true + // modelData might become undefined after Backend call + var signalId = modelData.signalId + var iconName_ = modelData.iconName + var future = Backend.clientManager.clients[chatPage.userId]. call(modelData.clientFunction, modelData.clientArgs) - future.onGotResult.connect( - function() { iconName = modelData.iconName } - ) + future.onGotResult.connect(function() { + iconName = iconName_ + }) + + if (signalId) { buttonClicked(signalId) } } Layout.maximumWidth: bannerButtons.compact ? height : -1 diff --git a/harmonyqml/components/chat/Daybreak.qml b/harmonyqml/components/chat/Daybreak.qml index a2c1fd01..baa85e2c 100644 --- a/harmonyqml/components/chat/Daybreak.qml +++ b/harmonyqml/components/chat/Daybreak.qml @@ -16,6 +16,6 @@ Base.HLabel { text: dateTime.toLocaleDateString() + (isToday ? qsTr(" (Today)") : "") horizontalAlignment: Text.AlignHCenter - font.pixelSize: normalSize * 1.1 + font.pixelSize: Base.HStyle.fontSize.big color: "darkolivegreen" } diff --git a/harmonyqml/components/chat/EventContent.qml b/harmonyqml/components/chat/EventContent.qml index ea035424..e8e6d82b 100644 --- a/harmonyqml/components/chat/EventContent.qml +++ b/harmonyqml/components/chat/EventContent.qml @@ -27,7 +27,8 @@ RowLayout { (displayName.value || dict.sender) + (contentText.startsWith("'s ") ? "" : " ") + contentText + - "  " + + "  " + Qt.formatDateTime(dateTime, "hh:mm:ss") + "" textFormat: Text.RichText diff --git a/harmonyqml/components/chat/InviteBanner.qml b/harmonyqml/components/chat/InviteBanner.qml index 47143414..7f952950 100644 --- a/harmonyqml/components/chat/InviteBanner.qml +++ b/harmonyqml/components/chat/InviteBanner.qml @@ -17,15 +17,15 @@ Banner { buttonModel: [ { text: "Accept", - iconName: "accept", - iconColor: Qt.hsla(0.45, 0.9, 0.3, 1), + iconName: "invite_accept", + //iconColor: Qt.hsla(0.45, 0.9, 0.3, 1), clientFunction: "joinRoom", clientArgs: [chatPage.roomId], }, { text: "Decline", - iconName: "decline", - iconColor: Qt.hsla(0.95, 0.9, 0.35, 1), + iconName: "invite_decline", + //iconColor: Qt.hsla(0.95, 0.9, 0.35, 1), clientFunction: "leaveRoom", clientArgs: [chatPage.roomId], } diff --git a/harmonyqml/components/chat/LeftBanner.qml b/harmonyqml/components/chat/LeftBanner.qml index ec06be40..b4aace11 100644 --- a/harmonyqml/components/chat/LeftBanner.qml +++ b/harmonyqml/components/chat/LeftBanner.qml @@ -7,14 +7,20 @@ import "utils.js" as ChatJS Banner { property var leftEvent: null + onButtonClicked: if (signalId === "forget") { + chatPage.canLoadPastEvents = false + pageStack.clear() + } + avatarName: ChatJS.getLeftBannerAvatarName(leftEvent, chatPage.userId) labelText: ChatJS.getLeftBannerText(leftEvent) buttonModel: [ { + signalId: "forget", text: "Forget", - iconName: "trash_can", - iconColor: Qt.hsla(0.95, 0.9, 0.35, 1), + iconName: "forget_room", + //iconColor: Qt.hsla(0.95, 0.9, 0.35, 1), clientFunction: "forgetRoom", clientArgs: [chatPage.roomId], } diff --git a/harmonyqml/components/chat/MessageContent.qml b/harmonyqml/components/chat/MessageContent.qml index 43c8febb..f59304a0 100644 --- a/harmonyqml/components/chat/MessageContent.qml +++ b/harmonyqml/components/chat/MessageContent.qml @@ -35,11 +35,13 @@ Row { text: (dict.formatted_body ? Backend.htmlFilter.filter(dict.formatted_body) : dict.body) + - "  " + + "  " + Qt.formatDateTime(dateTime, "hh:mm:ss") + "" + (isLocalEcho ? - " " : "") + " " : "") textFormat: Text.RichText background: Rectangle {color: "#DDD"} wrapMode: Text.Wrap diff --git a/harmonyqml/components/chat/MessageList.qml b/harmonyqml/components/chat/MessageList.qml index 82761bf1..36add807 100644 --- a/harmonyqml/components/chat/MessageList.qml +++ b/harmonyqml/components/chat/MessageList.qml @@ -4,6 +4,7 @@ import QtQuick.Layouts 1.4 import "../base" as Base Rectangle { + property bool canLoadPastEvents: true property int space: 8 Layout.fillWidth: true @@ -30,7 +31,7 @@ Rectangle { property real yPos: visibleArea.yPosition onYPosChanged: { - if (yPos <= 0.1) { + if (chatPage.canLoadPastEvents && yPos <= 0.1) { Backend.loadPastEvents(chatPage.roomId) } } diff --git a/harmonyqml/components/chat/RoomHeader.qml b/harmonyqml/components/chat/RoomHeader.qml index 06221a97..e104838b 100644 --- a/harmonyqml/components/chat/RoomHeader.qml +++ b/harmonyqml/components/chat/RoomHeader.qml @@ -28,7 +28,7 @@ Rectangle { Base.HLabel { id: roomName text: displayName - font.pixelSize: bigSize + font.pixelSize: Base.HStyle.fontSize.big elide: Text.ElideRight maximumLineCount: 1 Layout.maximumWidth: @@ -39,7 +39,7 @@ Rectangle { Base.HLabel { id: roomTopic text: topic - font.pixelSize: smallSize + font.pixelSize: Base.HStyle.fontSize.small elide: Text.ElideRight maximumLineCount: 1 Layout.maximumWidth: diff --git a/harmonyqml/components/chat/Root.qml b/harmonyqml/components/chat/Root.qml index f1b26e5e..06220bf3 100644 --- a/harmonyqml/components/chat/Root.qml +++ b/harmonyqml/components/chat/Root.qml @@ -9,6 +9,8 @@ ColumnLayout { readonly property var roomInfo: Backend.models.rooms.get(userId).getWhere("roomId", roomId) + property bool canLoadPastEvents: true + Component.onCompleted: console.log("replaced") diff --git a/harmonyqml/components/pages/AddAccountPage.qml b/harmonyqml/components/pages/AddAccountPage.qml deleted file mode 100644 index cd75b353..00000000 --- a/harmonyqml/components/pages/AddAccountPage.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick 2.7 -import "../base" as Base - -Rectangle { - Base.HLabel { - anchors.centerIn: parent - text: "Add account page" - } -} diff --git a/harmonyqml/components/pages/AddRoomPage.qml b/harmonyqml/components/pages/AddRoomPage.qml deleted file mode 100644 index a8f3b8b6..00000000 --- a/harmonyqml/components/pages/AddRoomPage.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick 2.7 -import "../base" as Base - -Rectangle { - Base.HLabel { - anchors.centerIn: parent - text: "Add room page" - } -} diff --git a/harmonyqml/components/pages/LoginPage.qml b/harmonyqml/components/pages/LoginPage.qml new file mode 100644 index 00000000..1da1e848 --- /dev/null +++ b/harmonyqml/components/pages/LoginPage.qml @@ -0,0 +1,122 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import QtQuick.Layouts 1.4 +import "../base" as Base + +Image { + id: loginBackground + asynchronous: true + fillMode: Image.PreserveAspectCrop + cache: false + source: "../../images/login_background.jpg" + + Rectangle { + color: Qt.hsla(1, 1, 1, 0.3) + + id: loginBox + + property real widthForHeight: 0.75 + property int baseHeight: 300 + property int baseWidth: baseHeight * widthForHeight + property int startScalingUpAboveHeight: 1080 + + anchors.centerIn: parent + height: Math.min(parent.height, baseHeight) + width: Math.min(parent.width, baseWidth) + scale: Math.max(1, parent.height / startScalingUpAboveHeight) + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + + ColumnLayout { + anchors.fill: parent + id: mainColumn + + property int hMargin: loginBox.baseWidth * 0.05 + property int vMargin: hMargin * loginBox.widthForHeight + + Base.HRowLayout { + Layout.alignment: Qt.AlignHCenter + Layout.margins: mainColumn.hMargin + Layout.topMargin: mainColumn.vMargin + Layout.bottomMargin: mainColumn.vMargin + + Base.HLabel { + text: "Sign in" + font.pixelSize: Base.HStyle.fontSize.big + } + } + + Item { Layout.fillHeight: true } + + Base.HRowLayout { + Layout.margins: mainColumn.hMargin + Layout.topMargin: mainColumn.vMargin + Layout.bottomMargin: mainColumn.vMargin + Layout.alignment: Qt.AlignHCenter + spacing: mainColumn.hMargin * 1.25 + + Base.HButton { + id: loginWithUsernameButton + iconName: "username" + circle: true + checked: true + checkable: true + autoExclusive: true + } + Base.HButton { + id: loginWithEmailButton + iconName: "email" + circle: true + checkable: true + autoExclusive: true + } + Base.HButton { + id: loginWithPhoneButton + iconName: "phone" + circle: true + checkable: true + autoExclusive: true + } + } + + Base.HTextField { + placeholderText: qsTr( + loginWithEmailButton.checked ? "Email" : + loginWithPhoneButton.checked ? "Phone" : + "Username" + ) + + Layout.fillWidth: true + Layout.margins: mainColumn.hMargin + Layout.topMargin: mainColumn.vMargin + Layout.bottomMargin: mainColumn.vMargin + } + + Base.HTextField { + placeholderText: qsTr("Password") + + Layout.fillWidth: true + Layout.margins: mainColumn.hMargin + Layout.topMargin: mainColumn.vMargin + Layout.bottomMargin: mainColumn.vMargin + } + + Item { Layout.fillHeight: true } + + Base.HRowLayout { + Base.HButton { + text: qsTr("Register") + Layout.fillWidth: true + } + Base.HButton { + text: qsTr("Login") + Layout.fillWidth: true + } + Base.HButton { + text: qsTr("Forgot?") + Layout.fillWidth: true + } + } + } + } +} diff --git a/harmonyqml/components/UI.qml b/harmonyqml/components/pages/MainUI.qml similarity index 78% rename from harmonyqml/components/UI.qml rename to harmonyqml/components/pages/MainUI.qml index 2e641faf..d42e3abe 100644 --- a/harmonyqml/components/UI.qml +++ b/harmonyqml/components/pages/MainUI.qml @@ -2,8 +2,8 @@ import QtQuick 2.7 import QtQuick.Controls 1.4 as Controls1 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.4 -import "sidePane" as SidePane -import "chat" as Chat +import "../sidePane" as SidePane +import "../chat" as Chat //https://doc.qt.io/qt-5/qml-qtquick-controls-splitview.html Controls1.SplitView { @@ -17,13 +17,15 @@ Controls1.SplitView { StackView { function showRoom(userId, roomId) { pageStack.replace( - "chat/Root.qml", { userId: userId, roomId: roomId } + "../chat/Root.qml", { userId: userId, roomId: roomId } ) } id: pageStack - onCurrentItemChanged: currentItem.forceActiveFocus() + onCurrentItemChanged: if (currentItem) { + currentItem.forceActiveFocus() + } initialItem: Item { // TODO: (test, remove) Keys.onEnterPressed: pageStack.showRoom( diff --git a/harmonyqml/components/pages/SettingsPage.qml b/harmonyqml/components/pages/SettingsPage.qml deleted file mode 100644 index c49a4e02..00000000 --- a/harmonyqml/components/pages/SettingsPage.qml +++ /dev/null @@ -1,9 +0,0 @@ -import QtQuick 2.7 -import "../base" as Base - -Rectangle { - Base.HLabel { - anchors.centerIn: parent - text: "Settings page" - } -} diff --git a/harmonyqml/components/sidePane/RoomDelegate.qml b/harmonyqml/components/sidePane/RoomDelegate.qml index 07962139..6c13fbea 100644 --- a/harmonyqml/components/sidePane/RoomDelegate.qml +++ b/harmonyqml/components/sidePane/RoomDelegate.qml @@ -52,7 +52,7 @@ MouseArea { text: getText() textFormat: Text.StyledText - font.pixelSize: smallSize + font.pixelSize: Base.HStyle.fontSize.small elide: Text.ElideRight maximumLineCount: 1 Layout.maximumWidth: roomLabel.Layout.maximumWidth diff --git a/harmonyqml/icons/accept.svg b/harmonyqml/icons/accept.svg deleted file mode 100644 index 9d13fa19..00000000 --- a/harmonyqml/icons/accept.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/harmonyqml/icons/decline.svg b/harmonyqml/icons/decline.svg deleted file mode 100644 index a7c8b2c0..00000000 --- a/harmonyqml/icons/decline.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/harmonyqml/icons/email.svg b/harmonyqml/icons/email.svg new file mode 100644 index 00000000..7459cb08 --- /dev/null +++ b/harmonyqml/icons/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/harmonyqml/icons/forget_room.svg b/harmonyqml/icons/forget_room.svg new file mode 100644 index 00000000..0a837a00 --- /dev/null +++ b/harmonyqml/icons/forget_room.svg @@ -0,0 +1,51 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/harmonyqml/icons/invite_accept.svg b/harmonyqml/icons/invite_accept.svg new file mode 100644 index 00000000..c2bef64e --- /dev/null +++ b/harmonyqml/icons/invite_accept.svg @@ -0,0 +1,51 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/harmonyqml/icons/invite_decline.svg b/harmonyqml/icons/invite_decline.svg new file mode 100644 index 00000000..584a4121 --- /dev/null +++ b/harmonyqml/icons/invite_decline.svg @@ -0,0 +1,51 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/harmonyqml/icons/phone.svg b/harmonyqml/icons/phone.svg new file mode 100644 index 00000000..a7b9b3f7 --- /dev/null +++ b/harmonyqml/icons/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/harmonyqml/icons/placeholder.svg b/harmonyqml/icons/placeholder.svg new file mode 100644 index 00000000..8868ede9 --- /dev/null +++ b/harmonyqml/icons/placeholder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/harmonyqml/icons/trash_can.svg b/harmonyqml/icons/trash_can.svg deleted file mode 100644 index 107485c1..00000000 --- a/harmonyqml/icons/trash_can.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/harmonyqml/icons/username.svg b/harmonyqml/icons/username.svg new file mode 100644 index 00000000..cf3671aa --- /dev/null +++ b/harmonyqml/icons/username.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/harmonyqml/images/login_background.jpg b/harmonyqml/images/login_background.jpg new file mode 100644 index 00000000..0309e656 Binary files /dev/null and b/harmonyqml/images/login_background.jpg differ diff --git a/harmonyqml/images/matrix_logo.svg b/harmonyqml/images/matrix_logo.svg new file mode 100644 index 00000000..743a1eed --- /dev/null +++ b/harmonyqml/images/matrix_logo.svg @@ -0,0 +1,26 @@ + + + + + + + + + + +