Loading and End of Timeline Delegates
Add delegate for showing the user a loading indicator and for the beginning of the timeline. BUG: 455045 BUG: 465285
This commit is contained in:
@@ -99,6 +99,7 @@ DelegateChooser {
|
||||
connection: root.connection
|
||||
}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: DelegateType.LiveLocation
|
||||
delegate: LiveLocationDelegate {
|
||||
@@ -107,6 +108,18 @@ DelegateChooser {
|
||||
}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: DelegateType.Loading
|
||||
delegate: LoadingDelegate {}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: DelegateType.TimelineEnd
|
||||
delegate: TimelineEndDelegate {
|
||||
room: root.room
|
||||
}
|
||||
}
|
||||
|
||||
DelegateChoice {
|
||||
roleValue: DelegateType.Other
|
||||
delegate: Item {}
|
||||
|
||||
15
src/qml/LoadingDelegate.qml
Normal file
15
src/qml/LoadingDelegate.qml
Normal file
@@ -0,0 +1,15 @@
|
||||
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
TimelineDelegate {
|
||||
id: root
|
||||
contentItem: Kirigami.PlaceholderMessage {
|
||||
text: i18n("Loading…")
|
||||
}
|
||||
}
|
||||
@@ -23,17 +23,17 @@ Kirigami.Page {
|
||||
required property NeoChatConnection connection
|
||||
|
||||
/**
|
||||
* @brief The MessageEventModel to use.
|
||||
* @brief The TimelineModel to use.
|
||||
*
|
||||
* Required so that new events can be requested when the end of the current
|
||||
* local timeline is reached.
|
||||
*
|
||||
* @note For loading a room in a different window, override this with a new
|
||||
* MessageEventModel set with the room to be shown.
|
||||
* TimelineModel set with the room to be shown.
|
||||
*
|
||||
* @sa MessageEventModel
|
||||
* @sa TimelineModel
|
||||
*/
|
||||
property MessageEventModel messageEventModel: RoomManager.messageEventModel
|
||||
property TimelineModel timelineModel: RoomManager.timelineModel
|
||||
|
||||
/**
|
||||
* @brief The MessageFilterModel to use.
|
||||
@@ -41,9 +41,9 @@ Kirigami.Page {
|
||||
* This model has the filtered list of events that should be shown in the timeline.
|
||||
*
|
||||
* @note For loading a room in a different window, override this with a new
|
||||
* MessageFilterModel with the new MessageEventModel as the source model.
|
||||
* MessageFilterModel with the new TimelineModel as the source model.
|
||||
*
|
||||
* @sa MessageEventModel, MessageFilterModel
|
||||
* @sa TimelineModel, MessageFilterModel
|
||||
*/
|
||||
property MessageFilterModel messageFilterModel: RoomManager.messageFilterModel
|
||||
|
||||
@@ -56,7 +56,7 @@ Kirigami.Page {
|
||||
* @note For loading a room in a different window, override this with a new
|
||||
* MediaMessageFilterModel with the new MessageFilterModel as the source model.
|
||||
*
|
||||
* @sa MessageEventModel, MessageFilterModel
|
||||
* @sa TimelineModel, MessageFilterModel
|
||||
*/
|
||||
property MediaMessageFilterModel mediaMessageFilterModel: RoomManager.mediaMessageFilterModel
|
||||
|
||||
@@ -120,7 +120,7 @@ Kirigami.Page {
|
||||
sourceComponent: TimelineView {
|
||||
id: timelineView
|
||||
currentRoom: root.currentRoom
|
||||
messageEventModel: root.messageEventModel
|
||||
timelineModel: root.timelineModel
|
||||
messageFilterModel: root.messageFilterModel
|
||||
actionsHandler: root.actionsHandler
|
||||
onFocusChatBar: {
|
||||
|
||||
@@ -29,7 +29,7 @@ Kirigami.ApplicationWindow {
|
||||
disableCancelShortcut: true
|
||||
connection: root.connection
|
||||
|
||||
messageEventModel: MessageEventModel {
|
||||
timelineModel: TimelineModel {
|
||||
room: currentRoom
|
||||
}
|
||||
messageFilterModel: MessageFilterModel {
|
||||
|
||||
90
src/qml/TimelineEndDelegate.qml
Normal file
90
src/qml/TimelineEndDelegate.qml
Normal file
@@ -0,0 +1,90 @@
|
||||
// SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
import org.kde.kirigami as Kirigami
|
||||
import org.kde.kirigamiaddons.labs.components as KirigamiComponents
|
||||
|
||||
import org.kde.neochat
|
||||
|
||||
TimelineDelegate {
|
||||
id: root
|
||||
|
||||
/**
|
||||
* @brief The current room that user is viewing.
|
||||
*/
|
||||
required property NeoChatRoom room
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
RowLayout {
|
||||
Layout.topMargin: Kirigami.Units.largeSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
KirigamiComponents.Avatar {
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.large
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.large
|
||||
|
||||
name: root.room ? root.room.displayName : ""
|
||||
source: root.room && root.room.avatarMediaId ? ("image://mxc/" + root.room.avatarMediaId) : ""
|
||||
|
||||
Rectangle {
|
||||
visible: room.usesEncryption
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
radius: Math.round(width / 2)
|
||||
|
||||
Kirigami.Icon {
|
||||
source: "channel-secure-symbolic"
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
spacing: 0
|
||||
|
||||
Kirigami.Heading {
|
||||
Layout.fillWidth: true
|
||||
text: root.room ? root.room.displayName : i18n("No name")
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
Kirigami.SelectableLabel {
|
||||
Layout.fillWidth: true
|
||||
font: Kirigami.Theme.smallFont
|
||||
textFormat: TextEdit.PlainText
|
||||
visible: root.room && root.room.canonicalAlias
|
||||
text: root.room && root.room.canonicalAlias ? root.room.canonicalAlias : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.SelectableLabel {
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Kirigami.Units.largeSpacing
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing
|
||||
|
||||
text: i18n("This is the beginning of the chat. There are no historical messages beyond this point.")
|
||||
wrapMode: Text.Wrap
|
||||
onLinkActivated: link => UrlHelper.openUrl(link)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,12 +28,12 @@ QQC2.ScrollView {
|
||||
property bool roomChanging: false
|
||||
|
||||
/**
|
||||
* @brief The MessageEventModel to use.
|
||||
* @brief The TimelineModel to use.
|
||||
*
|
||||
* Required so that new events can be requested when the end of the current
|
||||
* local timeline is reached.
|
||||
*/
|
||||
required property MessageEventModel messageEventModel
|
||||
required property TimelineModel timelineModel
|
||||
|
||||
/**
|
||||
* @brief The MessageFilterModel to use.
|
||||
@@ -85,16 +85,16 @@ QQC2.ScrollView {
|
||||
running: messageListView.atYBeginning
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
if (messageListView.atYBeginning && root.messageEventModel.canFetchMore(root.messageEventModel.index(0, 0))) {
|
||||
root.messageEventModel.fetchMore(root.messageEventModel.index(0, 0));
|
||||
if (messageListView.atYBeginning && root.timelineModel.messageEventModel.canFetchMore(root.timelineModel.index(0, 0))) {
|
||||
root.timelineModel.messageEventModel.fetchMore(root.timelineModel.index(0, 0));
|
||||
}
|
||||
}
|
||||
repeat: true
|
||||
}
|
||||
|
||||
// HACK: The view should do this automatically but doesn't.
|
||||
onAtYBeginningChanged: if (atYBeginning && root.messageEventModel.canFetchMore(root.messageEventModel.index(0, 0))) {
|
||||
root.messageEventModel.fetchMore(root.messageEventModel.index(0, 0));
|
||||
onAtYBeginningChanged: if (atYBeginning && root.timelineModel.messageEventModel.canFetchMore(root.timelineModel.index(0, 0))) {
|
||||
root.timelineModel.messageEventModel.fetchMore(root.timelineModel.index(0, 0));
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -270,7 +270,7 @@ QQC2.ScrollView {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.messageEventModel
|
||||
target: root.timelineModel
|
||||
|
||||
function onRowsInserted() {
|
||||
markReadIfVisibleTimer.restart()
|
||||
@@ -311,7 +311,7 @@ QQC2.ScrollView {
|
||||
|
||||
Connections {
|
||||
//enabled: Config.showFancyEffects
|
||||
target: root.messageEventModel
|
||||
target: root.timelineModel.messageEventModel
|
||||
|
||||
function onFancyEffectsReasonFound(fancyEffect) {
|
||||
fancyEffectsContainer.processFancyEffectsReason(fancyEffect)
|
||||
@@ -336,10 +336,10 @@ QQC2.ScrollView {
|
||||
}
|
||||
|
||||
function eventToIndex(eventID) {
|
||||
const index = root.messageEventModel.eventIdToRow(eventID)
|
||||
const index = root.timelineModel.messageEventModel.eventIdToRow(eventID)
|
||||
if (index === -1)
|
||||
return -1
|
||||
return root.messageFilterModel.mapFromSource(root.messageEventModel.index(index, 0)).row
|
||||
return root.messageFilterModel.mapFromSource(root.timelineModel.index(index, 0)).row
|
||||
}
|
||||
|
||||
function firstVisibleIndex() {
|
||||
|
||||
Reference in New Issue
Block a user