diff --git a/src/components/Author/index.tsx b/src/components/Author/index.tsx new file mode 100644 index 00000000..07231fd5 --- /dev/null +++ b/src/components/Author/index.tsx @@ -0,0 +1,37 @@ +import { Space, Typography } from 'antd'; +import { createStyles } from 'antd-style'; +import React, { memo } from 'react'; + +const { Link } = Typography; +const useStyles = createStyles(({ css, token }) => ({ + author: css` + font-size: ${token.fontSizeSM}px; + `, + date: css` + font-size: ${token.fontSizeSM}px; + color: ${token.colorTextDescription}; + `, +})); + +interface Props { + item?: { author: string; createAt: string; homepage: string }; +} + +export default memo((props: Props) => { + const { item } = props; + + const { styles } = useStyles(); + return ( + + + @{item?.author} + +
{item?.createAt}
+
+ ); +}); diff --git a/src/components/DanceInfo/index.tsx b/src/components/DanceInfo/index.tsx index 70b41873..9d77950c 100644 --- a/src/components/DanceInfo/index.tsx +++ b/src/components/DanceInfo/index.tsx @@ -10,11 +10,12 @@ import { useStyles } from './style'; interface DanceInfoProps { actions?: React.ReactNode[]; dance?: Dance; + extra?: React.ReactNode; } const DanceInfo = (props: DanceInfoProps) => { const { styles, theme } = useStyles(); - const { dance, actions = [] } = props; + const { dance, actions = [], extra } = props; const { name, readme, cover } = dance || {}; return ( @@ -25,6 +26,7 @@ const DanceInfo = (props: DanceInfoProps) => {
{actions}
+ {extra}
{readme}
diff --git a/src/constants/agent.ts b/src/constants/agent.ts index b7cf12a6..84a96dd0 100644 --- a/src/constants/agent.ts +++ b/src/constants/agent.ts @@ -1,9 +1,13 @@ -import { Agent } from '@/types/agent'; +import { Agent, CategoryEnum } from '@/types/agent'; export const V_CHAT_DEFAULT_AGENT_ID = 'v-chat-default-market'; export const DEFAULT_AGENT: Agent = { agentId: V_CHAT_DEFAULT_AGENT_ID, + greeting: '哈喽,亲爱的主人!我是你的私人助理维C,愉快地为你服务!有什么我可以帮你的吗?', + createAt: '2023-10-30', + author: 'Vidol', + homepage: '/~https://github.com/lobehub/lobe-vidol', meta: { avatar: 'https://registry.npmmirror.com/@v-idol/vidol-agent-sample-a/1.0.0/files/avatar.jpg', cover: 'https://registry.npmmirror.com/@v-idol/vidol-agent-sample-a/1.0.0/files/cover.jpg', @@ -11,6 +15,7 @@ export const DEFAULT_AGENT: Agent = { homepage: 'https://hub.vroid.com/characters/2843975675147313744/models/5644550979324015604', model: 'https://registry.npmmirror.com/@v-idol/vidol-agent-sample-a/1.0.0/files/model.vrm', name: '维 C', + category: CategoryEnum.VROID, readme: "AvatarSample_Aは、VRoid Studioに付属されているサンプルモデルの1つです。\r\n良識の範囲内で、本モデルに設定されているVRoid Hubの利用条件に沿って利用することができます。\r\nVRoid Hub連携アプリや、外部サービス等でぜひご活用ください。\r\nなお、本モデルはCC0ライセンスではありません、著作権は放棄はしておりませんので予めご了承ください。\r\n本モデルの利用条件は、以下ヘルプ記事をご覧ください。\r\nvroid.pixiv.help/hc/ja/articles/4402394424089\r\n\r\nAvatarSample_A is one of the sample models included in VRoid Studio.\r\nIt can be used in accordance with its VRoid Hub conditions of use, within reason.\r\nFeel free to use this model in applications linked to VRoid Hub and on external services.\r\nPlease note that this model is not under the CC0 license and its copyright has not been waived.\r\nTo learn more about this model's conditions of use, consult the following Help article.\r\nvroid.pixiv.help/hc/en-us/articles/4402394424089", }, diff --git a/src/constants/common.ts b/src/constants/common.ts index 8d0642d8..81ca90e2 100644 --- a/src/constants/common.ts +++ b/src/constants/common.ts @@ -1,6 +1,6 @@ -export const AGENT_INDEX_URL = 'https://market.vidol.chat/agents/index.json'; +export const AGENT_INDEX_URL = 'https://vidol-market.lobehub.com/agents/index.json'; -export const DANCE_INDEX_URL = 'https://market.vidol.chat/dances/index.json'; +export const DANCE_INDEX_URL = 'https://vidol-market.lobehub.com/dances/index.json'; export const VIDOL_THEME_APPEARANCE = 'VIDOL_THEME_APPEARANCE'; export const VIDOL_THEME_NEUTRAL_COLOR = 'VIDOL_THEME_NEUTRAL_COLOR'; diff --git a/src/constants/dance.ts b/src/constants/dance.ts index 98b736a0..e237f698 100644 --- a/src/constants/dance.ts +++ b/src/constants/dance.ts @@ -4,6 +4,8 @@ export const DEFAULT_DANCE: Dance = { danceId: 'vidol-dance-gokuraku', name: '極楽浄土', createAt: '2023-10-31', + author: 'Vidol', + homepage: '/~https://github.com/lobehub/lobe-vidol', src: 'https://registry.npmmirror.com/@v-idol/vidol-dance-gokuraku/1.0.0/files/gokuraku.vmd', audio: 'https://registry.npmmirror.com/@v-idol/vidol-dance-gokuraku/1.0.0/files/Gokuraku jodo.mp3', diff --git a/src/panels/AgentPanel/Market/Card/index.tsx b/src/panels/AgentPanel/Market/Card/index.tsx index d71cea7e..611fbcec 100644 --- a/src/panels/AgentPanel/Market/Card/index.tsx +++ b/src/panels/AgentPanel/Market/Card/index.tsx @@ -4,6 +4,7 @@ import { createStyles } from 'antd-style'; import { useRouter } from 'next/navigation'; import React, { memo, useState } from 'react'; +import Author from '@/components/Author'; import AgentCard from '@/components/agent/AgentCard'; import SystemRole from '@/components/agent/SystemRole'; import { SIDEBAR_MAX_WIDTH, SIDEBAR_WIDTH } from '@/constants/common'; @@ -101,7 +102,8 @@ const Header = () => { } + extra={} + footer={} /> ); diff --git a/src/panels/DancePanel/Dance/Card/index.tsx b/src/panels/DancePanel/Dance/Card/index.tsx index 6eb669fe..e8d55d05 100644 --- a/src/panels/DancePanel/Dance/Card/index.tsx +++ b/src/panels/DancePanel/Dance/Card/index.tsx @@ -5,7 +5,6 @@ import React, { memo, useState } from 'react'; import DanceInfo from '@/components/DanceInfo'; import { SIDEBAR_MAX_WIDTH, SIDEBAR_WIDTH } from '@/constants/common'; -import { PanelContext } from '@/panels/PanelContext'; import { danceListSelectors, useDanceStore } from '@/store/dance'; const useStyles = createStyles(({ css, token }) => ({ @@ -28,17 +27,16 @@ const SideBar = memo(() => { activateDance, deactivateDance, addAndPlayItem, - addPlayItem, + addToPlayList, unsubscribe, ] = useDanceStore((s) => [ danceListSelectors.showSideBar(s), s.activateDance, s.deactivateDance, s.addAndPlayItem, - s.addPlayItem, + s.addToPlayList, s.unsubscribe, ]); - const isInPanel = React.useContext(PanelContext); const currentDance = useDanceStore((s) => danceListSelectors.currentDanceItem(s)); @@ -62,32 +60,28 @@ const SideBar = memo(() => { > { - if (currentDance) { - addAndPlayItem(currentDance); - } - }} - type={'primary'} - > - 播放并添加到列表 - - ) : ( - - ), + , + , ({ content: css` display: flex; @@ -31,9 +32,59 @@ const Header = () => { ], ); + const [subscribe, unsubscribe, subscribed, addAndPlayItem, addToPlayList] = useDanceStore((s) => [ + s.subscribe, + s.unsubscribe, + danceListSelectors.subscribed(s), + s.addAndPlayItem, + s.addToPlayList, + ]); + const actions = []; if (currentDanceItem) { - actions.push(); + const isSubscribed = subscribed(currentDanceItem.danceId); + + if (isSubscribed) { + actions.push([ + , + , + ]); + } + + actions.push( + , + ); } return ( @@ -54,7 +105,11 @@ const Header = () => { }} placement={'right'} > - + } + /> ); }; diff --git a/src/store/dance/slices/playlist.ts b/src/store/dance/slices/playlist.ts index 23d53068..2a54f594 100644 --- a/src/store/dance/slices/playlist.ts +++ b/src/store/dance/slices/playlist.ts @@ -15,7 +15,7 @@ export interface PlayListStore { /** * Add a dance to the playlist. */ - addPlayItem: (dance: Dance) => void; + addToPlayList: (dance: Dance) => void; /** * Clear the playlist. */ @@ -64,6 +64,10 @@ export const createPlayListStore: StateCreator< PlayListStore > = (set, get) => { return { + /** + * Add a dance to the playlist and play it. add to the first. + * @param dance + */ addAndPlayItem: (dance) => { const { playlist, playItem } = get(); @@ -71,6 +75,9 @@ export const createPlayListStore: StateCreator< const index = draftState.findIndex((item) => item.name === dance.name); if (index === -1) { draftState.unshift(dance); + } else { + draftState.splice(index, 1); + draftState.unshift(dance); } }); @@ -78,13 +85,17 @@ export const createPlayListStore: StateCreator< playItem(dance); }, - addPlayItem: (dance) => { + /** + * Add a dance to the playlist. add to the last. + * @param dance + */ + addToPlayList: (dance) => { const { playlist } = get(); const nextPlayList = produce(playlist, (draftState) => { const index = draftState.findIndex((item) => item.name === dance.name); if (index === -1) { - draftState.unshift(dance); + draftState.push(dance); } }); diff --git a/src/types/agent.ts b/src/types/agent.ts index 1fa31263..b4724f75 100644 --- a/src/types/agent.ts +++ b/src/types/agent.ts @@ -1,11 +1,29 @@ import { TouchActionConfig } from './touch'; import { TTS } from './tts'; +/** + * Category Enum, 当前包括 Anime, Game, Realistic, VTuber, Book, History, Movie, Animal, Vroid + */ +export enum CategoryEnum { + ANIMAL = 'Animal', + ANIME = 'Anime', + BOOK = 'Book', + GAME = 'Game', + HISTORY = 'History', + MOVIE = 'Movie', + REALISTIC = 'Realistic', + VROID = 'Vroid', + VTUBER = 'VTuber', +} export interface AgentMeta { /** * 头像图片路径 */ avatar: string; + /** + * 模型分类 + */ + category?: CategoryEnum; /** * 封面图片路径 */ @@ -37,11 +55,26 @@ export interface Agent { * 角色 ID,为本地文件目录 */ agentId: string; + /** + * 作者名 + */ + author: string; + /** + * 创建时间 + */ + createAt: string; + /** + * 问候语,角色在每次聊天开始时说的第一句话 + */ + greeting: string; + /** + * 作者主页 + */ + homepage: string; /** * 角色元数据 */ meta: AgentMeta; - /** * 角色设定 */ diff --git a/src/types/dance.ts b/src/types/dance.ts index 4f09aa43..805b0028 100644 --- a/src/types/dance.ts +++ b/src/types/dance.ts @@ -3,6 +3,10 @@ export interface Dance { * 音频文件 */ audio: string; + /** + * 作者名 + */ + author: string; /** * 封面图片 */ @@ -15,6 +19,10 @@ export interface Dance { * 舞蹈 ID */ danceId: string; + /** + * 作者主页 + */ + homepage: string; /** * 舞蹈名 */