Somewhat better hierarchy.
Init separate .qml files.
This commit is contained in:
205
imports/Spectral/Panel/RoomDrawer.qml
Normal file
205
imports/Spectral/Panel/RoomDrawer.qml
Normal file
@@ -0,0 +1,205 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
|
||||
import Spectral.Component 2.0
|
||||
|
||||
import Spectral 0.1
|
||||
|
||||
import "qrc:/js/util.js" as Util
|
||||
|
||||
Drawer {
|
||||
property var room
|
||||
|
||||
id: roomDrawer
|
||||
|
||||
edge: Qt.RightEdge
|
||||
interactive: false
|
||||
|
||||
ToolButton {
|
||||
contentItem: MaterialIcon { icon: "\ue5c4" }
|
||||
|
||||
onClicked: roomDrawer.close()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 32
|
||||
|
||||
ImageItem {
|
||||
Layout.preferredWidth: 64
|
||||
Layout.preferredHeight: 64
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
hint: room ? room.displayName : "No name"
|
||||
image: spectralController.safeImage(room ? room.avatar : null)
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: room && room.id ? room.id : ""
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: room && room.canonicalAlias ? room.canonicalAlias : "No Canonical Alias"
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: room ? room.memberCount + " Members" : "No Member Count"
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
TextField {
|
||||
Layout.fillWidth: true
|
||||
|
||||
id: roomNameField
|
||||
text: room && room.name ? room.name : ""
|
||||
selectByMouse: true
|
||||
}
|
||||
|
||||
ItemDelegate {
|
||||
Layout.preferredWidth: height
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
contentItem: MaterialIcon { icon: "\ue5ca" }
|
||||
|
||||
onClicked: room.setName(roomNameField.text)
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
TextField {
|
||||
Layout.fillWidth: true
|
||||
|
||||
id: roomTopicField
|
||||
|
||||
text: room && room.topic ? room.topic : ""
|
||||
selectByMouse: true
|
||||
}
|
||||
|
||||
ItemDelegate {
|
||||
Layout.preferredWidth: height
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
contentItem: MaterialIcon { icon: "\ue5ca" }
|
||||
|
||||
onClicked: room.setTopic(roomTopicField.text)
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
id: userListView
|
||||
|
||||
clip: true
|
||||
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
|
||||
model: UserListModel {
|
||||
room: roomDrawer.room
|
||||
}
|
||||
|
||||
delegate: Column {
|
||||
property bool expanded: false
|
||||
|
||||
ItemDelegate {
|
||||
width: userListView.width
|
||||
height: 48
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
spacing: 12
|
||||
|
||||
ImageItem {
|
||||
Layout.preferredWidth: height
|
||||
Layout.fillHeight: true
|
||||
|
||||
image: avatar
|
||||
hint: name
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: name
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: expanded = !expanded
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width - 32
|
||||
height: expanded ? implicitHeight : 0
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
spacing: 0
|
||||
|
||||
clip: true
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: "Kick"
|
||||
highlighted: true
|
||||
|
||||
onClicked: room.kickMember(userId)
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: "Invite User"
|
||||
flat: true
|
||||
highlighted: true
|
||||
|
||||
onClicked: inviteUserDialog.open()
|
||||
|
||||
Dialog {
|
||||
x: (window.width - width) / 2
|
||||
y: (window.height - height) / 2
|
||||
width: 360
|
||||
|
||||
id: inviteUserDialog
|
||||
|
||||
parent: ApplicationWindow.overlay
|
||||
|
||||
title: "Input User ID"
|
||||
modal: true
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
|
||||
contentItem: TextField {
|
||||
id: inviteUserDialogTextField
|
||||
placeholderText: "@bot:matrix.org"
|
||||
}
|
||||
|
||||
onAccepted: room.inviteToRoom(inviteUserDialogTextField.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
69
imports/Spectral/Panel/RoomHeader.qml
Normal file
69
imports/Spectral/Panel/RoomHeader.qml
Normal file
@@ -0,0 +1,69 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls.Material 2.2
|
||||
|
||||
import Spectral 0.1
|
||||
|
||||
Rectangle {
|
||||
property alias image: headerImage.image
|
||||
property alias topic: headerTopicLabel.text
|
||||
signal clicked()
|
||||
|
||||
id: header
|
||||
|
||||
color: Material.accent
|
||||
|
||||
ItemDelegate {
|
||||
anchors.fill: parent
|
||||
|
||||
id: roomHeader
|
||||
|
||||
onClicked: header.clicked()
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
|
||||
spacing: 12
|
||||
|
||||
ImageItem {
|
||||
Layout.preferredWidth: height
|
||||
Layout.fillHeight: true
|
||||
|
||||
id: headerImage
|
||||
|
||||
hint: currentRoom ? currentRoom.displayName : "No name"
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
visible: parent.width > 64
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
text: currentRoom ? currentRoom.displayName : ""
|
||||
color: "white"
|
||||
font.pointSize: 12
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
id: headerTopicLabel
|
||||
|
||||
color: "white"
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
imports/Spectral/Panel/RoomListDelegate.qml
Normal file
101
imports/Spectral/Panel/RoomListDelegate.qml
Normal file
@@ -0,0 +1,101 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls.Material 2.2
|
||||
|
||||
import Spectral 0.1
|
||||
import Spectral.Setting 0.1
|
||||
|
||||
import Spectral.Component 2.0
|
||||
|
||||
Rectangle {
|
||||
readonly property bool highlighted: currentRoom === enteredRoom
|
||||
|
||||
color: MSettings.darkTheme ? "#303030" : "#fafafa"
|
||||
|
||||
AutoMouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
hoverEnabled: MSettings.miniMode
|
||||
|
||||
onSecondaryClicked: {
|
||||
roomContextMenu.model = model
|
||||
roomContextMenu.popup()
|
||||
}
|
||||
onPrimaryClicked: {
|
||||
if (category === RoomType.Invited) {
|
||||
inviteDialog.currentRoom = currentRoom
|
||||
inviteDialog.open()
|
||||
} else {
|
||||
enteredRoom = currentRoom
|
||||
}
|
||||
}
|
||||
|
||||
ToolTip.visible: MSettings.miniMode && containsMouse
|
||||
ToolTip.text: name
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
visible: highlightCount > 0 || highlighted
|
||||
color: Material.accent
|
||||
opacity: 0.1
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: unreadCount > 0 || highlighted ? 4 : 0
|
||||
height: parent.height
|
||||
|
||||
color: Material.accent
|
||||
|
||||
Behavior on width {
|
||||
PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 }
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 12
|
||||
|
||||
spacing: 12
|
||||
|
||||
ImageItem {
|
||||
id: imageItem
|
||||
|
||||
Layout.preferredWidth: height
|
||||
Layout.fillHeight: true
|
||||
|
||||
hint: name || "No Name"
|
||||
|
||||
image: avatar
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
visible: parent.width > 64
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
text: name || "No Name"
|
||||
font.pointSize: 12
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
text: (lastEvent == "" ? topic : lastEvent).replace(/(\r\n\t|\n|\r\t)/gm,"")
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.NoWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
imports/Spectral/Panel/RoomListPanel.qml
Normal file
44
imports/Spectral/Panel/RoomListPanel.qml
Normal file
@@ -0,0 +1,44 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
RoomListPanelForm {
|
||||
sortedRoomListModel.proxyRoles: ExpressionRole {
|
||||
name: "display"
|
||||
expression: {
|
||||
switch (category) {
|
||||
case 1: return "Invited"
|
||||
case 2: return "Favorites"
|
||||
case 3: return "Rooms"
|
||||
case 4: return "People"
|
||||
case 5: return "Low Priority"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: StandardKey.Find
|
||||
onActivated: searchField.forceActiveFocus()
|
||||
}
|
||||
|
||||
Dialog {
|
||||
property var currentRoom
|
||||
|
||||
id: inviteDialog
|
||||
parent: ApplicationWindow.overlay
|
||||
|
||||
x: (window.width - width) / 2
|
||||
y: (window.height - height) / 2
|
||||
width: 360
|
||||
|
||||
title: "Action Required"
|
||||
modal: true
|
||||
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||
|
||||
contentItem: Label { text: "Accept this invitation?" }
|
||||
|
||||
onAccepted: currentRoom.acceptInvitation()
|
||||
onRejected: currentRoom.forget()
|
||||
}
|
||||
}
|
||||
141
imports/Spectral/Panel/RoomListPanelForm.ui.qml
Normal file
141
imports/Spectral/Panel/RoomListPanelForm.ui.qml
Normal file
@@ -0,0 +1,141 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls.Material 2.2
|
||||
import QtQml.Models 2.3
|
||||
|
||||
import Spectral.Component 2.0
|
||||
import Spectral.Menu 2.0
|
||||
import Spectral.Effect 2.0
|
||||
|
||||
import Spectral 0.1
|
||||
import Spectral.Setting 0.1
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import "qrc:/js/util.js" as Util
|
||||
|
||||
Rectangle {
|
||||
property alias listModel: sortedRoomListModel.sourceModel
|
||||
property int filter: 0
|
||||
property var enteredRoom: null
|
||||
|
||||
property alias searchField: searchField
|
||||
property alias sortedRoomListModel: sortedRoomListModel
|
||||
|
||||
color: MSettings.darkTheme ? "#323232" : "#f3f3f3"
|
||||
|
||||
Label {
|
||||
text: MSettings.miniMode ? "Empty" : "Here? No, not here."
|
||||
anchors.centerIn: parent
|
||||
visible: listView.count === 0
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
TextField {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
Layout.margins: 12
|
||||
|
||||
id: searchField
|
||||
|
||||
leftPadding: MSettings.miniMode ? 4 : 32
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
placeholderText: "Search..."
|
||||
|
||||
background: Rectangle {
|
||||
color: MSettings.darkTheme ? "#303030" : "#fafafa"
|
||||
layer.enabled: true
|
||||
layer.effect: ElevationEffect {
|
||||
elevation: searchField.focus ? 2 : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: sortedRoomListModel
|
||||
|
||||
sorters: [
|
||||
RoleSorter { roleName: "category" },
|
||||
RoleSorter {
|
||||
roleName: "lastActiveTime"
|
||||
sortOrder: Qt.DescendingOrder
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: roomListProxyModel
|
||||
|
||||
sourceModel: sortedRoomListModel
|
||||
|
||||
filters: [
|
||||
RegExpFilter {
|
||||
roleName: "name"
|
||||
pattern: searchField.text
|
||||
caseSensitivity: Qt.CaseInsensitive
|
||||
},
|
||||
ExpressionFilter {
|
||||
enabled: filter === 1
|
||||
expression: unreadCount > 0
|
||||
},
|
||||
ExpressionFilter {
|
||||
enabled: filter === 2
|
||||
expression: category === 1 || category === 2 || category === 4
|
||||
},
|
||||
ExpressionFilter {
|
||||
enabled: filter === 3
|
||||
expression: category === 3 || category === 5
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
id: listView
|
||||
|
||||
spacing: 1
|
||||
clip: true
|
||||
|
||||
model: roomListProxyModel
|
||||
|
||||
currentIndex: -1
|
||||
|
||||
highlightFollowsCurrentItem: true
|
||||
|
||||
highlightMoveDuration: 200
|
||||
highlightResizeDuration: 0
|
||||
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
|
||||
delegate: RoomListDelegate {
|
||||
width: parent.width
|
||||
height: 64
|
||||
}
|
||||
|
||||
section.property: "display"
|
||||
section.criteria: ViewSection.FullString
|
||||
section.delegate: Label {
|
||||
width: parent.width
|
||||
height: 24
|
||||
|
||||
text: section
|
||||
color: "grey"
|
||||
leftPadding: MSettings.miniMode ? undefined : 16
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: MSettings.miniMode ? Text.AlignHCenter : undefined
|
||||
}
|
||||
|
||||
RoomContextMenu { id: roomContextMenu }
|
||||
}
|
||||
}
|
||||
}
|
||||
56
imports/Spectral/Panel/RoomPanel.qml
Normal file
56
imports/Spectral/Panel/RoomPanel.qml
Normal file
@@ -0,0 +1,56 @@
|
||||
import QtQuick 2.9
|
||||
|
||||
RoomPanelForm {
|
||||
roomHeader.onClicked: roomDrawer.open()
|
||||
roomHeader.image: spectralController.safeImage(currentRoom ? currentRoom.avatar : null)
|
||||
roomHeader.topic: currentRoom ? (currentRoom.topic).replace(/(\r\n\t|\n|\r\t)/gm,"") : ""
|
||||
|
||||
sortedMessageEventModel.onModelReset: {
|
||||
if (currentRoom)
|
||||
{
|
||||
var lastScrollPosition = sortedMessageEventModel.mapFromSource(currentRoom.savedTopVisibleIndex())
|
||||
if (lastScrollPosition === 0)
|
||||
messageListView.positionViewAtBeginning()
|
||||
else
|
||||
{
|
||||
console.log("Scrolling to position", lastScrollPosition)
|
||||
messageListView.currentIndex = lastScrollPosition
|
||||
}
|
||||
if (messageListView.contentY < messageListView.originY + 10 || currentRoom.timelineSize === 0)
|
||||
currentRoom.getPreviousContent(100)
|
||||
}
|
||||
console.log("Model timeline reset")
|
||||
}
|
||||
|
||||
messageListView {
|
||||
property int largestVisibleIndex: messageListView.count > 0 ? messageListView.indexAt(messageListView.contentX, messageListView.contentY + height - 1) : -1
|
||||
|
||||
onContentYChanged: {
|
||||
if(messageListView.verticalVelocity < 0 && messageListView.contentY - 5000 < messageListView.originY)
|
||||
currentRoom.getPreviousContent(50);
|
||||
}
|
||||
|
||||
onMovementEnded: {
|
||||
currentRoom.saveViewport(sortedMessageEventModel.mapToSource(messageListView.indexAt(messageListView.contentX, messageListView.contentY)), sortedMessageEventModel.mapToSource(largestVisibleIndex))
|
||||
var newReadMarker = sortedMessageEventModel.get(largestVisibleIndex).eventId
|
||||
if (newReadMarker) currentRoom.readMarkerEventId = newReadMarker
|
||||
}
|
||||
|
||||
displaced: Transition {
|
||||
NumberAnimation {
|
||||
property: "y"; duration: 200
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goTopFab {
|
||||
onClicked: messageListView.positionViewAtBeginning()
|
||||
|
||||
Behavior on opacity { NumberAnimation { duration: 200 } }
|
||||
}
|
||||
|
||||
uploadButton.onClicked: currentRoom.chooseAndUploadFile()
|
||||
|
||||
emojiButton.onClicked: emojiPicker.visible ? emojiPicker.close() : emojiPicker.open()
|
||||
}
|
||||
364
imports/Spectral/Panel/RoomPanelForm.ui.qml
Normal file
364
imports/Spectral/Panel/RoomPanelForm.ui.qml
Normal file
@@ -0,0 +1,364 @@
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls.Material 2.2
|
||||
|
||||
import Spectral.Component 2.0
|
||||
import Spectral.Component.Emoji 2.0
|
||||
import Spectral.Component.Timeline 2.0
|
||||
import Spectral.Menu 2.0
|
||||
import Spectral.Effect 2.0
|
||||
|
||||
import Spectral 0.1
|
||||
import Spectral.Setting 0.1
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import "qrc:/js/md.js" as Markdown
|
||||
import "qrc:/js/util.js" as Util
|
||||
|
||||
Item {
|
||||
property var currentRoom: null
|
||||
|
||||
property alias roomHeader: roomHeader
|
||||
property alias messageListView: messageListView
|
||||
property alias goTopFab: goTopFab
|
||||
property alias uploadButton: uploadButton
|
||||
property alias emojiButton: emojiButton
|
||||
property alias emojiPicker: emojiPicker
|
||||
property alias sortedMessageEventModel: sortedMessageEventModel
|
||||
property alias inputField: inputField
|
||||
property alias roomDrawer: roomDrawer
|
||||
|
||||
id: root
|
||||
|
||||
MessageEventModel {
|
||||
id: messageEventModel
|
||||
room: currentRoom
|
||||
}
|
||||
|
||||
RoomDrawer {
|
||||
width: Math.min(root.width * 0.7, 480)
|
||||
height: root.height
|
||||
|
||||
id: roomDrawer
|
||||
|
||||
room: currentRoom
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
visible: !currentRoom
|
||||
text: "Please choose a room."
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
visible: currentRoom
|
||||
|
||||
RoomHeader {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 64
|
||||
z: 10
|
||||
|
||||
id: roomHeader
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
Layout.fillWidth: true
|
||||
z: 10
|
||||
|
||||
visible: currentRoom && currentRoom.busy
|
||||
indeterminate: true
|
||||
}
|
||||
|
||||
ListView {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
id: messageListView
|
||||
|
||||
displayMarginBeginning: 40
|
||||
displayMarginEnd: 40
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
spacing: 8
|
||||
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
id: sortedMessageEventModel
|
||||
|
||||
sourceModel: messageEventModel
|
||||
|
||||
filters: ExpressionFilter {
|
||||
expression: marks !== 0x08 && marks !== 0x10
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ColumnLayout {
|
||||
width: parent.width
|
||||
|
||||
id: delegateColumn
|
||||
|
||||
spacing: 8
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
visible: section !== aboveSection
|
||||
|
||||
text: section
|
||||
color: "white"
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: 8
|
||||
rightPadding: 8
|
||||
topPadding: 4
|
||||
bottomPadding: 4
|
||||
|
||||
background: Rectangle {
|
||||
color: MSettings.darkTheme ? "#484848" : "grey"
|
||||
}
|
||||
}
|
||||
|
||||
MessageDelegate {
|
||||
visible: eventType === "notice" || eventType === "message"
|
||||
|| eventType === "image" || eventType === "video"
|
||||
|| eventType === "audio" || eventType === "file"
|
||||
}
|
||||
|
||||
StateDelegate {
|
||||
Layout.maximumWidth: messageListView.width * 0.8
|
||||
|
||||
visible: eventType === "emote" || eventType === "state"
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
visible: eventType === "other"
|
||||
|
||||
text: display
|
||||
color: "grey"
|
||||
font.italic: true
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
visible: readMarker === true && index !== 0
|
||||
|
||||
text: "And Now"
|
||||
color: "white"
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
leftPadding: 8
|
||||
rightPadding: 8
|
||||
topPadding: 4
|
||||
bottomPadding: 4
|
||||
|
||||
background: Rectangle {
|
||||
color: MSettings.darkTheme ? "#484848" : "grey"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RoundButton {
|
||||
width: 64
|
||||
height: 64
|
||||
|
||||
id: goTopFab
|
||||
|
||||
visible: !(parent.atYEnd || messageListView.moving)
|
||||
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
contentItem: MaterialIcon {
|
||||
anchors.fill: parent
|
||||
|
||||
icon: "\ue313"
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Material.background: Material.accent
|
||||
}
|
||||
|
||||
MessageContextMenu {
|
||||
id: messageContextMenu
|
||||
}
|
||||
|
||||
Popup {
|
||||
property string sourceText
|
||||
|
||||
x: (window.width - width) / 2
|
||||
y: (window.height - height) / 2
|
||||
width: 480
|
||||
|
||||
id: sourceDialog
|
||||
|
||||
parent: ApplicationWindow.overlay
|
||||
|
||||
modal: true
|
||||
|
||||
padding: 16
|
||||
|
||||
closePolicy: Dialog.CloseOnEscape | Dialog.CloseOnPressOutside
|
||||
|
||||
contentItem: ScrollView {
|
||||
TextArea {
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
|
||||
text: sourceDialog.sourceText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Popup {
|
||||
property alias listModel: readMarkerListView.model
|
||||
|
||||
x: (window.width - width) / 2
|
||||
y: (window.height - height) / 2
|
||||
width: 320
|
||||
|
||||
id: readMarkerDialog
|
||||
|
||||
parent: ApplicationWindow.overlay
|
||||
|
||||
modal: true
|
||||
padding: 16
|
||||
|
||||
closePolicy: Dialog.CloseOnEscape | Dialog.CloseOnPressOutside
|
||||
|
||||
contentItem: ListView {
|
||||
implicitHeight: Math.min(window.height - 64,
|
||||
readMarkerListView.contentHeight)
|
||||
|
||||
id: readMarkerListView
|
||||
|
||||
clip: true
|
||||
boundsBehavior: Flickable.DragOverBounds
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: parent.width
|
||||
height: 48
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 8
|
||||
spacing: 12
|
||||
|
||||
ImageItem {
|
||||
Layout.preferredWidth: height
|
||||
Layout.fillHeight: true
|
||||
|
||||
image: modelData.avatar
|
||||
hint: modelData.displayName
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: modelData.displayName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
color: Material.background
|
||||
|
||||
Rectangle {
|
||||
anchors.verticalCenter: parent.top
|
||||
width: parent.width
|
||||
height: 48
|
||||
|
||||
color: MSettings.darkTheme ? "#303030" : "#fafafa"
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: ElevationEffect {
|
||||
elevation: 2
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 0
|
||||
|
||||
ItemDelegate {
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
|
||||
id: uploadButton
|
||||
|
||||
contentItem: MaterialIcon {
|
||||
icon: "\ue226"
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 48
|
||||
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
clip: true
|
||||
|
||||
AutoTextArea {
|
||||
id: inputField
|
||||
}
|
||||
}
|
||||
|
||||
ItemDelegate {
|
||||
Layout.preferredWidth: 48
|
||||
Layout.preferredHeight: 48
|
||||
|
||||
id: emojiButton
|
||||
|
||||
contentItem: MaterialIcon {
|
||||
icon: "\ue24e"
|
||||
}
|
||||
|
||||
EmojiPicker {
|
||||
x: window.width - 370
|
||||
y: window.height - 400
|
||||
|
||||
width: 360
|
||||
height: 320
|
||||
|
||||
id: emojiPicker
|
||||
|
||||
parent: ApplicationWindow.overlay
|
||||
|
||||
Material.elevation: 2
|
||||
|
||||
textArea: inputField
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*##^## Designer {
|
||||
D{i:0;autoSize:true;height:480;width:640}
|
||||
}
|
||||
##^##*/
|
||||
3
imports/Spectral/Panel/qmldir
Normal file
3
imports/Spectral/Panel/qmldir
Normal file
@@ -0,0 +1,3 @@
|
||||
module Spectral.Panel
|
||||
RoomPanel 2.0 RoomPanel.qml
|
||||
RoomListPanel 2.0 RoomListPanel.qml
|
||||
Reference in New Issue
Block a user