Skip to content

Commit

Permalink
✨ feat: suported proInputArea extraModel
Browse files Browse the repository at this point in the history
  • Loading branch information
绾歌 committed Jun 20, 2024
1 parent c35afe4 commit d7a4129
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 46 deletions.
26 changes: 26 additions & 0 deletions src/ProChat/components/ProInputArea/AudioLines.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { memo } from 'react';

const AudioIcon = memo(() => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="lucide lucide-audio-lines"
>
<path d="M2 10v3" />
<path d="M6 6v11" />
<path d="M10 3v18" />
<path d="M14 8v7" />
<path d="M18 5v13" />
<path d="M22 10v3" />
</svg>
);
});
export default AudioIcon;
2 changes: 1 addition & 1 deletion src/ProChat/components/ProInputArea/ControlPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const ActionBar = ({ className }: { className?: string }) => {
>
<ActionIcon title={localeObject.clearCurrentDialogue} icon={Trash2} />
</Popconfirm>,
<ActionIcon key={'refresh'} title={localeObject.refresh} icon={RotateCw} />,
<ActionIcon key={'regenerate'} title={localeObject.regenerate} icon={RotateCw} />,
<ActionIcon key={'connectNetwork'} title={localeObject.connectNetwork} icon={Globe} />,
];

Expand Down
87 changes: 56 additions & 31 deletions src/ProChat/components/ProInputArea/ExtraModel.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,72 @@
import { createStyles, cx } from 'antd-style';
import { Flexbox } from 'react-layout-kit';

import ActionIcon from '@/ActionIcon';
import { ConfigProvider, Popconfirm } from 'antd';
import { Globe, RotateCw, Trash2 } from 'lucide-react';

import useProChatLocale from '@/ProChat/hooks/useProChatLocale';
import { useStore } from '../../store';
import { ConfigProvider } from 'antd';
import { createStyles, cx } from 'antd-style';
import { isObject, isString } from 'lodash-es';
import { FileVideo, Image } from 'lucide-react';
import { Flexbox } from 'react-layout-kit';
import AudioIcon from './AudioLines';

const useStyles = createStyles(({ css, token }) => ({
extra: css`
color: ${token.colorTextTertiary};
`,
}));

