feat: group information
This commit is contained in:
parent
846dc646e1
commit
78e8e6be93
|
@ -1,10 +1,12 @@
|
||||||
import NimQml
|
import NimQml
|
||||||
import std/wrapnils
|
import std/wrapnils
|
||||||
import ../../../status/chat/chat
|
import ../../../status/chat/chat
|
||||||
|
import chat_members
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type ChatItemView* = ref object of QObject
|
type ChatItemView* = ref object of QObject
|
||||||
chatItem*: Chat
|
chatItem*: Chat
|
||||||
|
chatMembers*: ChatMembersView
|
||||||
|
|
||||||
proc setup(self: ChatItemView) =
|
proc setup(self: ChatItemView) =
|
||||||
self.QObject.setup
|
self.QObject.setup
|
||||||
|
@ -16,10 +18,12 @@ QtObject:
|
||||||
new(result, delete)
|
new(result, delete)
|
||||||
result = ChatItemView()
|
result = ChatItemView()
|
||||||
result.chatItem = nil
|
result.chatItem = nil
|
||||||
|
result.chatMembers = newChatMembersView()
|
||||||
result.setup
|
result.setup
|
||||||
|
|
||||||
proc setChatItem*(self: ChatItemView, chatItem: Chat) =
|
proc setChatItem*(self: ChatItemView, chatItem: Chat) =
|
||||||
self.chatItem = chatItem
|
self.chatItem = chatItem
|
||||||
|
self.chatMembers.setMembers(chatItem.members)
|
||||||
|
|
||||||
proc id*(self: ChatItemView): string {.slot.} = result = ?.self.chatItem.id
|
proc id*(self: ChatItemView): string {.slot.} = result = ?.self.chatItem.id
|
||||||
|
|
||||||
|
@ -49,3 +53,9 @@ QtObject:
|
||||||
|
|
||||||
QtProperty[int] chatType:
|
QtProperty[int] chatType:
|
||||||
read = chatType
|
read = chatType
|
||||||
|
|
||||||
|
proc getMembers*(self: ChatItemView): QVariant {.slot.} =
|
||||||
|
result = newQVariant(self.chatMembers)
|
||||||
|
|
||||||
|
QtProperty[QVariant] members:
|
||||||
|
read = getMembers
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import NimQml, Tables
|
||||||
|
import ../../../status/chat/[chat, message]
|
||||||
|
|
||||||
|
type
|
||||||
|
ChatMemberRoles {.pure.} = enum
|
||||||
|
UserName = UserRole + 1,
|
||||||
|
PubKey = UserRole + 2,
|
||||||
|
IsAdmin = UserRole + 3,
|
||||||
|
Joined = UserRole + 4
|
||||||
|
Identicon = UserRole + 5
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
ChatMembersView* = ref object of QAbstractListModel
|
||||||
|
members*: seq[ChatMember]
|
||||||
|
|
||||||
|
proc setup(self: ChatMembersView) = self.QAbstractListModel.setup
|
||||||
|
|
||||||
|
proc delete(self: ChatMembersView) = self.QAbstractListModel.delete
|
||||||
|
|
||||||
|
proc newChatMembersView*(): ChatMembersView =
|
||||||
|
new(result, delete)
|
||||||
|
result.members = @[]
|
||||||
|
result.setup()
|
||||||
|
|
||||||
|
proc setMembers*(self: ChatMembersView, members: seq[ChatMember]) =
|
||||||
|
self.beginResetModel()
|
||||||
|
self.members = members
|
||||||
|
self.endResetModel()
|
||||||
|
|
||||||
|
proc len*(self: ChatMembersView): int {.slot.} = self.members.len
|
||||||
|
|
||||||
|
method rowCount(self: ChatMembersView, index: QModelIndex = nil): int = self.members.len
|
||||||
|
|
||||||
|
method data(self: ChatMembersView, index: QModelIndex, role: int): QVariant =
|
||||||
|
if not index.isValid:
|
||||||
|
return
|
||||||
|
if index.row < 0 or index.row >= self.members.len:
|
||||||
|
return
|
||||||
|
|
||||||
|
let chatMember = self.members[index.row]
|
||||||
|
let chatMemberRole = role.ChatMemberRoles
|
||||||
|
case chatMemberRole:
|
||||||
|
of ChatMemberRoles.UserName: result = newQVariant(chatMember.userName)
|
||||||
|
of ChatMemberRoles.PubKey: result = newQVariant(chatMember.id)
|
||||||
|
of ChatMemberRoles.IsAdmin: result = newQVariant(chatMember.admin)
|
||||||
|
of ChatMemberRoles.Joined: result = newQVariant(chatMember.joined)
|
||||||
|
of ChatMemberRoles.Identicon: result = newQVariant(chatMember.identicon)
|
||||||
|
|
||||||
|
method roleNames(self: ChatMembersView): Table[int, string] =
|
||||||
|
{
|
||||||
|
ChatMemberRoles.UserName.int:"userName",
|
||||||
|
ChatMemberRoles.PubKey.int:"pubKey",
|
||||||
|
ChatMemberRoles.IsAdmin.int: "isAdmin",
|
||||||
|
ChatMemberRoles.Joined.int: "joined",
|
||||||
|
ChatMemberRoles.Identicon.int: "identicon",
|
||||||
|
}.toTable
|
|
@ -23,10 +23,14 @@ proc fromEvent*(event: JsonNode): Signal =
|
||||||
result = signal
|
result = signal
|
||||||
|
|
||||||
proc toChatMember*(jsonMember: JsonNode): ChatMember =
|
proc toChatMember*(jsonMember: JsonNode): ChatMember =
|
||||||
|
let pubkey = jsonMember["id"].getStr
|
||||||
|
|
||||||
result = ChatMember(
|
result = ChatMember(
|
||||||
admin: jsonMember["admin"].getBool,
|
admin: jsonMember["admin"].getBool,
|
||||||
id: jsonMember["id"].getStr,
|
id: pubkey,
|
||||||
joined: jsonMember["joined"].getBool
|
joined: jsonMember["joined"].getBool,
|
||||||
|
identicon: generateIdenticon(pubkey),
|
||||||
|
userName: generateAlias(pubkey)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ type ChatMember* = object
|
||||||
admin*: bool
|
admin*: bool
|
||||||
id*: string
|
id*: string
|
||||||
joined*: bool
|
joined*: bool
|
||||||
|
identicon*: string
|
||||||
|
userName*: string
|
||||||
|
|
||||||
type Chat* = ref object
|
type Chat* = ref object
|
||||||
id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat
|
id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat
|
||||||
|
|
|
@ -12,7 +12,7 @@ Item {
|
||||||
property string message: "That's right. We're friends... Of justice, that is."
|
property string message: "That's right. We're friends... Of justice, that is."
|
||||||
property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
|
property string identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
|
||||||
property bool isCurrentUser: false
|
property bool isCurrentUser: false
|
||||||
property int timestamp: 1234567
|
property string timestamp: "1234567"
|
||||||
property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v"
|
property string sticker: "Qme8vJtyrEHxABcSVGPF95PtozDgUyfr1xGjePmFdZgk9v"
|
||||||
property int contentType: 1 // constants don't work in default props
|
property int contentType: 1 // constants don't work in default props
|
||||||
property string chatId: "chatId"
|
property string chatId: "chatId"
|
||||||
|
|
|
@ -48,7 +48,10 @@ Rectangle {
|
||||||
switch(chatsModel.activeChannel.chatType){
|
switch(chatsModel.activeChannel.chatType){
|
||||||
case Constants.chatTypePublic: return qsTr("Public chat")
|
case Constants.chatTypePublic: return qsTr("Public chat")
|
||||||
case Constants.chatTypeOneToOne: return qsTr("TODO: Contact/Not a contact")
|
case Constants.chatTypeOneToOne: return qsTr("TODO: Contact/Not a contact")
|
||||||
case Constants.chatTypePrivateGroupChat: return qsTr("TODO: N members")
|
case Constants.chatTypePrivateGroupChat:
|
||||||
|
let cnt = chatsModel.activeChannel.members.len();
|
||||||
|
if(cnt > 1) return qsTr("%1 members").arg(cnt);
|
||||||
|
return qsTr("1 member");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
font.pixelSize: 12
|
font.pixelSize: 12
|
||||||
|
@ -101,6 +104,11 @@ Rectangle {
|
||||||
|
|
||||||
PopupMenu {
|
PopupMenu {
|
||||||
id: groupContextMenu
|
id: groupContextMenu
|
||||||
|
QQC2.Action {
|
||||||
|
icon.source: "../../../img/group_chat.svg"
|
||||||
|
text: qsTr("Group Information")
|
||||||
|
onTriggered: groupInfoPopup.open()
|
||||||
|
}
|
||||||
QQC2.Action {
|
QQC2.Action {
|
||||||
icon.source: "../../../img/leave_chat.svg"
|
icon.source: "../../../img/leave_chat.svg"
|
||||||
text: qsTr("Leave Group")
|
text: qsTr("Leave Group")
|
||||||
|
@ -108,6 +116,11 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GroupInfoPopup {
|
||||||
|
id: groupInfoPopup
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Controls 2.3
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../../../../imports"
|
||||||
|
import "../../../../shared"
|
||||||
|
import "./"
|
||||||
|
|
||||||
|
ModalPopup {
|
||||||
|
id: popup
|
||||||
|
|
||||||
|
header: Item {
|
||||||
|
height: children[0].height
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: letterIdenticon
|
||||||
|
width: 36
|
||||||
|
height: 36
|
||||||
|
radius: 50
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: Theme.padding
|
||||||
|
color: chatsModel.activeChannel.color
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: chatsModel.activeChannel.name.charAt(0).toUpperCase();
|
||||||
|
opacity: 0.7
|
||||||
|
font.weight: Font.Bold
|
||||||
|
font.pixelSize: 21
|
||||||
|
color: Theme.white
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEdit {
|
||||||
|
id: groupName
|
||||||
|
text: chatsModel.activeChannel.name
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 18
|
||||||
|
anchors.left: letterIdenticon.right
|
||||||
|
anchors.leftMargin: Theme.smallPadding
|
||||||
|
font.bold: true
|
||||||
|
font.pixelSize: 14
|
||||||
|
readOnly: true
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: {
|
||||||
|
let cnt = chatsModel.activeChannel.members.len();
|
||||||
|
if(cnt > 1) return qsTr("%1 members").arg(cnt);
|
||||||
|
return qsTr("1 member");
|
||||||
|
}
|
||||||
|
width: 160
|
||||||
|
anchors.left: letterIdenticon.right
|
||||||
|
anchors.leftMargin: Theme.smallPadding
|
||||||
|
anchors.top: groupName.bottom
|
||||||
|
anchors.topMargin: 2
|
||||||
|
font.pixelSize: 14
|
||||||
|
color: Theme.darkGrey
|
||||||
|
font.family: "Inter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: container
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: memberLabel
|
||||||
|
text: qsTr("Members")
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.padding
|
||||||
|
font.pixelSize: 15
|
||||||
|
color: Theme.darkGrey
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: exampleModel
|
||||||
|
|
||||||
|
ListElement {
|
||||||
|
isAdmin: false
|
||||||
|
joined: true
|
||||||
|
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
|
||||||
|
userName: "The UserName"
|
||||||
|
pubKey: "0x12345678"
|
||||||
|
}
|
||||||
|
|
||||||
|
ListElement {
|
||||||
|
isAdmin: false
|
||||||
|
joined: true
|
||||||
|
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
|
||||||
|
userName: "The UserName"
|
||||||
|
pubKey: "0x12345678"
|
||||||
|
}
|
||||||
|
|
||||||
|
ListElement {
|
||||||
|
isAdmin: false
|
||||||
|
joined: true
|
||||||
|
identicon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
|
||||||
|
userName: "The UserName"
|
||||||
|
pubKey: "0x12345678"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: memberList
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.top: memberLabel.bottom
|
||||||
|
anchors.bottom: popup.bottom
|
||||||
|
anchors.topMargin: 30
|
||||||
|
anchors.bottomMargin: Theme.padding
|
||||||
|
spacing: 4
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
//model: exampleModel
|
||||||
|
model: chatsModel.activeChannel.members
|
||||||
|
delegate: Row {
|
||||||
|
Column {
|
||||||
|
Image {
|
||||||
|
source: model.identicon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Text {
|
||||||
|
text: model.userName
|
||||||
|
width: 300
|
||||||
|
elide: Text.ElideRight
|
||||||
|
Layout.fillWidth: true
|
||||||
|
font.pixelSize: 13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
Text {
|
||||||
|
visible: model.isAdmin
|
||||||
|
text: qsTr("Admin")
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
width: 100
|
||||||
|
font.pixelSize: 13
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
visible: !model.isAdmin
|
||||||
|
text: "..."
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
width: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
SuggestedChannel 1.0 SuggestedChannel.qml
|
SuggestedChannel 1.0 SuggestedChannel.qml
|
||||||
PublicChatPopup 1.0 PublicChatPopup.qml
|
PublicChatPopup 1.0 PublicChatPopup.qml
|
||||||
PrivateChatPopup 1.0 PrivateChatPopup.qml
|
PrivateChatPopup 1.0 PrivateChatPopup.qml
|
||||||
|
GroupInfoPopup 1.0 GroupInfoPopup.qml
|
||||||
ProfilePropup 1.0 ProfilePopup.qml
|
ProfilePropup 1.0 ProfilePopup.qml
|
||||||
ChannelIcon 1.0 ChannelIcon.qml
|
ChannelIcon 1.0 ChannelIcon.qml
|
||||||
|
|
Loading…
Reference in New Issue