From 58caaf4ecc61f1cfc9d92b160fad9bd2f5bf8074 Mon Sep 17 00:00:00 2001 From: qwqcode Date: Wed, 28 Aug 2024 23:17:00 +0800 Subject: [PATCH] refactor(ui/user): rename `nick` to `name` in `LocalUser` data structure --- ui/artalk-sidebar/src/App.vue | 4 +- .../src/components/AppHeader.vue | 2 +- .../src/components/AppNavigationMenu.ts | 2 +- ui/artalk-sidebar/src/global.ts | 13 ++++++- ui/artalk-sidebar/src/pages/comments.vue | 4 +- ui/artalk-sidebar/src/pages/login.vue | 6 +-- ui/artalk-sidebar/src/stores/user.ts | 38 ++++++++----------- ui/artalk/src/components/checker/admin.ts | 4 +- ui/artalk/src/config.ts | 2 +- ui/artalk/src/editor/editor.html | 2 +- ui/artalk/src/editor/editor.ts | 2 +- ui/artalk/src/editor/ui.ts | 4 +- ui/artalk/src/lib/user.ts | 10 ++--- ui/artalk/src/load.ts | 2 +- ui/artalk/src/plugins/admin-only-elem.ts | 2 +- ui/artalk/src/plugins/editor/closable.ts | 2 +- ui/artalk/src/plugins/editor/header-user.ts | 10 ++++- ui/artalk/src/plugins/editor/state-edit.ts | 8 ++-- ui/artalk/src/plugins/editor/submit-add.ts | 4 +- ui/artalk/src/plugins/list/sidebar-btn.ts | 4 +- ui/artalk/src/types/config.ts | 19 +++++----- ui/plugin-auth/EditorUser.tsx | 6 +-- ui/plugin-auth/lib/token-login.ts | 21 +++------- ui/plugin-auth/main.tsx | 2 +- 24 files changed, 85 insertions(+), 88 deletions(-) diff --git a/ui/artalk-sidebar/src/App.vue b/ui/artalk-sidebar/src/App.vue index 575436cd5..38c30f13c 100644 --- a/ui/artalk-sidebar/src/App.vue +++ b/ui/artalk-sidebar/src/App.vue @@ -67,7 +67,7 @@ function syncArtalk(artalk: Artalk) { .getApi() .user.getUserStatus({ email: artalkUserData.email, - name: artalkUserData.nick, + name: artalkUserData.name, }) .then((res) => { if (res.data.is_admin && !res.data.is_login) { @@ -76,7 +76,7 @@ function syncArtalk(artalk: Artalk) { // 将全部通知标记为已读 artalk.ctx.getApi().notifies.markAllNotifyRead({ email: artalkUserData.email, - name: artalkUserData.nick, + name: artalkUserData.name, }) } }) diff --git a/ui/artalk-sidebar/src/components/AppHeader.vue b/ui/artalk-sidebar/src/components/AppHeader.vue index 20b8c1edf..ffa98a318 100644 --- a/ui/artalk-sidebar/src/components/AppHeader.vue +++ b/ui/artalk-sidebar/src/components/AppHeader.vue @@ -8,7 +8,7 @@ const nav = useNavStore() const router = useRouter() const user = useUserStore() const { t } = useI18n() -const { site: curtSite, isAdmin, avatar } = storeToRefs(user) +const { site: curtSite, is_admin: isAdmin, avatar } = storeToRefs(user) const avatarClickHandler = () => { if (!isOpenFromSidebar()) logout() diff --git a/ui/artalk-sidebar/src/components/AppNavigationMenu.ts b/ui/artalk-sidebar/src/components/AppNavigationMenu.ts index d26417f83..f9760ed1e 100644 --- a/ui/artalk-sidebar/src/components/AppNavigationMenu.ts +++ b/ui/artalk-sidebar/src/components/AppNavigationMenu.ts @@ -79,7 +79,7 @@ export interface SearchStateApi { */ export const useNavigationMenu = (props: NavigationStoreProps = {}) => { const router = useRouter() - const { isAdmin } = storeToRefs(useUserStore()) + const { is_admin: isAdmin } = storeToRefs(useUserStore()) const { tabs, curtPage, curtTab, isMobile, isSearchEnabled } = storeToRefs(useNavStore()) /** diff --git a/ui/artalk-sidebar/src/global.ts b/ui/artalk-sidebar/src/global.ts index f501db45f..312b2a545 100644 --- a/ui/artalk-sidebar/src/global.ts +++ b/ui/artalk-sidebar/src/global.ts @@ -1,5 +1,5 @@ import Artalk from 'artalk' -import type { ArtalkType } from 'artalk' +import type { LocalUser } from 'artalk' export let artalk: Artalk | null = null @@ -24,10 +24,19 @@ function getBootParams() { window.history.replaceState({}, '', window.location.pathname) } + const userFromURL = JSON.parse(p.get('user') || '{}') + const user: LocalUser = { + name: userFromURL.name || '', + email: userFromURL.email || '', + link: userFromURL.link || '', + token: userFromURL.token || '', + is_admin: userFromURL.is_admin || false, + } + return { + user, pageKey: p.get('pageKey') || '', site: p.get('site') || '', - user: JSON.parse(p.get('user') || '{}'), view: p.get('view') || '', viewParams: null, darkMode: p.get('darkMode') === '1', diff --git a/ui/artalk-sidebar/src/pages/comments.vue b/ui/artalk-sidebar/src/pages/comments.vue index 60d764b9f..ea9f19da5 100644 --- a/ui/artalk-sidebar/src/pages/comments.vue +++ b/ui/artalk-sidebar/src/pages/comments.vue @@ -15,7 +15,7 @@ const search = ref('') onMounted(() => { // 初始化导航条 - if (user.isAdmin) { + if (user.is_admin) { nav.updateTabs( { all: 'all', @@ -55,7 +55,7 @@ onMounted(() => { listFetchParamsModifier: (params) => { params.site_name = curtSite.value // 站点名 - let scope = user.isAdmin ? 'site' : 'user' + let scope = user.is_admin ? 'site' : 'user' let type = curtTab.value if (curtTab.value === 'personal_all') { diff --git a/ui/artalk-sidebar/src/pages/login.vue b/ui/artalk-sidebar/src/pages/login.vue index d4c1dadf3..5b08c48c0 100644 --- a/ui/artalk-sidebar/src/pages/login.vue +++ b/ui/artalk-sidebar/src/pages/login.vue @@ -51,12 +51,8 @@ function login(username?: string) { password: userForm.value.password, }) .then((res) => { - const user = res.data.user artalk.ctx.get('user').update({ - nick: user.name, - email: user.email, - link: user.link, - isAdmin: user.is_admin, + ...res.data.user, token: res.data.token, }) useUserStore().sync() diff --git a/ui/artalk-sidebar/src/stores/user.ts b/ui/artalk-sidebar/src/stores/user.ts index e18303e18..65c5aed5f 100644 --- a/ui/artalk-sidebar/src/stores/user.ts +++ b/ui/artalk-sidebar/src/stores/user.ts @@ -1,42 +1,36 @@ +import type { LocalUser } from 'artalk' import { defineStore } from 'pinia' import sha256 from 'crypto-js/sha256' import md5 from 'crypto-js/md5' import { bootParams, getArtalk } from '../global' +interface UserState extends LocalUser { + /** + * Current site name + */ + site: string +} + export const useUserStore = defineStore('user', { - state: () => ({ - site: bootParams.site || '', - name: bootParams.user.nick || '', - email: bootParams.user.email || '', - isAdmin: bootParams.user.isAdmin || false, - token: bootParams.user.token || '', - }), + state: () => + { + site: bootParams.site || '', + ...bootParams.user, + }, actions: { logout() { - this.site = '' - this.name = '' - this.email = '' - this.isAdmin = false - this.token = '' - + this.$reset() getArtalk()?.ctx.get('user').logout() }, sync() { const user = getArtalk()?.ctx.get('user') if (!user) throw new Error('Artalk is not initialized') if (!user.checkHasBasicUserInfo()) throw new Error('User is not logged in') - const userData = user.getData() - this.site = '' - this.name = userData.nick - this.email = userData.email - this.isAdmin = userData.isAdmin - this.token = userData.token + this.$patch({ ...user.getData(), site: '' }) }, }, getters: { - avatar: (state) => { - return getGravatar(state.email) - }, + avatar: (state) => getGravatar(state.email), }, }) diff --git a/ui/artalk/src/components/checker/admin.ts b/ui/artalk/src/components/checker/admin.ts index bc26e7efb..954bef552 100644 --- a/ui/artalk/src/components/checker/admin.ts +++ b/ui/artalk/src/components/checker/admin.ts @@ -8,7 +8,7 @@ const AdminChecker: Checker<{ token: string }> = { async request(checker, inputVal) { return ( await checker.getApi().user.login({ - name: checker.getUser().getData().nick, + name: checker.getUser().getData().name, email: checker.getUser().getData().email, password: inputVal, }) @@ -21,7 +21,7 @@ const AdminChecker: Checker<{ token: string }> = { onSuccess(checker, res, inputVal, formEl) { checker.getUser().update({ - isAdmin: true, + is_admin: true, token: res.token, }) checker.getOpts().onReload() diff --git a/ui/artalk/src/config.ts b/ui/artalk/src/config.ts index dc69f2158..62de44a36 100644 --- a/ui/artalk/src/config.ts +++ b/ui/artalk/src/config.ts @@ -105,7 +105,7 @@ export function convertApiOptions(conf: Partial, ctx?: ContextApi) getApiToken: () => ctx?.get('user').getData().token, userInfo: ctx?.get('user').checkHasBasicUserInfo() ? { - name: ctx?.get('user').getData().nick, + name: ctx?.get('user').getData().name, email: ctx?.get('user').getData().email, } : undefined, diff --git a/ui/artalk/src/editor/editor.html b/ui/artalk/src/editor/editor.html index 9f7674182..9d6a4215a 100644 --- a/ui/artalk/src/editor/editor.html +++ b/ui/artalk/src/editor/editor.html @@ -1,6 +1,6 @@
- +
diff --git a/ui/artalk/src/editor/editor.ts b/ui/artalk/src/editor/editor.ts index e7b4e0de2..6a3678d71 100644 --- a/ui/artalk/src/editor/editor.ts +++ b/ui/artalk/src/editor/editor.ts @@ -31,7 +31,7 @@ class Editor extends Component implements EditorApi { } getHeaderInputEls() { - return { nick: this.ui.$nick, email: this.ui.$email, link: this.ui.$link } + return { name: this.ui.$name, email: this.ui.$email, link: this.ui.$link } } getContentFinal() { diff --git a/ui/artalk/src/editor/ui.ts b/ui/artalk/src/editor/ui.ts index c54b09a3c..8cfb34c06 100644 --- a/ui/artalk/src/editor/ui.ts +++ b/ui/artalk/src/editor/ui.ts @@ -3,7 +3,7 @@ import EditorHTML from './editor.html?raw' const Sel = { $header: '.atk-header', - $nick: '.atk-header [name="nick"]', + $name: '.atk-header [name="name"]', $email: '.atk-header [name="email"]', $link: '.atk-header [name="link"]', $textareaWrap: '.atk-textarea-wrap', @@ -19,7 +19,7 @@ const Sel = { export interface EditorUI extends Record { $el: HTMLElement - $nick: HTMLInputElement + $name: HTMLInputElement $email: HTMLInputElement $link: HTMLInputElement $textarea: HTMLTextAreaElement diff --git a/ui/artalk/src/lib/user.ts b/ui/artalk/src/lib/user.ts index fec4f76c0..8d0de67a5 100644 --- a/ui/artalk/src/lib/user.ts +++ b/ui/artalk/src/lib/user.ts @@ -15,11 +15,11 @@ class User { // Initialize this.data = { - nick: localUser.nick || '', + name: localUser.name || localUser.nick || '', // nick is deprecated (for historical compatibility) email: localUser.email || '', link: localUser.link || '', token: localUser.token || '', - isAdmin: localUser.isAdmin || false, + is_admin: localUser.is_admin || localUser.isAdmin || false, } } @@ -40,18 +40,18 @@ class User { /** * Logout * - * @description Logout will clear login status, but not clear user data (nick, email, link) + * @description Logout will clear login status, but not clear user data (name, email, link) */ logout() { this.update({ token: '', - isAdmin: false, + is_admin: false, }) } /** Check if user has filled basic data */ checkHasBasicUserInfo() { - return !!this.data.nick && !!this.data.email + return !!this.data.name && !!this.data.email } } diff --git a/ui/artalk/src/load.ts b/ui/artalk/src/load.ts index 878c1e206..1fb43a8d6 100644 --- a/ui/artalk/src/load.ts +++ b/ui/artalk/src/load.ts @@ -138,7 +138,7 @@ export function onLoadErr(ctx: ContextApi, err: any) { errMsg: err.msg || String(err), errData: err.data, retryFn: () => load(ctx), - onOpenSidebar: ctx.get('user').getData().isAdmin + onOpenSidebar: ctx.get('user').getData().is_admin ? () => ctx.showSidebar({ view: sidebarOpenView as any, diff --git a/ui/artalk/src/plugins/admin-only-elem.ts b/ui/artalk/src/plugins/admin-only-elem.ts index d9ed6b312..7f7b3c1b5 100644 --- a/ui/artalk/src/plugins/admin-only-elem.ts +++ b/ui/artalk/src/plugins/admin-only-elem.ts @@ -3,7 +3,7 @@ import type { ArtalkPlugin } from '@/types' export const AdminOnlyElem: ArtalkPlugin = (ctx) => { const scanApply = () => { applyAdminOnlyEls( - ctx.get('user').getData().isAdmin, + ctx.get('user').getData().is_admin, getAdminOnlyEls({ $root: ctx.$root, }), diff --git a/ui/artalk/src/plugins/editor/closable.ts b/ui/artalk/src/plugins/editor/closable.ts index c5f2b98bb..58ac8959b 100644 --- a/ui/artalk/src/plugins/editor/closable.ts +++ b/ui/artalk/src/plugins/editor/closable.ts @@ -34,7 +34,7 @@ export default class Closable extends EditorPlug { Utils.createElement(`
${$t('onlyAdminCanReply')}
`), ) - if (!this.kit.useUser().getData().isAdmin) { + if (!this.kit.useUser().getData().is_admin) { this.kit.useUI().$textarea.style.display = 'none' this.kit.useEvents().trigger('panel-close') this.kit.useUI().$bottom.style.display = 'none' diff --git a/ui/artalk/src/plugins/editor/header-user.ts b/ui/artalk/src/plugins/editor/header-user.ts index a6ba2e456..1eb5113cd 100644 --- a/ui/artalk/src/plugins/editor/header-user.ts +++ b/ui/artalk/src/plugins/editor/header-user.ts @@ -14,13 +14,19 @@ export default class HeaderUser extends EditorPlug { this.kit.useUser().update({ [field]: $input.value.trim() }) // remote fetch user info - if (field === 'nick' || field === 'email') this.fetchUserInfo() // must after update user data, since fetchUserInfo() will use User.data + if (field === 'name' || field === 'email') this.fetchUserInfo() // must after update user data, since fetchUserInfo() will use User.data + } + + const placeholders = { + name: $t('nick'), + email: $t('email'), + link: $t('link'), } this.kit.useMounted(() => { Object.entries(this.kit.useEditor().getHeaderInputEls()).forEach(([key, $input]) => { // set placeholder - $input.placeholder = `${$t(key as any)}` + $input.placeholder = placeholders[key] // sync header values from User.data $input.value = this.kit.useUser().getData()[key] || '' diff --git a/ui/artalk/src/plugins/editor/state-edit.ts b/ui/artalk/src/plugins/editor/state-edit.ts index 68279216d..834d69d71 100644 --- a/ui/artalk/src/plugins/editor/state-edit.ts +++ b/ui/artalk/src/plugins/editor/state-edit.ts @@ -30,7 +30,7 @@ export default class StateEdit extends EditorPlug { req: async () => { const saveData = { content: this.kit.useEditor().getContentFinal(), - nick: this.kit.useUI().$nick.value, + nick: this.kit.useUI().$name.value, email: this.kit.useUI().$email.value, link: this.kit.useUI().$link.value, } @@ -69,7 +69,7 @@ export default class StateEdit extends EditorPlug { ui.$header.style.display = 'none' // TODO: support modify header information - ui.$nick.value = comment.nick || '' + ui.$name.value = comment.nick || '' ui.$email.value = comment.email || '' ui.$link.value = comment.link || '' @@ -91,8 +91,8 @@ export default class StateEdit extends EditorPlug { this.comment = undefined - const { nick, email, link } = this.kit.useUser().getData() - ui.$nick.value = nick + const { name, email, link } = this.kit.useUser().getData() + ui.$name.value = name ui.$email.value = email ui.$link.value = link diff --git a/ui/artalk/src/plugins/editor/submit-add.ts b/ui/artalk/src/plugins/editor/submit-add.ts index 0f3322dfb..62ca0d62d 100644 --- a/ui/artalk/src/plugins/editor/submit-add.ts +++ b/ui/artalk/src/plugins/editor/submit-add.ts @@ -15,12 +15,12 @@ export default class SubmitAddPreset { } async getSubmitAddParams() { - const { nick, email, link } = this.kit.useUser().getData() + const { name, email, link } = this.kit.useUser().getData() const conf = this.kit.useConf() return { content: this.kit.useEditor().getContentFinal(), - name: nick, + name, email, link, rid: 0, diff --git a/ui/artalk/src/plugins/list/sidebar-btn.ts b/ui/artalk/src/plugins/list/sidebar-btn.ts index 139ab75f8..2f9c82e5e 100644 --- a/ui/artalk/src/plugins/list/sidebar-btn.ts +++ b/ui/artalk/src/plugins/list/sidebar-btn.ts @@ -9,12 +9,12 @@ export const SidebarBtn: ArtalkPlugin = (ctx) => { const user = ctx.get('user').getData() // 已输入个人信息 - if (!!user.nick && !!user.email) { + if (!!user.name && !!user.email) { $openSidebarBtn.classList.remove('atk-hide') // update button text (normal user or admin) const $btnText = $openSidebarBtn.querySelector('.atk-text') - if ($btnText) $btnText.innerText = !user.isAdmin ? $t('msgCenter') : $t('ctrlCenter') + if ($btnText) $btnText.innerText = !user.is_admin ? $t('msgCenter') : $t('ctrlCenter') } else { $openSidebarBtn.classList.add('atk-hide') } diff --git a/ui/artalk/src/types/config.ts b/ui/artalk/src/types/config.ts index 2ba54d640..74c72bd37 100644 --- a/ui/artalk/src/types/config.ts +++ b/ui/artalk/src/types/config.ts @@ -155,22 +155,23 @@ export interface ArtalkConfig { } /** - * 本地持久化用户数据 - * @note 始终保持一层结构,不支持多层结构 + * Local User Data (in localStorage) + * + * @note Keep flat for easy handling */ export interface LocalUser { - /** 昵称 */ - nick: string + /** Username (aka. Nickname) */ + name: string - /** 邮箱 */ + /** Email */ email: string - /** 链接 */ + /** Link (aka. Website) */ link: string - /** TOKEN */ + /** Token (for authorization) */ token: string - /** 是否为管理员 */ - isAdmin: boolean + /** Admin flag */ + is_admin: boolean } diff --git a/ui/plugin-auth/EditorUser.tsx b/ui/plugin-auth/EditorUser.tsx index be6bd94ba..592609174 100644 --- a/ui/plugin-auth/EditorUser.tsx +++ b/ui/plugin-auth/EditorUser.tsx @@ -7,10 +7,10 @@ const EditorUser = ({ ctx }: { ctx: ContextApi }) => { window.confirm(ctx.$t('logoutConfirm')) && ctx.get('user').update({ token: '', - nick: '', + name: '', email: '', link: '', - isAdmin: false, + is_admin: false, }) } @@ -33,7 +33,7 @@ const EditorUser = ({ ctx }: { ctx: ContextApi }) => {
{ - const { user, token } = data +export const loginByApiRes = (ctx: ContextApi, { user, token }: ResponseLoginData) => { ctx.get('user').update({ - nick: user.name, - email: user.email, - link: user.link, - isAdmin: user.is_admin, + ...user, token, }) } @@ -29,10 +20,10 @@ export const loginByToken = (ctx: ContextApi, token: string) => { .then((res) => { const { user } = res.data ctx.get('user').update({ - nick: user.name, + name: user.name, email: user.email, link: user.link, - isAdmin: user.is_admin, + is_admin: user.is_admin, }) }) } diff --git a/ui/plugin-auth/main.tsx b/ui/plugin-auth/main.tsx index 067f04968..ce11bd46b 100644 --- a/ui/plugin-auth/main.tsx +++ b/ui/plugin-auth/main.tsx @@ -30,7 +30,7 @@ export const ArtalkAuthPlugin: ArtalkPlugin = (ctx) => { const onSkip = () => { ctx.get('editor').getUI().$header.style.display = '' - ctx.get('editor').getUI().$nick.focus() + ctx.get('editor').getUI().$name.focus() ctx.updateConf({ beforeSubmit: undefined, })