Skip to content
Snippets Groups Projects
Commit 88d833aa authored by Nicolas Werner's avatar Nicolas Werner
Browse files

Basic room overview

parent 8e992344
No related branches found
No related tags found
No related merge requests found
......@@ -2,3 +2,4 @@
harbour-matrix.pro.user
/lib/
/rpm/harbour-matrix.spec.*
*.autosave
[Desktop Entry]
Type=Application
X-Nemo-Application-Type=silica-qt5
#X-Nemo-Application-Type=silica-qt5
X-Nemo-Application-Type=no-invoker
Icon=harbour-matrix
Exec=harbour-matrix
Name=Matrix
Categories=Chat;Network
# translation example:
# your app name in German locale (de)
#
......
......@@ -7,6 +7,13 @@ Page {
// The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All
onStatusChanged: {
if (status === PageStatus.Active) {
console.log("Try reconnect")
login.tryReconnect()
}
}
// To enable PullDownMenu, place our content in a SilicaFlickable
SilicaFlickable {
anchors.fill: parent
......
......@@ -7,10 +7,37 @@ Page {
// The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All
// To enable PullDownMenu, place our content in a SilicaFlickable
SilicaFlickable {
Component {
id: roomContextMenu
ContextMenu {
MenuItem {
text: "Remove"
onClicked: highlight()
}
}
}
Component {
id: sectionHeading
SectionHeader {
color: Theme.highlightColor
text: section
font.bold: true
font.pixelSize: Theme.fontSizeLarge
}
}
SilicaListView {
id: roomView
anchors.fill: parent
width: mainPage.width
contentHeight: mainPage.height
spacing: Theme.paddingLarge
contentWidth: mainPage.width
ScrollDecorator { flickable: roomView }
// PullDownMenu and PushUpMenu must be declared in SilicaFlickable, SilicaListView or SilicaGridView
PullDownMenu {
MenuItem {
......@@ -26,20 +53,140 @@ Page {
}
}
// Tell SilicaFlickable the height of its content.
contentHeight: column.height
header: PageHeader {
title: qsTr("Rooms")
}
model: ListModel {
ListElement {
roomName: "Room1"
unreadNotifications: 11
lastMessage: "Hi, I'm using spoon!"
roomPicture: "harbour-matrix.png"
tag: "group"
}
ListElement {
roomName: "Room2"
unreadNotifications: 0
lastMessage: "Hi, I'm using spoon!"
roomPicture: "icons/128x128/harbour-matrix.png"
tag: "group"
}
ListElement {
roomName: "Room2aaa"
unreadNotifications: 0
lastMessage: "Hi, I'm using spoon!"
roomPicture: "icons/128x128/harbour-matrix.png"
tag: "group"
}
ListElement {
roomName: "Room2 asfg sdfg retgh"
unreadNotifications: 4
lastMessage: "Hi, I'm using spoon!"
roomPicture: "icons/128x128/harbour-matrix.png"
tag: "group"
}
ListElement {
roomName: "UserA"
unreadNotifications: 0
lastMessage: "Hi, I'm using spoon and this is some ver long text that hopefully doesn't fit the line!"
roomPicture: "harbour-matrix.png"
tag: "direct"
}
ListElement {
roomName: "UserB"
unreadNotifications: 11
lastMessage: "Hi, I'm using spoonaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!"
roomPicture: "qtlogo.png"
tag: "direct"
}
ListElement {
roomName: "UserE"
unreadNotifications: 0
lastMessage: "Hey!"
roomPicture: "harbour-matrix.png"
tag: "direct"
}
ListElement {
roomName: "UserD"
unreadNotifications: 4000
lastMessage: "Hi, I'm using spoon and this is some ver long text that hopefully doesn't fit the line! But of course it does! Damn it"
roomPicture: "harbour-matrix.png"
tag: "direct"
}
}
delegate: ListItem {
id: roomItem
menu: roomContextMenu
contentHeight: mainRow.height + Theme.paddingSmall
contentWidth: parent.width
Row {
anchors.left: parent.left
anchors.right: parent.right
spacing: Theme.paddingMedium
width: roomItem.width
// Place our content in a Column. The PageHeader is always placed at the top
// of the page, followed by our content.
Column {
id: column
id: mainRow
width: mainPage.width
spacing: Theme.paddingLarge
Label {
BackgroundItem {
Rectangle {
color: Theme.highlightBackgroundColor
}
}
PageHeader {
title: qsTr("Rooms")
color: unreadNotifications > 0 ? Theme.highlightColor : Theme.secondaryColor
width: 2 * Theme.fontSizeLarge
id: unreadMessages
text: unreadNotifications
font.pixelSize: unreadNotifications < 100 ? Theme.fontSizeHuge : Theme.fontSizeLarge
horizontalAlignment: Text.AlignRight
}
Column {
width: mainRow.width - unreadMessages.width
- roomImageContainer.width - 3* Theme.paddingMedium
Label {
id: roomName
text: model.roomName
color: Theme.primaryColor
font.pixelSize: Theme.fontSizeLarge
font.bold: true
}
Text {
anchors {
left: parent.left
right: parent.right
}
id: lastMessage
text: model.lastMessage
color: unreadNotifications > 0 ? Theme.primaryColor : Theme.secondaryColor
font.bold: unreadNotifications > 0
wrapMode: Text.Wrap
elide: Text.ElideRight
maximumLineCount: 3
}
}
Rectangle {
id: roomImageContainer
height: unreadMessages.width
color: "lightgreen"
width: unreadMessages.width
Image {
id: roomImage
source: model.roomPicture
asynchronous: true
}
}
}
}
section.property: "tag"
section.criteria: ViewSection.FullString
section.delegate: sectionHeading
}
}
......@@ -36,5 +36,6 @@ int main(int argc, char *argv[]) {
// Start the application.
v->setSource(SailfishApp::pathTo("qml/harbour-matrix.qml"));
v->show();
return app->exec();
}
......@@ -9,6 +9,21 @@
Login::Login(QObject *parent) : QObject(parent) {}
void Login::tryReconnect() {
Settings s;
try {
http::client().set_user(s.user().value());
http::client().set_server(s.server().value());
http::client().set_port(s.server_port().value());
http::client().set_device_id(s.device_id().value());
http::client().set_access_token(s.access_token().value());
emit loginSuccess();
} catch (std::exception &e) {
qWarning() << "Relogin failed: " << QString::fromStdString(e.what());
}
}
void Login::mxidEntered(QString mxid) {
using namespace mtx::identifiers;
std::cout << mxid.toStdString() << "\n";
......@@ -116,6 +131,7 @@ void Login::login(QString mxid, QString password, QString server) {
Settings s;
s.access_token(response.access_token);
s.device_id(response.device_id);
s.user(response.user_id);
s.server(response.home_server);
s.server_port(http::client().port());
......@@ -128,9 +144,10 @@ void Login::logout() {
mtx::http::RequestErr error) {
if (error) {
qWarning() << "Error logging out";
return;
}
http::client().clear();
Settings s;
s.delete_access_token();
});
......
#include "login.h"
#include <QtDebug>
#include <mtx/identifiers.hpp>
#include "client.h"
#include "settings.h"
Login::Login(QObject *parent) : QObject(parent) {}
void Login::tryReconnect()
{
http::client().login();
}
void Login::mxidEntered(QString mxid) {
using namespace mtx::identifiers;
std::cout << mxid.toStdString() << "\n";
User user;
try {
user = parse<User>(mxid.toStdString());
} catch (const std::exception &) {
qDebug() << "Can't parse user!"
<< "\n";
emit userParseError("Can't parse User");
return;
}
QString server = QString::fromStdString(user.hostname());
this->validateServer(server);
}
void Login::homeserverEntered(QString server) { this->validateServer(server); }
void Login::validateServer(QString server) {
http::client().set_server(server.toStdString());
http::client().versions([this, server](const mtx::responses::Versions &,
mtx::http::RequestErr err) {
if (err) {
using namespace boost::beast::http;
if (err->status_code == status::not_found) {
emit homeserverInvalid(server,
tr("The required endpoints were not found. "
"Possibly not a Matrix server."));
return;
}
if (!err->parse_error.empty()) {
emit homeserverInvalid(server,
tr("Received malformed response. Make sure "
"the homeserver domain is valid."));
return;
}
emit homeserverInvalid(server, tr("An unknown error occured. Make sure "
"the homeserver domain is valid."));
return;
}
});
}
void Login::login(QString mxid, QString password, QString server) {
qInfo() << "Logging in\n";
using namespace mtx::identifiers;
std::cout << mxid.toStdString() << "\n";
User user;
try {
user = parse<User>(mxid.toStdString());
} catch (const std::exception &) {
qDebug() << "Can't parse user!"
<< "\n";
emit loginError("Can't parse User");
return;
}
if (password.isEmpty()) {
emit loginError(tr("Empty password"));
return;
}
auto homeserver = user.hostname();
if (server.size() > 0)
homeserver = server.toStdString();
http::client().login(
user.localpart(), password.toStdString(),
[this](const mtx::responses::Login &response,
mtx::http::RequestErr error) {
if (error) {
qDebug() << "Failed login!\n";
if (!error->matrix_error.error.empty()) {
emit loginError(QString::fromStdString(error->matrix_error.error));
return;
} else if (!error->parse_error.empty()) {
emit loginError(QString::fromStdString(error->parse_error));
return;
} else if (error->error_code) {
emit loginError(
QString::fromStdString(error->error_code.message()));
return;
} else if (error->status_code != boost::beast::http::status::ok) {
emit loginError(QString::fromStdString(
"http status" + std::to_string((unsigned)error->status_code)));
return;
} else {
emit loginError(tr("Failed to login"));
return;
}
}
qDebug() << "Access token:"
<< QString::fromStdString(response.access_token)
<< " , device: " << QString::fromStdString(response.device_id);
Settings s;
s.access_token(response.access_token);
s.device_id(response.device_id);
s.server(response.home_server);
s.server_port(http::client().port());
emit loginSuccess();
});
}
void Login::logout() {
http::client().logout([this](const mtx::responses::Logout &response,
mtx::http::RequestErr error) {
if (error) {
qWarning() << "Error logging out";
return;
}
Settings s;
s.delete_access_token();
});
}
......@@ -7,7 +7,6 @@ class Login : public QObject {
Q_OBJECT
public:
explicit Login(QObject *parent = nullptr);
void tryReconnect();
signals:
void userParseError(QString error);
......@@ -20,6 +19,7 @@ public slots:
void homeserverEntered(QString server);
void login(QString mxid, QString password, QString server);
void logout();
void tryReconnect();
private:
void validateServer(QString server);
......
#include "settings.h"
#include <QDebug>
Q_DECLARE_METATYPE(std::string)
Q_DECLARE_METATYPE(uint16_t)
......@@ -44,14 +46,25 @@ optional<std::string> Settings::server() {
}
}
void Settings::user(const std::string &s) {
settings.setValue(QStringLiteral("user"), QString::fromStdString(s));
void Settings::user(const mtx::identifiers::User &s) {
settings.setValue(QStringLiteral("user"),
QString::fromStdString(s.to_string()));
}
optional<std::string> Settings::user() {
if (settings.contains(QStringLiteral("user")))
return settings.value(QStringLiteral("user")).value<std::string>();
else {
optional<mtx::identifiers::User> Settings::user() {
if (settings.contains(QStringLiteral("user"))) {
std::string s = settings.value(QStringLiteral("user")).value<std::string>();
try {
return mtx::identifiers::parse<mtx::identifiers::User>(s);
} catch (std::exception &e) {
qWarning() << "Exception getting user from settings: "
<< QString::fromStdString(e.what())
<< " while parsing input: '" << QString::fromStdString(s)
<< "'";
return std::experimental::nullopt;
}
} else {
return std::experimental::nullopt;
}
}
......
......@@ -7,19 +7,21 @@
#include <experimental/optional>
#include <string>
#include <mtx/identifiers.hpp>
class Settings {
public:
Settings();
void access_token(const std::string &s);
void device_id(const std::string &s);
void user(const std::string &s);
void user(const mtx::identifiers::User &s);
void server(const std::string &s);
void server_port(uint16_t s);
std::experimental::optional<std::string> access_token();
std::experimental::optional<std::string> device_id();
std::experimental::optional<std::string> user();
std::experimental::optional<mtx::identifiers::User> user();
std::experimental::optional<std::string> server();
std::experimental::optional<uint16_t> server_port();
......
......@@ -5,41 +5,41 @@
<name>AboutPage</name>
<message>
<source>Nested Page</source>
<translation type="unfinished">Unterseite</translation>
<translation>Unterseite</translation>
</message>
<message>
<source>Item</source>
<translation type="unfinished">Element</translation>
<translation>Element</translation>
</message>
</context>
<context>
<name>CoverPage</name>
<message>
<source>Matrix</source>
<translation type="unfinished"></translation>
<translation>Matrix</translation>
</message>
</context>
<context>
<name>Login</name>
<message>
<source>The required endpoints were not found. Possibly not a Matrix server.</source>
<translation type="unfinished"></translation>
<translation>Die Endpunkte konnten nicht erreicht werden. Möglicherweise kein Matrix Server.</translation>
</message>
<message>
<source>Received malformed response. Make sure the homeserver domain is valid.</source>
<translation type="unfinished"></translation>
<translation>Ungültige Antwort des Servers. Überprüfen Sie die Heimserverdomain</translation>
</message>
<message>
<source>An unknown error occured. Make sure the homeserver domain is valid.</source>
<translation type="unfinished"></translation>
<translation>Ein unbekannter Fehler ist aufgetreten. Überprüfen Sie die Heimserverdomai</translation>
</message>
<message>
<source>Failed to login</source>
<translation type="unfinished"></translation>
<translation>Login fehlgeschlagen</translation>
</message>
<message>
<source>Empty password</source>
<translation type="unfinished"></translation>
<translation>Leeres Passwort</translation>
</message>
</context>
<context>
......@@ -50,7 +50,7 @@
</message>
<message>
<source>Login</source>
<translation>Anmeldung</translation>
<translation>Anmelden</translation>
</message>
<message>
<source>Register</source>
......@@ -69,22 +69,22 @@
<message>
<source>your.homeserver:optional port</source>
<extracomment>TextField hint for entering homeserver</extracomment>
<translation type="unfinished"></translation>
<translation>dein.heimserver:optionaler port</translation>
</message>
</context>
<context>
<name>MainView</name>
<message>
<source>About</source>
<translation type="unfinished">Über diese Applikation</translation>
<translation>Über diese Applikation</translation>
</message>
<message>
<source>Rooms</source>
<translation type="unfinished"></translation>
<translation>Räume</translation>
</message>
<message>
<source>Logout</source>
<translation type="unfinished"></translation>
<translation>Abmelden</translation>
</message>
</context>
</TS>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment