Skip to content

Commit

Permalink
fix: optimize time display
Browse files Browse the repository at this point in the history
  • Loading branch information
IceEnd committed May 16, 2023
1 parent 6da57fe commit f6cc32f
Show file tree
Hide file tree
Showing 18 changed files with 221 additions and 106 deletions.
6 changes: 6 additions & 0 deletions README-ZH_CN.md
Expand Up @@ -45,6 +45,12 @@
- .AppImage: Linux
- .msi: Windows

## 常见问题

1. macOS 提示:“应用程序 已损坏”,或者 “来自身分不明的开发者”

因为没有苹果开发者账号导致的。可以按照[这篇指引](https://sysin.org/blog/macos-if-crashes-when-opening/)操作。

## 开源许可

[GNU GENERAL PUBLIC LICENSE © IceEnd](./LICENSE)
6 changes: 6 additions & 0 deletions README.md
Expand Up @@ -45,6 +45,12 @@ Version description:
- .AppImage: For Linux
- .msi: For Windows

### Common Questions

1. macOS prompts "Application is damaged" or "unidentified developer"

This is because of not having an Apple developer account. You can follow the [instructions](https://iboysoft.com/news/app-is-damaged-and-cannot-be-opened.html) in this guide to resolve the issue.

## LICENSE

[GNU GENERAL PUBLIC LICENSE © IceEnd](./LICENSE)
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "1chat",
"private": true,
"version": "0.1.2",
"version": "0.1.3",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "one_chat"
version = "0.1.2"
version = "0.1.3"
description = "A Tauri App"
authors = ["you"]
license = ""
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "1chat",
"version": "0.1.2"
"version": "0.1.3"
},
"tauri": {
"allowlist": {
Expand Down
38 changes: 38 additions & 0 deletions src/i18n.ts
@@ -0,0 +1,38 @@
import { createI18n, DefineDateTimeFormat }from 'vue-i18n';
import { Language } from '@/constants';
import zhCN from './locales/zh-CN.json';
import en from './locales/en.json';

const dateTimeFormats: DefineDateTimeFormat = {
short: {
year: 'numeric',
month: 'short',
day: 'numeric',
},
weekday: {
weekday: 'short',
hour: 'numeric',
minute: 'numeric',
},
long: {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: false,
},
};

export const i18n = createI18n({
legacy: false,
datetimeFormats: {
en: dateTimeFormats,
'zh-CN': dateTimeFormats,
},
locale: Language.EN,
messages: {
en,
'zh-CN': zhCN,
},
});
3 changes: 2 additions & 1 deletion src/locales/en.json
Expand Up @@ -14,5 +14,6 @@
"Version": "Version",
"Proxy & Model": "Proxy & Model",
"API Host": "API Host",
"Model": "Model"
"Model": "Model",
"Yesterday": "Yesterday"
}
3 changes: 2 additions & 1 deletion src/locales/zh-CN.json
Expand Up @@ -14,5 +14,6 @@
"Version": "版本",
"Proxy & Model": "代理 & 模型",
"API Host": "API Host",
"Model": "模型"
"Model": "模型",
"Yesterday": "昨天"
}
14 changes: 1 addition & 13 deletions src/main.ts
Expand Up @@ -2,22 +2,10 @@ import 'element-plus/theme-chalk/dark/css-vars.css';
import '@/styles/index.less';

import { createApp } from 'vue';
import { createI18n } from 'vue-i18n';
import { createPinia } from 'pinia';
import { router } from '@/router';
import { Language } from '@/constants';
import { i18n } from './i18n';
import App from './App.vue';
import zhCN from './locales/zh-CN.json';
import en from './locales/en.json';

const i18n = createI18n({
legacy: false,
locale: Language.EN,
messages: {
en,
'zh-CN': zhCN,
},
});

const pinia = createPinia();

Expand Down
12 changes: 11 additions & 1 deletion src/store/session.ts
Expand Up @@ -37,7 +37,9 @@ export const useSessionStore = defineStore('session', () => {
try {
const [state, data] = await Promise.all(queue);
active.value = JSON.parse(state as string).active;
sessions.value = (data as string[]).map(item => JSON.parse(item) as ChatSession.ISession);
sessions.value = (data as string[])
.map(item => JSON.parse(item) as ChatSession.ISession);
sortSession();
} catch (error) {
// do nothing
console.error(error);
Expand Down Expand Up @@ -89,6 +91,7 @@ export const useSessionStore = defineStore('session', () => {
}
activeSession.value.latest = Date.now();
activeSession.value.messages.push(payload);
sortSession();
invoke(TauriCommand.SessionWriteData, {
id: activeSession.value.id,
content: JSON.stringify(activeSession.value),
Expand Down Expand Up @@ -124,6 +127,7 @@ export const useSessionStore = defineStore('session', () => {
const time = Date.now();
Object.assign(message, payload);
target.latest = time;
sortSession();
invoke(TauriCommand.SessionWriteData, {
id: target.id,
content: JSON.stringify(target),
Expand All @@ -142,12 +146,18 @@ export const useSessionStore = defineStore('session', () => {
return;
}
Object.assign(target, payload);
sortSession();
invoke(TauriCommand.SessionWriteData, {
id: target.id,
content: JSON.stringify(target),
});
};

// 更新排序
const sortSession = () => {
sessions.value.sort((pre, next) => next.latest - pre.latest);
};

return {
active,
activeSession,
Expand Down
6 changes: 6 additions & 0 deletions src/utils/common.ts
@@ -0,0 +1,6 @@
/**
* 生成provide key通用函数
* @param module 模块名称
* @returns func
*/
export const provideKeyFactory = (module: string) => (key: string) => Symbol(`@${module}:${key}`);
44 changes: 44 additions & 0 deletions src/utils/date.ts
@@ -0,0 +1,44 @@
import dayjs from 'dayjs';
import today from 'dayjs/plugin/isToday';
import yesterday from 'dayjs/plugin/isYesterday';
import between from 'dayjs/plugin/isBetween';

dayjs.extend(today);
dayjs.extend(yesterday);
dayjs.extend(between);

/**
* 显示聊天时间
* @param time 时间戳
* @returns 展示的时间
*/
export const getChatDate = (time?: number): string => {
if (!time) {
return '';
}
const date = dayjs(time);
if (date.isToday()) {
return date.format('HH:mm');
}
return date.format('YYYY/MM/DD');
};


/**
* 是否为昨天
*/
export const isYesterday = (time: number | string) => dayjs(time).isYesterday();

/**
* 是否在今天
*/
export const isToday = (time: number | string) => dayjs(time).isToday();

/**
* 是否为上周
*/
export const isLatestWeek = (time: number | string) => {
const left = dayjs(dayjs().subtract(7, 'd')).format('YYYY-MM-DD');
const right = dayjs().format('YYYY-MM-DD');
return dayjs(time).isBetween(left, right, 'day', '[)');
};
65 changes: 3 additions & 62 deletions src/utils/index.ts
@@ -1,62 +1,3 @@
import dayjs from 'dayjs';
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js';
import CopyDocument from '@/assets/copy-document.svg?raw';

const md = new MarkdownIt({
linkify: true,
breaks: true,
highlight: (str: string, lang: string): string => {
let content = str;
if (lang && hljs.getLanguage(lang)) {
try {
content = hljs.highlight(str, {
language: lang,
ignoreIllegals: true,
}).value;
} catch (e) {
console.log('语法高亮错误', e);
return str;
}
} else {
content = md.utils.escapeHtml(str);
}

lang = (lang || 'txt');

return [
'<pre class="code-prefix"><div class="code-wrapper ps-r"><pre>',
`<code class="language-${lang}">${content}</code></pre>`,
`<div class="code-label ps-a">${lang.toUpperCase()}</div>`,
`<div class="code-helper ps-a"><span class="copy-action">${CopyDocument}</span></div>`,
'</div></pre>',
].join('');
},
});

/**
* 生成provide key通用函数
* @param module 模块名称
* @returns func
*/
export const provideKeyFactory = (module: string) => (key: string) => Symbol(`@${module}:${key}`);

/**
* 显示聊天时间
* @param time 时间戳
* @returns 展示的时间
*/
export const getChatDate = (time?: number): string => {
if (!time) {
return '';
}
const date = dayjs(time);
if (date.isBefore(dayjs(), 'd')) {
return date.format('YYYY/MM/DD');
}
return date.format('HH:mm');
};

export const renderMarkDown = (content: string): string => {
return md.render(content);
};
export * from './common';
export * from './markdown';
export * from './date';
38 changes: 38 additions & 0 deletions src/utils/markdown.ts
@@ -0,0 +1,38 @@
import MarkdownIt from 'markdown-it';
import hljs from 'highlight.js';
import CopyDocument from '@/assets/copy-document.svg?raw';

const md = new MarkdownIt({
linkify: true,
breaks: true,
highlight: (str: string, lang: string): string => {
let content = str;
if (lang && hljs.getLanguage(lang)) {
try {
content = hljs.highlight(str, {
language: lang,
ignoreIllegals: true,
}).value;
} catch (e) {
console.log('语法高亮错误', e);
return str;
}
} else {
content = md.utils.escapeHtml(str);
}

lang = (lang || 'txt');

return [
'<pre class="code-prefix"><div class="code-wrapper ps-r"><pre>',
`<code class="language-${lang}">${content}</code></pre>`,
`<div class="code-label ps-a">${lang.toUpperCase()}</div>`,
`<div class="code-helper ps-a"><span class="copy-action">${CopyDocument}</span></div>`,
'</div></pre>',
].join('');
},
});

export const renderMarkDown = (content: string): string => {
return md.render(content);
};
54 changes: 54 additions & 0 deletions src/views/chat/date.vue
@@ -0,0 +1,54 @@
<template>
<div
class="date t-assist ta-c pvert-8"
v-if="date"
>
{{ date }}
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import dayjs from 'dayjs';
import { isToday, isYesterday, isLatestWeek } from '@/utils';
import { useI18n } from 'vue-i18n';
const TIME_SPACE = 10 * 60 * 1000; // 十分钟间隔
const { t, d } = useI18n();
const props = defineProps<{
latest?: number,
current: number,
}>();
// 根据间隔来判断是否渲染时间
const date = computed(() => {
const { latest, current } = props;
if (!latest || current - latest >= TIME_SPACE) {
return getDate(current);
}
return '';
});
const getDate = (time: string | number): string => {
const date = dayjs(time);
if (isToday(time)) {
return date.format('HH:mm');
}
if (isYesterday(time)) {
return `${t('Yesterday')} ${date.format('HH:mm')}`;
}
if (isLatestWeek(time)) {
return d(time ,'weekday');
}
return d(time, 'long');
};
</script>

<style lang="less" scoped>
.date {
user-select: none;
cursor: default;
}
</style>

0 comments on commit f6cc32f

Please sign in to comment.