redesign messages page

pull/191/head
larteyoh 10 months ago
parent 97a63bf031
commit 0c1a2cc310

@ -66,7 +66,7 @@ The name _neroshop_ is a combination of the words _nero_, which is Italian for _
- [x] Pseudonymous identities
- sellers and buyers are identified by their unique ids and/or optional display names
- [x] End-to-end encrypted messaging system for communications between sellers and buyers
- generated RSA-4096 private keys will be used to decrypt messages so keep yours safe, secure and accessible!
- generated RSA-4096 private keys will be used to decrypt messages.
- [ ] Subaddress generator for direct payments without an escrow
- a unique subaddress will be generated from a seller's synced wallet account for each order placed by a customer
- [x] Built-in Monero wallet with basic functionalities (`transaction history`, `send`, and `receive`)
@ -92,7 +92,7 @@ The name _neroshop_ is a combination of the words _nero_, which is Italian for _
| [sqlite3](https://sqlite.org/) | 3.38.0 | database management | :heavy_check_mark: |
| [QR Code generator](https://github.com/nayuki/QR-Code-generator) | ? | qr code generation | :heavy_check_mark: |
| [json](https://github.com/nlohmann/json/) | ? | json parsing and msgpack | :heavy_check_mark: |
| [curl](https://github.com/curl/curl) | ? | currency conversion | :o: |
| [curl](https://github.com/curl/curl) | ? | currency conversion | :o: :white_square_button: |
| [openssl](https://github.com/openssl/openssl) | 1.1.1 | for curl, sha256 sum and message encryption | :heavy_check_mark: |
| [Qt](https://www.qt.io/) | 5.12.8 | graphical user interface | :heavy_check_mark: |
| [raft](https://github.com/willemt/raft) | ? | consensus mechanism | :grey_question: |
@ -290,7 +290,7 @@ u/EchoingCat — for the revision of the official neroshop logo
woodser — for his guidance and for his work on the monero-cpp library which has made the development of this app possible
yuriio147 — for his work on various QML components, the currency converter, wallet address qr provider, fixing a major bug in the RSA encryption code, the RSA signing and verifying functions, and for teaching me some Qt/QML techniques
lza_menace — for his help on creating the new monero.fail JSON API endpoint
everyone in our matrix room — for sharing many great ideas that could be used to improve the project
everyone in our matrix room — for sharing many great ideas that have been useful to the project
```
[//]: # (./clean.sh)

@ -13,6 +13,7 @@ import FontAwesome 1.0
import "components"
import "components" as NeroshopComponents
import "pages"
import "pages/subpages"
ApplicationWindow {
id: mainWindow
@ -92,7 +93,7 @@ ApplicationWindow {
let pageComponent = Qt.createComponent(pageUrl);
if (pageComponent.status !== Component.Ready) {
console.log("Component creation error:", component.errorString());
console.log("Component creation error:", pageComponent.errorString());
return;
}
@ -132,6 +133,10 @@ ApplicationWindow {
console.log("Current page is Catalog (on back clicked)")
lastPushedSource = "qrc:/qml/pages/CatalogPage.qml"
lastPushedProperties = pageStack.get(depth - 1).model // still pushes to StackView (:/) but that's ok // Note: pageStack.currentItem.model returns false when compared to `lastPushedProperties` whereas pageStack.get(depth - 1) returns true
} else if(pageStack.currentItem instanceof MessagesPage) {
console.log("Current page is Messages (on back clicked)")
navBar.checkButtonByIndex(2)
lastPushedSource = "qrc:/qml/pages/subpages/MessagesPage.qml"
} else {
lastPushedSource = ""
lastPushedProperties = null

@ -10,41 +10,189 @@ Page {
color: "transparent"
}
ColumnLayout {
RowLayout {
anchors.fill: parent
ListView {
Layout.fillWidth: true
anchors.leftMargin: 20; anchors.rightMargin: 40
anchors.topMargin: 15; anchors.bottomMargin: anchors.topMargin
// Side Panel
Rectangle {
id: sidePanel
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.preferredWidth: 300
Layout.fillHeight: true
model: User.getMessages()
delegate: Rectangle {
width: parent.width
height: 250
color: index % 2 === 0 ? "#f0f0f0" : "#e0e0e0"
ColumnLayout {
anchors.fill: parent
Text {
id: senderText
text: modelData.sender_id
color: "#4169e1"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: {
navBar.uncheckAllButtons()
pageStack.pushPageWithProperties("qrc:/qml/pages/ProfilePage.qml", { "messagesModel": {"sender_id": modelData.sender_id} })
color: (NeroshopComponents.Style.darkTheme) ? (NeroshopComponents.Style.themeName == "PurpleDust" ? "#17171c" : "#181a1b") : "#c9c9cd"//"#f0f0f0"
clip: true
border.color: (NeroshopComponents.Style.darkTheme) ? "#404040" : "#4d4d4d"
radius: 7
ListView {
id: senderList
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: 5; anchors.bottomMargin: anchors.topMargin
width: 280
height: parent.height
spacing: 3
property var messages_model: User.getMessages()
model: ListModel {
Component.onCompleted: {
var uniqueSenderIds = [];
for (var i = 0; i < senderList.messages_model.length; i++) {
var senderId = senderList.messages_model[i].sender_id;
if (uniqueSenderIds.indexOf(senderId) === -1) {
uniqueSenderIds.push(senderId);
append({ sender_id: senderId });
}
}
}
}//50
delegate: Rectangle {
width: senderList.width
height: 60//40
color: "transparent"
radius: sidePanel.radius
Rectangle {
anchors.fill: parent
color: parent.ListView.isCurrentItem ? ((NeroshopComponents.Style.darkTheme) ? ((NeroshopComponents.Style.themeName == "PurpleDust") ? "#3a3a46" : "#3c4143") : "#d7d7da") : "transparent"
radius: parent.radius
}
Item {
anchors.fill: parent
RowLayout { // By default this should inherit its children rect size
anchors.left: parent.left
anchors.leftMargin: 10;
anchors.rightMargin: anchors.leftMargin
anchors.verticalCenter: parent.verticalCenter
spacing: 5
Rectangle {
id: senderAvatarRect
Layout.preferredWidth: 32; Layout.preferredHeight: width
border.color: parent.parent.parent.ListView.isCurrentItem ? "#7d6b9a" : "transparent"
radius: 5
Image {
source: "https://api.dicebear.com/6.x/identicon/png?seed=%1".arg(modelData)
anchors.centerIn: parent
width: (parent.width - 8) - (senderAvatarRect.border.width * 2); height: width
fillMode: Image.PreserveAspectFit
mipmap: true
asynchronous: true
}
}
Text {
id: senderNameIdText
Layout.preferredWidth: parent.parent.parent.width - (parent.anchors.leftMargin + senderAvatarRect.width + parent.spacing + parent.anchors.rightMargin)
text: Backend.getDisplayNameByUserId(modelData)//"Item " + (index + 1)
elide: Text.ElideRight
color: parent.parent.parent.ListView.isCurrentItem ? "#7d6b9a" : ((NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000")
font.bold: parent.parent.parent.ListView.isCurrentItem ? true : false
property string senderId: modelData
}
onEntered: parent.color = "blue"
onExited: parent.color = "#4169e1"
}
}
TextArea {
id: contentText
Layout.fillWidth: true
Layout.fillHeight: true
text: modelData.content
wrapMode: Text.Wrap
readOnly: true
selectByMouse: true
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: {
parent.color = (NeroshopComponents.Style.darkTheme) ? ((NeroshopComponents.Style.themeName == "PurpleDust") ? "#3a3a46" : "#3c4143") : "#d7d7da"
}
onExited: {
parent.color = "transparent"
}
onClicked: {
// Handle item selection
//console.log("Selected Item " + (index + 1))
// Set current item
senderList.currentIndex = index
senderList.positionViewAtIndex(index, ListView.Contain)
}
}
}
}
}
// Main Content
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: sidePanel.color//"#ffffff"
border.color: sidePanel.border.color
radius: sidePanel.radius
clip: true
Text {
visible: (senderList.count < 1)
anchors.centerIn: parent
text: "Nothing to see here ..."
color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
}
ListView {
id: messageList
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: 20; anchors.bottomMargin: anchors.topMargin
anchors.leftMargin: 20; anchors.rightMargin: anchors.leftMargin
spacing: 5
model: senderList.currentItem ? User.getMessages(senderList.currentItem.children[1].children[0].children[1].senderId, senderList.messages_model) : null
delegate: Rectangle {
width: parent.width
height: 250 // Adjust the height as needed
color: "transparent"//index % 2 === 0 ? "#f0f0f0" : "#e0e0e0"
border.color: messageList.parent.border.color
radius: messageList.parent.radius
ColumnLayout {
anchors.fill: parent
anchors.margins: 10
RowLayout {
spacing: 3
Text {
id: senderNameText
visible: (text !== modelData.sender_id)
wrapMode: Text.WordWrap
text: Backend.getDisplayNameByUserId(modelData.sender_id)
color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
}
Text {
id: senderIdText
Layout.fillWidth: true // Fill the remaining available width
wrapMode: Text.WordWrap
elide: Text.ElideRight
text: senderNameText.visible ? ("(" + modelData.sender_id + ")") : modelData.sender_id
color: "#4169e1"
MouseArea {
anchors.fill: parent
hoverEnabled: true
onClicked: {
navBar.uncheckAllButtons()
pageStack.pushPageWithProperties("qrc:/qml/pages/ProfilePage.qml", { "messagesModel": {"sender_id": modelData.sender_id} })
}
onEntered: parent.color = "blue"
onExited: parent.color = "#4169e1"
}
}
}
TextArea {
id: contentText
Layout.preferredWidth: parent.width//Layout.fillWidth: true
Layout.fillHeight: true
text: modelData.content
wrapMode: Text.Wrap
readOnly: true
selectByMouse: true
color: (NeroshopComponents.Style.darkTheme) ? "#ffffff" : "#000000"
}
}
}
}

@ -544,6 +544,35 @@ QVariantList neroshop::UserController::getMessages() const {
return messages_array;
}
//----------------------------------------------------------------
QVariantList neroshop::UserController::getMessages(const QString& sender_id) const {
QVariantList allMessages = getMessages();
QVariantList filteredMessages;
// Filter the messages based on the specified sender_id
for (const QVariant &message : allMessages) {
QVariantMap messageMap = message.toMap();
if (messageMap["sender_id"].toString() == sender_id) {
filteredMessages.append(messageMap);
}
}
return filteredMessages;
}
//----------------------------------------------------------------
QVariantList neroshop::UserController::getMessages(const QString& sender_id, const QVariantList& messages) const {
QVariantList filteredMessages;
// Filter the messages based on the specified sender_id
for (const QVariant &message : messages) {
QVariantMap messageMap = message.toMap();
if (messageMap["sender_id"].toString() == sender_id) {
filteredMessages.append(messageMap);
}
}
return filteredMessages;
}
//----------------------------------------------------------------
//----------------------------------------------------------------
bool neroshop::UserController::isUserLogged() const {
return (_user.get() != nullptr);

@ -97,6 +97,8 @@ public:
Q_INVOKABLE QVariantList getInventory(InventorySorting sorting = SortNone) const;
Q_INVOKABLE QVariantList getMessages() const;
Q_INVOKABLE QVariantList getMessages(const QString& sender_id) const;
Q_INVOKABLE QVariantList getMessages(const QString& sender_id, const QVariantList& messages) const;
Q_INVOKABLE neroshop::User * getUser() const;
neroshop::Seller * getSeller() const;

Loading…
Cancel
Save