Room Drawer Media Tab
Add a tab bar to the room drawer which includes a new media tab in addition to the room information tab. This mr completes the architecture for adding others easily later e.g. message highlights or threads. To put this together I had to make sure things like the menus and the maximize delegate were available to both the room drawer and page so there is some rework there to put it all together. Wide\  Mobile\ 
This commit is contained in:
@@ -100,6 +100,11 @@ Components.AlbumMaximizeComponent {
|
||||
dialog.currentFile = dialog.folder + "/" + currentRoom.fileNameToDownload(root.currentEventId)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fileDelegateContextMenu
|
||||
FileDelegateContextMenu {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: saveAsDialog
|
||||
Platform.FileDialog {
|
||||
|
||||
@@ -129,13 +129,19 @@ TimelineContainer {
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
gesturePolicy: TapHandler.ReleaseWithinBounds | TapHandler.WithinBounds
|
||||
onTapped: {
|
||||
imageContainer.QQC2.ToolTip.hide()
|
||||
if (root.mediaInfo.animated) {
|
||||
imageContainer.imageItem.paused = true
|
||||
}
|
||||
root.ListView.view.interactive = false
|
||||
root.ListView.view.showMaximizedMedia(root.index)
|
||||
// We need to make sure the index is that of the MediaMessageFilterModel.
|
||||
if (root.ListView.view.model instanceof MessageFilterModel) {
|
||||
RoomManager.maximizeMedia(RoomManager.mediaMessageFilterModel.getRowForSourceItem(root.index))
|
||||
} else {
|
||||
RoomManager.maximizeMedia(root.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +150,7 @@ TimelineContainer {
|
||||
openSavedFile()
|
||||
} else {
|
||||
openOnFinished = true
|
||||
currentRoom.downloadFile(root.eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + root.eventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(root.eventId))
|
||||
ListView.view.currentRoom.downloadFile(root.eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + root.eventId.replace(":", "_").replace("/", "_").replace("+", "_") + ListView.view.currentRoom.fileNameToDownload(root.eventId))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ QQC2.ItemDelegate {
|
||||
property alias labelText: sectionLabel.text
|
||||
property var maxWidth: Number.POSITIVE_INFINITY
|
||||
|
||||
property int colorSet: Kirigami.Theme.Window
|
||||
|
||||
topPadding: Kirigami.Units.largeSpacing
|
||||
bottomPadding: 0 // Note not 0 by default
|
||||
|
||||
@@ -42,6 +44,6 @@ QQC2.ItemDelegate {
|
||||
background: Rectangle {
|
||||
color: Config.blur ? "transparent" : Kirigami.Theme.backgroundColor
|
||||
Kirigami.Theme.inherit: false
|
||||
Kirigami.Theme.colorSet: Config.compactLayout ? Kirigami.Theme.View : Kirigami.Theme.Window
|
||||
Kirigami.Theme.colorSet: sectionDelegate.colorSet
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,16 @@ ColumnLayout {
|
||||
*/
|
||||
required property bool showAuthor
|
||||
|
||||
/**
|
||||
* @brief Whether the author should always be shown.
|
||||
*
|
||||
* This is primarily used when these delegates are used in a filtered list of
|
||||
* events rather than a sequential timeline, e.g. the media model view.
|
||||
*
|
||||
* @note This setting still respects the avatar configuration settings.
|
||||
*/
|
||||
property bool alwaysShowAuthor: false
|
||||
|
||||
/**
|
||||
* @brief The delegate type of the message.
|
||||
*/
|
||||
@@ -262,12 +272,17 @@ ColumnLayout {
|
||||
*/
|
||||
property bool cardBackground: true
|
||||
|
||||
/**
|
||||
* @brief Whether the delegate should always stretch to the maximum availabel width.
|
||||
*/
|
||||
property bool alwaysMaxWidth: false
|
||||
|
||||
/**
|
||||
* @brief Whether local user messages should be aligned right.
|
||||
*
|
||||
* TODO: make private
|
||||
*/
|
||||
property bool showUserMessageOnRight: Config.showLocalMessagesOnRight && root.author.isLocalUser && !Config.compactLayout
|
||||
property bool showUserMessageOnRight: Config.showLocalMessagesOnRight && root.author.isLocalUser && !Config.compactLayout && !alwaysMaxWidth
|
||||
|
||||
/**
|
||||
* @brief Whether the message should be highlighted.
|
||||
@@ -296,7 +311,7 @@ ColumnLayout {
|
||||
width: parent ? timelineDelegateSizeHelper.currentWidth : 0
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
state: Config.compactLayout ? "alignLeft" : "alignCenter"
|
||||
state: Config.compactLayout || root.alwaysMaxWidth ? "alignLeft" : "alignCenter"
|
||||
// Align left when in compact mode and center when using bubbles
|
||||
states: [
|
||||
State {
|
||||
@@ -325,21 +340,21 @@ ColumnLayout {
|
||||
|
||||
SectionDelegate {
|
||||
id: sectionDelegate
|
||||
|
||||
Layout.fillWidth: true
|
||||
visible: root.showSection
|
||||
labelText: root.section
|
||||
colorSet: Config.compactLayout || root.alwaysMaxWidth ? Kirigami.Theme.View : Kirigami.Theme.Window
|
||||
}
|
||||
|
||||
QQC2.ItemDelegate {
|
||||
id: mainContainer
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: root.showAuthor ? Kirigami.Units.largeSpacing : (Config.compactLayout ? 1 : Kirigami.Units.smallSpacing)
|
||||
Layout.topMargin: root.showAuthor || root.alwaysShowAuthor ? Kirigami.Units.largeSpacing : (Config.compactLayout ? 1 : Kirigami.Units.smallSpacing)
|
||||
Layout.leftMargin: Kirigami.Units.smallSpacing
|
||||
Layout.rightMargin: Kirigami.Units.smallSpacing
|
||||
|
||||
implicitHeight: Math.max(root.showAuthor ? avatar.implicitHeight : 0, bubble.height)
|
||||
implicitHeight: Math.max(root.showAuthor || root.alwaysShowAuthor ? avatar.implicitHeight : 0, bubble.height)
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.isReply && root.reply === undefined) {
|
||||
@@ -365,7 +380,7 @@ ColumnLayout {
|
||||
topMargin: Kirigami.Units.smallSpacing
|
||||
}
|
||||
|
||||
visible: root.showAuthor &&
|
||||
visible: (root.showAuthor || root.alwaysShowAuthor) &&
|
||||
Config.showAvatarInTimeline &&
|
||||
(Config.compactLayout || !showUserMessageOnRight)
|
||||
name: root.author.displayName
|
||||
@@ -395,7 +410,7 @@ ColumnLayout {
|
||||
rightMargin: Kirigami.Units.largeSpacing
|
||||
}
|
||||
// HACK: anchoring didn't reset anchors.right when switching from parent.right to undefined reliably
|
||||
width: Config.compactLayout ? mainContainer.width - (Config.showAvatarInTimeline ? Kirigami.Units.gridUnit * 2 : 0) + Kirigami.Units.largeSpacing * 2 : implicitWidth
|
||||
width: Config.compactLayout || root.alwaysMaxWidth ? mainContainer.width - (Config.showAvatarInTimeline ? Kirigami.Units.gridUnit * 2 : 0) + Kirigami.Units.largeSpacing * 2 : implicitWidth
|
||||
|
||||
state: showUserMessageOnRight ? "userMessageOnRight" : "userMessageOnLeft"
|
||||
// states for anchor animations on window resize
|
||||
@@ -440,7 +455,7 @@ ColumnLayout {
|
||||
id: rowLayout
|
||||
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
visible: root.showAuthor
|
||||
visible: root.showAuthor || root.alwaysShowAuthor
|
||||
|
||||
QQC2.Label {
|
||||
id: nameLabel
|
||||
@@ -535,7 +550,7 @@ ColumnLayout {
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
visible: mainContainer.hovered && Config.compactLayout
|
||||
visible: mainContainer.hovered && (Config.compactLayout || root.alwaysMaxWidth)
|
||||
color: Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15)
|
||||
radius: Kirigami.Units.smallSpacing
|
||||
}
|
||||
@@ -577,6 +592,16 @@ ColumnLayout {
|
||||
return (yoff + height > 0 && yoff < ListView.view.height)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: messageDelegateContextMenu
|
||||
MessageDelegateContextMenu {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fileDelegateContextMenu
|
||||
FileDelegateContextMenu {}
|
||||
}
|
||||
|
||||
/// Open message context dialog for file and videos
|
||||
function openFileContext(file) {
|
||||
const contextMenu = fileDelegateContextMenu.createObject(root, {
|
||||
@@ -616,8 +641,8 @@ ColumnLayout {
|
||||
startBreakpoint: Kirigami.Units.gridUnit * 46
|
||||
endBreakpoint: Kirigami.Units.gridUnit * 66
|
||||
startPercentWidth: 100
|
||||
endPercentWidth: Config.compactLayout ? 100 : 85
|
||||
maxWidth: Config.compactLayout ? -1 : Kirigami.Units.gridUnit * 60
|
||||
endPercentWidth: Config.compactLayout || root.alwaysMaxWidth ? 100 : 85
|
||||
maxWidth: Config.compactLayout || root.alwaysMaxWidth ? -1 : Kirigami.Units.gridUnit * 60
|
||||
|
||||
parentWidth: root.parent ? root.parent.width - (Config.compactLayout && root.ListView.view.width >= Kirigami.Units.gridUnit * 20 ? Kirigami.Units.gridUnit * 2 + Kirigami.Units.largeSpacing : 0) : 0
|
||||
}
|
||||
@@ -625,8 +650,8 @@ ColumnLayout {
|
||||
id: bubbleSizeHelper
|
||||
startBreakpoint: Kirigami.Units.gridUnit * 25
|
||||
endBreakpoint: Kirigami.Units.gridUnit * 40
|
||||
startPercentWidth: Config.compactLayout ? 100 : 90
|
||||
endPercentWidth: Config.compactLayout ? 100 : 60
|
||||
startPercentWidth: Config.compactLayout || root.alwaysMaxWidth ? 100 : 90
|
||||
endPercentWidth: Config.compactLayout || root.alwaysMaxWidth ? 100 : 60
|
||||
|
||||
parentWidth: mainContainer.availableWidth - (Config.showAvatarInTimeline ? avatar.width + bubble.anchors.leftMargin : 0)
|
||||
}
|
||||
|
||||
@@ -292,7 +292,12 @@ TimelineContainer {
|
||||
onTriggered: {
|
||||
root.ListView.view.interactive = false
|
||||
vid.pause()
|
||||
root.ListView.view.showMaximizedMedia(root.index)
|
||||
// We need to make sure the index is that of the MediaMessageFilterModel.
|
||||
if (root.ListView.view.model instanceof MessageFilterModel) {
|
||||
RoomManager.maximizeMedia(RoomManager.mediaMessageFilterModel.getRowForSourceItem(root.index))
|
||||
} else {
|
||||
RoomManager.maximizeMedia(root.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,6 +333,7 @@ TimelineContainer {
|
||||
|
||||
TapHandler {
|
||||
acceptedButtons: Qt.LeftButton
|
||||
gesturePolicy: TapHandler.ReleaseWithinBounds | TapHandler.WithinBounds
|
||||
onTapped: if (root.progressInfo.completed) {
|
||||
if (vid.playbackState == MediaPlayer.PlayingState) {
|
||||
vid.pause()
|
||||
@@ -352,7 +358,7 @@ TimelineContainer {
|
||||
playSavedFile()
|
||||
} else {
|
||||
playOnFinished = true
|
||||
currentRoom.downloadFile(root.eventId, Platform.StandardPaths.writableLocation(Platform.StandardPaths.CacheLocation) + "/" + root.eventId.replace(":", "_").replace("/", "_").replace("+", "_") + currentRoom.fileNameToDownload(root.eventId))
|
||||
ListView.view.currentRoom.downloadFile(root.eventId, Platform.StandardPaths.writableLocation(Platform.StandardPaths.CacheLocation) + "/" + root.eventId.replace(":", "_").replace("/", "_").replace("+", "_") + ListView.view.currentRoom.fileNameToDownload(root.eventId))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,9 @@ QQC2.ScrollView {
|
||||
|
||||
ListView {
|
||||
id: messageListView
|
||||
// So that delegates can access the current room properly.
|
||||
readonly property NeoChatRoom currentRoom: root.currentRoom
|
||||
|
||||
readonly property int largestVisibleIndex: count > 0 ? indexAt(contentX + (width / 2), contentY + height - 1) : -1
|
||||
readonly property var sectionBannerItem: contentHeight >= height ? itemAtIndex(sectionBannerIndex()) : undefined
|
||||
|
||||
@@ -47,33 +50,23 @@ QQC2.ScrollView {
|
||||
interactive: Kirigami.Settings.isMobile
|
||||
bottomMargin: Kirigami.Units.largeSpacing + Math.round(Kirigami.Theme.defaultFont.pointSize * 2)
|
||||
|
||||
model: sortedMessageEventModel
|
||||
|
||||
MessageEventModel {
|
||||
id: messageEventModel
|
||||
room: root.currentRoom
|
||||
}
|
||||
|
||||
MessageFilterModel {
|
||||
id: sortedMessageEventModel
|
||||
sourceModel: messageEventModel
|
||||
}
|
||||
model: RoomManager.messageFilterModel
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: messageListView.atYBeginning
|
||||
triggeredOnStart: true
|
||||
onTriggered: {
|
||||
if (messageListView.atYBeginning && messageEventModel.canFetchMore(messageEventModel.index(0, 0))) {
|
||||
messageEventModel.fetchMore(messageEventModel.index(0, 0));
|
||||
if (messageListView.atYBeginning && RoomManager.messageEventModel.canFetchMore(RoomManager.messageEventModel.index(0, 0))) {
|
||||
RoomManager.messageEventModel.fetchMore(RoomManager.messageEventModel.index(0, 0));
|
||||
}
|
||||
}
|
||||
repeat: true
|
||||
}
|
||||
|
||||
// HACK: The view should do this automatically but doesn't.
|
||||
onAtYBeginningChanged: if (atYBeginning && messageEventModel.canFetchMore(messageEventModel.index(0, 0))) {
|
||||
messageEventModel.fetchMore(messageEventModel.index(0, 0));
|
||||
onAtYBeginningChanged: if (atYBeginning && RoomManager.messageEventModel.canFetchMore(RoomManager.messageEventModel.index(0, 0))) {
|
||||
RoomManager.messageEventModel.fetchMore(RoomManager.messageEventModel.index(0, 0));
|
||||
}
|
||||
|
||||
Timer {
|
||||
@@ -207,18 +200,6 @@ QQC2.ScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: messageDelegateContextMenu
|
||||
|
||||
MessageDelegateContextMenu {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fileDelegateContextMenu
|
||||
|
||||
FileDelegateContextMenu {}
|
||||
}
|
||||
|
||||
TypingPane {
|
||||
id: typingPane
|
||||
visible: root.currentRoom && root.currentRoom.usersTyping.length > 0
|
||||
@@ -285,7 +266,7 @@ QQC2.ScrollView {
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: messageEventModel
|
||||
target: RoomManager.messageEventModel
|
||||
|
||||
function onRowsInserted() {
|
||||
markReadIfVisibleTimer.restart()
|
||||
@@ -326,7 +307,7 @@ QQC2.ScrollView {
|
||||
|
||||
Connections {
|
||||
//enabled: Config.showFancyEffects
|
||||
target: messageEventModel
|
||||
target: RoomManager.messageEventModel
|
||||
|
||||
function onFancyEffectsReasonFound(fancyEffect) {
|
||||
fancyEffectsContainer.processFancyEffectsReason(fancyEffect)
|
||||
@@ -344,21 +325,23 @@ QQC2.ScrollView {
|
||||
}
|
||||
}
|
||||
|
||||
MediaMessageFilterModel {
|
||||
id: mediaMessageFilterModel
|
||||
sourceModel: sortedMessageEventModel
|
||||
}
|
||||
|
||||
Component {
|
||||
id: maximizeComponent
|
||||
NeochatMaximizeComponent {
|
||||
model: mediaMessageFilterModel
|
||||
model: RoomManager.mediaMessageFilterModel
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: RoomManager
|
||||
function onShowMaximizedMedia(index) {
|
||||
messageListView.showMaximizedMedia(index)
|
||||
}
|
||||
}
|
||||
|
||||
function showMaximizedMedia(index) {
|
||||
var popup = maximizeComponent.createObject(QQC2.ApplicationWindow.overlay, {
|
||||
initialIndex: index === -1 ? -1 : mediaMessageFilterModel.getRowForSourceItem(index)
|
||||
initialIndex: index
|
||||
})
|
||||
popup.closed.connect(() => {
|
||||
messageListView.interactive = true
|
||||
@@ -374,10 +357,10 @@ QQC2.ScrollView {
|
||||
}
|
||||
|
||||
function eventToIndex(eventID) {
|
||||
const index = messageEventModel.eventIdToRow(eventID)
|
||||
const index = RoomManager.messageEventModel.eventIdToRow(eventID)
|
||||
if (index === -1)
|
||||
return -1
|
||||
return sortedMessageEventModel.mapFromSource(messageEventModel.index(index, 0)).row
|
||||
return RoomManager.messageFilterModel.mapFromSource(RoomManager.messageEventModel.index(index, 0)).row
|
||||
}
|
||||
|
||||
function firstVisibleIndex() {
|
||||
|
||||
Reference in New Issue
Block a user