Single room list approach, account bar scrolls
This commit is contained in:
parent
56c09e6b48
commit
fcf88209f2
2
TODO.md
2
TODO.md
|
@ -1,5 +1,7 @@
|
|||
# TODO
|
||||
|
||||
- rename goto*account → scrollto*account
|
||||
- account number binds
|
||||
- update glass theme
|
||||
- back/front buttons in small window
|
||||
- minimum sizes
|
||||
|
|
|
@ -871,6 +871,7 @@ class MatrixClient(nio.AsyncClient):
|
|||
"""
|
||||
|
||||
self.models[self.user_id, "rooms"].pop(room_id, None)
|
||||
self.models["every_room"].pop((self.user_id, room_id), None)
|
||||
self.models.pop((self.user_id, room_id, "events"), None)
|
||||
self.models.pop((self.user_id, room_id, "members"), None)
|
||||
|
||||
|
@ -1209,8 +1210,9 @@ class MatrixClient(nio.AsyncClient):
|
|||
mentions = 0
|
||||
unreads = 0
|
||||
|
||||
self.models[self.user_id, "rooms"][room.room_id] = Room(
|
||||
room_item = Room(
|
||||
id = room.room_id,
|
||||
for_account = self.user_id,
|
||||
given_name = room.name or "",
|
||||
display_name = room.display_name or "",
|
||||
avatar_url = room.gen_avatar_url or "",
|
||||
|
@ -1244,9 +1246,11 @@ class MatrixClient(nio.AsyncClient):
|
|||
last_event_date = last_event_date,
|
||||
mentions = mentions,
|
||||
unreads = unreads,
|
||||
|
||||
)
|
||||
|
||||
self.models[self.user_id, "rooms"][room.room_id] = room_item
|
||||
self.models["every_room"][self.user_id, room.room_id] = room_item
|
||||
|
||||
# List members that left the room, then remove them from our model
|
||||
left_the_room = [
|
||||
user_id
|
||||
|
|
|
@ -40,9 +40,9 @@ class Account(ModelItem):
|
|||
first_sync_done: bool = False
|
||||
|
||||
def __lt__(self, other: "Account") -> bool:
|
||||
"""Sort by display name or user ID."""
|
||||
name = self.display_name or self.id[1:]
|
||||
other_name = other.display_name or other.id[1:]
|
||||
"""Sort by user ID."""
|
||||
name = self.id[1:]
|
||||
other_name = other.id[1:]
|
||||
return name.lower() < other_name.lower()
|
||||
|
||||
|
||||
|
@ -51,6 +51,7 @@ class Room(ModelItem):
|
|||
"""A matrix room we are invited to, are or were member of."""
|
||||
|
||||
id: str = field()
|
||||
for_account: str = field()
|
||||
given_name: str = ""
|
||||
display_name: str = ""
|
||||
main_alias: str = ""
|
||||
|
@ -90,19 +91,22 @@ class Room(ModelItem):
|
|||
|
||||
Invited rooms are first, then joined rooms, then left rooms.
|
||||
Within these categories, sort by last event date (room with recent
|
||||
messages are first), then by display names, but
|
||||
messages are first), then by display names, then account, but
|
||||
keep rooms with mentions on top, followed by rooms with unread events.
|
||||
"""
|
||||
|
||||
# Left rooms may still have an inviter_id, so check left first.
|
||||
return (
|
||||
self.for_account,
|
||||
self.left,
|
||||
other.inviter_id,
|
||||
bool(other.mentions),
|
||||
bool(other.unreads),
|
||||
other.last_event_date,
|
||||
(self.display_name or self.id).lower(),
|
||||
|
||||
) < (
|
||||
other.for_account,
|
||||
other.left,
|
||||
self.inviter_id,
|
||||
bool(self.mentions),
|
||||
|
|
|
@ -217,7 +217,7 @@ HDrawer {
|
|||
|
||||
NumberAnimation {
|
||||
running: doUselessThing
|
||||
target: mainUI.mainPane.mainPaneList
|
||||
target: mainUI.mainPane.roomList
|
||||
property: "rotation"
|
||||
duration: 250
|
||||
from: 360
|
||||
|
@ -225,19 +225,4 @@ HDrawer {
|
|||
loops: Animation.Infinite
|
||||
onStopped: target.rotation = 0
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
running: doUselessThing
|
||||
target: mainUI.pageLoader
|
||||
property: "scale"
|
||||
duration: 250
|
||||
from: 1
|
||||
to: -1
|
||||
onStopped: if (doUselessThing) {
|
||||
[from, to] = [to, from]
|
||||
start()
|
||||
} else {
|
||||
target.scale = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,17 +17,19 @@ HTile {
|
|||
|
||||
HUserAvatar {
|
||||
id: avatar
|
||||
userId: model.id
|
||||
displayName: model.display_name
|
||||
mxc: model.avatar_url
|
||||
userId: accountModel.id
|
||||
displayName: accountModel.display_name
|
||||
mxc: accountModel.avatar_url
|
||||
radius: 0
|
||||
}
|
||||
|
||||
TitleLabel {
|
||||
text: model.display_name || model.id
|
||||
text: accountModel.display_name || accountModel.id
|
||||
color:
|
||||
hovered ?
|
||||
utils.nameColor(model.display_name || model.id.substring(1)) :
|
||||
utils.nameColor(
|
||||
accountModel.display_name || accountModel.id.substring(1),
|
||||
) :
|
||||
theme.accountView.account.name
|
||||
|
||||
Behavior on color { HColorAnimation {} }
|
||||
|
@ -40,7 +42,7 @@ HTile {
|
|||
backgroundColor: "transparent"
|
||||
toolTip.text: qsTr("Add new chat")
|
||||
onClicked: pageLoader.showPage(
|
||||
"AddChat/AddChat", {userId: model.id},
|
||||
"AddChat/AddChat", {userId: accountModel.id},
|
||||
)
|
||||
|
||||
Layout.fillHeight: true
|
||||
|
@ -59,7 +61,7 @@ HTile {
|
|||
HMenuItem {
|
||||
icon.name: "copy-user-id"
|
||||
text: qsTr("Copy user ID")
|
||||
onTriggered: Clipboard.text = model.id
|
||||
onTriggered: Clipboard.text = accountModel.id
|
||||
}
|
||||
|
||||
HMenuItemPopupSpawner {
|
||||
|
@ -68,17 +70,18 @@ HTile {
|
|||
text: qsTr("Sign out")
|
||||
|
||||
popup: "Popups/SignOutPopup.qml"
|
||||
properties: { "userId": model.id }
|
||||
properties: { "userId": accountModel.id }
|
||||
}
|
||||
}
|
||||
|
||||
onLeftClicked: {
|
||||
pageLoader.showPage(
|
||||
"AccountSettings/AccountSettings", { "userId": model.id }
|
||||
"AccountSettings/AccountSettings", { "userId": accountModel.id }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
property var accountModel
|
||||
property bool isCurrent: false
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
import QtQuick 2.12
|
||||
import ".."
|
||||
import "../Base"
|
||||
|
||||
HSwipeView {
|
||||
id: swipeView
|
||||
orientation: Qt.Vertical
|
||||
|
||||
Repeater {
|
||||
model: ModelStore.get("accounts")
|
||||
|
||||
AccountView {}
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import ".."
|
||||
import "../Base"
|
||||
|
||||
HLoader {
|
||||
id: loader
|
||||
active:
|
||||
HSwipeView.isCurrentItem ||
|
||||
HSwipeView.isNextItem ||
|
||||
HSwipeView.isPreviousItem
|
||||
|
||||
readonly property bool isCurrent: HSwipeView.isCurrentItem
|
||||
|
||||
sourceComponent: HColumnLayout {
|
||||
id: column
|
||||
|
||||
readonly property QtObject accountModel: model
|
||||
readonly property alias roomList: roomList
|
||||
|
||||
Account {
|
||||
id: account
|
||||
isCurrent: loader.isCurrent
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RoomList {
|
||||
id: roomList
|
||||
clip: true
|
||||
accountModel: column.accountModel
|
||||
roomPane: swipeView
|
||||
isCurrent: loader.isCurrent
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
FilterRoomsField {
|
||||
roomList: roomList
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,21 +8,21 @@ import "../Base"
|
|||
import "../Base/HTile"
|
||||
|
||||
HColumnLayout {
|
||||
property AccountSwipeView accountSwipeView
|
||||
property RoomList roomList
|
||||
|
||||
|
||||
HButton {
|
||||
id: everyRoomButton
|
||||
icon.name: "every-room"
|
||||
toolTip.text: qsTr("Every room")
|
||||
backgroundColor: theme.accountsBar.everyRoomButtonBackground
|
||||
// onClicked: pageLoader.showPage("AddAccount/AddAccount")
|
||||
id: addAccountButton
|
||||
icon.name: "add-account"
|
||||
toolTip.text: qsTr("Add another account")
|
||||
backgroundColor: theme.accountsBar.addAccountButtonBackground
|
||||
onClicked: pageLoader.showPage("AddAccount/AddAccount")
|
||||
|
||||
Layout.preferredHeight: theme.baseElementsHeight
|
||||
|
||||
HShortcut {
|
||||
sequences: window.settings.keys.showEveryRoom
|
||||
onActivated: everyRoomButton.clicked()
|
||||
sequences: window.settings.keys.addNewAccount
|
||||
onActivated: addAccountButton.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,10 +30,14 @@ HColumnLayout {
|
|||
id: accountList
|
||||
clip: true
|
||||
model: ModelStore.get("accounts")
|
||||
currentIndex: accountSwipeView.currentIndex
|
||||
currentIndex:
|
||||
roomList.currentIndex === -1 ?
|
||||
-1 :
|
||||
model.findIndex(
|
||||
roomList.model.get(roomList.currentIndex).for_account, -1,
|
||||
)
|
||||
|
||||
highlight: Item {
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: theme.accountsBar.accountList.account.selectedBackground
|
||||
|
@ -74,7 +78,7 @@ HColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
onLeftClicked: accountSwipeView.currentIndex = model.index
|
||||
onLeftClicked: roomList.goToAccount(model.id)
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
@ -82,12 +86,18 @@ HColumnLayout {
|
|||
|
||||
HShortcut {
|
||||
sequences: window.settings.keys.goToPreviousAccount
|
||||
onActivated: accountSwipeView.decrementWrapIndex()
|
||||
onActivated: {
|
||||
accountList.decrementCurrentIndex()
|
||||
accountList.currentItem.leftClicked()
|
||||
}
|
||||
}
|
||||
|
||||
HShortcut {
|
||||
sequences: window.settings.keys.goToNextAccount
|
||||
onActivated: accountSwipeView.incrementWrapIndex()
|
||||
onActivated: {
|
||||
accountList.incrementCurrentIndex()
|
||||
accountList.currentItem.leftClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
@ -97,21 +107,6 @@ HColumnLayout {
|
|||
}
|
||||
}
|
||||
|
||||
HButton {
|
||||
id: addAccountButton
|
||||
icon.name: "add-account"
|
||||
toolTip.text: qsTr("Add another account")
|
||||
backgroundColor: theme.accountsBar.addAccountButtonBackground
|
||||
onClicked: pageLoader.showPage("AddAccount/AddAccount")
|
||||
|
||||
Layout.preferredHeight: theme.baseElementsHeight
|
||||
|
||||
HShortcut {
|
||||
sequences: window.settings.keys.addNewAccount
|
||||
onActivated: addAccountButton.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
HButton {
|
||||
id: settingsButton
|
||||
backgroundColor: theme.accountsBar.settingsButtonBackground
|
||||
|
|
|
@ -21,7 +21,7 @@ HTextField {
|
|||
Keys.onEnterPressed: Keys.onReturnPressed(event)
|
||||
Keys.onReturnPressed: {
|
||||
if (window.settings.clearRoomFilterOnEnter) text = ""
|
||||
roomList.showRoom()
|
||||
roomList.showRoomAtIndex()
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
|
@ -36,13 +36,11 @@ HTextField {
|
|||
Behavior on opacity { HNumberAnimation {} }
|
||||
|
||||
HShortcut {
|
||||
enabled: loader.isCurrent
|
||||
sequences: window.settings.keys.clearRoomFilter
|
||||
onActivated: filterField.text = ""
|
||||
}
|
||||
|
||||
HShortcut {
|
||||
enabled: loader.isCurrent
|
||||
sequences: window.settings.keys.toggleFocusMainPane
|
||||
onActivated: {
|
||||
if (filterField.activeFocus) {
|
||||
|
|
|
@ -10,7 +10,9 @@ HDrawer {
|
|||
background: null
|
||||
// minimumSize: bottomBar.addAccountButton.width
|
||||
|
||||
// property alias filter: bottomBar.roomFilter
|
||||
readonly property alias accountBar: accountBar
|
||||
readonly property alias roomList: roomList
|
||||
readonly property alias filterRoomsField: filterRoomsField
|
||||
|
||||
readonly property bool small:
|
||||
width < theme.controls.avatar.size + theme.spacing * 2
|
||||
|
@ -28,17 +30,26 @@ HDrawer {
|
|||
|
||||
AccountsBar {
|
||||
id: accountBar
|
||||
accountSwipeView: accountSwipeView
|
||||
roomList: roomList
|
||||
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
AccountSwipeView {
|
||||
id: accountSwipeView
|
||||
currentIndex: 0
|
||||
HColumnLayout {
|
||||
RoomList {
|
||||
id: roomList
|
||||
clip: true
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
FilterRoomsField {
|
||||
id: filterRoomsField
|
||||
roomList: roomList
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ HTileDelegate {
|
|||
|
||||
popup: "Popups/InviteToRoomPopup.qml"
|
||||
properties: ({
|
||||
userId: userId,
|
||||
userId: model.for_account,
|
||||
roomId: model.id,
|
||||
roomName: model.display_name,
|
||||
invitingAllowed: Qt.binding(() => model.can_invite)
|
||||
|
@ -169,7 +169,7 @@ HTileDelegate {
|
|||
label.textFormat: Text.StyledText
|
||||
|
||||
onTriggered: py.callClientCoro(
|
||||
userId, "join", [model.id]
|
||||
model.for_account, "join", [model.id]
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ HTileDelegate {
|
|||
|
||||
popup: "Popups/LeaveRoomPopup.qml"
|
||||
properties: ({
|
||||
userId: userId,
|
||||
userId: model.for_account,
|
||||
roomId: model.id,
|
||||
roomName: model.display_name,
|
||||
})
|
||||
|
@ -195,7 +195,7 @@ HTileDelegate {
|
|||
popup: "Popups/ForgetRoomPopup.qml"
|
||||
autoDestruct: false
|
||||
properties: ({
|
||||
userId: userId,
|
||||
userId: model.for_account,
|
||||
roomId: model.id,
|
||||
roomName: model.display_name,
|
||||
})
|
||||
|
@ -203,14 +203,12 @@ HTileDelegate {
|
|||
}
|
||||
|
||||
|
||||
property string userId
|
||||
|
||||
readonly property bool joined: ! invited && ! parted
|
||||
readonly property bool invited: model.inviter_id && ! parted
|
||||
readonly property bool parted: model.left
|
||||
|
||||
readonly property ListModel eventModel:
|
||||
ModelStore.get(userId, model.id, "events")
|
||||
ModelStore.get(model.for_account, model.id, "events")
|
||||
|
||||
readonly property QtObject lastEvent:
|
||||
eventModel.count > 0 ? eventModel.get(0) : null
|
||||
|
|
|
@ -7,44 +7,78 @@ import "../Base"
|
|||
|
||||
HListView {
|
||||
id: roomList
|
||||
model: ModelStore.get(accountModel.id, "rooms")
|
||||
model: ModelStore.get("every_room")
|
||||
|
||||
section.property: "for_account"
|
||||
section.labelPositioning:
|
||||
ViewSection.InlineLabels | ViewSection.CurrentLabelAtStart
|
||||
section.delegate: Account {
|
||||
accountModel: ModelStore.get("accounts").find(section)
|
||||
width: roomList.width
|
||||
}
|
||||
|
||||
delegate: Room {
|
||||
width: roomList.width
|
||||
userId: accountModel.id
|
||||
onActivated: showRoom(model.index)
|
||||
onActivated: showRoomAtIndex(model.index)
|
||||
}
|
||||
|
||||
onIsCurrentChanged: if (isCurrent) showRoom()
|
||||
|
||||
readonly property var sectionIndice: {
|
||||
const sections = {}
|
||||
const accounts = ModelStore.get("accounts")
|
||||
let total = 0
|
||||
|
||||
for (let i = 0; i < accounts.count; i++) {
|
||||
const userId = accounts.get(i).id
|
||||
sections[userId] = total
|
||||
total += ModelStore.get(userId, "rooms").count
|
||||
}
|
||||
|
||||
return sections
|
||||
}
|
||||
|
||||
|
||||
property var accountModel
|
||||
property var roomPane
|
||||
property bool isCurrent: false
|
||||
function goToAccount(userId) {
|
||||
currentIndex = sectionIndice[userId]
|
||||
}
|
||||
|
||||
function goToAccountNumber(num) {
|
||||
currentIndex = Object.values(sectionIndice).sort()[num]
|
||||
}
|
||||
|
||||
function showRoom(index=currentIndex) {
|
||||
function showRoomAtIndex(index=currentIndex) {
|
||||
if (index === -1) index = 0
|
||||
if (index >= model.count) return
|
||||
pageLoader.showRoom(accountModel.id, model.get(index).id)
|
||||
index = Math.min(index, model.count - 1)
|
||||
|
||||
const room = model.get(index)
|
||||
pageLoader.showRoom(room.for_account, room.id)
|
||||
currentIndex = index
|
||||
}
|
||||
|
||||
function showAccountRoomAtIndex(index) {
|
||||
const userId =
|
||||
model.get(currentIndex === -1 ? 0 : currentIndex).for_account
|
||||
|
||||
const rooms = ModelStore.get(userId, "rooms")
|
||||
if (! rooms.count) return
|
||||
|
||||
const room = rooms.get(utils.numberWrapAt(index, rooms.count))
|
||||
showRoomAtIndex(model.findIndex(room.id))
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
id: showRoomLimiter
|
||||
interval: 200
|
||||
onTriggered: showRoom()
|
||||
onTriggered: showRoomAtIndex()
|
||||
}
|
||||
|
||||
HShortcut {
|
||||
enabled: isCurrent
|
||||
sequences: window.settings.keys.goToPreviousRoom
|
||||
onActivated: { decrementCurrentIndex(); showRoomLimiter.restart() }
|
||||
}
|
||||
|
||||
HShortcut {
|
||||
enabled: isCurrent
|
||||
sequences: window.settings.keys.goToNextRoom
|
||||
onActivated: { incrementCurrentIndex(); showRoomLimiter.restart() }
|
||||
}
|
||||
|
@ -54,28 +88,13 @@ HListView {
|
|||
|
||||
Item {
|
||||
HShortcut {
|
||||
enabled: isCurrent
|
||||
sequence: window.settings.keys.focusRoomAtIndex[modelData]
|
||||
onActivated: showRoom(parseInt(modelData - 1, 10))
|
||||
onActivated:
|
||||
showAccountRoomAtIndex(parseInt(modelData - 1, 10))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
onWheel: {
|
||||
const goingDown = wheel.angleDelta.y < 0
|
||||
|
||||
if (! goingDown && roomList.atYBeginning)
|
||||
roomPane.decrementCurrentIndex()
|
||||
else if (goingDown && roomList.atYEnd)
|
||||
roomPane.incrementCurrentIndex()
|
||||
else
|
||||
wheel.accepted = false
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
z: -100
|
||||
|
|
|
@ -14,18 +14,18 @@ QtObject {
|
|||
ListModel {
|
||||
property var modelId
|
||||
|
||||
function findIndex(id) {
|
||||
function findIndex(id, default_=null) {
|
||||
for (let i = 0; i < count; i++)
|
||||
if (get(i).id === id) return i
|
||||
|
||||
return null
|
||||
return default_
|
||||
}
|
||||
|
||||
function find(id) {
|
||||
function find(id, default_=null) {
|
||||
for (let i = 0; i < count; i++)
|
||||
if (get(i).id === id) return get(i)
|
||||
|
||||
return null
|
||||
return default_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user