mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Show rooms you share with someone
This commit is contained in:
parent
d46a67f64b
commit
aae3300860
8 changed files with 320 additions and 139 deletions
25
resources/qml/components/NhekoTabButton.qml
Normal file
25
resources/qml/components/NhekoTabButton.qml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import QtQuick 2.15
|
||||||
|
import QtQuick.Controls 2.15
|
||||||
|
import im.nheko 1.0
|
||||||
|
|
||||||
|
TabButton {
|
||||||
|
id: control
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
text: control.text
|
||||||
|
font: control.font
|
||||||
|
opacity: enabled ? 1.0 : 0.3
|
||||||
|
color: control.down ? Nheko.colors.highlightedText : Nheko.colors.text
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
border.color: control.down ? Nheko.colors.highlight : Nheko.theme.separator
|
||||||
|
color: control.checked ? Nheko.colors.highlight : Nheko.colors.base
|
||||||
|
border.width: 1
|
||||||
|
radius: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -49,30 +49,10 @@ ApplicationWindow {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
palette: Nheko.colors
|
palette: Nheko.colors
|
||||||
|
|
||||||
component TabB : TabButton {
|
NhekoTabButton {
|
||||||
id: control
|
|
||||||
|
|
||||||
contentItem: Text {
|
|
||||||
text: control.text
|
|
||||||
font: control.font
|
|
||||||
opacity: enabled ? 1.0 : 0.3
|
|
||||||
color: control.down ? Nheko.colors.highlightedText : Nheko.colors.text
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
elide: Text.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
border.color: control.down ? Nheko.colors.highlight : Nheko.theme.separator
|
|
||||||
color: control.checked ? Nheko.colors.highlight : Nheko.colors.base
|
|
||||||
border.width: 1
|
|
||||||
radius: 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TabB {
|
|
||||||
text: qsTr("Roles")
|
text: qsTr("Roles")
|
||||||
}
|
}
|
||||||
TabB {
|
NhekoTabButton {
|
||||||
text: qsTr("Users")
|
text: qsTr("Users")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
import ".."
|
import ".."
|
||||||
import "../device-verification"
|
import "../device-verification"
|
||||||
import "../ui"
|
import "../ui"
|
||||||
|
import "../components"
|
||||||
import QtQuick 2.15
|
import QtQuick 2.15
|
||||||
import QtQuick.Controls 2.15
|
import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.2
|
import QtQuick.Layouts 1.2
|
||||||
import QtQuick.Window 2.13
|
import QtQuick.Window 2.13
|
||||||
|
import QtQml.Models 2.2
|
||||||
import im.nheko 1.0
|
import im.nheko 1.0
|
||||||
|
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
|
@ -34,12 +36,13 @@ ApplicationWindow {
|
||||||
ListView {
|
ListView {
|
||||||
id: devicelist
|
id: devicelist
|
||||||
|
|
||||||
|
property int selectedTab: 0
|
||||||
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
clip: true
|
clip: true
|
||||||
spacing: 8
|
spacing: 8
|
||||||
boundsBehavior: Flickable.StopAtBounds
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
model: profile.deviceList
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 10
|
anchors.margins: 10
|
||||||
footerPositioning: ListView.OverlayFooter
|
footerPositioning: ListView.OverlayFooter
|
||||||
|
@ -297,147 +300,214 @@ ApplicationWindow {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabBar {
|
||||||
|
id: tabbar
|
||||||
|
visible: !profile.isSelf
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
onCurrentIndexChanged: devicelist.selectedTab = currentIndex
|
||||||
|
|
||||||
|
palette: Nheko.colors
|
||||||
|
|
||||||
|
NhekoTabButton {
|
||||||
|
text: qsTr("Devices")
|
||||||
|
}
|
||||||
|
NhekoTabButton {
|
||||||
|
text: qsTr("Shared Rooms")
|
||||||
|
}
|
||||||
|
|
||||||
|
Layout.bottomMargin: Nheko.paddingMedium
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: RowLayout {
|
model: (selectedTab == 0) ? devicesModel : sharedRoomsModel
|
||||||
required property int verificationStatus
|
|
||||||
required property string deviceId
|
|
||||||
required property string deviceName
|
|
||||||
required property string lastIp
|
|
||||||
required property var lastTs
|
|
||||||
|
|
||||||
width: devicelist.width
|
DelegateModel {
|
||||||
spacing: 4
|
id: devicesModel
|
||||||
|
model: profile.deviceList
|
||||||
|
delegate: RowLayout {
|
||||||
|
required property int verificationStatus
|
||||||
|
required property string deviceId
|
||||||
|
required property string deviceName
|
||||||
|
required property string lastIp
|
||||||
|
required property var lastTs
|
||||||
|
|
||||||
ColumnLayout {
|
width: devicelist.width
|
||||||
spacing: 0
|
spacing: 4
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Layout.leftMargin: Nheko.paddingMedium
|
||||||
|
Layout.rightMargin: Nheko.paddingMedium
|
||||||
|
RowLayout {
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.bold: true
|
||||||
|
color: Nheko.colors.text
|
||||||
|
text: deviceId
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
Layout.preferredHeight: 16
|
||||||
|
Layout.preferredWidth: 16
|
||||||
|
visible: profile.isSelf && verificationStatus != VerificationStatus.NOT_APPLICABLE
|
||||||
|
sourceSize.height: 16 * Screen.devicePixelRatio
|
||||||
|
sourceSize.width: 16 * Screen.devicePixelRatio
|
||||||
|
source: {
|
||||||
|
switch (verificationStatus) {
|
||||||
|
case VerificationStatus.VERIFIED:
|
||||||
|
return "image://colorimage/:/icons/icons/ui/shield-filled-checkmark.svg?" + Nheko.theme.green;
|
||||||
|
case VerificationStatus.UNVERIFIED:
|
||||||
|
return "image://colorimage/:/icons/icons/ui/shield-filled-exclamation-mark.svg?" + Nheko.theme.orange;
|
||||||
|
case VerificationStatus.SELF:
|
||||||
|
return "image://colorimage/:/icons/icons/ui/checkmark.svg?" + Nheko.theme.green;
|
||||||
|
default:
|
||||||
|
return "image://colorimage/:/icons/icons/ui/shield-filled-cross.svg?" + Nheko.theme.orange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
image: ":/icons/icons/ui/power-off.svg"
|
||||||
|
hoverEnabled: true
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Sign out this device.")
|
||||||
|
onClicked: profile.signOutDevice(deviceId)
|
||||||
|
visible: profile.isSelf
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: deviceNameRow
|
||||||
|
|
||||||
|
property bool isEditingAllowed
|
||||||
|
|
||||||
|
TextInput {
|
||||||
|
id: deviceNameField
|
||||||
|
|
||||||
|
readOnly: !deviceNameRow.isEditingAllowed
|
||||||
|
text: deviceName
|
||||||
|
color: Nheko.colors.text
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
Layout.fillWidth: true
|
||||||
|
selectByMouse: true
|
||||||
|
onAccepted: {
|
||||||
|
profile.changeDeviceName(deviceId, deviceNameField.text);
|
||||||
|
deviceNameRow.isEditingAllowed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
visible: profile.isSelf
|
||||||
|
hoverEnabled: true
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Change device name.")
|
||||||
|
image: deviceNameRow.isEditingAllowed ? ":/icons/icons/ui/checkmark.svg" : ":/icons/icons/ui/edit.svg"
|
||||||
|
onClicked: {
|
||||||
|
if (deviceNameRow.isEditingAllowed) {
|
||||||
|
profile.changeDeviceName(deviceId, deviceNameField.text);
|
||||||
|
deviceNameRow.isEditingAllowed = false;
|
||||||
|
} else {
|
||||||
|
deviceNameRow.isEditingAllowed = true;
|
||||||
|
deviceNameField.focus = true;
|
||||||
|
deviceNameField.selectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Layout.leftMargin: Nheko.paddingMedium
|
|
||||||
Layout.rightMargin: Nheko.paddingMedium
|
|
||||||
RowLayout {
|
|
||||||
Text {
|
Text {
|
||||||
|
visible: profile.isSelf
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
font.bold: true
|
|
||||||
color: Nheko.colors.text
|
color: Nheko.colors.text
|
||||||
text: deviceId
|
text: qsTr("Last seen %1 from %2").arg(new Date(lastTs).toLocaleString(Locale.ShortFormat)).arg(lastIp ? lastIp : "???")
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
}
|
||||||
Layout.preferredHeight: 16
|
|
||||||
Layout.preferredWidth: 16
|
Image {
|
||||||
visible: profile.isSelf && verificationStatus != VerificationStatus.NOT_APPLICABLE
|
Layout.preferredHeight: 16
|
||||||
sourceSize.height: 16 * Screen.devicePixelRatio
|
Layout.preferredWidth: 16
|
||||||
sourceSize.width: 16 * Screen.devicePixelRatio
|
visible: !profile.isSelf && verificationStatus != VerificationStatus.NOT_APPLICABLE
|
||||||
source: {
|
source: {
|
||||||
switch (verificationStatus) {
|
switch (verificationStatus) {
|
||||||
case VerificationStatus.VERIFIED:
|
case VerificationStatus.VERIFIED:
|
||||||
return "image://colorimage/:/icons/icons/ui/shield-filled-checkmark.svg?" + Nheko.theme.green;
|
return "image://colorimage/:/icons/icons/ui/shield-filled-checkmark.svg?" + Nheko.theme.green;
|
||||||
case VerificationStatus.UNVERIFIED:
|
case VerificationStatus.UNVERIFIED:
|
||||||
return "image://colorimage/:/icons/icons/ui/shield-filled-exclamation-mark.svg?" + Nheko.theme.orange;
|
return "image://colorimage/:/icons/icons/ui/shield-filled-exclamation-mark.svg?" + Nheko.theme.orange;
|
||||||
case VerificationStatus.SELF:
|
case VerificationStatus.SELF:
|
||||||
return "image://colorimage/:/icons/icons/ui/checkmark.svg?" + Nheko.theme.green;
|
return "image://colorimage/:/icons/icons/ui/checkmark.svg?" + Nheko.theme.green;
|
||||||
default:
|
default:
|
||||||
return "image://colorimage/:/icons/icons/ui/shield-filled-cross.svg?" + Nheko.theme.orange;
|
return "image://colorimage/:/icons/icons/ui/shield-filled.svg?" + Nheko.theme.red;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButton {
|
|
||||||
Layout.alignment: Qt.AlignTop
|
|
||||||
image: ":/icons/icons/ui/power-off.svg"
|
|
||||||
hoverEnabled: true
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
ToolTip.text: qsTr("Sign out this device.")
|
|
||||||
onClicked: profile.signOutDevice(deviceId)
|
|
||||||
visible: profile.isSelf
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
Button {
|
||||||
id: deviceNameRow
|
id: verifyButton
|
||||||
|
|
||||||
property bool isEditingAllowed
|
visible: verificationStatus == VerificationStatus.UNVERIFIED && (profile.isSelf || !profile.userVerificationEnabled)
|
||||||
|
text: (verificationStatus != VerificationStatus.VERIFIED) ? qsTr("Verify") : qsTr("Unverify")
|
||||||
TextInput {
|
onClicked: {
|
||||||
id: deviceNameField
|
if (verificationStatus == VerificationStatus.VERIFIED)
|
||||||
|
|
||||||
readOnly: !deviceNameRow.isEditingAllowed
|
|
||||||
text: deviceName
|
|
||||||
color: Nheko.colors.text
|
|
||||||
Layout.alignment: Qt.AlignLeft
|
|
||||||
Layout.fillWidth: true
|
|
||||||
selectByMouse: true
|
|
||||||
onAccepted: {
|
|
||||||
profile.changeDeviceName(deviceId, deviceNameField.text);
|
|
||||||
deviceNameRow.isEditingAllowed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageButton {
|
|
||||||
visible: profile.isSelf
|
|
||||||
hoverEnabled: true
|
|
||||||
ToolTip.visible: hovered
|
|
||||||
ToolTip.text: qsTr("Change device name.")
|
|
||||||
image: deviceNameRow.isEditingAllowed ? ":/icons/icons/ui/checkmark.svg" : ":/icons/icons/ui/edit.svg"
|
|
||||||
onClicked: {
|
|
||||||
if (deviceNameRow.isEditingAllowed) {
|
|
||||||
profile.changeDeviceName(deviceId, deviceNameField.text);
|
|
||||||
deviceNameRow.isEditingAllowed = false;
|
|
||||||
} else {
|
|
||||||
deviceNameRow.isEditingAllowed = true;
|
|
||||||
deviceNameField.focus = true;
|
|
||||||
deviceNameField.selectAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
visible: profile.isSelf
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignLeft
|
|
||||||
elide: Text.ElideRight
|
|
||||||
color: Nheko.colors.text
|
|
||||||
text: qsTr("Last seen %1 from %2").arg(new Date(lastTs).toLocaleString(Locale.ShortFormat)).arg(lastIp ? lastIp : "???")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
Layout.preferredHeight: 16
|
|
||||||
Layout.preferredWidth: 16
|
|
||||||
visible: !profile.isSelf && verificationStatus != VerificationStatus.NOT_APPLICABLE
|
|
||||||
source: {
|
|
||||||
switch (verificationStatus) {
|
|
||||||
case VerificationStatus.VERIFIED:
|
|
||||||
return "image://colorimage/:/icons/icons/ui/shield-filled-checkmark.svg?" + Nheko.theme.green;
|
|
||||||
case VerificationStatus.UNVERIFIED:
|
|
||||||
return "image://colorimage/:/icons/icons/ui/shield-filled-exclamation-mark.svg?" + Nheko.theme.orange;
|
|
||||||
case VerificationStatus.SELF:
|
|
||||||
return "image://colorimage/:/icons/icons/ui/checkmark.svg?" + Nheko.theme.green;
|
|
||||||
default:
|
|
||||||
return "image://colorimage/:/icons/icons/ui/shield-filled.svg?" + Nheko.theme.red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
id: verifyButton
|
|
||||||
|
|
||||||
visible: verificationStatus == VerificationStatus.UNVERIFIED && (profile.isSelf || !profile.userVerificationEnabled)
|
|
||||||
text: (verificationStatus != VerificationStatus.VERIFIED) ? qsTr("Verify") : qsTr("Unverify")
|
|
||||||
onClicked: {
|
|
||||||
if (verificationStatus == VerificationStatus.VERIFIED)
|
|
||||||
profile.unverify(deviceId);
|
profile.unverify(deviceId);
|
||||||
else
|
else
|
||||||
profile.verify(deviceId);
|
profile.verify(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateModel {
|
||||||
|
id: sharedRoomsModel
|
||||||
|
model: profile.sharedRooms
|
||||||
|
delegate: RowLayout {
|
||||||
|
required property string roomId
|
||||||
|
required property string roomName
|
||||||
|
required property string avatarUrl
|
||||||
|
|
||||||
|
width: devicelist.width
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
id: avatar
|
||||||
|
|
||||||
|
enabled: false
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.leftMargin: Nheko.paddingMedium
|
||||||
|
|
||||||
|
property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 1.6)
|
||||||
|
height: avatarSize
|
||||||
|
width: avatarSize
|
||||||
|
url: avatarUrl.replace("mxc://", "image://MxcImage/")
|
||||||
|
roomid: roomId
|
||||||
|
displayName: roomName
|
||||||
|
}
|
||||||
|
|
||||||
|
ElidedLabel {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
color: Nheko.colors.text
|
||||||
|
Layout.fillWidth: true
|
||||||
|
elideWidth: width
|
||||||
|
fullText: roomName
|
||||||
|
textFormat: Text.PlainText
|
||||||
|
Layout.rightMargin: Nheko.paddingMedium
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: DialogButtonBox {
|
footer: DialogButtonBox {
|
||||||
|
|
|
@ -129,6 +129,7 @@
|
||||||
<file>qml/components/AvatarListTile.qml</file>
|
<file>qml/components/AvatarListTile.qml</file>
|
||||||
<file>qml/components/FlatButton.qml</file>
|
<file>qml/components/FlatButton.qml</file>
|
||||||
<file>qml/components/MainWindowDialog.qml</file>
|
<file>qml/components/MainWindowDialog.qml</file>
|
||||||
|
<file>qml/components/NhekoTabButton.qml</file>
|
||||||
<file>qml/components/NotificationBubble.qml</file>
|
<file>qml/components/NotificationBubble.qml</file>
|
||||||
<file>qml/components/ReorderableListview.qml</file>
|
<file>qml/components/ReorderableListview.qml</file>
|
||||||
<file>qml/components/SpaceMenuLevel.qml</file>
|
<file>qml/components/SpaceMenuLevel.qml</file>
|
||||||
|
|
|
@ -3146,6 +3146,36 @@ Cache::joinedRooms()
|
||||||
return room_ids;
|
return room_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::string, RoomInfo>
|
||||||
|
Cache::getCommonRooms(const std::string &user_id)
|
||||||
|
{
|
||||||
|
std::map<std::string, RoomInfo> result;
|
||||||
|
|
||||||
|
auto txn = ro_txn(env_);
|
||||||
|
|
||||||
|
std::string_view room_id;
|
||||||
|
std::string_view room_data;
|
||||||
|
std::string_view member_info;
|
||||||
|
|
||||||
|
auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
|
||||||
|
while (roomsCursor.get(room_id, room_data, MDB_NEXT)) {
|
||||||
|
try {
|
||||||
|
if (getMembersDb(txn, std::string(room_id)).get(txn, user_id, member_info)) {
|
||||||
|
RoomInfo tmp = nlohmann::json::parse(std::move(room_data)).get<RoomInfo>();
|
||||||
|
result.emplace(std::string(room_id), std::move(tmp));
|
||||||
|
}
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
nhlog::db()->warn("Failed to read common room for member ({}) in room ({}): {}",
|
||||||
|
user_id,
|
||||||
|
room_id,
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roomsCursor.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<MemberInfo>
|
std::optional<MemberInfo>
|
||||||
Cache::getMember(const std::string &room_id, const std::string &user_id)
|
Cache::getMember(const std::string &room_id, const std::string &user_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
crypto::Trust roomVerificationStatus(const std::string &room_id);
|
crypto::Trust roomVerificationStatus(const std::string &room_id);
|
||||||
|
|
||||||
std::vector<std::string> joinedRooms();
|
std::vector<std::string> joinedRooms();
|
||||||
|
std::map<std::string, RoomInfo> getCommonRooms(const std::string &user_id);
|
||||||
|
|
||||||
QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
|
QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
|
||||||
QHash<QString, RoomInfo> invites();
|
QHash<QString, RoomInfo> invites();
|
||||||
|
|
|
@ -58,6 +58,12 @@ UserProfile::UserProfile(const QString &roomid,
|
||||||
emit verificationStatiChanged();
|
emit verificationStatiChanged();
|
||||||
});
|
});
|
||||||
fetchDeviceList(this->userid_);
|
fetchDeviceList(this->userid_);
|
||||||
|
|
||||||
|
if (userid != utils::localUser())
|
||||||
|
sharedRooms_ =
|
||||||
|
new RoomInfoModel(cache::client()->getCommonRooms(userid.toStdString()), this);
|
||||||
|
else
|
||||||
|
sharedRooms_ = new RoomInfoModel({}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<int, QByteArray>
|
QHash<int, QByteArray>
|
||||||
|
@ -102,12 +108,53 @@ DeviceInfoModel::reset(const std::vector<DeviceInfo> &deviceList)
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RoomInfoModel::RoomInfoModel(const std::map<std::string, RoomInfo> &raw, QObject *parent)
|
||||||
|
: QAbstractListModel(parent)
|
||||||
|
{
|
||||||
|
for (const auto &e : raw)
|
||||||
|
roomInfos_.push_back(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray>
|
||||||
|
RoomInfoModel::roleNames() const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
{RoomId, "roomId"},
|
||||||
|
{RoomName, "roomName"},
|
||||||
|
{AvatarUrl, "avatarUrl"},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant
|
||||||
|
RoomInfoModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.row() >= (int)roomInfos_.size() || index.row() < 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case RoomId:
|
||||||
|
return QString::fromStdString(roomInfos_[index.row()].first);
|
||||||
|
case RoomName:
|
||||||
|
return QString::fromStdString(roomInfos_[index.row()].second.name);
|
||||||
|
case AvatarUrl:
|
||||||
|
return QString::fromStdString(roomInfos_[index.row()].second.avatar_url);
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DeviceInfoModel *
|
DeviceInfoModel *
|
||||||
UserProfile::deviceList()
|
UserProfile::deviceList()
|
||||||
{
|
{
|
||||||
return &this->deviceList_;
|
return &this->deviceList_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RoomInfoModel *
|
||||||
|
UserProfile::sharedRooms()
|
||||||
|
{
|
||||||
|
return this->sharedRooms_;
|
||||||
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
UserProfile::userid()
|
UserProfile::userid()
|
||||||
{
|
{
|
||||||
|
|
|
@ -119,6 +119,30 @@ private:
|
||||||
friend class UserProfile;
|
friend class UserProfile;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RoomInfoModel final : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Roles
|
||||||
|
{
|
||||||
|
RoomId,
|
||||||
|
RoomName,
|
||||||
|
AvatarUrl,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit RoomInfoModel(const std::map<std::string, RoomInfo> &, QObject *parent = nullptr);
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override
|
||||||
|
{
|
||||||
|
(void)parent;
|
||||||
|
return (int)roomInfos_.size();
|
||||||
|
}
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<std::string, RoomInfo>> roomInfos_;
|
||||||
|
};
|
||||||
|
|
||||||
class UserProfile final : public QObject
|
class UserProfile final : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -126,6 +150,7 @@ class UserProfile final : public QObject
|
||||||
Q_PROPERTY(QString userid READ userid CONSTANT)
|
Q_PROPERTY(QString userid READ userid CONSTANT)
|
||||||
Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
|
Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
|
||||||
Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList NOTIFY devicesChanged)
|
Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList NOTIFY devicesChanged)
|
||||||
|
Q_PROPERTY(RoomInfoModel *sharedRooms READ sharedRooms CONSTANT)
|
||||||
Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
|
Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
|
||||||
Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged)
|
Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged)
|
||||||
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
|
||||||
|
@ -139,6 +164,7 @@ public:
|
||||||
TimelineModel *parent = nullptr);
|
TimelineModel *parent = nullptr);
|
||||||
|
|
||||||
DeviceInfoModel *deviceList();
|
DeviceInfoModel *deviceList();
|
||||||
|
RoomInfoModel *sharedRooms();
|
||||||
|
|
||||||
QString userid();
|
QString userid();
|
||||||
QString displayName();
|
QString displayName();
|
||||||
|
@ -198,4 +224,5 @@ private:
|
||||||
bool isLoading_ = false;
|
bool isLoading_ = false;
|
||||||
TimelineViewManager *manager;
|
TimelineViewManager *manager;
|
||||||
TimelineModel *model;
|
TimelineModel *model;
|
||||||
|
RoomInfoModel *sharedRooms_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue