From 45919c6a2ae9e318f6e46789446d0e8a0ee66e52 Mon Sep 17 00:00:00 2001 From: BFlat Date: Tue, 9 Jul 2024 22:03:51 +0700 Subject: [PATCH 1/3] outliner selected color change (#597) put more focus onto selected object so outliner is more visible ![image](https://github.com/storytold/GottaGoFast/assets/46063141/e6fe6cab-dc2b-404c-83f9-cb3d82ac5ca6) --- .../PageEnigma/comps/Outliner/Outliner.tsx | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/app/pages/PageEnigma/comps/Outliner/Outliner.tsx b/app/pages/PageEnigma/comps/Outliner/Outliner.tsx index 38a2dde8ef..3b54de26c1 100644 --- a/app/pages/PageEnigma/comps/Outliner/Outliner.tsx +++ b/app/pages/PageEnigma/comps/Outliner/Outliner.tsx @@ -33,8 +33,7 @@ const OutlinerItem = ({ item }: { item: SceneObject }) => { const isSelected = outlinerState.selectedItem.value?.id === item.id; - - const editorEngine = useContext(EngineContext) + const editorEngine = useContext(EngineContext); // Delete object logic here const handleDeleteKeyPress = (event: React.KeyboardEvent) => { @@ -53,8 +52,9 @@ const OutlinerItem = ({ item }: { item: SceneObject }) => {
setHovered(true)} onMouseLeave={() => setHovered(false)} @@ -73,7 +73,10 @@ const OutlinerItem = ({ item }: { item: SceneObject }) => {
diff --git a/app/components/reusable/UploadModal3DPreview/UploadFiles3D.tsx b/app/components/reusable/UploadModal3DPreview/UploadFiles3D.tsx index 0842adcec3..1f81ce1d5c 100644 --- a/app/components/reusable/UploadModal3DPreview/UploadFiles3D.tsx +++ b/app/components/reusable/UploadModal3DPreview/UploadFiles3D.tsx @@ -149,7 +149,7 @@ export const UploadFiles3D = ({ {!assetFile.value && (
- File Preivew + File Preview
)} {previewStatus.type.includes("Error") && ( diff --git a/app/components/reusable/UploadModalImages/UploadFilesImages.tsx b/app/components/reusable/UploadModalImages/UploadFilesImages.tsx index ce9e2c2b1b..b8790a1acc 100644 --- a/app/components/reusable/UploadModalImages/UploadFilesImages.tsx +++ b/app/components/reusable/UploadModalImages/UploadFilesImages.tsx @@ -108,7 +108,7 @@ export const UploadFilesImages = ({
{!assetFile.value && (
- File Preivew + File Preview
)} {assetFile.value && ( diff --git a/app/pages/PageEnigma/comps/SidePanelMenu/SidePanelMenu.tsx b/app/pages/PageEnigma/comps/SidePanelMenu/SidePanelMenu.tsx index 9c8dc1b0d4..09ad5282bf 100644 --- a/app/pages/PageEnigma/comps/SidePanelMenu/SidePanelMenu.tsx +++ b/app/pages/PageEnigma/comps/SidePanelMenu/SidePanelMenu.tsx @@ -80,7 +80,10 @@ export const SidePanelMenu = ({
-
+
{tab.title}
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/AnimationTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/AnimationTab.tsx index 0f2ee045ee..5999613bd6 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/AnimationTab.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/AnimationTab.tsx @@ -1,42 +1,79 @@ import { useCallback, useEffect, useState } from "react"; import { useSignals } from "@preact/signals-react/runtime"; import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons"; - -import { MediaInfo, MediaItem } from "~/pages/PageEnigma/models"; import { AssetFilterOption, - AssetType, + FeatureFlags, FilterEngineCategories, MediaFileAnimationType, - ToastTypes, } from "~/enums"; - import { animationItems } from "~/pages/PageEnigma/signals"; -import { addToast } from "~/signals"; - -import { Button, FilterButtons, Pagination, UploadModal } from "~/components"; +import { + Button, + FilterButtons, + Pagination, + SearchFilter, + UploadModal, +} from "~/components"; import { TabTitle, ItemElements, } from "~/pages/PageEnigma/comps/SidePanelTabs/sharedComps"; - -import { MediaFilesApi } from "~/Classes/ApiManager"; import { FetchStatus } from "~/pages/PageEnigma/enums"; -import { BucketConfig } from "~/api/BucketConfig"; +import { + fetchFeaturedMediaItems, + fetchFeaturedMediaItemsSearchResults, + FetchMediaItemStates, + fetchUserMediaItems, + fetchUserMediaItemsSearchResults, + isAnyStatusFetching, +} from "../utilities"; +import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; export const AnimationTab = () => { useSignals(); + const showSearchObjectComponent = usePosthogFeatureFlag( + FeatureFlags.SHOW_SEARCH_OBJECTS, + ); + const [open, setOpen] = useState(false); + const [searchTermFeatured, setSearchTermFeatured] = useState(""); + const [searchTermUser, setSearchTermUser] = useState(""); + + const [ + { mediaItems: userAnimations, status: userFetchStatus }, + setUserFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredAnimations, status: featuredFetchStatus }, + setFeaturedFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredSearchResults, status: featuredSearchFetchStatus }, + setFeaturedSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: userSearchResults, status: userSearchFetchStatus }, + setUserSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); - const [userAnimations, setUserAnimations] = useState(); - const [featuredAnimations, setFeaturedAnimations] = useState< - MediaItem[] | undefined - >(undefined); const [selectedFilter, setSelectedFilter] = useState( AssetFilterOption.FEATURED, ); - const filteredAnimations = + const displayedItems = selectedFilter === AssetFilterOption.FEATURED ? [...(featuredAnimations || []), ...animationItems.value] : userAnimations ?? []; @@ -44,104 +81,88 @@ export const AnimationTab = () => { const [currentPage, setCurrentPage] = useState(0); const pageSize = 21; - const totalPages = Math.ceil(filteredAnimations.length / pageSize); + const totalPages = Math.ceil(displayedItems.length / pageSize); - const [fetchStatuses, setFetchStatuses] = useState({ - userObjectsFetch: FetchStatus.READY, - featuredObjectsFetch: FetchStatus.READY, - }); - const isFetching = - fetchStatuses.userObjectsFetch === FetchStatus.READY || - fetchStatuses.userObjectsFetch === FetchStatus.IN_PROGRESS || - fetchStatuses.featuredObjectsFetch === FetchStatus.READY || - fetchStatuses.featuredObjectsFetch === FetchStatus.IN_PROGRESS; + const isFetching = isAnyStatusFetching([ + userFetchStatus, + featuredFetchStatus, + featuredSearchFetchStatus, + userSearchFetchStatus, + ]); - const responseMapping = (data: MediaInfo[]) => { - return data.map((item) => { - const bucketConfig = new BucketConfig(); - const itemThumb = bucketConfig.getCdnUrl( - item.cover_image.maybe_cover_image_public_bucket_path ?? "", - 600, - 100, - ); - return { - colorIndex: item.cover_image.default_cover.color_index, - imageIndex: item.cover_image.default_cover.image_index, - media_id: item.token, - name: item.maybe_title ?? "Unknown", - type: AssetType.ANIMATION, - media_type: item.media_type, - length: ((item.maybe_duration_millis ?? 1000) / 1000) * 60, - version: 1, - ...(item.cover_image.maybe_cover_image_public_bucket_path - ? { - thumbnail: itemThumb, - } - : {}), - }; - }); - }; + const fetchUserAnimations = useCallback( + () => + fetchUserMediaItems({ + filterEngineCategories: [FilterEngineCategories.ANIMATION], + setState: (newState: FetchMediaItemStates) => { + setUserFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching User Set Objects", + }), + [], + ); - const fetchUserAnimations = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.IN_PROGRESS, - })); - const mediaFilesApi = new MediaFilesApi(); + const fetchFeaturedAnimations = useCallback( + () => + fetchFeaturedMediaItems({ + filterEngineCategories: [FilterEngineCategories.ANIMATION], + setState: (newState: FetchMediaItemStates) => { + setFeaturedFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching Featured Set Objects", + }), + [], + ); - const response = await mediaFilesApi.ListUserMediaFiles({ - page_size: 100, - filter_engine_categories: [FilterEngineCategories.ANIMATION], - }); - - if (response.success && response.data) { - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.SUCCESS, - })); - const newAnimations = responseMapping(response.data); - setUserAnimations(newAnimations); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching User Animations", + const filterAnimationItems = (searchTerm: string) => + animationItems.value.filter((item) => + item.name.toLowerCase().includes(searchTerm.toLowerCase()), ); - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.ERROR, - })); - }, []); - const fetchFeaturedAnimations = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.IN_PROGRESS, - })); - const mediaFilesApi = new MediaFilesApi(); - - const response = await mediaFilesApi.ListFeaturedMediaFiles({ - filter_engine_categories: [FilterEngineCategories.ANIMATION], + const fetchFeaturedSearchResults = useCallback(async () => { + const filteredAnimationItems = filterAnimationItems(searchTermFeatured); + fetchFeaturedMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.ANIMATION], + setState: (newState: FetchMediaItemStates) => { + setFeaturedSearchFetch(() => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? [...filteredAnimationItems, ...newState.mediaItems] + : filteredAnimationItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching Featured Set Objects Search Results", + searchTerm: searchTermFeatured, }); + }, [searchTermFeatured]); - if (response.success && response.data) { - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.SUCCESS, - })); - const newAnimations = responseMapping(response.data); - setFeaturedAnimations(newAnimations); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching Featured Animations", - ); - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.ERROR, - })); - }, []); + const fetchUserSearchResults = useCallback(async () => { + fetchUserMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.ANIMATION], + setState: (newState: FetchMediaItemStates) => { + setUserSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching User Set Objects Search Results", + searchTerm: searchTermUser, + }); + }, [searchTermUser]); useEffect(() => { if (!userAnimations) { @@ -157,6 +178,22 @@ export const AnimationTab = () => { fetchFeaturedAnimations, ]); + useEffect(() => { + if (selectedFilter === AssetFilterOption.FEATURED) { + setCurrentPage(0); + fetchFeaturedSearchResults(); + } else if (selectedFilter === AssetFilterOption.MINE) { + setCurrentPage(0); + fetchUserSearchResults(); + } + }, [ + searchTermFeatured, + searchTermUser, + fetchFeaturedSearchResults, + fetchUserSearchResults, + selectedFilter, + ]); + return ( <> @@ -169,7 +206,7 @@ export const AnimationTab = () => { }} /> -
+
+ {showSearchObjectComponent && ( + + )}
{ debug="animations tab" currentPage={currentPage} pageSize={pageSize} - items={filteredAnimations} + items={ + selectedFilter === AssetFilterOption.FEATURED + ? searchTermFeatured + ? featuredSearchResults ?? [] + : displayedItems + : searchTermUser + ? userSearchResults ?? [] + : displayedItems + } />
{totalPages > 1 && ( diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersTab.tsx index d6c768ab12..97f5b24bef 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersTab.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/CharactersTab.tsx @@ -1,37 +1,74 @@ import { useCallback, useEffect, useState } from "react"; import { useSignals } from "@preact/signals-react/runtime"; import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons"; - import { AssetFilterOption, AssetType, + FeatureFlags, FilterEngineCategories, - ToastTypes, } from "~/enums"; import { FetchStatus } from "~/pages/PageEnigma/enums"; -import { MediaInfo, MediaItem } from "~/pages/PageEnigma/models"; import { characterItems as demoCharacterItems } from "~/pages/PageEnigma/signals"; -import { addToast } from "~/signals"; - -import { BucketConfig } from "~/api/BucketConfig"; - -import { Button, FileWrapper, FilterButtons, Pagination } from "~/components"; +import { + Button, + FileWrapper, + FilterButtons, + Pagination, + SearchFilter, +} from "~/components"; import { ItemElements, TabTitle, } from "~/pages/PageEnigma/comps/SidePanelTabs/sharedComps"; - -import { MediaFilesApi } from "~/Classes/ApiManager"; +import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; +import { + fetchFeaturedMediaItems, + fetchFeaturedMediaItemsSearchResults, + FetchMediaItemStates, + fetchUserMediaItems, + fetchUserMediaItemsSearchResults, + isAnyStatusFetching, +} from "../utilities"; export const CharactersTab = () => { useSignals(); - const [userCharacters, setUserCharacters] = useState( - undefined, + const showSearchObjectComponent = usePosthogFeatureFlag( + FeatureFlags.SHOW_SEARCH_OBJECTS, ); - const [featuredCharacters, setFeaturedCharacters] = useState< - MediaItem[] | undefined - >(undefined); + + const [searchTermFeatured, setSearchTermFeatured] = useState(""); + const [searchTermUser, setSearchTermUser] = useState(""); + + const [ + { mediaItems: userCharacters, status: userFetchStatus }, + setUserFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredCharacters, status: featuredFetchStatus }, + setFeaturedFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredSearchResults, status: featuredSearchFetchStatus }, + setFeaturedSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: userSearchResults, status: userSearchFetchStatus }, + setUserSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [selectedFilter, setSelectedFilter] = useState( AssetFilterOption.FEATURED, ); @@ -39,7 +76,7 @@ export const CharactersTab = () => { ...demoCharacterItems.value, ...(featuredCharacters ?? []), ]; - const filteredCharacters = + const displayedItems = selectedFilter === AssetFilterOption.FEATURED ? allFeaturedCharacters ?? [] : userCharacters ?? []; @@ -47,104 +84,88 @@ export const CharactersTab = () => { const [currentPage, setCurrentPage] = useState(0); const pageSize = 21; - const totalPages = Math.ceil(filteredCharacters.length / pageSize); + const totalPages = Math.ceil(displayedItems.length / pageSize); - const [fetchStatuses, setFetchStatuses] = useState({ - userObjectsFetch: FetchStatus.READY, - featuredObjectsFetch: FetchStatus.READY, - }); - const isFetching = - fetchStatuses.userObjectsFetch === FetchStatus.READY || - fetchStatuses.userObjectsFetch === FetchStatus.IN_PROGRESS || - fetchStatuses.featuredObjectsFetch === FetchStatus.READY || - fetchStatuses.featuredObjectsFetch === FetchStatus.IN_PROGRESS; + const isFetching = isAnyStatusFetching([ + userFetchStatus, + featuredFetchStatus, + featuredSearchFetchStatus, + userSearchFetchStatus, + ]); - const responseMapping = (data: MediaInfo[]): MediaItem[] => { - return data.map((item) => { - const bucketConfig = new BucketConfig(); - const itemThumb = bucketConfig.getCdnUrl( - item.cover_image.maybe_cover_image_public_bucket_path ?? "", - 600, - 100, - ); - return { - colorIndex: item.cover_image.default_cover.color_index, - imageIndex: item.cover_image.default_cover.image_index, - media_id: item.token, - name: item.maybe_title ?? "Unknown", - type: AssetType.CHARACTER, - media_type: item.media_type, - // maybe_animation_type: item.maybe_animation_type || undefined, - version: 1, - ...(item.cover_image.maybe_cover_image_public_bucket_path - ? { - thumbnail: itemThumb, - } - : {}), - }; - }); - }; - const fetchUserCharacters = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.IN_PROGRESS, - })); - const mediaFilesApi = new MediaFilesApi(); + const fetchUserCharacters = useCallback( + () => + fetchUserMediaItems({ + filterEngineCategories: [FilterEngineCategories.CHARACTER], + setState: (newState: FetchMediaItemStates) => { + setUserFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching User Characters", + }), + [], + ); - const response = await mediaFilesApi.ListUserMediaFiles({ - page_size: 100, - filter_engine_categories: [FilterEngineCategories.CHARACTER], - }); + const fetchFeaturedCharacters = useCallback( + () => + fetchFeaturedMediaItems({ + filterEngineCategories: [FilterEngineCategories.CHARACTER], + setState: (newState: FetchMediaItemStates) => { + setFeaturedFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching Featured Characters", + }), + [], + ); - if (response.success && response.data) { - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.SUCCESS, - })); - const newCharacters = responseMapping(response.data); - setUserCharacters(newCharacters); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching User Characters", + const filterCharacterItems = (searchTerm: string) => + demoCharacterItems.value.filter((item) => + item.name.toLowerCase().includes(searchTerm.toLowerCase()), ); - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.ERROR, - })); - }, []); - const fetchFeaturedCharacters = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.IN_PROGRESS, - })); - const mediaFilesApi = new MediaFilesApi(); - - const response = await mediaFilesApi.ListFeaturedMediaFiles({ - filter_engine_categories: [FilterEngineCategories.CHARACTER], + const fetchFeaturedSearchResults = useCallback(async () => { + const filteredCharacterItems = filterCharacterItems(searchTermFeatured); + fetchFeaturedMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.CHARACTER], + setState: (newState: FetchMediaItemStates) => { + setFeaturedSearchFetch(() => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? [...filteredCharacterItems, ...newState.mediaItems] + : filteredCharacterItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching Featured Characters Search Results", + searchTerm: searchTermFeatured, }); + }, [searchTermFeatured]); - if (response.success && response.data) { - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.SUCCESS, - })); - const newCharacters = responseMapping(response.data); - - setFeaturedCharacters(newCharacters); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching Featured Characters", - ); - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.ERROR, - })); - }, []); + const fetchUserSearchResults = useCallback(async () => { + fetchUserMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.CHARACTER], + setState: (newState: FetchMediaItemStates) => { + setUserSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching User Characters Search Results", + searchTerm: searchTermUser, + }); + }, [searchTermUser]); useEffect(() => { if (!userCharacters) { @@ -160,6 +181,22 @@ export const CharactersTab = () => { fetchFeaturedCharacters, ]); + useEffect(() => { + if (selectedFilter === AssetFilterOption.FEATURED) { + setCurrentPage(0); + fetchFeaturedSearchResults(); + } else if (selectedFilter === AssetFilterOption.MINE) { + setCurrentPage(0); + fetchUserSearchResults(); + } + }, [ + searchTermFeatured, + searchTermUser, + fetchFeaturedSearchResults, + fetchUserSearchResults, + selectedFilter, + ]); + return ( <> { }} />
-
+
+ {showSearchObjectComponent && ( + + )}
{totalPages > 1 && ( @@ -207,7 +272,7 @@ export const CharactersTab = () => { /> )} - )} // End FileWrapper Render + )} /> ); diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ExpressionTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ExpressionTab.tsx index 43b505e7d6..798f4b623c 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ExpressionTab.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ExpressionTab.tsx @@ -1,102 +1,160 @@ import { useCallback, useEffect, useState } from "react"; import { useSignals } from "@preact/signals-react/runtime"; import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons"; - -import { MediaInfo, MediaItem } from "~/pages/PageEnigma/models"; import { AssetFilterOption, - AssetType, FilterEngineCategories, - ToastTypes, MediaFileAnimationType, + FeatureFlags, } from "~/enums"; - import { Button, FilterButtons, Pagination, + SearchFilter, UploadModal, } from "~/components"; import { ItemElements, TabTitle, } from "~/pages/PageEnigma/comps/SidePanelTabs/sharedComps"; - -import { MediaFilesApi } from "~/Classes/ApiManager"; -import { addToast } from "~/signals"; +import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; +import { + fetchFeaturedMediaItems, + fetchFeaturedMediaItemsSearchResults, + FetchMediaItemStates, + fetchUserMediaItems, + fetchUserMediaItemsSearchResults, + isAnyStatusFetching, +} from "../utilities"; +import { FetchStatus } from "~/pages/PageEnigma/enums"; export const ExpressionTab = () => { useSignals(); - const [open, setOpen] = useState(false); - const [userExpressions, setUserExpressions] = useState(); - const [featuredExpressions, setFeaturedExpressions] = useState< - MediaItem[] | undefined - >(undefined); + const showSearchObjectComponent = usePosthogFeatureFlag( + FeatureFlags.SHOW_SEARCH_OBJECTS, + ); + + const [open, setOpen] = useState(false); + const [searchTermFeatured, setSearchTermFeatured] = useState(""); + const [searchTermUser, setSearchTermUser] = useState(""); + + const [ + { mediaItems: userExpressions, status: userFetchStatus }, + setUserFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredExpressions, status: featuredFetchStatus }, + setFeaturedFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredSearchResults, status: featuredSearchFetchStatus }, + setFeaturedSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: userSearchResults, status: userSearchFetchStatus }, + setUserSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [selectedFilter, setSelectedFilter] = useState( AssetFilterOption.FEATURED, ); - const filteredExpressions = + const displayedItems = selectedFilter === AssetFilterOption.FEATURED ? featuredExpressions ?? [] : userExpressions ?? []; const [currentPage, setCurrentPage] = useState(0); const pageSize = 21; - const totalPages = Math.ceil(filteredExpressions.length / pageSize); + const totalPages = Math.ceil(displayedItems.length / pageSize); - const responseMapping = (data: MediaInfo[], isMine: boolean) => { - return data.map((item, index: number) => { - return { - version: 1, - type: AssetType.EXPRESSION, - media_type: item.media_type, - media_id: item.token, - name: item.maybe_title, - publicBucketPath: item.public_bucket_path, - length: ((item.maybe_duration_millis ?? 1000) / 1000) * 60, - thumbnail: item.cover_image?.maybe_cover_image_public_bucket_path - ? "https://cdn.fakeyou.com/cdn-cgi/image/width=600,quality=100" + - item.cover_image?.maybe_cover_image_public_bucket_path - : undefined, - isMine: isMine, - imageIndex: index, - } as MediaItem; - }); - }; + const isFetching = isAnyStatusFetching([ + userFetchStatus, + featuredFetchStatus, + featuredSearchFetchStatus, + userSearchFetchStatus, + ]); - const fetchUserExpressions = useCallback(async () => { - const mediaFilesApi = new MediaFilesApi(); - const response = await mediaFilesApi.ListUserMediaFiles({ - page_size: 100, - filter_engine_categories: [FilterEngineCategories.EXPRESSION], - }); - if (response.success && response.data) { - const newExpressions = responseMapping(response.data, true); - setUserExpressions(newExpressions); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching User Expressions", - ); - }, []); + const fetchUserExpressions = useCallback( + () => + fetchUserMediaItems({ + filterEngineCategories: [FilterEngineCategories.EXPRESSION], + setState: (newState: FetchMediaItemStates) => { + setUserFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching User Expressions", + }), + [], + ); - const fetchFeaturedExpressions = useCallback(async () => { - const mediaFilesApi = new MediaFilesApi(); - const response = await mediaFilesApi.ListFeaturedMediaFiles({ - filter_engine_categories: [FilterEngineCategories.EXPRESSION], + const fetchFeaturedExpressions = useCallback( + () => + fetchFeaturedMediaItems({ + filterEngineCategories: [FilterEngineCategories.EXPRESSION], + setState: (newState: FetchMediaItemStates) => { + setFeaturedFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching Featured Expressions", + }), + [], + ); + + const fetchFeaturedSearchResults = useCallback(async () => { + fetchFeaturedMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.EXPRESSION], + setState: (newState: FetchMediaItemStates) => { + setFeaturedSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching Featured Expressions Search Results", + searchTerm: searchTermFeatured, }); - if (response.success && response.data) { - const newExpressions = responseMapping(response.data, false); - setFeaturedExpressions(newExpressions); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching Featured Expressions", - ); - }, []); + }, [searchTermFeatured]); + + const fetchUserSearchResults = useCallback(async () => { + fetchUserMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.EXPRESSION], + setState: (newState: FetchMediaItemStates) => { + setUserSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching User Expressions Search Results", + searchTerm: searchTermUser, + }); + }, [searchTermUser]); useEffect(() => { if (!userExpressions) { @@ -107,11 +165,27 @@ export const ExpressionTab = () => { } }, [ userExpressions, - featuredExpressions, fetchUserExpressions, + featuredExpressions, fetchFeaturedExpressions, ]); + useEffect(() => { + if (selectedFilter === AssetFilterOption.FEATURED) { + setCurrentPage(0); + fetchFeaturedSearchResults(); + } else if (selectedFilter === AssetFilterOption.MINE) { + setCurrentPage(0); + fetchUserSearchResults(); + } + }, [ + searchTermFeatured, + searchTermUser, + fetchFeaturedSearchResults, + fetchUserSearchResults, + selectedFilter, + ]); + return ( <> @@ -122,42 +196,50 @@ export const ExpressionTab = () => { setCurrentPage(0); }} /> -
+
- {/* Video Tutorial: Creating your own expressions} - > - - */} + {showSearchObjectComponent && ( + + )}
{totalPages > 1 && ( diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ImagePlanesTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ImagePlanesTab.tsx index 8f912060df..267120deef 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ImagePlanesTab.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ImagePlanesTab.tsx @@ -1,34 +1,41 @@ import { useCallback, useEffect, useState } from "react"; import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons"; - import { AssetFilterOption, + FeatureFlags, FilterEngineCategories, IMAGE_FILE_TYPE, } from "~/enums"; import { FetchStatus } from "~/pages/PageEnigma/enums"; - import { Button, FilterButtons, Pagination, + SearchFilter, UploadModalImages, } from "~/components"; - import { TabTitle, ItemElements, } from "~/pages/PageEnigma/comps/SidePanelTabs/sharedComps"; - import { fetchFeaturedMediaItems, fetchUserMediaItems, FetchMediaItemStates, isAnyStatusFetching, + fetchFeaturedMediaItemsSearchResults, + fetchUserMediaItemsSearchResults, } from "../utilities"; +import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; export const ImagePlanesTab = () => { + const showSearchObjectComponent = usePosthogFeatureFlag( + FeatureFlags.SHOW_SEARCH_OBJECTS, + ); + const [openUploadModal, setOpenUploadModal] = useState(false); + const [searchTermFeatured, setSearchTermFeatured] = useState(""); + const [searchTermUser, setSearchTermUser] = useState(""); const [{ mediaItems: userImages, status: userFetchStatus }, setUserFetch] = useState({ @@ -36,15 +43,29 @@ export const ImagePlanesTab = () => { status: FetchStatus.READY, }); const [ - { mediaItems: featuredImages, status: feateredFetchStatus }, + { mediaItems: featuredImages, status: featuredFetchStatus }, setFeaturedFetch, ] = useState({ mediaItems: undefined, status: FetchStatus.READY, }); + const [ + { mediaItems: featuredSearchResults, status: featuredSearchFetchStatus }, + setFeaturedSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: userSearchResults, status: userSearchFetchStatus }, + setUserSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); const [selectedFilter, setSelectedFilter] = useState(AssetFilterOption.MINE); - const diasplayedItems = + const displayedItems = selectedFilter === AssetFilterOption.FEATURED ? featuredImages ?? [] : userImages ?? []; @@ -52,11 +73,13 @@ export const ImagePlanesTab = () => { const [currentPage, setCurrentPage] = useState(0); const pageSize = 21; - const totalPages = Math.ceil(diasplayedItems.length / pageSize); + const totalPages = Math.ceil(displayedItems.length / pageSize); const isFetching = isAnyStatusFetching([ userFetchStatus, - feateredFetchStatus, + featuredFetchStatus, + featuredSearchFetchStatus, + userSearchFetchStatus, ]); const fetchUserImages = useCallback( @@ -93,6 +116,40 @@ export const ImagePlanesTab = () => { [], ); + const fetchFeaturedSearchResults = useCallback(async () => { + fetchFeaturedMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.IMAGE_PLANE], + setState: (newState: FetchMediaItemStates) => { + setFeaturedSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching Featured Images Search Results", + searchTerm: searchTermFeatured, + }); + }, [searchTermFeatured]); + + const fetchUserSearchResults = useCallback(async () => { + fetchUserMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.IMAGE_PLANE], + setState: (newState: FetchMediaItemStates) => { + setUserSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching User Images Search Results", + searchTerm: searchTermUser, + }); + }, [searchTermUser]); + useEffect(() => { if (!userImages) { fetchUserImages(); @@ -102,6 +159,22 @@ export const ImagePlanesTab = () => { } }, [userImages, fetchUserImages, featuredImages, fetchFeaturedImages]); + useEffect(() => { + if (selectedFilter === AssetFilterOption.FEATURED) { + setCurrentPage(0); + fetchFeaturedSearchResults(); + } else if (selectedFilter === AssetFilterOption.MINE) { + setCurrentPage(0); + fetchUserSearchResults(); + } + }, [ + searchTermFeatured, + searchTermUser, + fetchFeaturedSearchResults, + fetchUserSearchResults, + selectedFilter, + ]); + return ( <> @@ -113,7 +186,7 @@ export const ImagePlanesTab = () => { }} /> -
+
+ {showSearchObjectComponent && ( + + )}
{totalPages > 1 && ( diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ObjectsTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ObjectsTab.tsx index 4e017a4f57..5c4292ee0a 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ObjectsTab.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/ObjectsTab.tsx @@ -1,22 +1,16 @@ import { useCallback, useEffect, useState } from "react"; import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; import { useSignals } from "@preact/signals-react/runtime"; - import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons"; - import { AssetFilterOption, AssetType, FeatureFlags, FilterEngineCategories, - ToastTypes, } from "~/enums"; import { FetchStatus } from "~/pages/PageEnigma/enums"; -import { MediaInfo, MediaItem } from "~/pages/PageEnigma/models"; import { shapeItems } from "~/pages/PageEnigma/signals"; -import { BucketConfig } from "~/api/BucketConfig"; - import { TabTitle, ItemElements, @@ -28,8 +22,14 @@ import { SearchFilter, Pagination, } from "~/components"; -import { MediaFilesApi } from "~/Classes/ApiManager"; -import { addToast } from "~/signals"; +import { + fetchFeaturedMediaItems, + fetchFeaturedMediaItemsSearchResults, + FetchMediaItemStates, + fetchUserMediaItems, + fetchUserMediaItemsSearchResults, + isAnyStatusFetching, +} from "../utilities"; export const ObjectsTab = () => { useSignals(); @@ -39,209 +39,128 @@ export const ObjectsTab = () => { ); const [searchTermFeatured, setSearchTermFeatured] = useState(""); - const [searchTermMine, setSearchTermMine] = useState(""); - const [filteredSearchObjectsFeatured, setFilteredSearchObjectsFeatured] = - useState([]); - const [filteredSearchObjectsMine, setFilteredSearchObjectsMine] = useState< - MediaItem[] - >([]); - const [userObjects, setUserObjects] = useState( - undefined, - ); - const [featuredObjects, setFeaturedObjects] = useState< - MediaItem[] | undefined - >(undefined); + const [searchTermUser, setSearchTermUser] = useState(""); + + const [{ mediaItems: userObjects, status: userFetchStatus }, setUserFetch] = + useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredObjects, status: featuredFetchStatus }, + setFeaturedFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: featuredSearchResults, status: featuredSearchFetchStatus }, + setFeaturedSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: userSearchResults, status: userSearchFetchStatus }, + setUserSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [selectedFilter, setSelectedFilter] = useState( AssetFilterOption.FEATURED, ); const [currentPage, setCurrentPage] = useState(0); - const filteredObjects = + const displayedItems = selectedFilter === AssetFilterOption.FEATURED ? [...shapeItems.value, ...(featuredObjects ?? [])] : userObjects ?? []; const pageSize = 21; - const totalPages = Math.ceil(filteredObjects.length / pageSize); + const totalPages = Math.ceil(displayedItems.length / pageSize); - const [fetchStatuses, setFetchStatuses] = useState({ - userObjectsFetch: FetchStatus.READY, - featuredObjectsFetch: FetchStatus.READY, - searchFetch: FetchStatus.READY, - }); - const isFetching = - fetchStatuses.userObjectsFetch === FetchStatus.READY || - fetchStatuses.userObjectsFetch === FetchStatus.IN_PROGRESS || - fetchStatuses.featuredObjectsFetch === FetchStatus.READY || - fetchStatuses.featuredObjectsFetch === FetchStatus.IN_PROGRESS || - fetchStatuses.searchFetch === FetchStatus.READY || - fetchStatuses.searchFetch === FetchStatus.IN_PROGRESS; + const isFetching = isAnyStatusFetching([ + userFetchStatus, + featuredFetchStatus, + featuredSearchFetchStatus, + userSearchFetchStatus, + ]); - const responseMapping = (data: MediaInfo[]) => { - return data.map((item) => { - const bucketConfig = new BucketConfig(); - const itemThumb = bucketConfig.getCdnUrl( - item.cover_image.maybe_cover_image_public_bucket_path ?? "", - 600, - 100, - ); - return { - colorIndex: item.cover_image.default_cover.color_index, - imageIndex: item.cover_image.default_cover.image_index, - media_id: item.token, - name: item.maybe_title ?? "Unknown", - type: AssetType.OBJECT, - media_type: item.media_type, - version: 1, - ...(item.cover_image.maybe_cover_image_public_bucket_path - ? { - thumbnail: itemThumb, - } - : {}), - }; - }); - }; + const fetchUserObjects = useCallback( + () => + fetchUserMediaItems({ + filterEngineCategories: [FilterEngineCategories.OBJECT], + setState: (newState: FetchMediaItemStates) => { + setUserFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching User Set Objects", + }), + [], + ); + + const fetchFeaturedObjects = useCallback( + () => + fetchFeaturedMediaItems({ + filterEngineCategories: [FilterEngineCategories.OBJECT], + setState: (newState: FetchMediaItemStates) => { + setFeaturedFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: "Unknown Error in Fetching Featured Set Objects", + }), + [], + ); + + const filterObjectItems = (searchTerm: string) => + shapeItems.value.filter((item) => + item.name.toLowerCase().includes(searchTerm.toLowerCase()), + ); const fetchFeaturedSearchResults = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.IN_PROGRESS, - })); - const searchTerm = searchTermFeatured; - if (!searchTerm.trim()) { - setFilteredSearchObjectsFeatured([]); - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.SUCCESS, - })); - return; - } - - const mediaFilesApi = new MediaFilesApi(); - const response = await mediaFilesApi.SearchFeaturedMediaFiles({ - search_term: searchTerm, - filter_engine_categories: [FilterEngineCategories.IMAGE_PLANE], + const filteredObjectItems = filterObjectItems(searchTermFeatured); + fetchFeaturedMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.OBJECT], + setState: (newState: FetchMediaItemStates) => { + setFeaturedSearchFetch(() => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? [...filteredObjectItems, ...newState.mediaItems] + : filteredObjectItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching Featured Set Objects Search Results", + searchTerm: searchTermFeatured, }); - - if (response.success && response.data) { - const newSearchObjects = responseMapping(response.data); - setFilteredSearchObjectsFeatured(newSearchObjects); - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.SUCCESS, - })); - } else { - addToast( - ToastTypes.ERROR, - response.errorMessage || "Failed to fetch search results", - ); - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.ERROR, - })); - } }, [searchTermFeatured]); const fetchUserSearchResults = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.IN_PROGRESS, - })); - const searchTerm = searchTermMine; - if (!searchTerm.trim()) { - setFilteredSearchObjectsMine([]); - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.SUCCESS, - })); - return; - } - - const mediaFilesApi = new MediaFilesApi(); - const response = await mediaFilesApi.SearchUserMediaFiles({ - search_term: searchTerm, - filter_engine_categories: [FilterEngineCategories.OBJECT], + fetchUserMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.OBJECT], + setState: (newState: FetchMediaItemStates) => { + setUserSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching User Set Objects Search Results", + searchTerm: searchTermUser, }); - - if (response.success && response.data) { - const newSearchObjects = responseMapping(response.data); - setFilteredSearchObjectsMine(newSearchObjects); - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.SUCCESS, - })); - } else { - addToast( - ToastTypes.ERROR, - response.errorMessage || "Failed to fetch search results", - ); - setFetchStatuses((curr) => ({ - ...curr, - searchFetch: FetchStatus.ERROR, - })); - } - }, [searchTermMine]); - - const fetchUserObjects = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.IN_PROGRESS, - })); - const mediaFilesApi = new MediaFilesApi(); - const response = await mediaFilesApi.ListUserMediaFiles({ - page_size: 100, - filter_engine_categories: [ - FilterEngineCategories.OBJECT, - FilterEngineCategories.IMAGE_PLANE, - ], - }); - - if (response.success && response.data) { - const newObjects = responseMapping(response.data); - setUserObjects(newObjects); - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.SUCCESS, - })); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching User Objects", - ); - setFetchStatuses((curr) => ({ - ...curr, - userObjectsFetch: FetchStatus.ERROR, - })); - }, []); - - const fetchFeaturedObjects = useCallback(async () => { - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.IN_PROGRESS, - })); - const mediaFilesApi = new MediaFilesApi(); - const response = await mediaFilesApi.ListFeaturedMediaFiles({ - filter_engine_categories: [FilterEngineCategories.OBJECT], - }); - if (response.success && response.data) { - const newObjects = responseMapping(response.data); - setFeaturedObjects(newObjects); - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.SUCCESS, - })); - return; - } - addToast( - ToastTypes.ERROR, - response.errorMessage || "Unknown Error in Fetching Featured Objects", - ); - setFetchStatuses((curr) => ({ - ...curr, - featuredObjectsFetch: FetchStatus.ERROR, - })); - }, []); + }, [searchTermUser]); useEffect(() => { if (!userObjects) { @@ -254,13 +173,15 @@ export const ObjectsTab = () => { useEffect(() => { if (selectedFilter === AssetFilterOption.FEATURED) { + setCurrentPage(0); fetchFeaturedSearchResults(); } else if (selectedFilter === AssetFilterOption.MINE) { + setCurrentPage(0); fetchUserSearchResults(); } }, [ searchTermFeatured, - searchTermMine, + searchTermUser, fetchFeaturedSearchResults, fetchUserSearchResults, selectedFilter, @@ -294,14 +215,19 @@ export const ObjectsTab = () => { searchTerm={ selectedFilter === AssetFilterOption.FEATURED ? searchTermFeatured - : searchTermMine + : searchTermUser } onSearchChange={ selectedFilter === AssetFilterOption.FEATURED ? setSearchTermFeatured - : setSearchTermMine + : setSearchTermUser } key={selectedFilter} + placeholder={ + selectedFilter === AssetFilterOption.FEATURED + ? "Search featured objects" + : "Search my objects" + } /> )}
@@ -314,11 +240,11 @@ export const ObjectsTab = () => { items={ selectedFilter === AssetFilterOption.FEATURED ? searchTermFeatured - ? filteredSearchObjectsFeatured - : filteredObjects - : searchTermMine - ? filteredSearchObjectsMine - : filteredObjects + ? featuredSearchResults ?? [] + : displayedItems + : searchTermUser + ? userSearchResults ?? [] + : displayedItems } />
diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/SetsTab.tsx b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/SetsTab.tsx index 8fa8bbbef0..04d757bb22 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/SetsTab.tsx +++ b/app/pages/PageEnigma/comps/SidePanelTabs/tabComps/SetsTab.tsx @@ -3,6 +3,7 @@ import { faCirclePlus } from "@fortawesome/pro-solid-svg-icons"; import { AssetFilterOption, + FeatureFlags, FilterEngineCategories, IMAGE_FILE_TYPE, OBJECT_FILE_TYPE, @@ -13,6 +14,7 @@ import { Button, FilterButtons, Pagination, + SearchFilter, UploadModal3DPreview, } from "~/components"; @@ -26,10 +28,19 @@ import { fetchUserMediaItems, FetchMediaItemStates, isAnyStatusFetching, + fetchFeaturedMediaItemsSearchResults, + fetchUserMediaItemsSearchResults, } from "../utilities"; +import { usePosthogFeatureFlag } from "~/hooks/usePosthogFeatureFlag"; export const SetsTab = () => { + const showSearchObjectComponent = usePosthogFeatureFlag( + FeatureFlags.SHOW_SEARCH_OBJECTS, + ); + const [openUploadModal, setOpenUploadModal] = useState(false); + const [searchTermFeatured, setSearchTermFeatured] = useState(""); + const [searchTermUser, setSearchTermUser] = useState(""); const [ { mediaItems: userSetObjects, status: userFetchStatus }, @@ -39,17 +50,31 @@ export const SetsTab = () => { status: FetchStatus.READY, }); const [ - { mediaItems: featuredSetObjects, status: feateredFetchStatus }, + { mediaItems: featuredSetObjects, status: featuredFetchStatus }, setFeaturedFetch, ] = useState({ mediaItems: undefined, status: FetchStatus.READY, }); + const [ + { mediaItems: featuredSearchResults, status: featuredSearchFetchStatus }, + setFeaturedSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); + const [ + { mediaItems: userSearchResults, status: userSearchFetchStatus }, + setUserSearchFetch, + ] = useState({ + mediaItems: undefined, + status: FetchStatus.READY, + }); const [selectedFilter, setSelectedFilter] = useState( AssetFilterOption.FEATURED, ); - const diasplayedItems = + const displayedItems = selectedFilter === AssetFilterOption.FEATURED ? featuredSetObjects ?? [] : userSetObjects ?? []; @@ -57,20 +82,19 @@ export const SetsTab = () => { const [currentPage, setCurrentPage] = useState(0); const pageSize = 21; - const totalPages = Math.ceil(diasplayedItems.length / pageSize); + const totalPages = Math.ceil(displayedItems.length / pageSize); const isFetching = isAnyStatusFetching([ userFetchStatus, - feateredFetchStatus, + featuredFetchStatus, + featuredSearchFetchStatus, + userSearchFetchStatus, ]); const fetchUserSetObjects = useCallback( () => fetchUserMediaItems({ - filterEngineCategories: [ - FilterEngineCategories.OBJECT, - FilterEngineCategories.IMAGE_PLANE, - ], + filterEngineCategories: [FilterEngineCategories.OBJECT], setState: (newState: FetchMediaItemStates) => { setUserFetch((curr) => ({ status: newState.status, @@ -101,6 +125,40 @@ export const SetsTab = () => { [], ); + const fetchFeaturedSearchResults = useCallback(async () => { + fetchFeaturedMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.OBJECT], + setState: (newState: FetchMediaItemStates) => { + setFeaturedSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching Featured Set Objects Search Results", + searchTerm: searchTermFeatured, + }); + }, [searchTermFeatured]); + + const fetchUserSearchResults = useCallback(async () => { + fetchUserMediaItemsSearchResults({ + filterEngineCategories: [FilterEngineCategories.OBJECT], + setState: (newState: FetchMediaItemStates) => { + setUserSearchFetch((curr) => ({ + status: newState.status, + mediaItems: newState.mediaItems + ? newState.mediaItems + : curr.mediaItems, + })); + }, + defaultErrorMessage: + "Unknown Error in Fetching User Set Objects Search Results", + searchTerm: searchTermUser, + }); + }, [searchTermUser]); + useEffect(() => { if (!userSetObjects) { fetchUserSetObjects(); @@ -115,6 +173,22 @@ export const SetsTab = () => { fetchFeaturedSetObjects, ]); + useEffect(() => { + if (selectedFilter === AssetFilterOption.FEATURED) { + setCurrentPage(0); + fetchFeaturedSearchResults(); + } else if (selectedFilter === AssetFilterOption.MINE) { + setCurrentPage(0); + fetchUserSearchResults(); + } + }, [ + searchTermFeatured, + searchTermUser, + fetchFeaturedSearchResults, + fetchUserSearchResults, + selectedFilter, + ]); + return ( <> @@ -126,7 +200,7 @@ export const SetsTab = () => { }} /> -
+
+ {showSearchObjectComponent && ( + + )}
{totalPages > 1 && ( diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/utilities/fetchMediaItems.ts b/app/pages/PageEnigma/comps/SidePanelTabs/utilities/fetchMediaItems.ts index 0eae87aabd..e9ac03c8a0 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/utilities/fetchMediaItems.ts +++ b/app/pages/PageEnigma/comps/SidePanelTabs/utilities/fetchMediaItems.ts @@ -14,6 +14,7 @@ interface fetchMediaItemsInterface { setState: ({ mediaItems, status }: FetchMediaItemStates) => void; filterEngineCategories: FilterEngineCategories[]; defaultErrorMessage?: string; + searchTerm?: string; } export const fetchUserMediaItems = async ({ @@ -83,3 +84,98 @@ export const fetchFeaturedMediaItems = async ({ setState({ status: FetchStatus.ERROR }); return; }; + +// Search Results +export const fetchFeaturedMediaItemsSearchResults = async ({ + setState, + searchTerm, + filterEngineCategories, + defaultErrorMessage, +}: { + setState: ({ mediaItems, status }: FetchMediaItemStates) => void; + searchTerm: string; + filterEngineCategories: FilterEngineCategories[]; + defaultErrorMessage?: string; +}) => { + setState({ status: FetchStatus.IN_PROGRESS }); + + if (!searchTerm.trim()) { + console.log("Search term is empty after trim"); + setState({ + mediaItems: [], + status: FetchStatus.SUCCESS, + }); + return; + } + + const mediaFilesApi = new MediaFilesApi(); + const response = await mediaFilesApi.SearchFeaturedMediaFiles({ + search_term: searchTerm, + filter_engine_categories: filterEngineCategories, + }); + + if (response.success && response.data) { + const newSearchObjects = responseMapping( + response.data, + filterEngineCategories, + ); + setState({ + mediaItems: newSearchObjects, + status: FetchStatus.SUCCESS, + }); + } else { + addToast( + ToastTypes.ERROR, + response.errorMessage || + defaultErrorMessage || + "Failed to fetch search results", + ); + setState({ status: FetchStatus.ERROR }); + } +}; + +export const fetchUserMediaItemsSearchResults = async ({ + setState, + searchTerm, + filterEngineCategories, + defaultErrorMessage, +}: { + setState: ({ mediaItems, status }: FetchMediaItemStates) => void; + searchTerm: string; + filterEngineCategories: FilterEngineCategories[]; + defaultErrorMessage?: string; +}) => { + setState({ status: FetchStatus.IN_PROGRESS }); + if (!searchTerm.trim()) { + setState({ + mediaItems: [], + status: FetchStatus.SUCCESS, + }); + return; + } + + const mediaFilesApi = new MediaFilesApi(); + const response = await mediaFilesApi.SearchUserMediaFiles({ + search_term: searchTerm, + filter_engine_categories: filterEngineCategories, + }); + + if (response.success && response.data) { + const newSearchObjects = responseMapping( + response.data, + filterEngineCategories, + ); + setState({ + mediaItems: newSearchObjects, + status: FetchStatus.SUCCESS, + }); + } else { + addToast( + ToastTypes.ERROR, + response.errorMessage || + defaultErrorMessage || + "Failed to fetch search results", + ); + setState({ status: FetchStatus.ERROR }); + } +}; diff --git a/app/pages/PageEnigma/comps/SidePanelTabs/utilities/misc.ts b/app/pages/PageEnigma/comps/SidePanelTabs/utilities/misc.ts index 4f8f84992c..4fc8e29434 100644 --- a/app/pages/PageEnigma/comps/SidePanelTabs/utilities/misc.ts +++ b/app/pages/PageEnigma/comps/SidePanelTabs/utilities/misc.ts @@ -4,9 +4,7 @@ import { MediaInfo, MediaItem } from "~/pages/PageEnigma/models"; import { BucketConfig } from "~/api/BucketConfig"; export const isAnyStatusFetching = (statuses: FetchStatus[]): boolean => { - return statuses.some((status) => { - return status === FetchStatus.READY || status === FetchStatus.IN_PROGRESS; - }); + return statuses.some((status) => status === FetchStatus.IN_PROGRESS); }; export const responseMapping = (