/>,
);
- fireEvent.change(
- await screen.findByLabelText('审核备注:角色形象 1'),
- {target: {value: '质量通过'}},
- );
- fireEvent.click(screen.getByRole('button', {name: '通过'}));
+ fireEvent.change(await screen.findByLabelText('审核备注:角色形象 1'), {
+ target: { value: '质量通过' },
+ });
+ fireEvent.click(screen.getByRole('button', { name: '通过' }));
await waitFor(() => {
expect(reviewAdminEditorShowcaseAsset).toHaveBeenCalledWith('admin-token', {
@@ -191,8 +226,8 @@ test('后台精选审核可以通过素材并查看完整提示词', async () =>
});
});
- fireEvent.click(screen.getByRole('button', {name: '完整提示词内容'}));
- const dialog = screen.getByRole('dialog', {name: '完整提示词'});
+ fireEvent.click(screen.getByRole('button', { name: '完整提示词内容' }));
+ const dialog = screen.getByRole('dialog', { name: '完整提示词' });
expect(within(dialog).getByText('完整提示词内容')).toBeTruthy();
});
@@ -209,7 +244,7 @@ test('后台精选审核可以切换展示和保存活动卡', async () => {
/>,
);
- fireEvent.click(await screen.findByRole('button', {name: '隐藏'}));
+ fireEvent.click(await screen.findByRole('button', { name: '隐藏' }));
await waitFor(() => {
expect(updateAdminEditorShowcaseDisplay).toHaveBeenCalledWith(
'admin-token',
@@ -222,15 +257,15 @@ test('后台精选审核可以切换展示和保存活动卡', async () => {
});
fireEvent.change(await screen.findByLabelText('标题'), {
- target: {value: '新活动卡'},
+ target: { value: '新活动卡' },
});
fireEvent.change(screen.getByLabelText('图片地址'), {
- target: {value: '/new-campaign.png'},
+ target: { value: '/new-campaign.png' },
});
fireEvent.change(screen.getByLabelText('成本文案'), {
- target: {value: '6 泥点'},
+ target: { value: '6 泥点' },
});
- fireEvent.click(screen.getByRole('button', {name: '保存活动卡'}));
+ fireEvent.click(screen.getByRole('button', { name: '保存活动卡' }));
await waitFor(() => {
expect(upsertAdminEditorShowcaseCampaign).toHaveBeenCalledWith(
@@ -271,7 +306,7 @@ test('后台精选审核已通过素材可以设置精选分类', async () => {
);
fireEvent.change(await screen.findByLabelText('精选分类:角色形象 2'), {
- target: {value: 'ui'},
+ target: { value: 'ui' },
});
await waitFor(() => {
@@ -307,7 +342,7 @@ test('后台精选审核清空精选分类时自动隐藏素材', async () => {
);
fireEvent.change(await screen.findByLabelText('精选分类:角色形象 2'), {
- target: {value: ''},
+ target: { value: '' },
});
await waitFor(() => {
diff --git a/apps/admin-web/src/pages/AdminEditorShowcaseReviewPage.tsx b/apps/admin-web/src/pages/AdminEditorShowcaseReviewPage.tsx
index f3fbd561c..302d4d074 100644
--- a/apps/admin-web/src/pages/AdminEditorShowcaseReviewPage.tsx
+++ b/apps/admin-web/src/pages/AdminEditorShowcaseReviewPage.tsx
@@ -1,6 +1,6 @@
-import {Eye, FileText, RefreshCcw, X} from 'lucide-react';
-import type {ReactNode} from 'react';
-import {useEffect, useState} from 'react';
+import { Eye, FileText, RefreshCcw, X } from 'lucide-react';
+import type { ReactNode } from 'react';
+import { useEffect, useState } from 'react';
import {
getAdminAssetReadUrl,
@@ -10,13 +10,13 @@ import {
updateAdminEditorShowcaseDisplay,
upsertAdminEditorShowcaseCampaign,
} from '../api/adminApiClient';
-import type {AdminAssetReadUrlResponse} from '../api/adminApiClient';
+import type { AdminAssetReadUrlResponse } from '../api/adminApiClient';
import type {
AdminEditorShowcaseAssetPayload,
AdminEditorShowcaseCampaignPayload,
AdminEditorShowcaseListQuery,
} from '../api/adminApiTypes';
-import {handlePageError} from './pageUtils';
+import { handlePageError } from './pageUtils';
interface AdminEditorShowcaseReviewPageProps {
token: string;
@@ -24,20 +24,21 @@ interface AdminEditorShowcaseReviewPageProps {
}
const ADMIN_SHOWCASE_READ_EXPIRE_SECONDS = 300;
+const AUDIO_ASSET_COVER_SRC = '/creation-home/audio-asset-cover.svg';
const showcaseCategoryOptions = [
- {value: 'packs', label: '素材包'},
- {value: 'characters', label: '角色'},
- {value: 'ui', label: 'UI'},
- {value: 'music', label: '音乐'},
- {value: 'marketing', label: '美宣'},
+ { value: 'packs', label: '素材包' },
+ { value: 'characters', label: '角色' },
+ { value: 'ui', label: 'UI' },
+ { value: 'music', label: '音乐' },
+ { value: 'marketing', label: '美宣' },
];
const reviewStatusOptions = [
- {value: '', label: '全部'},
- {value: 'pending', label: '待审核'},
- {value: 'approved', label: '已通过'},
- {value: 'rejected', label: '已拒绝'},
+ { value: '', label: '全部' },
+ { value: 'pending', label: '待审核' },
+ { value: 'approved', label: '已通过' },
+ { value: 'rejected', label: '已拒绝' },
];
export function AdminEditorShowcaseReviewPage({
@@ -314,9 +315,7 @@ export function AdminEditorShowcaseReviewPage({
{entry.label || '-'}
- |
- {formatDateTime(entry.submittedAt)}
- |
+ {formatDateTime(entry.submittedAt)} |
{authorDisplayName(entry)}
{entry.authorPublicUserCode?.trim() || '-'}
@@ -342,7 +341,9 @@ export function AdminEditorShowcaseReviewPage({
)}
|
-
+
{reviewStatusLabel(entry.reviewStatus)}
{entry.reviewStatus === 'approved' ? (
@@ -589,7 +590,11 @@ function AdminShowcaseThumbnail({
}: {
entry: AdminEditorShowcaseAssetPayload;
}) {
- const imageSrc = useAdminResolvedAssetImageSrc(entry.imageSrc, entry.objectKey);
+ const isAudio = isAdminShowcaseAudioAsset(entry);
+ const imageSrc = useAdminResolvedAssetImageSrc(
+ isAudio ? AUDIO_ASSET_COVER_SRC : entry.imageSrc,
+ isAudio ? null : entry.objectKey,
+ );
const alt = `精选素材:${entry.label || entry.showcaseId}`;
return imageSrc ? (
@@ -599,6 +604,16 @@ function AdminShowcaseThumbnail({
);
}
+function isAdminShowcaseAudioAsset(entry: AdminEditorShowcaseAssetPayload) {
+ const assetKind = entry.assetKind?.trim() ?? '';
+ return (
+ assetKind === 'sound-effect' ||
+ assetKind === 'background-music' ||
+ assetKind === 'editor_uploaded_audio' ||
+ /\.(?:mp3|wav|m4a|aac|ogg)(?:$|[?#])/iu.test(entry.imageSrc.trim())
+ );
+}
+
function AdminShowcaseDetailDialog({
entry,
onClose,
@@ -659,7 +674,9 @@ function AdminShowcaseDetailDialog({
{entry.likeCount}
{entry.model || '-'}
- {entry.provider || '-'}
+
+ {entry.provider || '-'}
+
{entry.taskId || '-'}
{entry.objectKey || '-'}
@@ -869,13 +886,13 @@ function reviewStatusClassName(value: string) {
function authorDisplayName(entry: AdminEditorShowcaseAssetPayload) {
return (
- entry.authorDisplayName?.trim() ||
- entry.authorPublicUserCode?.trim() ||
- '-'
+ entry.authorDisplayName?.trim() || entry.authorPublicUserCode?.trim() || '-'
);
}
-function formatGenerationInputs(value: Record | null | undefined) {
+function formatGenerationInputs(
+ value: Record | null | undefined,
+) {
if (!value) {
return '-';
}
diff --git a/public/creation-home/audio-asset-cover.svg b/public/creation-home/audio-asset-cover.svg
new file mode 100644
index 000000000..0e96909aa
--- /dev/null
+++ b/public/creation-home/audio-asset-cover.svg
@@ -0,0 +1,19 @@
+
diff --git a/src/components/creation-home/CreationLandingView.test.tsx b/src/components/creation-home/CreationLandingView.test.tsx
index 82449027e..b80a8d7f6 100644
--- a/src/components/creation-home/CreationLandingView.test.tsx
+++ b/src/components/creation-home/CreationLandingView.test.tsx
@@ -125,12 +125,10 @@ function installIntersectionObserverMock() {
return observers;
}
-function triggerIntersection(
- observer: {
- callback: IntersectionObserverCallback;
- instance: IntersectionObserver;
- },
-) {
+function triggerIntersection(observer: {
+ callback: IntersectionObserverCallback;
+ instance: IntersectionObserver;
+}) {
act(() => {
observer.callback(
[{ isIntersecting: true } as IntersectionObserverEntry],
@@ -157,15 +155,15 @@ describe('CreationLandingView', () => {
renderCreationLanding();
- expect(
- screen.getByRole('main', { name: '陶泥儿创作主页' }),
- ).toBeTruthy();
+ expect(screen.getByRole('main', { name: '陶泥儿创作主页' })).toBeTruthy();
expect(
screen.getByRole('heading', {
name: '陶泥儿 - 开启全民精品游戏创作',
}),
).toBeTruthy();
- expect(screen.getByText('登录即送100泥点,可以免费制作50个素材')).toBeTruthy();
+ expect(
+ screen.getByText('登录即送100泥点,可以免费制作50个素材'),
+ ).toBeTruthy();
expect(screen.getByRole('heading', { name: '创作工具' })).toBeTruthy();
expect(screen.getByText('游戏视觉规范')).toBeTruthy();
expect(screen.getByRole('heading', { name: '陶泥儿精选' })).toBeTruthy();
@@ -193,7 +191,9 @@ describe('CreationLandingView', () => {
,
);
- expect(await screen.findByRole('heading', { name: '最近项目' })).toBeTruthy();
+ expect(
+ await screen.findByRole('heading', { name: '最近项目' }),
+ ).toBeTruthy();
expect(screen.getByText('最新项目')).toBeTruthy();
expect(screen.getByText('旧项目')).toBeTruthy();
await user.click(screen.getByRole('button', { name: '查看全部' }));
@@ -302,10 +302,7 @@ describe('CreationLandingView', () => {
render(
-
+
,
);
@@ -375,9 +372,13 @@ describe('CreationLandingView', () => {
const assetCard = await screen.findByText('角色英雄');
const card = assetCard.closest('.creation-landing__asset-card');
expect(card).toBeTruthy();
- expect(within(card as HTMLElement).getByText('character hero prompt')).toBeTruthy();
+ expect(
+ within(card as HTMLElement).getByText('character hero prompt'),
+ ).toBeTruthy();
expect(within(card as HTMLElement).getByText('创作者A')).toBeTruthy();
- expect(within(card as HTMLElement).queryByText('user-internal-author')).toBeNull();
+ expect(
+ within(card as HTMLElement).queryByText('user-internal-author'),
+ ).toBeNull();
expect(within(card as HTMLElement).getByText('20泥点')).toBeTruthy();
});
@@ -500,18 +501,56 @@ describe('CreationLandingView', () => {
expect(within(dialog).getByText('生成总成本')).toBeTruthy();
expect(within(dialog).getByText('60泥点')).toBeTruthy();
expect(within(dialog).getByText('创作者A')).toBeTruthy();
- expect(
- within(dialog).getByLabelText('素材缩略图导航'),
- ).toBeTruthy();
+ expect(within(dialog).getByLabelText('素材缩略图导航')).toBeTruthy();
- await user.click(within(dialog).getByRole('button', { name: '查看待机动画' }));
+ await user.click(
+ within(dialog).getByRole('button', { name: '查看待机动画' }),
+ );
expect(
- within(dialog).getByRole('button', { name: '查看待机动画' }).getAttribute(
- 'aria-current',
- ),
+ within(dialog)
+ .getByRole('button', { name: '查看待机动画' })
+ .getAttribute('aria-current'),
).toBe('true');
});
+ it('uses the unified audio cover image for featured audio assets', async () => {
+ const user = userEvent.setup();
+ listEditorProjectsMock.mockResolvedValueOnce(projectItems);
+ listPublicEditorProjectResourcesMock.mockResolvedValueOnce([
+ {
+ resourceId: 'resource-music',
+ projectId: 'project-newest',
+ label: '背景音乐',
+ imageSrc: '/generated-editor-audios/music.mp3',
+ objectKey: 'generated-editor-audios/music.mp3',
+ width: 1,
+ height: 1,
+ sourceType: 'generated',
+ prompt: '舒缓背景音乐',
+ actualPrompt: null,
+ model: 'audio1.0',
+ provider: 'ark',
+ taskId: 'task-audio-1',
+ assetKind: 'background-music',
+ priceMudPoints: 5,
+ },
+ ]);
+
+ renderCreationLanding();
+
+ await user.click(screen.getByRole('tab', { name: '音乐' }));
+ const card = (await screen.findByText('背景音乐')).closest(
+ '.creation-landing__asset-card',
+ );
+ expect(card).toBeTruthy();
+ const image = within(card as HTMLElement).getByRole('img', {
+ name: '背景音乐',
+ });
+ expect(image.getAttribute('src')).toBe(
+ '/creation-home/audio-asset-cover.svg',
+ );
+ });
+
it('uses Taonier featured as the generated project resource waterfall instead of creation entries', async () => {
listEditorProjectsMock.mockResolvedValueOnce(projectItems);
listPublicEditorProjectResourcesMock.mockResolvedValueOnce([
@@ -564,9 +603,9 @@ describe('CreationLandingView', () => {
expect(await screen.findByText('素材包 A')).toBeTruthy();
expect(screen.getByText('素材包 B')).toBeTruthy();
expect(screen.queryByText('上传素材')).toBeNull();
- expect(
- screen.getByLabelText('用户素材瀑布流').className,
- ).toContain('creation-landing__asset-waterfall');
+ expect(screen.getByLabelText('用户素材瀑布流').className).toContain(
+ 'creation-landing__asset-waterfall',
+ );
const firstPreview = container.querySelector(
'.creation-landing__asset-preview',
) as HTMLElement | null;
@@ -665,7 +704,9 @@ describe('CreationLandingView', () => {
await waitFor(() => expect(observers).toHaveLength(1));
triggerIntersection(observers[0]!);
- expect(await screen.findByRole('button', { name: '读取更多素材失败,点击重试' })).toBeTruthy();
+ expect(
+ await screen.findByRole('button', { name: '读取更多素材失败,点击重试' }),
+ ).toBeTruthy();
expect(screen.getByText('素材包 A')).toBeTruthy();
expect(screen.getByLabelText('用户素材瀑布流')).toBeTruthy();
});
diff --git a/src/components/creation-home/CreationLandingView.tsx b/src/components/creation-home/CreationLandingView.tsx
index 3a50a5a70..833e6f490 100644
--- a/src/components/creation-home/CreationLandingView.tsx
+++ b/src/components/creation-home/CreationLandingView.tsx
@@ -61,8 +61,7 @@ const CREATION_HOME_ASSETS = {
projectNew: '/creation-home/project-new.png',
} as const;
-const SHOWCASE_LIKE_ICON_SRC =
- '/creation-home/showcase-like-thumb.png';
+const SHOWCASE_LIKE_ICON_SRC = '/creation-home/showcase-like-thumb.png';
const CREATION_FEATURES: CreationFeatureItem[] = [
{
@@ -137,7 +136,9 @@ function mergeShowcaseResources(
current: EditorProjectResourceSnapshot[],
incoming: EditorProjectResourceSnapshot[],
) {
- const seenResourceIds = new Set(current.map((resource) => resource.resourceId));
+ const seenResourceIds = new Set(
+ current.map((resource) => resource.resourceId),
+ );
return [
...current,
...incoming.filter((resource) => {
@@ -189,10 +190,17 @@ function ShowcaseAudioPreview({
const { resolvedUrl } = useResolvedAssetReadUrl(preview.src, {
objectKey: preview.objectKey,
});
+ const coverSrc =
+ preview.coverSrc?.trim() || '/creation-home/audio-asset-cover.svg';
return (
-
+ 
{controls && resolvedUrl ? (
) : null}
@@ -271,11 +279,7 @@ function ShowcaseVideoPreview({
);
}
-function ShowcaseBundlePreview({
- item,
-}: {
- item: ShowcaseAssetItem;
-}) {
+function ShowcaseBundlePreview({ item }: { item: ShowcaseAssetItem }) {
const visiblePreviews = item.previews.slice(0, 4);
const primaryPreview = visiblePreviews[0];
@@ -396,7 +400,9 @@ function CreationShowcaseModal({
alt=""
aria-hidden="true"
/>
- {isLikePending ? '处理中' : isLiked ? '已点赞' : '点赞'}
+
+ {isLikePending ? '处理中' : isLiked ? '已点赞' : '点赞'}
+
) : null}
@@ -418,7 +424,8 @@ function CreationShowcaseModal({
onClick={() => onSelectIndex(index)}
>
- {preview.mediaType === 'image' ? (
+ {preview.mediaType === 'image' ||
+ preview.mediaType === 'audio' ? (
) : (
getPreviewIcon(preview)
@@ -455,9 +462,13 @@ export function CreationLandingView({
>([]);
const [showcaseCampaign, setShowcaseCampaign] =
useState(null);
- const [showcaseNextCursor, setShowcaseNextCursor] = useState(null);
+ const [showcaseNextCursor, setShowcaseNextCursor] = useState(
+ null,
+ );
const [assetError, setAssetError] = useState(null);
- const [showcaseLoadMoreError, setShowcaseLoadMoreError] = useState(null);
+ const [showcaseLoadMoreError, setShowcaseLoadMoreError] = useState<
+ string | null
+ >(null);
const [activeShowcaseTab, setActiveShowcaseTab] =
useState('packs');
const [selectedShowcaseItem, setSelectedShowcaseItem] =
@@ -499,9 +510,7 @@ export function CreationLandingView({
}
const message =
error instanceof Error ? error.message : '读取最近项目失败';
- setProjectError(
- message,
- );
+ setProjectError(message);
})
.finally(() => setIsLoadingProjects(false));
}, [authUi, isAuthenticated]);
@@ -540,47 +549,58 @@ export function CreationLandingView({
refreshShowcaseResources();
}, [refreshShowcaseResources]);
- const loadMoreShowcaseResources = useCallback((options: { force?: boolean } = {}) => {
- const cursor = showcaseNextCursor;
- if (!cursor || isLoadingShowcase || isLoadingMoreShowcase) {
- return;
- }
- if (showcaseLoadingMoreCursorRef.current === cursor) {
- return;
- }
- if (!options.force && showcaseFailedLoadMoreCursorRef.current === cursor) {
- return;
- }
- showcaseLoadingMoreCursorRef.current = cursor;
- setIsLoadingMoreShowcase(true);
- setShowcaseLoadMoreError(null);
- listPublicEditorProjectResources({ cursor })
- .then((page) => {
- const normalizedPage = normalizeShowcaseResourcePage(page);
- setProjectShowcaseResources((current) =>
- mergeShowcaseResources(current, normalizedPage.resources),
- );
- setShowcaseCampaign((current) => normalizedPage.campaign ?? current);
- setShowcaseNextCursor(normalizedPage.nextCursor);
- showcaseFailedLoadMoreCursorRef.current = null;
- })
- .catch((error: unknown) => {
- showcaseFailedLoadMoreCursorRef.current = cursor;
- setShowcaseLoadMoreError(
- error instanceof Error ? error.message : '读取陶泥儿精选失败',
- );
- })
- .finally(() => {
- if (showcaseLoadingMoreCursorRef.current === cursor) {
- showcaseLoadingMoreCursorRef.current = null;
- }
- setIsLoadingMoreShowcase(false);
- });
- }, [isLoadingMoreShowcase, isLoadingShowcase, showcaseNextCursor]);
+ const loadMoreShowcaseResources = useCallback(
+ (options: { force?: boolean } = {}) => {
+ const cursor = showcaseNextCursor;
+ if (!cursor || isLoadingShowcase || isLoadingMoreShowcase) {
+ return;
+ }
+ if (showcaseLoadingMoreCursorRef.current === cursor) {
+ return;
+ }
+ if (
+ !options.force &&
+ showcaseFailedLoadMoreCursorRef.current === cursor
+ ) {
+ return;
+ }
+ showcaseLoadingMoreCursorRef.current = cursor;
+ setIsLoadingMoreShowcase(true);
+ setShowcaseLoadMoreError(null);
+ listPublicEditorProjectResources({ cursor })
+ .then((page) => {
+ const normalizedPage = normalizeShowcaseResourcePage(page);
+ setProjectShowcaseResources((current) =>
+ mergeShowcaseResources(current, normalizedPage.resources),
+ );
+ setShowcaseCampaign((current) => normalizedPage.campaign ?? current);
+ setShowcaseNextCursor(normalizedPage.nextCursor);
+ showcaseFailedLoadMoreCursorRef.current = null;
+ })
+ .catch((error: unknown) => {
+ showcaseFailedLoadMoreCursorRef.current = cursor;
+ setShowcaseLoadMoreError(
+ error instanceof Error ? error.message : '读取陶泥儿精选失败',
+ );
+ })
+ .finally(() => {
+ if (showcaseLoadingMoreCursorRef.current === cursor) {
+ showcaseLoadingMoreCursorRef.current = null;
+ }
+ setIsLoadingMoreShowcase(false);
+ });
+ },
+ [isLoadingMoreShowcase, isLoadingShowcase, showcaseNextCursor],
+ );
useEffect(() => {
const element = showcaseLoadMoreRef.current;
- if (!element || !showcaseNextCursor || isLoadingShowcase || isLoadingMoreShowcase) {
+ if (
+ !element ||
+ !showcaseNextCursor ||
+ isLoadingShowcase ||
+ isLoadingMoreShowcase
+ ) {
return;
}
if (showcaseFailedLoadMoreCursorRef.current === showcaseNextCursor) {
@@ -608,28 +628,31 @@ export function CreationLandingView({
showcaseNextCursor,
]);
- const createProject = useCallback((tool?: CreationFeatureTool) => {
- if (authUi && !authUi.user) {
- authUi.openLoginModal(() => createProject(tool));
- return;
- }
- setIsCreatingProject(true);
- setProjectError(null);
- createEditorProject()
- .then((project) =>
- onOpenProject(project.projectId, tool ? { tool } : { guide: true }),
- )
- .catch((error: unknown) => {
- if (isUnauthorizedError(error)) {
- authUi?.openLoginModal(() => createProject(tool));
- return;
- }
- setProjectError(
- error instanceof Error ? error.message : '创建项目失败',
- );
- })
- .finally(() => setIsCreatingProject(false));
- }, [authUi, onOpenProject]);
+ const createProject = useCallback(
+ (tool?: CreationFeatureTool) => {
+ if (authUi && !authUi.user) {
+ authUi.openLoginModal(() => createProject(tool));
+ return;
+ }
+ setIsCreatingProject(true);
+ setProjectError(null);
+ createEditorProject()
+ .then((project) =>
+ onOpenProject(project.projectId, tool ? { tool } : { guide: true }),
+ )
+ .catch((error: unknown) => {
+ if (isUnauthorizedError(error)) {
+ authUi?.openLoginModal(() => createProject(tool));
+ return;
+ }
+ setProjectError(
+ error instanceof Error ? error.message : '创建项目失败',
+ );
+ })
+ .finally(() => setIsCreatingProject(false));
+ },
+ [authUi, onOpenProject],
+ );
const handleFeatureClick = useCallback(
(feature: CreationFeatureItem) => {
@@ -646,13 +669,16 @@ export function CreationLandingView({
(showcaseId: string, likeCount: number) => {
setProjectShowcaseResources((current) =>
current.map((resource) =>
- resource.showcaseId === showcaseId || resource.resourceId === showcaseId
+ resource.showcaseId === showcaseId ||
+ resource.resourceId === showcaseId
? { ...resource, likeCount }
: resource,
),
);
setSelectedShowcaseItem((current) =>
- current?.showcaseId === showcaseId ? { ...current, likeCount } : current,
+ current?.showcaseId === showcaseId
+ ? { ...current, likeCount }
+ : current,
);
},
[],
@@ -783,7 +809,10 @@ export function CreationLandingView({
return (
<>
-
+
{showcaseItems.map((item) => {
const showcaseId = item.showcaseId?.trim();
const isLiked = Boolean(
@@ -830,7 +859,11 @@ export function CreationLandingView({
disabled={isLikePending}
onClick={() => handleToggleShowcaseLike(item)}
>
- 
+
{item.likeCount ?? 0}
) : null}
@@ -1015,7 +1048,11 @@ export function CreationLandingView({
陶泥儿精选
-
+
{SHOWCASE_TABS.map((tab) => (
);
},
}));
beforeEach(() => {
useResolvedAssetReadUrlMock.mockImplementation(
- (source: string | null | undefined, options?: { objectKey?: string | null }) => ({
+ (
+ source: string | null | undefined,
+ options?: { objectKey?: string | null },
+ ) => ({
resolvedUrl: options?.objectKey
? `https://signed.example.com/${options.objectKey}`
: (source ?? ''),
@@ -138,9 +143,7 @@ describe('ImageCanvasAssetRowView', () => {
const onDownloadAsset = vi.fn();
renderAssetRow({ asset, onDownloadAsset });
- fireEvent.click(
- screen.getByRole('button', { name: '下载素材账号素材A' }),
- );
+ fireEvent.click(screen.getByRole('button', { name: '下载素材账号素材A' }));
expect(onDownloadAsset).toHaveBeenCalledWith(asset);
});
@@ -154,20 +157,26 @@ describe('ImageCanvasAssetRowView', () => {
const onDownloadAsset = vi.fn();
renderAssetRow({ asset, addAssetLayer, onDownloadAsset });
- fireEvent.contextMenu(screen.getByRole('button', { name: '添加账号素材A' }), {
- clientX: 120,
- clientY: 80,
- });
+ fireEvent.contextMenu(
+ screen.getByRole('button', { name: '添加账号素材A' }),
+ {
+ clientX: 120,
+ clientY: 80,
+ },
+ );
expect(screen.getByRole('menu')).toBeTruthy();
fireEvent.click(screen.getByRole('button', { name: '下载素材账号素材A' }));
expect(onDownloadAsset).toHaveBeenCalledWith(asset);
expect(screen.queryByRole('menu')).toBeNull();
- fireEvent.contextMenu(screen.getByRole('button', { name: '添加账号素材A' }), {
- clientX: 120,
- clientY: 80,
- });
+ fireEvent.contextMenu(
+ screen.getByRole('button', { name: '添加账号素材A' }),
+ {
+ clientX: 120,
+ clientY: 80,
+ },
+ );
fireEvent.click(screen.getByRole('button', { name: '添加账号素材A' }));
expect(addAssetLayer).toHaveBeenCalledWith(asset);
expect(screen.queryByRole('menu')).toBeNull();
@@ -199,7 +208,9 @@ describe('ImageCanvasAssetRowView', () => {
fireEvent.keyDown(input, { key: 'Enter' });
expect(input.className).toContain('platform-text-field');
- expect(input.className).toContain('image-canvas-editor__asset-rename-input');
+ expect(input.className).toContain(
+ 'image-canvas-editor__asset-rename-input',
+ );
expect(commitAssetRename).toHaveBeenCalledWith(
expect.objectContaining({ id: 'asset-1' }),
);
@@ -226,7 +237,7 @@ describe('ImageCanvasAssetRowView', () => {
).toBe('42');
});
- it('uses icon thumbnails for audio assets instead of rendering media as images', () => {
+ it('uses the audio cover thumbnail for audio assets', () => {
renderAssetRow({
asset: createAsset({
label: '胜利音效.mp3',
@@ -236,13 +247,13 @@ describe('ImageCanvasAssetRowView', () => {
});
expect(screen.getByText('音频')).toBeTruthy();
- expect(screen.queryByRole('img', { name: '素材:胜利音效.mp3' })).toBeNull();
+ const image = screen.getByRole('img', { name: '素材:胜利音效.mp3' });
+ expect(image.getAttribute('src')).toBe(
+ '/creation-home/audio-asset-cover.svg',
+ );
expect(
document.querySelector('.image-canvas-editor__asset-media-overlay'),
- ).toBeTruthy();
- expect(
- document.querySelector('.image-canvas-editor__media-preview--audio'),
- ).toBeTruthy();
+ ).toBeNull();
});
it('uses a stable visual preview for video asset cards without image thumbnails', () => {
@@ -250,13 +261,16 @@ describe('ImageCanvasAssetRowView', () => {
asset: createAsset({
label: '生成视频.mp4',
src: '/generated-character-drafts/editor/asset-library/video/demo.mp4',
- objectKey: 'generated-character-drafts/editor/asset-library/video/demo.mp4',
+ objectKey:
+ 'generated-character-drafts/editor/asset-library/video/demo.mp4',
mediaType: 'video',
}),
});
expect(screen.getByText('视频')).toBeTruthy();
- expect(screen.queryByRole('img', { name: '素材:生成视频.mp4' })).toBeNull();
+ expect(
+ screen.queryByRole('img', { name: '素材:生成视频.mp4' }),
+ ).toBeNull();
const video = screen.getByLabelText(
'视频素材预览:生成视频.mp4',
) as HTMLVideoElement;
@@ -315,10 +329,13 @@ describe('ImageCanvasAssetRowView', () => {
screen.queryByRole('button', { name: '删除素材账号素材A' }),
).toBeNull();
- fireEvent.contextMenu(screen.getByRole('button', { name: '添加账号素材A' }), {
- clientX: 120,
- clientY: 80,
- });
+ fireEvent.contextMenu(
+ screen.getByRole('button', { name: '添加账号素材A' }),
+ {
+ clientX: 120,
+ clientY: 80,
+ },
+ );
const submitMenuItem = screen.getByRole('menuitem', {
name: /提交精选审核/u,
@@ -327,10 +344,13 @@ describe('ImageCanvasAssetRowView', () => {
fireEvent.click(submitMenuItem);
expect(submitAssetToShowcase).toHaveBeenCalledWith(asset);
- fireEvent.contextMenu(screen.getByRole('button', { name: '添加账号素材A' }), {
- clientX: 120,
- clientY: 80,
- });
+ fireEvent.contextMenu(
+ screen.getByRole('button', { name: '添加账号素材A' }),
+ {
+ clientX: 120,
+ clientY: 80,
+ },
+ );
fireEvent.click(screen.getByRole('menuitem', { name: '删除' }));
expect(deleteUploadedAsset).toHaveBeenCalledWith(asset);
});
@@ -339,10 +359,13 @@ describe('ImageCanvasAssetRowView', () => {
const submitAssetToShowcase = vi.fn();
renderAssetRow({ submitAssetToShowcase });
- fireEvent.contextMenu(screen.getByRole('button', { name: '添加账号素材A' }), {
- clientX: 120,
- clientY: 80,
- });
+ fireEvent.contextMenu(
+ screen.getByRole('button', { name: '添加账号素材A' }),
+ {
+ clientX: 120,
+ clientY: 80,
+ },
+ );
const submitMenuItem = screen.getByRole('menuitem', {
name: /提交精选审核/u,
@@ -360,10 +383,13 @@ describe('ImageCanvasAssetRowView', () => {
const submitAssetToShowcase = vi.fn();
renderAssetRow({ asset, submitAssetToShowcase });
- fireEvent.contextMenu(screen.getByRole('button', { name: '添加账号素材A' }), {
- clientX: 120,
- clientY: 80,
- });
+ fireEvent.contextMenu(
+ screen.getByRole('button', { name: '添加账号素材A' }),
+ {
+ clientX: 120,
+ clientY: 80,
+ },
+ );
const submitMenuItem = screen.getByRole('menuitem', {
name: /提交精选审核/u,
diff --git a/src/components/image-editor/ImageCanvasAssetRowView.tsx b/src/components/image-editor/ImageCanvasAssetRowView.tsx
index 393500139..c6bd2093a 100644
--- a/src/components/image-editor/ImageCanvasAssetRowView.tsx
+++ b/src/components/image-editor/ImageCanvasAssetRowView.tsx
@@ -1,4 +1,4 @@
-import { Check, Download, Music2, Pencil, Video, X } from 'lucide-react';
+import { Check, Download, Pencil, Video, X } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
import type { Dispatch, SetStateAction } from 'react';
@@ -24,6 +24,8 @@ import {
getCanvasMediaPreviewMarker,
} from './ImageCanvasMediaModel';
+const AUDIO_ASSET_COVER_SRC = '/creation-home/audio-asset-cover.svg';
+
export type ImageCanvasAssetRowViewProps = {
asset: EditorAsset;
assetPointerDragRef: { current: AssetPointerDragState | null };
@@ -38,7 +40,10 @@ export type ImageCanvasAssetRowViewProps = {
setAssetPointerDrag: Dispatch >;
setSelectedAssetIds: Dispatch>>;
updateAssetMoveDropFolder: (folderId: string | null) => void;
- addUploadedFiles: (files: FileList | File[], options?: UploadFilesOptions) => void;
+ addUploadedFiles: (
+ files: FileList | File[],
+ options?: UploadFilesOptions,
+ ) => void;
moveAssetToFolder: (assetId: string, folderId: string) => void;
startRenamingAsset: (asset: EditorAsset) => void;
commitAssetRename: (asset: EditorAsset) => void;
@@ -81,7 +86,9 @@ export function ImageCanvasAssetRowView({
const isFailedUpload = asset.uploadStatus === 'failed';
const showcaseReviewStatus = asset.showcaseReviewStatus ?? null;
const canSubmitShowcaseAsset =
- asset.sourceType === 'generated' && asset.persisted && !showcaseReviewStatus;
+ asset.sourceType === 'generated' &&
+ asset.persisted &&
+ !showcaseReviewStatus;
const showcaseMenuLabel =
showcaseReviewStatus === 'pending'
? '精选审核中'
@@ -153,13 +160,7 @@ export function ImageCanvasAssetRowView({
? '视频'
: `${asset.width} x ${asset.height}`;
const mediaOverlay =
- asset.mediaType === 'audio' ? (
-
-
-
- ) : asset.mediaType === 'video' ? (
+ asset.mediaType === 'video' ? (
@@ -279,9 +280,7 @@ export function ImageCanvasAssetRowView({
rowClassName={[
'image-canvas-editor__asset-row',
isUploadingAsset ? 'image-canvas-editor__asset-row--uploading' : '',
- isFailedUpload
- ? 'image-canvas-editor__asset-row--upload-failed'
- : '',
+ isFailedUpload ? 'image-canvas-editor__asset-row--upload-failed' : '',
]
.filter(Boolean)
.join(' ')}
@@ -291,12 +290,18 @@ export function ImageCanvasAssetRowView({
imageSrc={
asset.mediaType === 'image'
? asset.src
- : (asset.thumbnailSrc ?? '')
+ : asset.mediaType === 'audio'
+ ? AUDIO_ASSET_COVER_SRC
+ : (asset.thumbnailSrc ?? '')
}
objectKey={asset.mediaType === 'image' ? asset.objectKey : undefined}
previewNode={videoPreview}
titleNode={
- isUploadingAsset || isFailedUpload ? {asset.label} : titleNode
+ isUploadingAsset || isFailedUpload ? (
+ {asset.label}
+ ) : (
+ titleNode
+ )
}
actions={actions}
draggable={!isRenaming && !isUploadingAsset && !isFailedUpload}
diff --git a/src/index.css b/src/index.css
index 7d873657e..f1022184c 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1585,7 +1585,9 @@ html[data-mobile-keyboard-open='true'] #root {
background: rgba(255, 252, 248, 0.97);
box-shadow: 0 18px 36px rgba(74, 34, 15, 0.18);
pointer-events: none;
- transform: translateX(calc(-50% + var(--floating-feedback-contact-offset, 0px)));
+ transform: translateX(
+ calc(-50% + var(--floating-feedback-contact-offset, 0px))
+ );
}
.floating-feedback-entry-contact-panel img {
@@ -3183,8 +3185,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
width: 100%;
height: 100%;
overflow: hidden;
- background:
- linear-gradient(135deg, rgba(15, 23, 42, 0.06), transparent 56%),
+ background: linear-gradient(135deg, rgba(15, 23, 42, 0.06), transparent 56%),
#f3f4f6;
}
@@ -3397,7 +3398,8 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
overflow: auto;
background:
linear-gradient(rgba(255, 250, 244, 0.56), rgba(255, 250, 244, 0.56)),
- url('/creation-home/background-clay-workspace.png') center top / 64rem 64rem repeat,
+ url('/creation-home/background-clay-workspace.png') center top / 64rem 64rem
+ repeat,
linear-gradient(180deg, #fff9f3 0%, #fffdf9 52%, #fff8f0 100%);
color: var(--creation-ink);
}
@@ -3434,8 +3436,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
margin: 0;
max-width: 62rem;
color: var(--creation-ink);
- font-family:
- "Songti SC", "STSong", "Noto Serif SC", "SimSun", serif;
+ font-family: 'Songti SC', 'STSong', 'Noto Serif SC', 'SimSun', serif;
font-size: clamp(2.35rem, 4.25vw, 3.85rem);
font-weight: 950;
letter-spacing: 0;
@@ -3512,8 +3513,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
top: 14%;
width: 58%;
aspect-ratio: 4 / 3;
- background:
- linear-gradient(135deg, rgba(75, 181, 170, 0.24), transparent 52%),
+ background: linear-gradient(135deg, rgba(75, 181, 170, 0.24), transparent 52%),
#ffffff;
}
@@ -3522,8 +3522,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
top: 28%;
width: 34%;
aspect-ratio: 1;
- background:
- linear-gradient(135deg, rgba(246, 171, 76, 0.24), transparent 56%),
+ background: linear-gradient(135deg, rgba(246, 171, 76, 0.24), transparent 56%),
#ffffff;
}
@@ -3532,8 +3531,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
bottom: 10%;
width: 36%;
aspect-ratio: 16 / 9;
- background:
- linear-gradient(135deg, rgba(129, 140, 248, 0.2), transparent 56%),
+ background: linear-gradient(135deg, rgba(129, 140, 248, 0.2), transparent 56%),
#ffffff;
}
@@ -3585,9 +3583,16 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
min-height: 9.55rem;
border: 1px solid rgba(220, 189, 163, 0.78);
border-radius: 1.12rem;
- background:
- radial-gradient(circle at 21% 42%, rgba(222, 130, 66, 0.12), transparent 9rem),
- linear-gradient(135deg, rgba(255, 254, 251, 0.92), rgba(255, 247, 238, 0.82));
+ background: radial-gradient(
+ circle at 21% 42%,
+ rgba(222, 130, 66, 0.12),
+ transparent 9rem
+ ),
+ linear-gradient(
+ 135deg,
+ rgba(255, 254, 251, 0.92),
+ rgba(255, 247, 238, 0.82)
+ );
padding: 1.05rem 1.3rem;
color: inherit;
font: inherit;
@@ -3646,7 +3651,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
border-radius: 999px;
background: rgba(112, 62, 32, 0.22);
filter: blur(0.16rem);
- content: "";
+ content: '';
}
.creation-landing__feature-art {
@@ -3961,15 +3966,25 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
place-items: center;
gap: 1rem;
padding: 1rem;
- background:
- linear-gradient(135deg, rgba(244, 187, 129, 0.4), rgba(255, 247, 236, 0.92)),
- radial-gradient(circle at 30% 24%, rgba(255, 255, 255, 0.9), transparent 42%);
- color: #9a5428;
+ background: linear-gradient(
+ 135deg,
+ rgba(244, 187, 129, 0.4),
+ rgba(255, 247, 236, 0.92)
+ ),
+ radial-gradient(
+ circle at 30% 24%,
+ rgba(255, 255, 255, 0.9),
+ transparent 42%
+ );
}
-.creation-landing__asset-audio-preview svg {
- width: 2.6rem;
- height: 2.6rem;
+.creation-landing__asset-audio-cover {
+ display: block;
+ width: min(48%, 11rem);
+ min-width: 3.2rem;
+ height: auto;
+ object-fit: contain;
+ object-position: center;
}
.creation-landing__asset-audio-preview audio {
@@ -4054,8 +4069,11 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
min-height: 0;
grid-template-rows: minmax(0, 1fr) auto;
overflow: hidden;
- background:
- radial-gradient(circle at 18% 12%, rgba(186, 117, 65, 0.18), transparent 32%),
+ background: radial-gradient(
+ circle at 18% 12%,
+ rgba(186, 117, 65, 0.18),
+ transparent 32%
+ ),
#100d0b;
}
@@ -4376,7 +4394,10 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
--platform-button-primary-fill,
linear-gradient(135deg, #df7f40, #b95d3a)
);
- --image-canvas-brand-text-on-fill: var(--platform-button-primary-text, #fffaf5);
+ --image-canvas-brand-text-on-fill: var(
+ --platform-button-primary-text,
+ #fffaf5
+ );
--image-canvas-brand-border: rgba(204, 117, 76, 0.34);
--image-canvas-brand-border-strong: rgba(199, 101, 61, 0.64);
--image-canvas-brand-border-soft: rgba(226, 203, 184, 0.82);
@@ -4881,8 +4902,11 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
.image-canvas-editor__media-preview {
position: relative;
isolation: isolate;
- background:
- radial-gradient(circle at 25% 24%, rgba(255, 255, 255, 0.22), transparent 0.72rem),
+ background: radial-gradient(
+ circle at 25% 24%,
+ rgba(255, 255, 255, 0.22),
+ transparent 0.72rem
+ ),
linear-gradient(135deg, rgba(15, 23, 42, 0.84), rgba(20, 83, 45, 0.58));
}
@@ -4895,8 +4919,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
}
.image-canvas-editor__media-preview--audio::before {
- background:
- repeating-linear-gradient(
+ background: repeating-linear-gradient(
90deg,
rgba(103, 232, 249, 0.34) 0 0.18rem,
transparent 0.18rem 0.52rem
@@ -4905,8 +4928,12 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
}
.image-canvas-editor__media-preview--video::before {
- background:
- linear-gradient(90deg, rgba(15, 23, 42, 0.42) 0 14%, transparent 14% 86%, rgba(15, 23, 42, 0.42) 86%),
+ background: linear-gradient(
+ 90deg,
+ rgba(15, 23, 42, 0.42) 0 14%,
+ transparent 14% 86%,
+ rgba(15, 23, 42, 0.42) 86%
+ ),
repeating-linear-gradient(
0deg,
rgba(248, 250, 252, 0.34) 0 0.2rem,
@@ -5840,7 +5867,11 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
rgba(250, 245, 255, 0.94),
transparent 30%
),
- linear-gradient(135deg, rgba(250, 245, 255, 0.84), rgba(243, 232, 255, 0.72));
+ linear-gradient(
+ 135deg,
+ rgba(250, 245, 255, 0.84),
+ rgba(243, 232, 255, 0.72)
+ );
}
.image-canvas-editor__generation-frame--character.image-canvas-editor__generation-frame--focused {
@@ -5853,9 +5884,16 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
}
.image-canvas-editor__generation-frame--character-animation {
- background:
- radial-gradient(circle at 50% 36%, rgba(255, 247, 237, 0.96), transparent 32%),
- linear-gradient(135deg, rgba(255, 247, 237, 0.92), rgba(254, 215, 170, 0.74));
+ background: radial-gradient(
+ circle at 50% 36%,
+ rgba(255, 247, 237, 0.96),
+ transparent 32%
+ ),
+ linear-gradient(
+ 135deg,
+ rgba(255, 247, 237, 0.92),
+ rgba(254, 215, 170, 0.74)
+ );
}
.image-canvas-editor__generation-frame--character-animation.image-canvas-editor__generation-frame--focused {
@@ -5868,8 +5906,12 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
}
.image-canvas-editor__generation-frame--video {
- background:
- linear-gradient(90deg, rgba(15, 23, 42, 0.12) 10%, transparent 10% 90%, rgba(15, 23, 42, 0.12) 90%),
+ background: linear-gradient(
+ 90deg,
+ rgba(15, 23, 42, 0.12) 10%,
+ transparent 10% 90%,
+ rgba(15, 23, 42, 0.12) 90%
+ ),
linear-gradient(135deg, rgba(239, 246, 255, 0.9), rgba(219, 234, 254, 0.82));
}
@@ -5884,8 +5926,7 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
.image-canvas-editor__generation-frame--audio-sound-effect,
.image-canvas-editor__generation-frame--audio-background-music {
- background:
- repeating-linear-gradient(
+ background: repeating-linear-gradient(
90deg,
rgba(79, 70, 229, 0.14) 0 0.22rem,
transparent 0.22rem 0.58rem
@@ -6091,8 +6132,11 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
.image-canvas-editor__generation-frame--quick-edit {
border-color: var(--image-canvas-brand-border);
- background:
- linear-gradient(135deg, rgba(204, 117, 76, 0.12), rgba(240, 203, 169, 0.12)),
+ background: linear-gradient(
+ 135deg,
+ rgba(204, 117, 76, 0.12),
+ rgba(240, 203, 169, 0.12)
+ ),
rgba(255, 255, 255, 0.72);
}
@@ -6109,8 +6153,11 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
.image-canvas-editor__generation-frame--publication {
border-color: rgba(236, 72, 153, 0.28);
- background:
- radial-gradient(circle at 30% 20%, rgba(244, 114, 182, 0.18), transparent 38%),
+ background: radial-gradient(
+ circle at 30% 20%,
+ rgba(244, 114, 182, 0.18),
+ transparent 38%
+ ),
linear-gradient(135deg, rgba(236, 72, 153, 0.12), rgba(251, 146, 60, 0.08)),
rgba(255, 247, 252, 0.78);
}
@@ -6311,7 +6358,8 @@ html[data-mobile-keyboard-open='true'] .platform-mobile-bottom-dock {
transform: translate(-50%, -100%);
}
-.image-canvas-editor__floating-toolbar button.image-canvas-editor__floating-toolbar-text-button {
+.image-canvas-editor__floating-toolbar
+ button.image-canvas-editor__floating-toolbar-text-button {
width: auto;
min-width: 0;
gap: 0.35rem;
@@ -8779,8 +8827,11 @@ button.image-canvas-editor__reference-chip:disabled {
z-index: 999;
box-sizing: border-box;
border: 2px solid var(--image-canvas-brand-accent);
- background:
- linear-gradient(90deg, rgba(204, 117, 76, 0.2) 1px, transparent 1px),
+ background: linear-gradient(
+ 90deg,
+ rgba(204, 117, 76, 0.2) 1px,
+ transparent 1px
+ ),
linear-gradient(rgba(204, 117, 76, 0.2) 1px, transparent 1px);
background-size: 33.333% 33.333%;
box-shadow:
@@ -9335,7 +9386,8 @@ button.image-canvas-editor__reference-chip:disabled {
height: 2rem;
}
- .image-canvas-editor__floating-toolbar button.image-canvas-editor__floating-toolbar-text-button {
+ .image-canvas-editor__floating-toolbar
+ button.image-canvas-editor__floating-toolbar-text-button {
width: auto;
}
@@ -9632,8 +9684,11 @@ button.image-canvas-editor__reference-chip:disabled {
}
.platform-mobile-home-welcome-overlay {
- background:
- radial-gradient(circle at 50% 18%, rgba(255, 254, 252, 0.54), transparent 32%),
+ background: radial-gradient(
+ circle at 50% 18%,
+ rgba(255, 254, 252, 0.54),
+ transparent 32%
+ ),
rgba(61, 31, 16, 0.24);
}
@@ -9642,8 +9697,11 @@ button.image-canvas-editor__reference-chip:disabled {
overflow: hidden;
border-radius: 1.65rem;
border: 1px solid rgba(255, 255, 255, 0.68);
- background:
- radial-gradient(circle at 18% 0%, rgba(240, 203, 169, 0.28), transparent 38%),
+ background: radial-gradient(
+ circle at 18% 0%,
+ rgba(240, 203, 169, 0.28),
+ transparent 38%
+ ),
var(--platform-modal-fill);
box-shadow:
0 24px 58px rgba(112, 57, 30, 0.2),
@@ -12521,7 +12579,8 @@ button.image-canvas-editor__reference-chip:disabled {
padding: 0 !important;
background:
linear-gradient(rgba(255, 250, 244, 0.72), rgba(255, 250, 244, 0.72)),
- url('/creation-home/background-clay-workspace.png') center top / 64rem 64rem repeat,
+ url('/creation-home/background-clay-workspace.png') center top / 64rem 64rem
+ repeat,
linear-gradient(180deg, #fffaf4 0%, #fffdf9 52%, #fff8f0 100%);
box-shadow: 0 24px 58px rgba(112, 57, 30, 0.08);
}
@@ -12656,7 +12715,7 @@ button.image-canvas-editor__reference-chip:disabled {
width: 1px;
height: 1.66rem;
background: rgba(217, 190, 166, 0.82);
- content: "";
+ content: '';
transform: translateY(-50%);
}
@@ -12691,7 +12750,9 @@ button.image-canvas-editor__reference-chip:disabled {
display: none;
}
-.platform-desktop-shell--workbench .platform-desktop-topbar button.platform-desktop-search {
+.platform-desktop-shell--workbench
+ .platform-desktop-topbar
+ button.platform-desktop-search {
width: auto;
max-width: none !important;
min-width: 7.35rem;
@@ -12702,12 +12763,17 @@ button.image-canvas-editor__reference-chip:disabled {
gap: 0.38rem !important;
}
-.platform-desktop-shell--workbench .platform-desktop-topbar button.platform-desktop-search:hover {
+.platform-desktop-shell--workbench
+ .platform-desktop-topbar
+ button.platform-desktop-search:hover {
border-color: rgba(214, 184, 159, 0.52);
background: rgba(255, 250, 244, 0.56);
}
-.platform-desktop-shell--workbench .platform-desktop-topbar button.platform-desktop-search > span:first-child {
+.platform-desktop-shell--workbench
+ .platform-desktop-topbar
+ button.platform-desktop-search
+ > span:first-child {
width: 2.06rem;
height: 2.06rem;
}
@@ -12750,12 +12816,16 @@ button.image-canvas-editor__reference-chip:disabled {
box-shadow: none;
}
-.platform-desktop-shell--workbench .platform-desktop-rail__button--active .platform-desktop-rail__icon-shell {
+.platform-desktop-shell--workbench
+ .platform-desktop-rail__button--active
+ .platform-desktop-rail__icon-shell {
background: #fff2e7;
box-shadow: none;
}
-.platform-desktop-shell--workbench .platform-desktop-rail__button--active .platform-desktop-rail__icon {
+.platform-desktop-shell--workbench
+ .platform-desktop-rail__button--active
+ .platform-desktop-rail__icon {
color: #c7653d;
}
@@ -12795,7 +12865,9 @@ button.image-canvas-editor__reference-chip:disabled {
box-shadow: none;
}
-.platform-desktop-shell--workbench .platform-desktop-rail__button--active .platform-desktop-rail__label {
+.platform-desktop-shell--workbench
+ .platform-desktop-rail__button--active
+ .platform-desktop-rail__label {
color: #c7653d;
}
|