Send progress in main view
This commit is contained in:
parent
41232fbd90
commit
e9accdebf1
11 changed files with 465 additions and 86 deletions
|
|
@ -52,6 +52,7 @@ import ReadMarker from "./messages/ReadMarker.vue";
|
|||
import RoomTombstone from "./messages/composition/RoomTombstone.vue";
|
||||
import roomDisplayOptionsMixin from "./roomDisplayOptionsMixin";
|
||||
import roomTypeMixin from "./roomTypeMixin";
|
||||
import MessageThreadSending from "./messages/composition/MessageThreadSending.vue";
|
||||
|
||||
export const ROOM_READ_MARKER_EVENT_PLACEHOLDER = { getId: () => "ROOM_READ_MARKER", getTs: () => Date.now() };
|
||||
|
||||
|
|
@ -225,6 +226,9 @@ export default {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
if (!isForExport && event.uploadBatch) {
|
||||
return MessageThreadSending;
|
||||
}
|
||||
if (event.isMxThread) {
|
||||
// Outgoing thread
|
||||
return isForExport ? MessageThreadExport : MessageThread;
|
||||
|
|
|
|||
|
|
@ -245,8 +245,8 @@ export default defineComponent({
|
|||
|
||||
batch: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return reactive(createUploadBatch(null, null, 0));
|
||||
default: () => {
|
||||
return createUploadBatch(null, null);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -294,7 +294,7 @@ export default defineComponent({
|
|||
this.currentItemIndex = newValue.length - 1;
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
deep: 1,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -323,6 +323,7 @@ export default defineComponent({
|
|||
},
|
||||
sendAll() {
|
||||
this.status = this.mainStatuses.SENDING;
|
||||
this.$emit("close");
|
||||
this.batch
|
||||
.send(this.messageInput && this.messageInput.length > 0 ? this.messageInput : this.defaultRootMessageText)
|
||||
.then(() => {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import utils from "../../plugins/utils";
|
||||
import { singleOrDoubleTapRecognizer } from "../../plugins/touch";
|
||||
import { computed, inject, onBeforeUnmount, onMounted, Ref, ref, useTemplateRef, watch } from "vue";
|
||||
import { EventAttachment } from "../../models/eventAttachment";
|
||||
import { useThumbnail } from "../messages/composition/useThumbnail";
|
||||
|
|
@ -119,7 +119,7 @@ const loadingProgress = computed(() => {
|
|||
|
||||
onMounted(() => {
|
||||
if (thumbnailRef.value && (item as EventAttachment)) {
|
||||
const hammerInstance = utils.singleOrDoubleTabRecognizer(thumbnailRef.value);
|
||||
const hammerInstance = singleOrDoubleTapRecognizer(thumbnailRef.value);
|
||||
hammerInstance.on("singletap doubletap", (ev: any) => {
|
||||
if (ev.type === "singletap") {
|
||||
emits("itemclick", { item: item as EventAttachment });
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { singleOrDoubleTapRecognizer } from "@/plugins/touch";
|
||||
import { computed, inject, onMounted, ref, useTemplateRef, watch } from "vue";
|
||||
import MessageIncoming from "./MessageIncoming.vue";
|
||||
import MessageOutgoing from "./MessageOutgoing.vue";
|
||||
|
|
@ -30,7 +31,6 @@ import { useI18n } from "vue-i18n";
|
|||
import { MessageProps, useMessage } from "./useMessage";
|
||||
import { EventAttachment } from "../../../models/eventAttachment";
|
||||
import { useDisplay } from "vuetify";
|
||||
import utils from "@/plugins/utils";
|
||||
import Hammer from "hammerjs";
|
||||
|
||||
const { t } = useI18n()
|
||||
|
|
@ -80,7 +80,7 @@ onMounted(() => {
|
|||
contain.value = true;
|
||||
}
|
||||
if (imageRef.value) {
|
||||
const hammerInstance = utils.singleOrDoubleTabRecognizer(imageRef.value);
|
||||
const hammerInstance = singleOrDoubleTapRecognizer(imageRef.value);
|
||||
hammerInstance.on("singletap doubletap", (ev: Hammer.HammerInput) => {
|
||||
if (ev.type === "singletap") {
|
||||
attachment.value?.loadSrc();
|
||||
|
|
|
|||
194
src/components/messages/composition/MessageThreadSending.vue
Normal file
194
src/components/messages/composition/MessageThreadSending.vue
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
<template>
|
||||
<MessageOutgoing :is="rootComponent" ref="root" v-bind="{ ...$props, ...$attrs }">
|
||||
<div class="bubble">
|
||||
<div class="original-message" v-if="inReplyToText">
|
||||
<div class="original-message-sender">{{ inReplyToSender }}</div>
|
||||
<div class="original-message-text" v-html="linkify($$sanitize(inReplyToText))" />
|
||||
</div>
|
||||
|
||||
<div class="message">
|
||||
<div class="message-upload-progress" v-if="unref(uploadBatch?.sendingStatus) === 'sending'">
|
||||
<v-progress-circular
|
||||
class="message-upload-progress__progress clickable"
|
||||
:model-value="unref(uploadBatch?.progressPercent ?? 0)"
|
||||
color="white"
|
||||
bg-color="rgba(255,255,255,0.5)"
|
||||
width="2"
|
||||
size="16"
|
||||
@click.stop="cancelUpload"
|
||||
>
|
||||
<v-icon size="8">close</v-icon> </v-progress-circular
|
||||
>{{ uploadBatch?.progressPercent }}%
|
||||
</div>
|
||||
<SwipeableThumbnailsView :items="items" v-if="room.displayType == ROOM_TYPE_CHANNEL" v-bind="$attrs" />
|
||||
<v-container v-else fluid class="imageCollection">
|
||||
<v-row wrap>
|
||||
<v-col v-for="{ size, item } in layoutedItems" :key="item.file.name + item.file.size" :cols="size">
|
||||
<ThumbnailView :file="item" v-on:itemclick="onItemClick($event)" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
<span v-html="linkify($$sanitize(messageText))" v-if="messageText" />
|
||||
<span class="edit-marker" v-if="event && event.replacingEventId() && !event.isRedacted()">
|
||||
{{ t("message.edited") }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<GalleryItemsView
|
||||
:originalEvent="originalEvent"
|
||||
:items="items"
|
||||
:initialItem="showItem"
|
||||
v-if="!!showItem"
|
||||
v-on:close="showItem = undefined"
|
||||
/>
|
||||
</MessageOutgoing>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MessageOutgoing from "./MessageOutgoing.vue";
|
||||
import { MessageProps, useMessage } from "./useMessage";
|
||||
import { 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";
|
||||
import { inject, ref, Ref, unref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { Attachment, AttachmentBatch } from "../../../models/attachment";
|
||||
|
||||
const { t } = useI18n();
|
||||
const $matrix: any = inject("globalMatrix");
|
||||
const $$sanitize: any = inject("globalSanitize");
|
||||
|
||||
let items: Ref<Attachment[]> = ref([]);
|
||||
const layoutedItems: Ref<{ size: number; item: Attachment }[]> = ref([]);
|
||||
const showItem: Ref<Attachment | undefined> = ref(undefined);
|
||||
|
||||
const uploadBatch: Ref<AttachmentBatch | undefined> = ref(undefined);
|
||||
|
||||
const props = defineProps<MessageProps>();
|
||||
|
||||
const { room } = props;
|
||||
|
||||
const {
|
||||
event,
|
||||
inReplyToSender,
|
||||
inReplyToText,
|
||||
messageText,
|
||||
linkify,
|
||||
} = useMessage($matrix, t, props, undefined, undefined);
|
||||
|
||||
const cancelUpload = () => {
|
||||
if (uploadBatch.value) {
|
||||
uploadBatch.value.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
const onItemClick = (event: any) => {
|
||||
showItem.value = event.item;
|
||||
};
|
||||
|
||||
const layout = () => {
|
||||
if (!items.value || items.value.length == 0) {
|
||||
layoutedItems.value = [];
|
||||
return;
|
||||
}
|
||||
let array = items.value.slice(0);
|
||||
let rows = [];
|
||||
while (array.length > 0) {
|
||||
if (array.length >= 7) {
|
||||
rows.push({ size: 6, item: array[0] });
|
||||
rows.push({ size: 6, item: array[1] });
|
||||
rows.push({ size: 12, item: array[2] });
|
||||
rows.push({ size: 3, item: array[3] });
|
||||
rows.push({ size: 3, item: array[4] });
|
||||
rows.push({ size: 3, item: array[5] });
|
||||
rows.push({ size: 3, item: array[6] });
|
||||
array = array.slice(7);
|
||||
} else if (array.length >= 3) {
|
||||
rows.push({ size: 6, item: array[0] });
|
||||
rows.push({ size: 6, item: array[1] });
|
||||
rows.push({ size: 12, item: array[2] });
|
||||
array = array.slice(3);
|
||||
} else if (array.length >= 2) {
|
||||
rows.push({ size: 6, item: array[0] });
|
||||
rows.push({ size: 6, item: array[1] });
|
||||
array = array.slice(2);
|
||||
} else {
|
||||
rows.push({ size: 12, item: array[0] });
|
||||
array = array.slice(1);
|
||||
}
|
||||
}
|
||||
layoutedItems.value = rows;
|
||||
};
|
||||
|
||||
watch(
|
||||
event,
|
||||
(updated) => {
|
||||
const batch = updated?.uploadBatch;
|
||||
if (batch) {
|
||||
uploadBatch.value = updated?.uploadBatch;
|
||||
items = ref(batch.attachments);
|
||||
layout();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use "@/assets/css/chat.scss" as *;
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bubble {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imageCollection {
|
||||
border-radius: 15px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.row {
|
||||
margin: -4px; // Compensate for column padding, so the border-radius above looks round!
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.col {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.6rem;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.message-upload-progress {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
height: 20px;
|
||||
border-radius: 10px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
font-family: "Inter";
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-size: 10px;
|
||||
line-height: 125%;
|
||||
letter-spacing: 0.4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 2px;
|
||||
padding-right: 4px;
|
||||
.message-upload-progress__progress {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue