diff --git a/backend/controllers/file-controller.ts b/backend/controllers/file-controller.ts index 830e175..e79b65c 100644 --- a/backend/controllers/file-controller.ts +++ b/backend/controllers/file-controller.ts @@ -413,6 +413,7 @@ class FileController { const startAtName = (query.startAtName as string) || undefined; const trashMode = query.trashMode === "true"; const mediaMode = query.mediaMode === "true"; + const mediaFilter = (query.mediaFilter as string) || "all"; const queryData: FileListQueryType = { userID, @@ -423,6 +424,7 @@ class FileController { trashMode, mediaMode, sortBy, + mediaFilter, }; const fileList = await fileService.getList(queryData, sortBy, limit); diff --git a/backend/middleware/files/files-middleware.ts b/backend/middleware/files/files-middleware.ts index 52ffe8c..0f93207 100644 --- a/backend/middleware/files/files-middleware.ts +++ b/backend/middleware/files/files-middleware.ts @@ -40,6 +40,10 @@ export const getListValidationRules = [ .optional() .isBoolean() .withMessage("Trash Mode must be a boolean"), + query("mediaFilter") + .optional() + .isString() + .withMessage("Media Filter must be a string"), query("mediaMode") .optional() .isBoolean() diff --git a/backend/services/chunk-service/utils/storageHelper.ts b/backend/services/chunk-service/utils/storageHelper.ts index f2cf1c6..127d9a8 100644 --- a/backend/services/chunk-service/utils/storageHelper.ts +++ b/backend/services/chunk-service/utils/storageHelper.ts @@ -9,11 +9,17 @@ type GenericParmasType = { export const createGenericParams = ({ filePath, Key }: GenericParmasType) => { // TODO: Remove file split after migration if (env.dbType === "fs") { - const filePathSplit = filePath!.split("/"); - const fileName = filePathSplit[filePathSplit.length - 1]; - return { - filePath: env.fsDirectory + fileName, - }; + if (filePath?.includes("/")) { + const filePathSplit = filePath!.split("/"); + const fileName = filePathSplit[filePathSplit.length - 1]; + return { + filePath: env.fsDirectory + fileName, + }; + } else { + return { + filePath: env.fsDirectory + Key!, + }; + } } else { return { Key, diff --git a/backend/types/file-types.ts b/backend/types/file-types.ts index 5c4b6ca..94b1e91 100644 --- a/backend/types/file-types.ts +++ b/backend/types/file-types.ts @@ -7,4 +7,5 @@ export interface FileListQueryType { trashMode: boolean; mediaMode: boolean; sortBy: string; + mediaFilter: string; } diff --git a/backend/utils/createQuery.ts b/backend/utils/createQuery.ts index edbec1b..3715998 100644 --- a/backend/utils/createQuery.ts +++ b/backend/utils/createQuery.ts @@ -19,6 +19,7 @@ export interface FileQueryInterface { "metadata.personalFile"?: boolean | null; "metadata.trashed"?: boolean | null; "metadata.hasThumbnail"?: boolean | null; + "metadata.isVideo"?: boolean | null; } export const createFileQuery = ({ @@ -30,6 +31,7 @@ export const createFileQuery = ({ trashMode, mediaMode, sortBy, + mediaFilter, }: FileListQueryType) => { const query: FileQueryInterface = { "metadata.owner": userID }; @@ -57,6 +59,12 @@ export const createFileQuery = ({ if (mediaMode) { query["metadata.hasThumbnail"] = true; + + if (mediaFilter === "photos") { + query["metadata.isVideo"] = false; + } else if (mediaFilter === "videos") { + query["metadata.isVideo"] = true; + } } return query; diff --git a/serverUtils/createVideoThumbnails.js b/serverUtils/createVideoThumbnails.js index 7b0b993..1548157 100644 --- a/serverUtils/createVideoThumbnails.js +++ b/serverUtils/createVideoThumbnails.js @@ -39,7 +39,6 @@ const updateDocs = async () => { /\.(mp4|mov|avi|mkv|webm|wmv|flv|mpg|mpeg|3gp|3g2|mxf|ogv|ogg|m4v)$/i, }, "metadata.thumbnailID": "", - "metadata.owner": "670c8c321ebf0d4211617eb9", }); console.log("Found", files.length, "files"); diff --git a/src/api/filesAPI.ts b/src/api/filesAPI.ts index 47e63d5..d71cc1b 100644 --- a/src/api/filesAPI.ts +++ b/src/api/filesAPI.ts @@ -12,6 +12,7 @@ interface QueryKeyParams { startAt?: boolean; trashMode?: boolean; mediaMode?: boolean; + mediaFilter?: string; } // GET @@ -29,6 +30,7 @@ export const getFilesListAPI = async ({ limit = 50, trashMode, mediaMode, + mediaFilter, }, ] = queryKey; @@ -39,6 +41,7 @@ export const getFilesListAPI = async ({ limit, trashMode, mediaMode, + mediaFilter, }; if (pageParam?.startAtDate && pageParam?.startAtName) { diff --git a/src/components/ContextMenu/ContextMenu.tsx b/src/components/ContextMenu/ContextMenu.tsx index 11defdb..35c3801 100644 --- a/src/components/ContextMenu/ContextMenu.tsx +++ b/src/components/ContextMenu/ContextMenu.tsx @@ -78,6 +78,7 @@ const ContextMenu: React.FC = memo((props) => { useEffect(() => { if (!wrapperRef.current) return; + const modalWidth = wrapperRef.current.clientWidth; const modalHeight = wrapperRef.current.clientHeight; @@ -87,7 +88,7 @@ const ContextMenu: React.FC = memo((props) => { let Y = contextSelected.Y; if (X + modalWidth > windowWidth) { - X = windowWidth - windowWidth; + X = windowWidth - modalWidth - 10; } if (Y + modalHeight > windowHeight) { diff --git a/src/components/Files/Files.tsx b/src/components/Files/Files.tsx index 03771c5..08c7c9a 100644 --- a/src/components/Files/Files.tsx +++ b/src/components/Files/Files.tsx @@ -1,6 +1,6 @@ import { useFiles } from "../../hooks/files"; import { useUtils } from "../../hooks/utils"; -import React, { memo } from "react"; +import React, { memo, useMemo } from "react"; import FileItem from "../FileItem/FileItem"; import ParentBar from "../ParentBar/ParentBar"; import classNames from "classnames"; @@ -17,8 +17,18 @@ const Files = memo(() => { const changeListViewMode = () => { dispatch(toggleListView()); }; + + const title = useMemo(() => { + const hasFiles = !!files?.pages.find((file) => file); + if (hasFiles) { + return "Files"; + } else { + return "No Files"; + } + }, [files?.pages]); + return ( -
+
{isHome &&

Home Files

} diff --git a/src/components/Folders/Folders.tsx b/src/components/Folders/Folders.tsx index 522284f..e5eb580 100644 --- a/src/components/Folders/Folders.tsx +++ b/src/components/Folders/Folders.tsx @@ -1,6 +1,6 @@ import { useFolders } from "../../hooks/folders"; import FolderItem from "../FolderItem/FolderItem"; -import { memo, useCallback } from "react"; +import { memo, useCallback, useMemo } from "react"; import classNames from "classnames"; import { useUtils } from "../../hooks/utils"; import { useAppDispatch, useAppSelector } from "../../hooks/store"; @@ -8,7 +8,7 @@ import { setSortBy } from "../../reducers/filter"; const Folders = memo(() => { const { data: folders } = useFolders(false); - const { isHome } = useUtils(); + const { isHome, isTrash, isSearch } = useUtils(); const sortBy = useAppSelector((state) => state.filter.sortBy); const dispatch = useAppDispatch(); @@ -65,16 +65,26 @@ const Folders = memo(() => { [sortBy] ); + const title = useMemo(() => { + if (isTrash) { + return "Trash"; + } else if (isSearch) { + return "Search"; + } else { + return folders?.length === 0 ? "No Folders" : "Folders"; + } + }, [isHome, isTrash, isSearch, folders?.length]); + return ( -
+

- {folders?.length === 0 ? "No Folders" : "Folders"} + {title}

diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index d2c8437..cd1df62 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -31,7 +31,7 @@ const Header = () => { ); return ( -