feat: 增加列表虚拟化与个人设置项

pull/81/head
moonrailgun 3 years ago
parent 6d8d260b42
commit cb7ccf8c77

@ -0,0 +1,55 @@
import { useQuery, useQueryClient } from 'react-query';
import {
getUserSettings,
setUserSettings,
UserSettings,
} from '../../model/user';
import { useAsyncRequest } from '../useAsyncRequest';
/**
* hooks
*/
export function useUserSettings() {
const client = useQueryClient();
const { data: settings, isLoading } = useQuery(
['useUserSettings'],
() => getUserSettings(),
{
staleTime: 1 * 60 * 1000, // 缓存1分钟
}
);
const [{ loading: saveLoading }, setSettings] = useAsyncRequest(
async (settings: UserSettings) => {
const newSettings = await setUserSettings(settings);
client.setQueryData(['useUserSettings'], () => newSettings);
},
[client]
);
return {
settings: settings ?? {},
setSettings,
loading: isLoading || saveLoading,
};
}
/**
*
*/
export function useSingleUserSetting<T>(
name: keyof UserSettings,
defaultValue?: T
) {
const { settings, setSettings, loading } = useUserSettings();
return {
value: settings[name] ?? defaultValue,
setValue: async (newVal: T) =>
setSettings({
[name]: newVal,
}),
loading,
};
}

@ -11,6 +11,7 @@
"k1885734a": "Effective after refreshing the page", "k1885734a": "Effective after refreshing the page",
"k18c716ce": "Password cannot be less than 6 digits", "k18c716ce": "Password cannot be less than 6 digits",
"k19885be1": "Panel name is too long", "k19885be1": "Panel name is too long",
"k1a377364": "Message List Virtualization",
"k1b38bb5c": "Register Now", "k1b38bb5c": "Register Now",
"k1bd56481": "Close independent window", "k1bd56481": "Close independent window",
"k1cbe2507": "Confirm", "k1cbe2507": "Confirm",

@ -11,6 +11,7 @@
"k1885734a": "刷新页面后生效", "k1885734a": "刷新页面后生效",
"k18c716ce": "密码不能低于6位", "k18c716ce": "密码不能低于6位",
"k19885be1": "面板名过长", "k19885be1": "面板名过长",
"k1a377364": "聊天列表虚拟化",
"k1b38bb5c": "立即注册", "k1b38bb5c": "立即注册",
"k1bd56481": "关闭独立窗口", "k1bd56481": "关闭独立窗口",
"k1cbe2507": "确认", "k1cbe2507": "确认",

@ -66,6 +66,10 @@ export { useLanguage } from './i18n/language';
// hooks // hooks
export { useAvailableServices } from './hooks/model/useAvailableServices'; export { useAvailableServices } from './hooks/model/useAvailableServices';
export { useUsernames } from './hooks/model/useUsernames'; export { useUsernames } from './hooks/model/useUsernames';
export {
useUserSettings,
useSingleUserSetting,
} from './hooks/model/useUserSettings';
export { useAsync } from './hooks/useAsync'; export { useAsync } from './hooks/useAsync';
export { useAsyncFn } from './hooks/useAsyncFn'; export { useAsyncFn } from './hooks/useAsyncFn';
export { useAsyncRefresh } from './hooks/useAsyncRefresh'; export { useAsyncRefresh } from './hooks/useAsyncRefresh';
@ -135,7 +139,7 @@ export type {
SendMessagePayloadMeta, SendMessagePayloadMeta,
} from './model/message'; } from './model/message';
export type { PluginManifest } from './model/plugin'; export type { PluginManifest } from './model/plugin';
export type { UserBaseInfo, UserLoginInfo } from './model/user'; export type { UserBaseInfo, UserLoginInfo, UserSettings } from './model/user';
export { export {
loginWithEmail, loginWithEmail,
loginWithToken, loginWithToken,

@ -16,6 +16,13 @@ export interface UserLoginInfo extends UserBaseInfo {
createdAt: string; createdAt: string;
} }
export interface UserSettings {
/**
*
*/
messageListVirtualization?: boolean;
}
// 内置用户信息 // 内置用户信息
const builtinUserInfo: Record<string, UserBaseInfo> = { const builtinUserInfo: Record<string, UserBaseInfo> = {
[SYSTEM_USERID]: { [SYSTEM_USERID]: {
@ -237,6 +244,28 @@ export async function modifyUserField(
return data; return data;
} }
/**
*
*/
export async function getUserSettings(): Promise<UserSettings> {
const { data } = await request.get('/api/user/getUserSettings');
return data;
}
/**
*
*/
export async function setUserSettings(
settings: UserSettings
): Promise<UserSettings> {
const { data } = await request.post('/api/user/setUserSettings', {
settings,
});
return data;
}
/** /**
* Token * Token
*/ */

@ -1,12 +1,21 @@
import { LoadingSpinner } from '@/components/LoadingSpinner';
import React from 'react'; import React from 'react';
import { useSingleUserSetting } from 'tailchat-shared';
import { NormalMessageList } from './NormalList'; import { NormalMessageList } from './NormalList';
import type { MessageListProps } from './types'; import type { MessageListProps } from './types';
import { VirtualizedMessageList } from './VirtualizedList'; import { VirtualizedMessageList } from './VirtualizedList';
const useVirtualizedList = true; // 是否使用虚拟化列表
export const ChatMessageList: React.FC<MessageListProps> = React.memo( export const ChatMessageList: React.FC<MessageListProps> = React.memo(
(props) => { (props) => {
const { value: useVirtualizedList, loading } = useSingleUserSetting(
'messageListVirtualization',
false
);
if (loading) {
return <LoadingSpinner />;
}
return useVirtualizedList ? ( return useVirtualizedList ? (
<div className="flex-1"> <div className="flex-1">
<VirtualizedMessageList {...props} /> <VirtualizedMessageList {...props} />

@ -1,13 +1,23 @@
import { FullModalField } from '@/components/FullModal/Field'; import { FullModalField } from '@/components/FullModal/Field';
import { pluginColorScheme } from '@/plugin/common'; import { pluginColorScheme } from '@/plugin/common';
import { Select } from 'antd'; import { Select, Switch } from 'antd';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { showToasts, t, useColorScheme } from 'tailchat-shared'; import {
showToasts,
t,
useColorScheme,
useSingleUserSetting,
} from 'tailchat-shared';
import { useLanguage } from 'tailchat-shared'; import { useLanguage } from 'tailchat-shared';
export const SettingsSystem: React.FC = React.memo(() => { export const SettingsSystem: React.FC = React.memo(() => {
const { language, setLanguage } = useLanguage(); const { language, setLanguage } = useLanguage();
const { colorScheme, setColorScheme } = useColorScheme(); const { colorScheme, setColorScheme } = useColorScheme();
const {
value: messageListVirtualization,
setValue: setMessageListVirtualization,
loading,
} = useSingleUserSetting('messageListVirtualization', false);
const handleChangeLanguage = useCallback( const handleChangeLanguage = useCallback(
(newLang: string) => { (newLang: string) => {
@ -54,6 +64,17 @@ export const SettingsSystem: React.FC = React.memo(() => {
</Select> </Select>
} }
/> />
<FullModalField
title={t('聊天列表虚拟化') + ' (Beta)'}
content={
<Switch
disabled={loading}
checked={messageListVirtualization}
onChange={(checked) => setMessageListVirtualization(checked)}
/>
}
/>
</div> </div>
); );
}); });

Loading…
Cancel
Save