Support pinning thread messages (media)

This commit is contained in:
N-Pex 2024-10-17 10:22:24 +02:00
parent d3ffc3d15b
commit 5e1223fc01
10 changed files with 152 additions and 27 deletions

View file

@ -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>

View file

@ -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,
}

View file

@ -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">

View file

@ -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,
}

View file

@ -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>

View 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>

View file

@ -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 };
}
},