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",
"k18c716ce": "Password cannot be less than 6 digits",
"k19885be1": "Panel name is too long",
"k1a377364": "Message List Virtualization",
"k1b38bb5c": "Register Now",
"k1bd56481": "Close independent window",
"k1cbe2507": "Confirm",

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

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

@ -16,6 +16,13 @@ export interface UserLoginInfo extends UserBaseInfo {
createdAt: string;
}
export interface UserSettings {
/**
*
*/
messageListVirtualization?: boolean;
}
// 内置用户信息
const builtinUserInfo: Record<string, UserBaseInfo> = {
[SYSTEM_USERID]: {
@ -237,6 +244,28 @@ export async function modifyUserField(
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
*/

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

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

Loading…
Cancel
Save