fchat-rising/chat/message_view.ts

130 lines
5.2 KiB
TypeScript
Raw Permalink Normal View History

2019-07-07 21:44:32 +00:00
import { Component, Hook, Prop } from '@f-list/vue-ts';
2019-01-03 17:38:17 +00:00
import {CreateElement, default as Vue, VNode, VNodeChildrenArrayContents} from 'vue';
2018-01-06 16:14:21 +00:00
import {Channel} from '../fchat';
2021-03-25 20:53:37 +00:00
import { Score } from '../learn/matcher';
2020-03-14 21:24:49 +00:00
import {BBCodeView} from '../bbcode/view';
2023-03-30 00:23:54 +00:00
import { formatTime } from './common';
2017-09-02 01:50:31 +00:00
import core from './core';
import {Conversation} from './interfaces';
2019-07-15 16:59:16 +00:00
import UserView from './UserView.vue';
2021-03-25 20:53:37 +00:00
import { Scoring } from '../learn/matcher-types';
2017-09-02 01:50:31 +00:00
const userPostfix: {[key: number]: string | undefined} = {
[Conversation.Message.Type.Message]: ': ',
[Conversation.Message.Type.Ad]: ': ',
[Conversation.Message.Type.Action]: ''
};
2019-01-03 17:38:17 +00:00
@Component({
render(this: MessageView, createElement: CreateElement): VNode {
const message = this.message;
2019-07-07 21:44:32 +00:00
// setTimeout(
// () => {
// console.log('Now scoring high!', message.text.substr(0, 64));
// message.score = Scoring.MATCH;
// },
// 5000
// );
2018-03-28 13:51:05 +00:00
const children: VNodeChildrenArrayContents =
2019-07-08 23:27:14 +00:00
[createElement('span', {staticClass: 'message-time'}, `${formatTime(message.time)}`)];
const separators = core.connection.isOpen ? core.state.settings.messageSeparators : false;
2017-09-02 01:50:31 +00:00
/*tslint:disable-next-line:prefer-template*///unreasonable here
let classes = `message message-${Conversation.Message.Type[message.type].toLowerCase()}` + (separators ? ' message-block' : '') +
2017-09-02 01:50:31 +00:00
(message.type !== Conversation.Message.Type.Event && message.sender.name === core.connection.character ? ' message-own' : '') +
2019-07-07 01:37:15 +00:00
((this.classes !== undefined) ? ` ${this.classes}` : '') +
2022-01-01 00:06:08 +00:00
` ${this.scoreClasses}` +
` ${this.filterClasses}`;
2017-09-02 01:50:31 +00:00
if(message.type !== Conversation.Message.Type.Event) {
2021-01-31 00:46:27 +00:00
children.push(
2022-12-10 21:16:07 +00:00
(message.type === Conversation.Message.Type.Action) ? createElement('i', { class: 'message-pre fas fa-star-of-life' }) : '',
2023-03-30 00:23:54 +00:00
createElement(UserView, {props: {avatar: core.state.settings.risingShowPortraitInMessage, character: message.sender, channel: this.channel}}),
2021-01-31 00:46:27 +00:00
userPostfix[message.type] !== undefined ? createElement('span', { class: 'message-post' }, userPostfix[message.type]) : ' '
);
if('isHighlight' in message && message.isHighlight) classes += ' message-highlight';
2017-09-02 01:50:31 +00:00
}
2019-01-03 17:38:17 +00:00
const isAd = message.type === Conversation.Message.Type.Ad && !this.logs;
2019-09-17 17:14:14 +00:00
children.push(createElement(BBCodeView(core.bbCodeParser),
{props: {unsafeText: message.text, afterInsert: isAd ? (elm: HTMLElement) => {
2019-01-03 17:38:17 +00:00
setImmediate(() => {
elm = elm.parentElement!;
if(elm.scrollHeight > elm.offsetHeight) {
const expand = document.createElement('div');
expand.className = 'expand fas fa-caret-down';
expand.addEventListener('click', function(): void { this.parentElement!.className += ' expanded'; });
elm.appendChild(expand);
}
});
} : undefined}}));
2017-09-02 01:50:31 +00:00
const node = createElement('div', {attrs: {class: classes}}, children);
2019-01-03 17:38:17 +00:00
node.key = message.id;
2017-09-02 01:50:31 +00:00
return node;
}
2019-01-03 17:38:17 +00:00
})
export default class MessageView extends Vue {
@Prop({required: true})
readonly message!: Conversation.Message;
@Prop
readonly classes?: string;
@Prop
readonly channel?: Channel;
@Prop
readonly logs?: true;
2019-07-07 01:37:15 +00:00
scoreClasses = this.getMessageScoreClasses(this.message);
2022-01-01 00:06:08 +00:00
filterClasses = this.getMessageFilterClasses(this.message);
2019-07-07 01:37:15 +00:00
2019-07-07 21:44:32 +00:00
scoreWatcher: (() => void) | null = ((this.message.type === Conversation.Message.Type.Ad) && (this.message.score === 0))
? this.$watch('message.score', () => this.scoreUpdate())
: null;
@Hook('beforeDestroy')
onBeforeDestroy(): void {
// console.log('onbeforedestroy');
2019-07-07 21:44:32 +00:00
if (this.scoreWatcher) {
// console.log('onbeforedestroy killed');
2019-07-07 21:44:32 +00:00
this.scoreWatcher(); // stop watching
this.scoreWatcher = null;
}
}
// @Watch('message.score')
2019-07-07 01:37:15 +00:00
scoreUpdate(): void {
2022-01-01 00:06:08 +00:00
const oldScoreClasses = this.scoreClasses;
const oldFilterClasses = this.filterClasses;
2019-07-07 01:37:15 +00:00
this.scoreClasses = this.getMessageScoreClasses(this.message);
2022-01-01 00:06:08 +00:00
this.filterClasses = this.getMessageFilterClasses(this.message);
2019-07-07 01:37:15 +00:00
2022-01-01 00:06:08 +00:00
if (this.scoreClasses !== oldScoreClasses || this.filterClasses !== oldFilterClasses) {
2019-07-07 21:44:32 +00:00
this.$forceUpdate();
}
2019-07-07 01:37:15 +00:00
2019-07-07 21:44:32 +00:00
if (this.scoreWatcher) {
// console.log('watch killed');
2019-07-07 21:44:32 +00:00
this.scoreWatcher(); // stop watching
this.scoreWatcher = null;
}
}
2019-07-07 01:37:15 +00:00
getMessageScoreClasses(message: Conversation.Message): string {
if ((!core.state.settings.risingAdScore) || (message.type !== Conversation.Message.Type.Ad)) {
2019-07-07 01:37:15 +00:00
return '';
}
return `message-score ${Score.getClasses(message.score as Scoring)}`;
}
2022-01-01 00:06:08 +00:00
getMessageFilterClasses(message: Conversation.Message): string {
if (!message.filterMatch) {
return '';
}
return 'filter-match';
}
}