Merge branch 'catch-component-errors' into 'dev'
Handle message rendering errors via the errorCaptured hook See merge request keanuapp/keanuapp-weblite!298
This commit is contained in:
commit
134b1f8cff
5 changed files with 68 additions and 34 deletions
|
|
@ -109,7 +109,8 @@
|
||||||
"files": "Files",
|
"files": "Files",
|
||||||
"images": "Images",
|
"images": "Images",
|
||||||
"send_attachements_dialog_title": "Do you want to send following attachments ?",
|
"send_attachements_dialog_title": "Do you want to send following attachments ?",
|
||||||
"download_all": "Download all"
|
"download_all": "Download all",
|
||||||
|
"failed_to_render": "Failed to render event"
|
||||||
},
|
},
|
||||||
"room": {
|
"room": {
|
||||||
"invitations": "You have no invitations | You have 1 invitation | You have {count} invitations",
|
"invitations": "You have no invitations | You have 1 invitation | You have {count} invitations",
|
||||||
|
|
|
||||||
|
|
@ -62,35 +62,37 @@
|
||||||
<div v-if="showDayMarkerBeforeEvent(event) && !!componentForEvent(event, isForExport = false)" class="day-marker"><div class="line"></div><div class="text">{{ dayForEvent(event) }}</div><div class="line"></div></div>
|
<div v-if="showDayMarkerBeforeEvent(event) && !!componentForEvent(event, isForExport = false)" class="day-marker"><div class="line"></div><div class="text">{{ dayForEvent(event) }}</div><div class="line"></div></div>
|
||||||
|
|
||||||
<div v-if="!event.isRelation() && !event.isRedaction()" :ref="event.getId()">
|
<div v-if="!event.isRelation() && !event.isRedaction()" :ref="event.getId()">
|
||||||
<div class="message-wrapper" v-on:touchstart="
|
<MessageErrorHandler>
|
||||||
(e) => {
|
<div class="message-wrapper" v-on:touchstart="
|
||||||
touchStart(e, event);
|
(e) => {
|
||||||
}
|
touchStart(e, event);
|
||||||
" v-on:touchend="touchEnd" v-on:touchcancel="touchCancel" v-on:touchmove="touchMove">
|
}
|
||||||
<!-- Note: For threaded media messages, IF there is only one item we show that media item as a single component.
|
" v-on:touchend="touchEnd" v-on:touchcancel="touchCancel" v-on:touchmove="touchMove">
|
||||||
We might therefore get calls to v-on:context-menu that has the event set to that single media item, not the top level thread event
|
<!-- Note: For threaded media messages, IF there is only one item we show that media item as a single component.
|
||||||
that is really displayed in the flow. Therefore, we rewrite these events with "{event: event, anchor: $event.anchor}",
|
We might therefore get calls to v-on:context-menu that has the event set to that single media item, not the top level thread event
|
||||||
see below. Otherwise things like context menus won't work as designed.
|
that is really displayed in the flow. Therefore, we rewrite these events with "{event: event, anchor: $event.anchor}",
|
||||||
-->
|
see below. Otherwise things like context menus won't work as designed.
|
||||||
<component :is="componentForEvent(event)" :room="room" :originalEvent="event" :nextEvent="filteredEvents[index + 1]"
|
-->
|
||||||
:timelineSet="timelineSet" v-on:send-quick-reaction.stop="sendQuickReaction"
|
<component :is="componentForEvent(event)" :room="room" :originalEvent="event" :nextEvent="filteredEvents[index + 1]"
|
||||||
:componentFn="componentForEvent"
|
:timelineSet="timelineSet" v-on:send-quick-reaction.stop="sendQuickReaction"
|
||||||
v-on:context-menu="showContextMenuForEvent({event: event, anchor: $event.anchor})"
|
:componentFn="componentForEvent"
|
||||||
v-on:own-avatar-clicked="viewProfile"
|
v-on:context-menu="showContextMenuForEvent({event: event, anchor: $event.anchor})"
|
||||||
v-on:other-avatar-clicked="showAvatarMenuForEvent({event: event, anchor: $event.anchor})"
|
v-on:own-avatar-clicked="viewProfile"
|
||||||
v-on:download="download(event)"
|
v-on:other-avatar-clicked="showAvatarMenuForEvent({event: event, anchor: $event.anchor})"
|
||||||
v-on:poll-closed="pollWasClosed(event)"
|
v-on:download="download(event)"
|
||||||
v-on:more="
|
v-on:poll-closed="pollWasClosed(event)"
|
||||||
isEmojiQuickReaction = true
|
v-on:more="
|
||||||
showMoreMessageOperations({event: event, anchor: $event.anchor})
|
isEmojiQuickReaction = true
|
||||||
"
|
showMoreMessageOperations({event: event, anchor: $event.anchor})
|
||||||
v-on:layout-change="onLayoutChange"
|
"
|
||||||
v-on:addQuickHeartReaction="addQuickHeartReaction(event)"
|
v-on:layout-change="onLayoutChange"
|
||||||
/>
|
v-on:addQuickHeartReaction="addQuickHeartReaction(event)"
|
||||||
<!-- <div v-if="debugging" style="user-select:text">EventID: {{ event.getId() }}</div> -->
|
/>
|
||||||
<!-- <div v-if="debugging" style="user-select:text">Event: {{ JSON.stringify(event) }}</div> -->
|
<!-- <div v-if="debugging" style="user-select:text">EventID: {{ event.getId() }}</div> -->
|
||||||
<div v-if="event.getId() == readMarker && index < filteredEvents.length - 1" class="read-marker"><div class="line"></div><div class="text">{{ $t('message.unread_messages') }}</div><div class="line"></div></div>
|
<!-- <div v-if="debugging" style="user-select:text">Event: {{ JSON.stringify(event) }}</div> -->
|
||||||
</div>
|
<div v-if="event.getId() == readMarker && index < filteredEvents.length - 1" class="read-marker"><div class="line"></div><div class="text">{{ $t('message.unread_messages') }}</div><div class="line"></div></div>
|
||||||
|
</div>
|
||||||
|
</MessageErrorHandler>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -213,7 +215,7 @@
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|
||||||
<input ref="attachment" type="file" name="attachment" @change="handlePickedAttachment($event)"
|
<input ref="attachment" type="file" name="attachment" @change="handlePickedAttachment($event)"
|
||||||
accept="image/*,audio/*,video/*,.pdf,application/pdf,.apk,application/vnd.android.package-archive,.ipa,.zip,application/zip,application/x-zip-compressed,multipart/x-zip" class="d-none" multiple/>
|
accept="image/*,audio/*,video/*,.mp3,.mp4,.wav,.m4a,.pdf,application/pdf,.apk,application/vnd.android.package-archive,.ipa,.zip,application/zip,application/x-zip-compressed,multipart/x-zip" class="d-none" multiple/>
|
||||||
|
|
||||||
<div v-if="currentFileInputsDialog && !useFileModeNonAdmin">
|
<div v-if="currentFileInputsDialog && !useFileModeNonAdmin">
|
||||||
<v-dialog v-model="currentFileInputsDialog" class="ma-0 pa-0" :width="$vuetify.breakpoint.smAndUp ? '50%' : '85%'" persistent scrollable>
|
<v-dialog v-model="currentFileInputsDialog" class="ma-0 pa-0" :width="$vuetify.breakpoint.smAndUp ? '50%' : '85%'" persistent scrollable>
|
||||||
|
|
@ -364,6 +366,7 @@ import FileDropLayout from "./file_mode/FileDropLayout";
|
||||||
import roomTypeMixin from "./roomTypeMixin";
|
import roomTypeMixin from "./roomTypeMixin";
|
||||||
import roomMembersMixin from "./roomMembersMixin";
|
import roomMembersMixin from "./roomMembersMixin";
|
||||||
import PurgeRoomDialog from "../components/PurgeRoomDialog";
|
import PurgeRoomDialog from "../components/PurgeRoomDialog";
|
||||||
|
import MessageErrorHandler from "./MessageErrorHandler";
|
||||||
|
|
||||||
const sizeOf = require("image-size");
|
const sizeOf = require("image-size");
|
||||||
const dataUriToBuffer = require("data-uri-to-buffer");
|
const dataUriToBuffer = require("data-uri-to-buffer");
|
||||||
|
|
@ -417,7 +420,8 @@ export default {
|
||||||
FileDropLayout,
|
FileDropLayout,
|
||||||
UserProfileDialog,
|
UserProfileDialog,
|
||||||
PurgeRoomDialog,
|
PurgeRoomDialog,
|
||||||
WelcomeHeaderChannelUser
|
WelcomeHeaderChannelUser,
|
||||||
|
MessageErrorHandler
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
|
||||||
29
src/components/MessageErrorHandler.vue
Normal file
29
src/components/MessageErrorHandler.vue
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot
|
||||||
|
v-if="err"
|
||||||
|
name="error"
|
||||||
|
v-bind:err="err"
|
||||||
|
><div class="text-center">{{ $t('message.failed_to_render') }}</div></slot>
|
||||||
|
<slot v-else></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "MessageErrorHandler",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
err: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
errorCaptured(err, ignoredvm, ignoredinfo) {
|
||||||
|
this.err = err;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
|
|
@ -27,7 +27,7 @@ export default {
|
||||||
components: { MessageIncoming },
|
components: { MessageIncoming },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
src: null,
|
src: undefined,
|
||||||
cover: true,
|
cover: true,
|
||||||
contain: false,
|
contain: false,
|
||||||
dialog: false
|
dialog: false
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export default {
|
||||||
components: { MessageOutgoing },
|
components: { MessageOutgoing },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
src: null,
|
src: undefined,
|
||||||
cover: true,
|
cover: true,
|
||||||
contain: false,
|
contain: false,
|
||||||
dialog: false
|
dialog: false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue