diff options
Diffstat (limited to 'apps/web/src/components/editor/panels/assets')
4 files changed, 77 insertions, 42 deletions
diff --git a/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx b/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx index b412de7b..9e9f77c6 100644 --- a/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx +++ b/apps/web/src/components/editor/panels/assets/assets-panel-store.tsx @@ -3,17 +3,16 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; import { ArrowRightDoubleIcon, - ClosedCaptionIcon, + CameraLensIcon, Folder03Icon, Happy01Icon, HeadphonesIcon, MagicWand05Icon, TextIcon, Settings01Icon, - SlidersHorizontalIcon, - ColorsIcon, } from "@hugeicons/core-free-icons"; import { HugeiconsIcon, type IconSvgElement } from "@hugeicons/react"; +import { effectsRegistry } from "@/effects"; export const TAB_KEYS = [ "media", @@ -21,9 +20,8 @@ export const TAB_KEYS = [ "text", "stickers", "effects", + "lens", "transitions", - "captions", - "adjustment", "settings", ] as const; @@ -56,18 +54,14 @@ export const tabs = { icon: createHugeiconsIcon({ icon: MagicWand05Icon }), label: "Effects", }, + lens: { + icon: createHugeiconsIcon({ icon: CameraLensIcon }), + label: "Lens", + }, transitions: { icon: createHugeiconsIcon({ icon: ArrowRightDoubleIcon }), label: "Transitions", }, - captions: { - icon: createHugeiconsIcon({ icon: ClosedCaptionIcon }), - label: "Captions", - }, - adjustment: { - icon: createHugeiconsIcon({ icon: SlidersHorizontalIcon }), - label: "Adjustment", - }, settings: { icon: createHugeiconsIcon({ icon: Settings01Icon }), label: "Settings", @@ -81,6 +75,13 @@ export type MediaViewMode = "grid" | "list"; export type MediaSortKey = "name" | "type" | "duration" | "size"; export type MediaSortOrder = "asc" | "desc"; +export function getDefaultEffectsTab(): Tab { + const hasLensEffects = effectsRegistry + .getAll() + .some((definition) => definition.category === "lens"); + return hasLensEffects ? "lens" : "effects"; +} + interface AssetsPanelStore { activeTab: Tab; setActiveTab: (tab: Tab) => void; diff --git a/apps/web/src/components/editor/panels/assets/index.tsx b/apps/web/src/components/editor/panels/assets/index.tsx index 09d64eed..c0204b12 100644 --- a/apps/web/src/components/editor/panels/assets/index.tsx +++ b/apps/web/src/components/editor/panels/assets/index.tsx @@ -3,7 +3,6 @@ import { Separator } from "@/components/ui/separator"; import { type Tab, useAssetsPanelStore } from "@/components/editor/panels/assets/assets-panel-store"; import { TabBar } from "./tabbar"; -import { Captions } from "@/subtitles/components/assets-view"; import { MediaView } from "./views/assets"; import { SettingsView } from "./views/settings"; import { SoundsView } from "@/sounds/components/assets-view"; @@ -20,18 +19,13 @@ export function AssetsPanel() { sounds: FEATURES.sounds ? <SoundsView /> : null, text: <TextView />, stickers: FEATURES.stickers ? <StickersView /> : null, - effects: FEATURES.effects ? <EffectsView /> : null, + effects: FEATURES.effects ? <EffectsView category="effect" /> : null, + lens: FEATURES.effects ? <EffectsView category="lens" /> : null, transitions: ( <div className="text-muted-foreground p-4"> Transitions view coming soon... </div> ), - captions: <Captions />, - adjustment: ( - <div className="text-muted-foreground p-4"> - Adjustment view coming soon... - </div> - ), settings: <SettingsView />, }; diff --git a/apps/web/src/components/editor/panels/assets/tabbar.tsx b/apps/web/src/components/editor/panels/assets/tabbar.tsx index b468b5bb..9b029e3d 100644 --- a/apps/web/src/components/editor/panels/assets/tabbar.tsx +++ b/apps/web/src/components/editor/panels/assets/tabbar.tsx @@ -14,13 +14,22 @@ import { useAssetsPanelStore,
} from "@/components/editor/panels/assets/assets-panel-store";
import { FEATURES } from "@/features";
+import { effectsRegistry } from "@/effects";
-const VISIBLE_TAB_KEYS = TAB_KEYS.filter((tabKey) => {
- if (tabKey === "sounds") return FEATURES.sounds;
- if (tabKey === "stickers") return FEATURES.stickers;
- if (tabKey === "effects") return FEATURES.effects;
- return true;
-});
+function getVisibleTabKeys() {
+ const effectCategories = new Set(
+ effectsRegistry.getAll().map((definition) => definition.category),
+ );
+ return TAB_KEYS.filter((tabKey) => {
+ if (tabKey === "sounds") return FEATURES.sounds;
+ if (tabKey === "stickers") return FEATURES.stickers;
+ if (tabKey === "effects")
+ return FEATURES.effects && effectCategories.has("effect");
+ if (tabKey === "lens")
+ return FEATURES.effects && effectCategories.has("lens");
+ return true;
+ });
+}
export function TabBar() {
const { activeTab, setActiveTab } = useAssetsPanelStore();
@@ -59,7 +68,7 @@ export function TabBar() { ref={scrollRef}
className="scrollbar-hidden relative flex size-full p-1 flex-col items-center justify-start gap-0.5 overflow-y-auto"
>
- {VISIBLE_TAB_KEYS.map((tabKey) => {
+ {getVisibleTabKeys().map((tabKey) => {
const tab = tabs[tabKey];
return (
<Tooltip key={tabKey} delayDuration={10}>
diff --git a/apps/web/src/components/editor/panels/assets/views/assets.tsx b/apps/web/src/components/editor/panels/assets/views/assets.tsx index 4dbed41e..049cb5f4 100644 --- a/apps/web/src/components/editor/panels/assets/views/assets.tsx +++ b/apps/web/src/components/editor/panels/assets/views/assets.tsx @@ -48,8 +48,10 @@ import { import { MASKABLE_ELEMENT_TYPES } from "@/timeline"; import type { MediaAsset } from "@/media/types"; import { cn } from "@/utils/ui"; +import { RenameDialog } from "@/components/editor/rename-dialog"; import { CloudUploadIcon, + Edit02Icon, GridViewIcon, LeftToRightListDashIcon, SortingOneNineIcon, @@ -316,25 +318,54 @@ function MediaItemWithContextMenu({ }) => void; }) { const { isSelected, selectedIds } = useSelection(); + const editor = useEditor(); + const activeProject = useEditor((e) => e.project.getActive()); + const [isRenameDialogOpen, setIsRenameDialogOpen] = useState(false); const idsToDelete = isSelected(item.id) ? selectedIds : [item.id]; const deleteLabel = idsToDelete.length > 1 ? `Delete ${idsToDelete.length} items` : "Delete"; return ( - <ContextMenu> - <ContextMenuTrigger asChild>{children}</ContextMenuTrigger> - <ContextMenuContent> - <ContextMenuItem>Export clips</ContextMenuItem> - <ContextMenuItem - variant="destructive" - onClick={(event: React.MouseEvent<HTMLDivElement>) => - onRemove({ event, ids: idsToDelete }) - } - > - {deleteLabel} - </ContextMenuItem> - </ContextMenuContent> - </ContextMenu> + <> + <ContextMenu> + <ContextMenuTrigger asChild>{children}</ContextMenuTrigger> + <ContextMenuContent> + <ContextMenuItem + icon={<HugeiconsIcon icon={Edit02Icon} />} + onClick={(event: React.MouseEvent<HTMLDivElement>) => { + event.stopPropagation(); + setIsRenameDialogOpen(true); + }} + > + Rename + </ContextMenuItem> + <ContextMenuItem>Export clips</ContextMenuItem> + <ContextMenuItem + variant="destructive" + onClick={(event: React.MouseEvent<HTMLDivElement>) => + onRemove({ event, ids: idsToDelete }) + } + > + {deleteLabel} + </ContextMenuItem> + </ContextMenuContent> + </ContextMenu> + <RenameDialog + isOpen={isRenameDialogOpen} + onOpenChange={setIsRenameDialogOpen} + currentName={item.name} + title="Rename asset" + onConfirm={(newName) => { + if (!activeProject) return; + editor.media.renameMediaAsset({ + projectId: activeProject.metadata.id, + id: item.id, + name: newName, + }); + setIsRenameDialogOpen(false); + }} + /> + </> ); } |
