mirror of
https://github.com/thelounge/thelounge
synced 2024-11-25 21:40:22 +00:00
173 lines
5.1 KiB
Vue
173 lines
5.1 KiB
Vue
<template>
|
|
<div
|
|
:id="'msg-' + message.id"
|
|
:class="[
|
|
'msg',
|
|
{
|
|
self: message.self,
|
|
highlight: message.highlight || focused,
|
|
'previous-source': isPreviousSource,
|
|
},
|
|
]"
|
|
:data-type="message.type"
|
|
:data-command="message.command"
|
|
:data-from="message.from && message.from.nick"
|
|
>
|
|
<span
|
|
aria-hidden="true"
|
|
:aria-label="messageTimeLocale"
|
|
class="time tooltipped tooltipped-e"
|
|
>{{ `${messageTime} ` }}
|
|
</span>
|
|
<template v-if="message.type === 'unhandled'">
|
|
<span class="from">[{{ message.command }}]</span>
|
|
<span class="content">
|
|
<span v-for="(param, id) in message.params" :key="id">{{
|
|
` ${param} `
|
|
}}</span>
|
|
</span>
|
|
</template>
|
|
<template v-else-if="isAction()">
|
|
<span class="from"><span class="only-copy">*** </span></span>
|
|
<component :is="messageComponent" :network="network" :message="message" />
|
|
</template>
|
|
<template v-else-if="message.type === 'action'">
|
|
<span class="from"><span class="only-copy">* </span></span>
|
|
<span class="content" dir="auto">
|
|
<Username
|
|
:user="message.from"
|
|
:network="network"
|
|
:channel="channel"
|
|
dir="auto"
|
|
/> <ParsedMessage :message="message" />
|
|
<LinkPreview
|
|
v-for="preview in message.previews"
|
|
:key="preview.link"
|
|
:keep-scroll-position="keepScrollPosition"
|
|
:link="preview"
|
|
:channel="channel"
|
|
/>
|
|
</span>
|
|
</template>
|
|
<template v-else>
|
|
<span v-if="message.type === 'message'" class="from">
|
|
<template v-if="message.from && message.from.nick">
|
|
<span class="only-copy" aria-hidden="true"><</span>
|
|
<Username :user="message.from" :network="network" :channel="channel" />
|
|
<span class="only-copy" aria-hidden="true">> </span>
|
|
</template>
|
|
</span>
|
|
<span v-else-if="message.type === 'plugin'" class="from">
|
|
<template v-if="message.from && message.from.nick">
|
|
<span class="only-copy" aria-hidden="true">[</span>
|
|
{{ message.from.nick }}
|
|
<span class="only-copy" aria-hidden="true">] </span>
|
|
</template>
|
|
</span>
|
|
<span v-else class="from">
|
|
<template v-if="message.from && message.from.nick">
|
|
<span class="only-copy" aria-hidden="true">-</span>
|
|
<Username :user="message.from" :network="network" :channel="channel" />
|
|
<span class="only-copy" aria-hidden="true">- </span>
|
|
</template>
|
|
</span>
|
|
<span class="content" dir="auto">
|
|
<span
|
|
v-if="message.showInActive"
|
|
aria-label="This message was shown in your active channel"
|
|
class="msg-shown-in-active tooltipped tooltipped-e"
|
|
><span></span
|
|
></span>
|
|
<span
|
|
v-if="message.statusmsgGroup"
|
|
:aria-label="`This message was only shown to users with ${message.statusmsgGroup} mode`"
|
|
class="msg-statusmsg tooltipped tooltipped-e"
|
|
><span>{{ message.statusmsgGroup }}</span></span
|
|
>
|
|
<ParsedMessage :network="network" :message="message" />
|
|
<LinkPreview
|
|
v-for="preview in message.previews"
|
|
:key="preview.link"
|
|
:keep-scroll-position="keepScrollPosition"
|
|
:link="preview"
|
|
:channel="channel"
|
|
/>
|
|
</span>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import {computed, defineComponent, PropType} from "vue";
|
|
import dayjs from "dayjs";
|
|
|
|
import constants from "../js/constants";
|
|
import localetime from "../js/helpers/localetime";
|
|
import Username from "./Username.vue";
|
|
import LinkPreview from "./LinkPreview.vue";
|
|
import ParsedMessage from "./ParsedMessage.vue";
|
|
import MessageTypes from "./MessageTypes";
|
|
|
|
import type {ClientChan, ClientMessage, ClientNetwork} from "../js/types";
|
|
import {useStore} from "../js/store";
|
|
|
|
MessageTypes.ParsedMessage = ParsedMessage;
|
|
MessageTypes.LinkPreview = LinkPreview;
|
|
MessageTypes.Username = Username;
|
|
|
|
export default defineComponent({
|
|
name: "Message",
|
|
components: MessageTypes,
|
|
props: {
|
|
message: {type: Object as PropType<ClientMessage>, required: true},
|
|
channel: {type: Object as PropType<ClientChan>, required: false},
|
|
network: {type: Object as PropType<ClientNetwork>, required: true},
|
|
keepScrollPosition: Function as PropType<() => void>,
|
|
isPreviousSource: Boolean,
|
|
focused: Boolean,
|
|
},
|
|
setup(props) {
|
|
const store = useStore();
|
|
|
|
const timeFormat = computed(() => {
|
|
let format: keyof typeof constants.timeFormats;
|
|
|
|
if (store.state.settings.use12hClock) {
|
|
format = store.state.settings.showSeconds ? "msg12hWithSeconds" : "msg12h";
|
|
} else {
|
|
format = store.state.settings.showSeconds ? "msgWithSeconds" : "msgDefault";
|
|
}
|
|
|
|
return constants.timeFormats[format];
|
|
});
|
|
|
|
const messageTime = computed(() => {
|
|
return dayjs(props.message.time).format(timeFormat.value);
|
|
});
|
|
|
|
const messageTimeLocale = computed(() => {
|
|
return localetime(props.message.time);
|
|
});
|
|
|
|
const messageComponent = computed(() => {
|
|
return "message-" + (props.message.type || "invalid"); // TODO: force existence of type in sharedmsg
|
|
});
|
|
|
|
const isAction = () => {
|
|
if (!props.message.type) {
|
|
return false;
|
|
}
|
|
|
|
return typeof MessageTypes["message-" + props.message.type] !== "undefined";
|
|
};
|
|
|
|
return {
|
|
timeFormat,
|
|
messageTime,
|
|
messageTimeLocale,
|
|
messageComponent,
|
|
isAction,
|
|
};
|
|
},
|
|
});
|
|
</script>
|