Support pinning thread messages (media)
This commit is contained in:
parent
d3ffc3d15b
commit
5e1223fc01
10 changed files with 152 additions and 27 deletions
|
|
@ -727,6 +727,11 @@ export default {
|
|||
// Filter out relations and redactions
|
||||
events = this.events.toReversed().filter((e) => !e.isRelation() && !e.isRedaction());
|
||||
|
||||
// If Channel, remove all redacted events as well.
|
||||
if (this.room && this.room.displayType == ROOM_TYPE_CHANNEL) {
|
||||
events = events.filter((e) => !e.isRedacted());
|
||||
}
|
||||
|
||||
// Add read marker, if it is not newer than the "latest" message we are going to display
|
||||
//
|
||||
let showReadMarker = false;
|
||||
|
|
@ -981,20 +986,22 @@ export default {
|
|||
|
||||
// Handle pinning
|
||||
//
|
||||
const pinnedEvents = this.$matrix.getPinnedEvents(this.room);
|
||||
console.log("Pinned events in room", JSON.stringify(pinnedEvents));
|
||||
events.forEach((e) => {
|
||||
Vue.set(e, "isPinned", pinnedEvents.includes(e.getId()));
|
||||
});
|
||||
updated = updated.sort((e1, e2) => {
|
||||
if (!e1.isPinned && !e2.isPinned) return 0;
|
||||
else if (e1.isPinned && !e2.isPinned) return this.reverseOrder ? 1 : -1;
|
||||
else if (e2.isPinned && !e1.isPinned) return this.reverseOrder ? -1 : 1;
|
||||
else {
|
||||
// Look at order in "pinned" value in the m.room.pinned_events event!
|
||||
return pinnedEvents.indexOf(e1.getId()) < pinnedEvents.indexOf(e2.getId()) ? (this.reverseOrder ? 1 : -1) : (this.reverseOrder ? -1 : 1)
|
||||
}
|
||||
});
|
||||
if (this.room) {
|
||||
const pinnedEvents = this.$matrix.getPinnedEvents(this.room);
|
||||
updated.forEach((e) => {
|
||||
Vue.set(e, "isPinned", pinnedEvents.includes(e.threadParent ? e.threadParent.getId() : e.getId()));
|
||||
});
|
||||
|
||||
updated = updated.sort((e1, e2) => {
|
||||
if (!e1.isPinned && !e2.isPinned) return 0;
|
||||
else if (e1.isPinned && !e2.isPinned) return this.reverseOrder ? 1 : -1;
|
||||
else if (e2.isPinned && !e1.isPinned) return this.reverseOrder ? -1 : 1;
|
||||
else {
|
||||
// Look at order in "pinned" value in the m.room.pinned_events event!
|
||||
return pinnedEvents.indexOf(e1.getId()) < pinnedEvents.indexOf(e2.getId()) ? (this.reverseOrder ? 1 : -1) : (this.reverseOrder ? -1 : 1)
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!onlyIfLengthChanges || updated.length != this.events.length) {
|
||||
this.events = updated; // Changed
|
||||
}
|
||||
|
|
@ -1781,11 +1788,13 @@ export default {
|
|||
},
|
||||
|
||||
pin(event) {
|
||||
this.$matrix.setEventPinned(this.room, event, true);
|
||||
const eventToPin = event.parentThread ? event.parentThread : event;
|
||||
this.$matrix.setEventPinned(this.room, eventToPin, true);
|
||||
},
|
||||
|
||||
unpin(event) {
|
||||
this.$matrix.setEventPinned(this.room, event, false);
|
||||
const eventToUnpin = event.parentThread ? event.parentThread : event;
|
||||
this.$matrix.setEventPinned(this.room, eventToUnpin, false);
|
||||
},
|
||||
|
||||
cancelEditReply() {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<span ref="messageInOutRef" class="content">
|
||||
<slot></slot>
|
||||
</span>
|
||||
<div class="pin-icon" v-if="event.isPinned"><v-icon>$vuetify.icons.ic_pin_filled</v-icon></div>
|
||||
<div class="pin-icon" v-if="isPinned"><v-icon>$vuetify.icons.ic_pin_filled</v-icon></div>
|
||||
<div class="op-button" ref="opbutton" v-if="!event.isRedacted() && room.displayType != ROOM_TYPE_CHANNEL">
|
||||
<v-btn id="btn-more" icon @click.stop="showContextMenu($refs.opbutton)">
|
||||
<v-icon>more_vert</v-icon>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
</div>
|
||||
|
||||
<div class="message">
|
||||
<v-container v-if="!event.isRedacted()" fluid class="imageCollection">
|
||||
<SwipeableThumbnailsView :items="items" v-if="!event.isRedacted() && room.displayType == ROOM_TYPE_CHANNEL" />
|
||||
<v-container v-else-if="!event.isRedacted()" fluid class="imageCollection">
|
||||
<v-row wrap>
|
||||
<v-col v-for="({ size, item }) in layoutedItems()" :key="item.event.getId()" :cols="size">
|
||||
<ThumbnailView :item="item" :previewOnly="true" v-on:itemclick="onItemClick($event)" />
|
||||
|
|
@ -38,16 +39,18 @@
|
|||
<script>
|
||||
import MessageIncoming from "./MessageIncoming.vue";
|
||||
import messageMixin from "./messageMixin";
|
||||
import util from "../../plugins/utils";
|
||||
import util, { ROOM_TYPE_CHANNEL } from "../../plugins/utils";
|
||||
import GalleryItemsView from '../file_mode/GalleryItemsView.vue';
|
||||
import ThumbnailView from '../file_mode/ThumbnailView.vue';
|
||||
import SwipeableThumbnailsView from "./channel/SwipeableThumbnailsView.vue";
|
||||
|
||||
export default {
|
||||
extends: MessageIncoming,
|
||||
components: { MessageIncoming, GalleryItemsView, ThumbnailView },
|
||||
components: { MessageIncoming, GalleryItemsView, ThumbnailView, SwipeableThumbnailsView },
|
||||
mixins: [messageMixin],
|
||||
data() {
|
||||
return {
|
||||
ROOM_TYPE_CHANNEL: ROOM_TYPE_CHANNEL,
|
||||
items: [],
|
||||
showItem: null,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
<v-icon>more_vert</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
<div class="pin-icon" v-if="event.isPinned"><v-icon>$vuetify.icons.ic_pin_filled</v-icon></div>
|
||||
<div class="pin-icon" v-if="isPinned"><v-icon>$vuetify.icons.ic_pin_filled</v-icon></div>
|
||||
|
||||
<!-- SLOT FOR CONTENT -->
|
||||
<span ref="messageInOutRef" class="content">
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@
|
|||
|
||||
|
||||
<div class="message">
|
||||
<v-container v-if="!event.isRedacted()" fluid class="imageCollection">
|
||||
<SwipeableThumbnailsView :items="items" v-if="!event.isRedacted() && room.displayType == ROOM_TYPE_CHANNEL" />
|
||||
<v-container v-else-if="!event.isRedacted()" fluid class="imageCollection">
|
||||
<v-row wrap>
|
||||
<v-col v-for="({ size, item }) in layoutedItems()" :key="item.event.getId()" :cols="size">
|
||||
<ThumbnailView :item="item" :previewOnly="true" v-on:itemclick="onItemClick($event)" />
|
||||
|
|
@ -39,16 +40,18 @@
|
|||
<script>
|
||||
import MessageOutgoing from "./MessageOutgoing.vue";
|
||||
import messageMixin from "./messageMixin";
|
||||
import util from "../../plugins/utils";
|
||||
import util, { ROOM_TYPE_CHANNEL } from "../../plugins/utils";
|
||||
import GalleryItemsView from '../file_mode/GalleryItemsView.vue';
|
||||
import ThumbnailView from '../file_mode/ThumbnailView.vue';
|
||||
import SwipeableThumbnailsView from "./channel/SwipeableThumbnailsView.vue";
|
||||
|
||||
export default {
|
||||
extends: MessageOutgoing,
|
||||
components: { MessageOutgoing, GalleryItemsView, ThumbnailView },
|
||||
components: { MessageOutgoing, GalleryItemsView, ThumbnailView, SwipeableThumbnailsView },
|
||||
mixins: [messageMixin],
|
||||
data() {
|
||||
return {
|
||||
ROOM_TYPE_CHANNEL: ROOM_TYPE_CHANNEL,
|
||||
items: [],
|
||||
showItem: null,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@
|
|||
<v-list-item-title>{{ $t("menu.unpin") }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item key="redact" v-if="isRedactable" @click.stop="redact">
|
||||
<v-list-item-icon><v-icon color="#222222">delete_outline</v-icon></v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>{{ $t("menu.delete") }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
41
src/components/messages/channel/SwipeableThumbnailsView.vue
Normal file
41
src/components/messages/channel/SwipeableThumbnailsView.vue
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<div class="swipeable-thumbnails-view">
|
||||
<v-responsive :aspect-ratio="16 / 9" class="ma-0 pa-0">
|
||||
<v-carousel height="100%" hide-delimiters show-arrows-on-hover v-model="currentIndex">
|
||||
<v-carousel-item v-for="(item,index) in items" :key="item.event.getId()">
|
||||
<ThumbnailView :item="items[index]" :previewOnly="true" />
|
||||
</v-carousel-item>
|
||||
</v-carousel>
|
||||
</v-responsive>
|
||||
<div class="indicator-container">
|
||||
<div v-for="(item,index) in items" :key="index" :class="{'indicator': true, 'current': index == currentIndex}" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import messageMixin from "../../messages/messageMixin";
|
||||
import ThumbnailView from '../../file_mode/ThumbnailView.vue';
|
||||
|
||||
export default {
|
||||
mixins: [messageMixin],
|
||||
components: { ThumbnailView },
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/assets/css/chat.scss";
|
||||
</style>
|
||||
|
|
@ -109,7 +109,7 @@ export default {
|
|||
* Don't show sender and time if the next event is within 2 minutes and also from us (= back to back messages)
|
||||
*/
|
||||
showSenderAndTime() {
|
||||
if (!this.event.isPinned && this.nextEvent && this.nextEvent.getSender() == this.event.getSender()) {
|
||||
if (!this.isPinned && this.nextEvent && this.nextEvent.getSender() == this.event.getSender()) {
|
||||
const ts1 = this.nextEvent.event.origin_server_ts;
|
||||
const ts2 = this.event.event.origin_server_ts;
|
||||
return ts1 - ts2 < 2 * 60 * 1000; // less than 2 minutes
|
||||
|
|
@ -180,15 +180,19 @@ export default {
|
|||
return this.event.getContent().body;
|
||||
},
|
||||
|
||||
isPinned() {
|
||||
return this.event.parentThread ? this.event.parentThread.isPinned : this.event.isPinned;
|
||||
},
|
||||
|
||||
/**
|
||||
* Classes to set for the message. Currently only for "messageIn"
|
||||
*/
|
||||
|
||||
messageClasses() {
|
||||
if (this.incoming) {
|
||||
return { messageIn: true, "from-admin": this.senderIsAdminOrModerator(this.event), "pinned": this.event.isPinned };
|
||||
return { messageIn: true, "from-admin": this.senderIsAdminOrModerator(this.event), "pinned": this.isPinned };
|
||||
} else {
|
||||
return { messageOut: true, "pinned": this.event.isPinned };
|
||||
return { messageOut: true, "pinned": this.isPinned };
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue