feat: 增加系统设置页面的自定义设置项注册(for plugin)

pull/64/head
moonrailgun 3 years ago
parent badfaa07d3
commit e9b96a15a2

@ -11,10 +11,19 @@ import {
fetchServiceRegistryPlugins,
PluginManifest,
} from '../model/plugin';
import { fetchUserInfo, UserBaseInfo } from '../model/user';
import { fetchUserInfo, getUserSettings, UserBaseInfo } from '../model/user';
import { parseUrlStr } from '../utils/url-helper';
import { queryClient } from './index';
export enum CacheKey {
user = 'user',
converse = 'converse',
baseGroupInfo = 'baseGroupInfo',
groupInvite = 'groupInvite',
pluginRegistry = 'pluginRegistry',
userSettings = 'userSettings',
}
/**
*
*/
@ -23,7 +32,7 @@ export async function getCachedUserInfo(
refetch = false
): Promise<UserBaseInfo> {
const data = await queryClient.fetchQuery(
['user', userId],
[CacheKey.user, userId],
() => fetchUserInfo(userId),
{
staleTime: refetch ? 0 : 2 * 60 * 60 * 1000, // 缓存2小时
@ -39,8 +48,9 @@ export async function getCachedUserInfo(
export async function getCachedConverseInfo(
converseId: string
): Promise<ChatConverseInfo> {
const data = await queryClient.fetchQuery(['converse', converseId], () =>
fetchConverseInfo(converseId)
const data = await queryClient.fetchQuery(
[CacheKey.converse, converseId],
() => fetchConverseInfo(converseId)
);
return data;
@ -52,8 +62,9 @@ export async function getCachedConverseInfo(
export async function getCachedBaseGroupInfo(
groupId: string
): Promise<GroupBasicInfo | null> {
const data = await queryClient.fetchQuery(['baseGroupInfo', groupId], () =>
getGroupBasicInfo(groupId)
const data = await queryClient.fetchQuery(
[CacheKey.baseGroupInfo, groupId],
() => getGroupBasicInfo(groupId)
);
return data;
@ -65,8 +76,9 @@ export async function getCachedBaseGroupInfo(
export async function getCachedGroupInviteInfo(
inviteCode: string
): Promise<GroupInvite | null> {
const data = await queryClient.fetchQuery(['groupInvite', inviteCode], () =>
findGroupInviteByCode(inviteCode)
const data = await queryClient.fetchQuery(
[CacheKey.groupInvite, inviteCode],
() => findGroupInviteByCode(inviteCode)
);
return data;
@ -77,7 +89,7 @@ export async function getCachedGroupInviteInfo(
*/
export async function getCachedRegistryPlugins(): Promise<PluginManifest[]> {
const data = await queryClient.fetchQuery(
['pluginRegistry'],
[CacheKey.pluginRegistry],
() =>
Promise.all([
fetchRegistryPlugins().catch(() => []),
@ -111,3 +123,18 @@ export async function getCachedRegistryPlugins(): Promise<PluginManifest[]> {
return data;
}
/**
*
*/
export async function getCachedUserSettings() {
const data = await queryClient.fetchQuery(
[CacheKey.userSettings],
() => getUserSettings,
{
staleTime: 1 * 60 * 1000, // 缓存1分钟
}
);
return data;
}

@ -2,7 +2,7 @@ import { useEffect } from 'react';
import { useUpdateRef } from '../hooks/useUpdateRef';
import type { ChatMessage, SendMessagePayload } from '../model/message';
import { EventEmitter } from 'eventemitter-strict';
import type { UserBaseInfo } from '../model/user';
import type { UserBaseInfo, UserSettings } from '../model/user';
/**
*
@ -51,6 +51,11 @@ export interface SharedEventMap {
*
*/
groupPanelBadgeUpdate: () => void;
/**
*
*/
userSettingsUpdate: (userSettings: UserSettings) => void;
}
export type SharedEventType = keyof SharedEventMap;

@ -1,4 +1,6 @@
import { CacheKey } from '../../cache/cache';
import { useQuery, useQueryClient } from '../../cache/useCache';
import { sharedEvent } from '../../event';
import {
getUserSettings,
setUserSettings,
@ -12,7 +14,7 @@ import { useAsyncRequest } from '../useAsyncRequest';
export function useUserSettings() {
const client = useQueryClient();
const { data: settings, isLoading } = useQuery(
['useUserSettings'],
[CacheKey],
() => getUserSettings(),
{
staleTime: 1 * 60 * 1000, // 缓存1分钟
@ -23,7 +25,8 @@ export function useUserSettings() {
async (settings: UserSettings) => {
const newSettings = await setUserSettings(settings);
client.setQueryData(['useUserSettings'], () => newSettings);
client.setQueryData([CacheKey], () => newSettings);
sharedEvent.emit('userSettingsUpdate', newSettings);
},
[client]
);

@ -12,6 +12,7 @@ export {
getCachedBaseGroupInfo,
getCachedGroupInviteInfo,
getCachedRegistryPlugins,
getCachedUserSettings,
} from './cache/cache';
export { useCachedUserInfo, useCachedOnlineStatus } from './cache/useCache';

@ -27,6 +27,11 @@ export interface UserSettings {
*
*/
messageListVirtualization?: boolean;
/**
*
*/
[key: string]: any;
}
export function pickUserBaseInfo(userInfo: UserLoginInfo) {

@ -0,0 +1,105 @@
import { Select, Switch } from 'antd';
import React from 'react';
import {
DefaultFullModalInputEditorRender,
DefaultFullModalTextAreaEditorRender,
FullModalField,
} from './Field';
export type FullModalFactoryConfig = {
name: string;
label: string;
desc?: string;
} & (
| {
type: 'text';
}
| {
type: 'textarea';
}
| {
type: 'boolean';
}
| {
type: 'select';
options: { label: string; value: string }[];
}
);
interface FullModalFactoryProps<T = any> {
value: T;
onChange: (val: T) => void;
config: FullModalFactoryConfig;
}
/**
*
*/
export const FullModalFactory: React.FC<FullModalFactoryProps> = React.memo(
(props) => {
const { value, onChange, config } = props;
if (config.type === 'text') {
return (
<FullModalField
title={config.label}
value={value}
editable={true}
renderEditor={DefaultFullModalInputEditorRender}
onSave={(val) => onChange(val)}
/>
);
}
if (config.type === 'textarea') {
return (
<FullModalField
title={config.label}
value={value}
editable={true}
renderEditor={DefaultFullModalTextAreaEditorRender}
onSave={(val) => onChange(val)}
/>
);
}
if (config.type === 'boolean') {
return (
<FullModalField
title={config.label}
tip={config.desc}
content={
<Switch
checked={value ?? false}
onChange={(checked) => onChange(checked)}
/>
}
/>
);
}
if (config.type === 'select') {
return (
<FullModalField
title={config.label}
tip={config.desc}
content={
<Select
style={{ width: 280 }}
size="large"
value={value}
onChange={(val) => onChange(val)}
>
{config.options.map((opt) => (
<Select.Option key={opt.value} value={opt.value}>
{opt.label}
</Select.Option>
))}
</Select>
}
/>
);
}
return null;
}
);
FullModalFactory.displayName = 'FullModalFactory';

@ -1,23 +1,20 @@
import { FullModalFactory } from '@/components/FullModal/Factory';
import { FullModalField } from '@/components/FullModal/Field';
import { LanguageSelect } from '@/components/LanguageSelect';
import { pluginColorScheme } from '@/plugin/common';
import { pluginColorScheme, pluginSettings } from '@/plugin/common';
import { Select, Switch } from 'antd';
import React from 'react';
import {
AlphaContainer,
t,
useAlphaMode,
useColorScheme,
useSingleUserSetting,
useUserSettings,
} from 'tailchat-shared';
import _get from 'lodash/get';
export const SettingsSystem: React.FC = React.memo(() => {
const { colorScheme, setColorScheme } = useColorScheme();
const {
value: messageListVirtualization,
setValue: setMessageListVirtualization,
loading,
} = useSingleUserSetting('messageListVirtualization', false);
const { settings, setSettings, loading } = useUserSettings();
const { isAlphaMode, setAlphaMode } = useAlphaMode();
return (
@ -45,6 +42,23 @@ export const SettingsSystem: React.FC = React.memo(() => {
}
/>
{pluginSettings
.filter((item) => item.position === 'system')
.map((item) => {
return (
<FullModalFactory
key={item.name}
value={_get(settings, item.name, false)}
onChange={(val) => {
setSettings({
[item.name]: val,
});
}}
config={item}
/>
);
})}
<FullModalField
title={t('Alpha测试开关')}
tip={t(
@ -52,7 +66,6 @@ export const SettingsSystem: React.FC = React.memo(() => {
)}
content={
<Switch
disabled={loading}
checked={isAlphaMode}
onChange={(checked) => setAlphaMode(checked)}
/>
@ -65,8 +78,13 @@ export const SettingsSystem: React.FC = React.memo(() => {
content={
<Switch
disabled={loading}
checked={messageListVirtualization}
onChange={(checked) => setMessageListVirtualization(checked)}
loading={loading}
checked={settings.messageListVirtualization ?? false}
onChange={(checked) =>
setSettings({
messageListVirtualization: checked,
})
}
/>
}
/>

@ -38,6 +38,7 @@ export {
getCachedUserInfo,
getCachedConverseInfo,
getCachedBaseGroupInfo,
getCachedUserSettings,
localTrans,
getLanguage,
sharedEvent,

@ -8,6 +8,7 @@ import {
PermissionItemType,
} from 'tailchat-shared';
import type { MetaFormFieldMeta } from 'tailchat-design';
import type { FullModalFactoryConfig } from '@/components/FullModal/Factory';
/**
*
@ -254,3 +255,13 @@ interface PluginUserExtraInfo {
*/
export const [pluginUserExtraInfo, regUserExtraInfo] =
buildRegList<PluginUserExtraInfo>();
type PluginSettings = FullModalFactoryConfig & {
position: 'system'; // 后面可能还会有个人设置/群组设置
};
/**
*
*/
export const [pluginSettings, regPluginSettings] =
buildRegList<PluginSettings>();

Loading…
Cancel
Save