export const ActionBar = ({ className }: { className?: string }) => {
const [clearMessage, actionsRender, flexConfig] = useStore((s) => [
s.clearMessage,
s.actions?.render,
s.actions?.flexConfig,
]);
export type ExtraType = 'image' | 'audio' | 'video';
export interface ExtraItem {
type: ExtraType;
onChange?: () => void;
onFinish?: () => void;
render: () => JSX.Element;
}
export type ExtraModelProps = {
className?: string;
extra?: Array<ExtraItem | ExtraType>;
};

export const ExtraModel = (props: ExtraModelProps) => {
const { className, extra } = props;

const { localeObject } = useProChatLocale();

const { styles, theme } = useStyles();
const defaultDoms = [
<Popconfirm
title={localeObject.clearModalTitle}
okButtonProps={{ danger: true }}
okText={localeObject.clearDialogue}
cancelText={localeObject.cancel}
key={'clear'}
onConfirm={() => {
clearMessage();
}}
>
<ActionIcon title={localeObject.clearCurrentDialogue} icon={Trash2} />
</Popconfirm>,
<ActionIcon key={'refresh'} title={localeObject.refresh} icon={RotateCw} />,
<ActionIcon key={'connectNetwork'} title={localeObject.connectNetwork} icon={Globe} />,
{
type: 'video',
render: <ActionIcon key={'video'} title={localeObject.video} icon={FileVideo} />,
},
{
type: 'audio',
render: <ActionIcon key={'audio'} title={localeObject.audio} icon={AudioIcon} />,
},
{
type: 'image',
render: <ActionIcon key={'image'} title={localeObject.image} icon={Image} />,
},
];

const { styles, theme } = useStyles();

const renderContent = () => {
if (!extra || extra.length === 0) {
return null;
}

const getDefaultRender = (type: ExtraType) => {
const defaultComponent = defaultDoms.find((dom) => dom.type === type);
return defaultComponent ? defaultComponent.render : null;
};

return extra.reverse().map((item) => {
if (isString(item)) {
return getDefaultRender(item as ExtraType);
} else if (isObject(item) && 'type' in item && 'render' in item) {
return item.render();
} else {
return null;
}
});
};
return (
<ConfigProvider theme={{ token: { colorText: theme.colorTextSecondary } }}>
<Flexbox
Expand All @@ -49,12 +75,11 @@ export const ActionBar = ({ className }: { className?: string }) => {
paddingInline={12}
className={cx(styles.extra, className)}
gap={8}
{...flexConfig}
>
{actionsRender?.(defaultDoms) ?? defaultDoms}
{renderContent()}
</Flexbox>
</ConfigProvider>
);
};

export default ActionBar;
export default ExtraModel;
29 changes: 15 additions & 14 deletions src/ProChat/components/ProInputArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ReactNode, useContext, useEffect, useMemo, useRef, useState } from 'rea
import { Flexbox } from 'react-layout-kit';
import { useStore } from '../../store';
import ControlPanel from './ControlPanel';
import ExtraModel, { ExtraItem, ExtraType } from './ExtraModel';
import { ProTextArea } from './ProTextArea';
import StopLoadingIcon from './StopLoading';
const ENTER = 'enter';
Expand Down Expand Up @@ -52,17 +53,7 @@ const useStyles = createStyles(({ css, responsive, token }) => ({
color: ${token.colorTextTertiary};
`,
}));
export enum ExtraType {
Image = 'image',
Voice = 'voice',
Video = 'video',
}
export interface ExtraItem {
type: ExtraType;
onChange?: () => void;
onFinish?: () => void;
render: () => JSX.Element;
}

export type ProInputAreaProps = {
className?: string;
extra?: Array<ExtraItem | ExtraType>;
Expand All @@ -83,8 +74,15 @@ export type ProInputAreaProps = {

export const ProInputArea = (props: ProInputAreaProps) => {
// 拿到 Props 中的 需求
const { className, onSend, inputAreaRender, inputRender, sendButtonRender, sendShortcutKey } =
props || {};
const {
className,
onSend,
inputAreaRender,
inputRender,
sendButtonRender,
sendShortcutKey,
extra,
} = props || {};
// 拿到 本地仓库 透出的 方法
const [sendMessage, isLoading, placeholder, inputAreaProps, clearMessage, stopGenerateMessage] =
useStore((s) => [
Expand Down Expand Up @@ -243,7 +241,10 @@ export const ProInputArea = (props: ProInputAreaProps) => {
}}
>
<Flexbox gap={8} padding={16} className={cx(styles.container, `${prefixClass}`, className)}>
<ControlPanel className={`${prefixClass}-action-bar`} />
<Flexbox horizontal justify="space-between">
<ExtraModel className={`${prefixClass}-extra`} extra={extra} />
<ControlPanel className={`${prefixClass}-action-bar`} />
</Flexbox>
<Flexbox
horizontal
gap={8}
Expand Down
11 changes: 11 additions & 0 deletions src/ProChat/container/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Flexbox } from 'react-layout-kit';

import { ChatListItemProps } from '@/ChatList/ChatListItem';
import { ConfigProvider } from 'antd';
import { ALargeSmall } from 'lucide-react';

Check failure on line 9 in src/ProChat/container/App.tsx

View workflow job for this annotation

GitHub Actions / test

Module '"lucide-react"' has no exported member 'ALargeSmall'.
import ChatList from '../components/ChatList';
import ProInputArea, { ProInputAreaProps } from '../components/ProInputArea';
import ChatScrollAnchor from '../components/ScrollAnchor';
Expand Down Expand Up @@ -170,6 +171,16 @@ const App = memo<ConversationProps>(
inputAreaRender={inputAreaRender || renderInputArea}
inputRender={inputRender}
sendShortcutKey="enter"
extra={[
'image',
'audio',
{
type: 'video',
render: () => {
return <ALargeSmall></ALargeSmall>;
},
},
]}
/>
}
</div>
Expand Down

0 comments on commit d7a4129

Please sign in to comment.