Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: attachment preview issue #4282

Merged
merged 3 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions web/hooks/usePath.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { openFileExplorer, joinPath, baseName } from '@janhq/core'
import { openFileExplorer, joinPath, baseName, fs } from '@janhq/core'

Check warning on line 1 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / test-on-macos

'fs' is defined but never used

Check warning on line 1 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / test-on-ubuntu

'fs' is defined but never used

Check warning on line 1 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / test-on-windows-pr

'fs' is defined but never used

Check warning on line 1 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

'fs' is defined but never used
import { useAtomValue } from 'jotai'

import { getFileInfo } from '@/utils/file'

import { janDataFolderPathAtom } from '@/helpers/atoms/AppConfig.atom'
import { activeAssistantAtom } from '@/helpers/atoms/Assistant.atom'
import { selectedModelAtom } from '@/helpers/atoms/Model.atom'
Expand All @@ -14,46 +16,56 @@

const onRevealInFinder = async (type: string) => {
// TODO: this logic should be refactored.
if (type !== 'Model' && !activeThread) return

Check warning on line 19 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

19 line is not covered with tests

let filePath = undefined
const assistantId = activeAssistant?.assistant_id
switch (type) {

Check warning on line 23 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

21-23 lines are not covered with tests
case 'Engine':
case 'Thread':
filePath = await joinPath(['threads', activeThread?.id ?? ''])
break

Check warning on line 27 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

26-27 lines are not covered with tests
case 'Model':
if (!selectedModel) return
filePath = await joinPath(['models', selectedModel.id])
break

Check warning on line 31 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

29-31 lines are not covered with tests
case 'Tools':
case 'Assistant':
if (!assistantId) return
filePath = await joinPath(['assistants', assistantId])
break

Check warning on line 36 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

34-36 lines are not covered with tests
case 'Logs':
filePath = 'logs'
break

Check warning on line 39 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

38-39 lines are not covered with tests
default:
break

Check warning on line 41 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

41 line is not covered with tests
}

if (!filePath) return
const fullPath = await joinPath([janDataFolderPath, filePath])
openFileExplorer(fullPath)

Check warning on line 46 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

44-46 lines are not covered with tests
}

const onViewFile = async (id: string) => {
if (!activeThread) return

Check warning on line 50 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

50 line is not covered with tests

let filePath = undefined

id = await baseName(id)

Check warning on line 52 in web/hooks/usePath.ts

View workflow job for this annotation

GitHub Actions / coverage-check

52 line is not covered with tests
filePath = await joinPath(['threads', `${activeThread.id}/files`, `${id}`])
if (!filePath) return
const fullPath = await joinPath([janDataFolderPath, filePath])
openFileExplorer(fullPath)

// New ID System
if (!id.startsWith('file-')) {
const threadFilePath = await joinPath([
janDataFolderPath,
'threads',
`${activeThread.id}/files`,
id,
])
openFileExplorer(threadFilePath)
} else {
id = id.split('.')[0]
const fileName = (await getFileInfo(id)).filename
const filesPath = await joinPath([janDataFolderPath, 'files', fileName])
openFileExplorer(filesPath)
}
}

