diff --git a/electron/handlers/native.ts b/electron/handlers/native.ts index 79fa994bfa..19a473e730 100644 --- a/electron/handlers/native.ts +++ b/electron/handlers/native.ts @@ -93,12 +93,12 @@ export function handleAppIPCs() { const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, { title: 'Select model files', buttonLabel: 'Select', - properties: ['openFile', 'multiSelections'], + properties: ['openFile', 'openDirectory', 'multiSelections'], }) if (canceled) { return - } else { - return filePaths } + + return filePaths }) } diff --git a/web/containers/ItemCardSidebar/index.tsx b/web/containers/ItemCardSidebar/index.tsx deleted file mode 100644 index 627d7f45dc..0000000000 --- a/web/containers/ItemCardSidebar/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -type Props = { - title: string - description?: string - disabled?: boolean - onChange?: (text?: string) => void -} - -export default function ItemCardSidebar({ - description, - title, - disabled, - onChange, -}: Props) { - return ( -
-
- {title} -
- onChange?.(e.target.value)} - /> -
- ) -} diff --git a/web/hooks/useDropModelBinaries.ts b/web/hooks/useDropModelBinaries.ts index c08e1dc735..d87e96627e 100644 --- a/web/hooks/useDropModelBinaries.ts +++ b/web/hooks/useDropModelBinaries.ts @@ -39,7 +39,7 @@ export default function useDropModelBinaries() { })) if (unsupportedFiles.length > 0) { snackbar({ - description: `File has to be a .gguf file`, + description: `Only files with .gguf extension can be imported.`, type: 'error', }) } diff --git a/web/screens/Settings/EditModelInfoModal/index.tsx b/web/screens/Settings/EditModelInfoModal/index.tsx index bc9d6521d7..7625ae9fd3 100644 --- a/web/screens/Settings/EditModelInfoModal/index.tsx +++ b/web/screens/Settings/EditModelInfoModal/index.tsx @@ -116,6 +116,11 @@ const EditModelInfoModal: React.FC = () => { return null } + const onTagsChange = (e: React.ChangeEvent) => { + const tags = e.target.value.split(',') + setTags(tags) + } + return ( {
- +
-
+

{editingModel.name}

{toGibibytes(editingModel.size)} - - Format:{' '} - - - {editingModel.format.toUpperCase()} - +
+ + Format: + + + {editingModel.format.toUpperCase()} + +
@@ -189,7 +196,7 @@ const EditModelInfoModal: React.FC = () => {
- +
diff --git a/web/screens/Settings/SelectingModelModal/index.tsx b/web/screens/Settings/SelectingModelModal/index.tsx index 35bd9b7720..c5b292ea70 100644 --- a/web/screens/Settings/SelectingModelModal/index.tsx +++ b/web/screens/Settings/SelectingModelModal/index.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react' import { useDropzone } from 'react-dropzone' -import { ImportingModel, baseName, fs } from '@janhq/core' +import { ImportingModel, baseName, fs, joinPath } from '@janhq/core' import { Modal, ModalContent, ModalHeader, ModalTitle } from '@janhq/uikit' import { useAtomValue, useSetAtom } from 'jotai' @@ -34,14 +34,31 @@ const SelectingModelModal: React.FC = () => { const sanitizedFilePaths: FilePathWithSize[] = [] for (const filePath of filePaths) { const fileStats = await fs.fileStat(filePath, true) - if (!fileStats || fileStats.isDirectory) continue - - const fileName = await baseName(filePath) - sanitizedFilePaths.push({ - path: filePath, - name: fileName, - size: fileStats.size, - }) + if (!fileStats) continue + + if (!fileStats.isDirectory) { + const fileName = await baseName(filePath) + sanitizedFilePaths.push({ + path: filePath, + name: fileName, + size: fileStats.size, + }) + } else { + // allowing only one level of directory + const files = await fs.readdirSync(filePath) + + for (const file of files) { + const fullPath = await joinPath([filePath, file]) + const fileStats = await fs.fileStat(fullPath, true) + if (!fileStats || fileStats.isDirectory) continue + + sanitizedFilePaths.push({ + path: fullPath, + name: file, + size: fileStats.size, + }) + } + } } const unsupportedFiles = sanitizedFilePaths.filter( @@ -68,7 +85,7 @@ const SelectingModelModal: React.FC = () => { ) if (unsupportedFiles.length > 0) { snackbar({ - description: `File has to be a .gguf file`, + description: `Only files with .gguf extension can be imported.`, type: 'error', }) }