161 lines
4.8 KiB
Vue
161 lines
4.8 KiB
Vue
<script>
|
|
const MINUTE_IN_MILLI_SECONDS = 60000;
|
|
const HOUR_IN_MILLI_SECONDS = MINUTE_IN_MILLI_SECONDS * 60;
|
|
const DAY_IN_MILLI_SECONDS = HOUR_IN_MILLI_SECONDS * 24;
|
|
|
|
const chineseShortTimestamp = timestamp => {
|
|
if (timestamp === 'now') return '刚刚';
|
|
return timestamp
|
|
.replace(/^(\d+)mo$/, '$1个月')
|
|
.replace(/^(\d+)m$/, '$1分钟')
|
|
.replace(/^(\d+)h$/, '$1小时')
|
|
.replace(/^(\d+)d$/, '$1天')
|
|
.replace(/^(\d+)y$/, '$1年');
|
|
};
|
|
|
|
export { chineseShortTimestamp };
|
|
|
|
import { zhCN } from 'date-fns/locale';
|
|
import {
|
|
dynamicTime,
|
|
dateFormat,
|
|
shortTimestamp,
|
|
} from 'shared/helpers/timeHelper';
|
|
|
|
export default {
|
|
name: 'TimeAgo',
|
|
props: {
|
|
isAutoRefreshEnabled: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
lastActivityTimestamp: {
|
|
type: [String, Date, Number],
|
|
default: '',
|
|
},
|
|
createdAtTimestamp: {
|
|
type: [String, Date, Number],
|
|
default: '',
|
|
},
|
|
conversationId: {
|
|
type: [String, Number],
|
|
default: '',
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
lastActivityAtTimeAgo: dynamicTime(this.lastActivityTimestamp),
|
|
createdAtTimeAgo: dynamicTime(this.createdAtTimestamp),
|
|
timer: null,
|
|
};
|
|
},
|
|
computed: {
|
|
isChineseLocale() {
|
|
return this.$i18n.locale === 'zh_CN';
|
|
},
|
|
lastActivityTime() {
|
|
const timestamp = shortTimestamp(this.lastActivityAtTimeAgo);
|
|
return this.isChineseLocale ? chineseShortTimestamp(timestamp) : timestamp;
|
|
},
|
|
createdAtTime() {
|
|
const timestamp = shortTimestamp(this.createdAtTimeAgo);
|
|
return this.isChineseLocale ? chineseShortTimestamp(timestamp) : timestamp;
|
|
},
|
|
createdAt() {
|
|
const createdTimeDiff = Date.now() - this.createdAtTimestamp * 1000;
|
|
const isBeforeAMonth = createdTimeDiff > DAY_IN_MILLI_SECONDS * 30;
|
|
const relativeTime = this.isChineseLocale
|
|
? dynamicTime(this.createdAtTimestamp, { locale: zhCN })
|
|
: this.createdAtTimeAgo;
|
|
const absoluteTime = this.isChineseLocale
|
|
? dateFormat(this.createdAtTimestamp, 'yyyy年M月d日', { locale: zhCN })
|
|
: dateFormat(this.createdAtTimestamp);
|
|
return !isBeforeAMonth
|
|
? `${this.$t('CHAT_LIST.CHAT_TIME_STAMP.CREATED.LATEST')} ${
|
|
relativeTime
|
|
}`
|
|
: `${this.$t('CHAT_LIST.CHAT_TIME_STAMP.CREATED.OLDEST')} ${absoluteTime}`;
|
|
},
|
|
lastActivity() {
|
|
const lastActivityTimeDiff =
|
|
Date.now() - this.lastActivityTimestamp * 1000;
|
|
const isNotActive = lastActivityTimeDiff > DAY_IN_MILLI_SECONDS * 30;
|
|
const relativeTime = this.isChineseLocale
|
|
? dynamicTime(this.lastActivityTimestamp, { locale: zhCN })
|
|
: this.lastActivityAtTimeAgo;
|
|
const absoluteTime = this.isChineseLocale
|
|
? dateFormat(this.lastActivityTimestamp, 'yyyy年M月d日', { locale: zhCN })
|
|
: dateFormat(this.lastActivityTimestamp);
|
|
return !isNotActive
|
|
? `${this.$t('CHAT_LIST.CHAT_TIME_STAMP.LAST_ACTIVITY.ACTIVE')} ${
|
|
relativeTime
|
|
}`
|
|
: `${this.$t(
|
|
'CHAT_LIST.CHAT_TIME_STAMP.LAST_ACTIVITY.NOT_ACTIVE'
|
|
)} ${absoluteTime}`;
|
|
},
|
|
tooltipText() {
|
|
return `${this.createdAt}
|
|
${this.lastActivity}`;
|
|
},
|
|
},
|
|
watch: {
|
|
lastActivityTimestamp() {
|
|
this.lastActivityAtTimeAgo = dynamicTime(this.lastActivityTimestamp);
|
|
},
|
|
createdAtTimestamp() {
|
|
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
|
|
},
|
|
conversationId() {
|
|
// Reset display values and timer when the row is recycled to a different conversation.
|
|
this.lastActivityAtTimeAgo = dynamicTime(this.lastActivityTimestamp);
|
|
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
|
|
if (this.isAutoRefreshEnabled) {
|
|
clearTimeout(this.timer);
|
|
this.createTimer();
|
|
}
|
|
},
|
|
},
|
|
mounted() {
|
|
if (this.isAutoRefreshEnabled) {
|
|
this.createTimer();
|
|
}
|
|
},
|
|
unmounted() {
|
|
clearTimeout(this.timer);
|
|
},
|
|
methods: {
|
|
createTimer() {
|
|
this.timer = setTimeout(() => {
|
|
this.lastActivityAtTimeAgo = dynamicTime(this.lastActivityTimestamp);
|
|
this.createdAtTimeAgo = dynamicTime(this.createdAtTimestamp);
|
|
this.createTimer();
|
|
}, this.refreshTime());
|
|
},
|
|
refreshTime() {
|
|
const timeDiff = Date.now() - this.lastActivityTimestamp * 1000;
|
|
if (timeDiff > DAY_IN_MILLI_SECONDS) {
|
|
return DAY_IN_MILLI_SECONDS;
|
|
}
|
|
if (timeDiff > HOUR_IN_MILLI_SECONDS) {
|
|
return HOUR_IN_MILLI_SECONDS;
|
|
}
|
|
|
|
return MINUTE_IN_MILLI_SECONDS;
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
v-tooltip.top="{
|
|
content: tooltipText,
|
|
delay: { show: 1000, hide: 0 },
|
|
}"
|
|
class="ml-auto whitespace-nowrap leading-4 text-xxs text-n-slate-10 hover:text-n-slate-11"
|
|
>
|
|
<span>{{ `${createdAtTime} • ${lastActivityTime}` }}</span>
|
|
</div>
|
|
</template>
|