const onViewFileContainer = async () => {
Expand Down
2 changes: 1 addition & 1 deletion web/screens/Thread/ThreadCenterPanel/ChatInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const ChatInput = () => {
const renderPreview = (fileUpload: any) => {
if (fileUpload) {
if (fileUpload.type === 'image') {
return <ImageUploadPreview file={fileUpload[0].file} />
return <ImageUploadPreview file={fileUpload.file} />
} else {
return <FileUploadPreview />
}
Expand Down
47 changes: 21 additions & 26 deletions web/screens/Thread/ThreadCenterPanel/TextMessage/DocMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,39 @@
import { memo } from 'react'

import { Tooltip } from '@janhq/joi'

import { FolderOpenIcon } from 'lucide-react'
import { memo, useEffect, useState } from 'react'

import { usePath } from '@/hooks/usePath'

import { toGibibytes } from '@/utils/converter'
import { openFileTitle } from '@/utils/titleUtils'
import { getFileInfo } from '@/utils/file'

import Icon from '../FileUploadPreview/Icon'

const DocMessage = ({ id, name }: { id: string; name?: string }) => {
const { onViewFile, onViewFileContainer } = usePath()
const DocMessage = ({ id }: { id: string }) => {
const { onViewFile } = usePath()
const [fileInfo, setFileInfo] = useState<
{ filename: string; id: string } | undefined
>()
useEffect(() => {
if (!fileInfo) {
getFileInfo(id).then((data) => {
setFileInfo(data)
})
}
}, [fileInfo, id])

return (
<div className="group/file bg-secondary relative mb-2 inline-flex w-60 cursor-pointer gap-x-3 overflow-hidden rounded-lg p-4">
<div
className="absolute left-0 top-0 z-20 hidden h-full w-full bg-black/20 backdrop-blur-sm group-hover/file:inline-block"
className="absolute left-0 top-0 z-20 hidden h-full w-full bg-black/20 opacity-50 group-hover/file:inline-block"
onClick={() => onViewFile(`${id}.pdf`)}
/>
<Tooltip
trigger={
<div
className="absolute right-2 top-2 z-20 hidden h-8 w-8 cursor-pointer items-center justify-center rounded-md bg-[hsla(var(--app-bg))] group-hover/file:flex"
onClick={onViewFileContainer}
>
<FolderOpenIcon size={20} />
</div>
}
content={<span>{openFileTitle()}</span>}
/>

<Icon type="pdf" />
<div className="w-full">
<h6 className="line-clamp-1 w-4/5 font-medium">
{name?.replaceAll(/[-._]/g, ' ')}
<h6 className="line-clamp-1 w-4/5 overflow-hidden font-medium">
{fileInfo?.filename}
</h6>
{/* <p className="text-[hsla(var(--text-secondary)]">
{toGibibytes(Number(size))}
</p> */}
<p className="text-[hsla(var(--text-secondary)] line-clamp-1 overflow-hidden truncate">
{fileInfo?.id ?? id}
</p>
</div>
</div>
)
Expand Down
27 changes: 2 additions & 25 deletions web/screens/Thread/ThreadCenterPanel/TextMessage/ImageMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,11 @@
import { memo } from 'react'

import { Tooltip } from '@janhq/joi'

import { FolderOpenIcon } from 'lucide-react'

import { usePath } from '@/hooks/usePath'

import { openFileTitle } from '@/utils/titleUtils'

import { RelativeImage } from '../TextMessage/RelativeImage'

const ImageMessage = ({ image }: { image: string }) => {
const { onViewFile, onViewFileContainer } = usePath()

return (
<div className="group/image relative mb-2 inline-flex cursor-pointer overflow-hidden rounded-xl">
<div className="left-0 top-0 z-20 h-full w-full group-hover/image:inline-block">
<RelativeImage src={image} onClick={() => onViewFile(image)} />
</div>
<Tooltip
trigger={
<div
className="absolute right-2 top-2 z-20 hidden h-8 w-8 cursor-pointer items-center justify-center rounded-md bg-[hsla(var(--app-bg))] group-hover/image:flex"
onClick={onViewFileContainer}
>
<FolderOpenIcon size={20} />
</div>
}
content={<span>{openFileTitle()}</span>}
/>
<div className="group/file relative mb-2 inline-flex overflow-hidden rounded-xl">
<RelativeImage src={image} />
</div>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const RelativeImage = ({
onClick,
}: {
src: string
onClick: () => void
onClick?: () => void
}) => {
const [path, setPath] = useState<string>('')

Expand All @@ -17,9 +17,12 @@ export const RelativeImage = ({
})
}, [])
return (
<button onClick={onClick}>
<button
onClick={onClick}
className={onClick ? 'cursor-pointer' : 'cursor-default'}
>
<img
className="aspect-auto h-[300px] cursor-pointer"
className="aspect-auto h-[300px]"
alt={src}
src={src.includes('files/') ? `file://${path}/${src}` : src}
/>
Expand Down
4 changes: 3 additions & 1 deletion web/screens/Thread/ThreadCenterPanel/TextMessage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ const MessageContainer: React.FC<
>
<>
{image && <ImageMessage image={image} />}
{attachedFile && <DocMessage id={props.id} name={props.id} />}
{attachedFile && (
<DocMessage id={props.attachments?.[0]?.file_id ?? props.id} />
)}

{editMessage === props.id ? (
<div>
Expand Down
9 changes: 9 additions & 0 deletions web/utils/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,12 @@ export const uploader = () => {
})
return uppy
}

/**
* Get the file information from the server.
*/
export const getFileInfo = (id: string) => {
return fetch(`${API_BASE_URL}/v1/files/${id}`)
.then((e) => e.json())
.catch(() => undefined)
}
Loading