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

Add basic text messages to chat view

parent bcdf0db5
No related branches found
No related tags found
No related merge requests found
import QtQuick 2.0
import Sailfish.Silica 1.0
import dev.neko.spoon 1.0
Page {
id: chatPage
// The effective value will be restricted by ApplicationWindow.allowedOrientations
allowedOrientations: Orientation.All
property alias room: chatView.model
SilicaListView {
id: chatView
anchors.fill: parent
anchors.leftMargin: Theme.horizontalPageMargin
anchors.rightMargin: Theme.horizontalPageMargin
ScrollDecorator { flickable: chatView }
header: PageHeader {
title: qsTr("Chat")
}
delegate: ListItem {
id: messageItem
contentHeight: loader.item.contentHeight
Loader {
id: loader
source: switch(model.Type) {
case EventType.TextMessage: return "delegates/TextMessage.qml"
default: return "delegates/placeholder.qml"
}
property variant modelData: model
onLoaded: {
console.log("Loaded item with hight: " + item.height)
messageItem.contentHeight = item.height
}
}
}
section.property: "UserId"
section.criteria: ViewSection.FullString
section.delegate: Text {
text: room.userIdToUserName(section)
color: room.userColor(section, "#00000000")
}
}
}
......@@ -49,6 +49,8 @@ Page {
id: roomItem
menu: roomContextMenu
onClicked: pageStack.push(Qt.resolvedUrl("ChatPage.qml"), {room: model.roomModel} );
property bool collapsed: false
visible: !collapsed
......
import QtQuick 2.0
import Sailfish.Silica 1.0
Rectangle {
height: messageText.contentHeight
Text {
id: messageText
text: modelData.Body
color: Theme.primaryColor
wrapMode: Text.Wrap
width: chatView.width
}
}
import QtQuick 2.0
import Sailfish.Silica 1.0
Item {
height: textItem.contentHeight
Text {
id: textItem
text: "generic placeholder"
color: Theme.primaryColor
}
}
......@@ -2,6 +2,7 @@
#include <QMetaType>
#include <QSharedPointer>
#include <QtMath>
#include <QDebug>
......@@ -10,6 +11,15 @@ Q_DECLARE_METATYPE(QSharedPointer<Room>);
using mtx::events::Event;
template <class T> std::string eventBody(const Event<T> &) { return ""; }
template <class T> auto eventBody(const mtx::events::RoomEvent<T> &e) -> decltype(e.content.body) {
return e.content.body;
}
template <class T> auto eventUserId(const mtx::events::Event<T> &e) -> std::string { return ""; }
template <class T> auto eventUserId(const mtx::events::RoomEvent<T> &e) -> std::string { return e.sender; }
template <class T>::EventType::Type toRoomEventType(const Event<T> &e) {
using mtx::events::EventType;
switch (e.type) {
......@@ -184,7 +194,145 @@ QVariant Room::data(const QModelIndex &index, int role) const {
case Type:
return boost::apply_visitor([](const auto &e) -> ::EventType::Type { return toRoomEventType(e); }, event.data);
case Body:
return QString::fromStdString(
boost::apply_visitor([](const auto &e) -> std::string { return eventBody(e); }, event.data));
case UserId:
return QString::fromStdString(
boost::apply_visitor([](const auto &e) -> std::string { return eventUserId(e); }, event.data));
case UserName:
return QString::fromStdString(boost::apply_visitor(
[this](const auto &e) -> std::string {
try {
return this->memberInfos.at(eventUserId(e)).display_name;
} catch (...) {
return "";
}
},
event.data));
default:
return QVariant();
}
}
QString Room::userIdToUserName(QString id) {
try {
return QString::fromStdString(this->memberInfos.at(id.toStdString()).display_name);
} catch (...) {
return "";
}
}
// from nheko
QColor Room::userColor(QString id, QColor background) {
if (userColors.count(id))
return userColors.at(id);
auto luminance = [](const QColor &col) -> qreal {
int colRgb[3] = {col.red(), col.green(), col.blue()};
qreal lumRgb[3];
for (int i = 0; i < 3; i++) {
qreal v = colRgb[i] / 255.0;
v <= 0.03928 ? lumRgb[i] = v / 12.92 : lumRgb[i] = qPow((v + 0.055) / 1.055, 2.4);
}
auto lum = lumRgb[0] * 0.2126 + lumRgb[1] * 0.7152 + lumRgb[2] * 0.0722;
return lum;
};
auto computeContrast = [](const qreal &one, const qreal &two) -> qreal {
auto ratio = (one + 0.05) / (two + 0.05);
if (two > one) {
ratio = 1 / ratio;
}
return ratio;
};
auto hashQString = [](const QString &input) {
unsigned hash = 0;
for (int i = 0; i < input.length(); i++) {
hash = input.at(i).digitValue() + ((hash << 5) - hash);
}
return (int)hash;
};
const qreal backgroundLum = luminance(background);
// Create a color for the input
auto hash = hashQString(id);
// create a hue value based on the hash of the input.
auto userHue = qAbs(hash % 360);
// start with moderate saturation and lightness values.
auto sat = 220;
auto lightness = 125;
// converting to a QColor makes the luminance calc easier.
QColor inputColor = QColor::fromHsl(userHue, sat, lightness);
// calculate the initial luminance and contrast of the
// generated color. It's possible that no additional
// work will be necessary.
auto lum = luminance(inputColor);
auto contrast = computeContrast(lum, backgroundLum);
// If the contrast doesn't meet our criteria,
// try again and again until they do by modifying first
// the lightness and then the saturation of the color.
while (contrast < 5) {
// if our lightness is at it's bounds, try changing
// saturation instead.
if (lightness == 242 || lightness == 13) {
qreal newSat = qBound(26.0, sat * 1.25, 242.0);
inputColor.setHsl(userHue, qFloor(newSat), lightness);
auto tmpLum = luminance(inputColor);
auto higherContrast = computeContrast(tmpLum, backgroundLum);
if (higherContrast > contrast) {
contrast = higherContrast;
sat = newSat;
} else {
newSat = qBound(26.0, sat / 1.25, 242.0);
inputColor.setHsl(userHue, qFloor(newSat), lightness);
tmpLum = luminance(inputColor);
auto lowerContrast = computeContrast(tmpLum, backgroundLum);
if (lowerContrast > contrast) {
contrast = lowerContrast;
sat = newSat;
}
}
} else {
qreal newLightness = qBound(13.0, lightness * 1.25, 242.0);
inputColor.setHsl(userHue, sat, qFloor(newLightness));
auto tmpLum = luminance(inputColor);
auto higherContrast = computeContrast(tmpLum, backgroundLum);
// Check to make sure we have actually improved contrast
if (higherContrast > contrast) {
contrast = higherContrast;
lightness = newLightness;
// otherwise, try going the other way instead.
} else {
newLightness = qBound(13.0, lightness / 1.25, 242.0);
inputColor.setHsl(userHue, sat, qFloor(newLightness));
tmpLum = luminance(inputColor);
auto lowerContrast = computeContrast(tmpLum, backgroundLum);
if (lowerContrast > contrast) {
contrast = lowerContrast;
lightness = newLightness;
}
}
}
}
userColors[id] = inputColor;
return inputColor;
}
......@@ -6,6 +6,7 @@
#include <vector>
#include <QAbstractListModel>
#include <QColor>
#include <QDateTime>
#include <QString>
......@@ -98,6 +99,9 @@ struct Room : public QAbstractListModel {
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
Q_INVOKABLE QString userIdToUserName(QString id);
Q_INVOKABLE QColor userColor(QString id, QColor background);
std::string id, lastMessage, tag;
int unreadNotifications = 0;
......@@ -130,4 +134,6 @@ struct Room : public QAbstractListModel {
private:
std::vector<mtx::events::collections::TimelineEvent> events;
std::string prev_batch;
std::map<QString, QColor> userColors;
};
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