feat: update icon alert warning and copies tooltip model dropdown (#3021)
* feat: update icon alert warning and copies tooltip model dropdown * chore: update loader when user click download model dropdown
This commit is contained in:
parent
aecc645a1a
commit
cf8f401dab
50
web/containers/Loader/ProgressCircle.tsx
Normal file
50
web/containers/Loader/ProgressCircle.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import React from 'react'
|
||||
|
||||
interface ProgressCircleProps {
|
||||
percentage: number
|
||||
size?: number
|
||||
strokeWidth?: number
|
||||
}
|
||||
|
||||
const ProgressCircle: React.FC<ProgressCircleProps> = ({
|
||||
percentage,
|
||||
size = 100,
|
||||
strokeWidth = 14,
|
||||
}) => {
|
||||
const radius = (size - strokeWidth) / 2
|
||||
const circumference = 2 * Math.PI * radius
|
||||
const offset = circumference - (percentage / 100) * circumference
|
||||
|
||||
return (
|
||||
<svg
|
||||
className="ml-0.5 h-4 w-4 rotate-[-90deg] transform text-[hsla(var(--primary-bg))]"
|
||||
height={size}
|
||||
width={size}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox={`0 0 ${size} ${size}`}
|
||||
>
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx={size / 2}
|
||||
cy={size / 2}
|
||||
r={radius}
|
||||
stroke="currentColor"
|
||||
strokeWidth={strokeWidth}
|
||||
fill="none"
|
||||
></circle>
|
||||
<circle
|
||||
className="transition-stroke-dashoffset duration-300"
|
||||
cx={size / 2}
|
||||
cy={size / 2}
|
||||
r={radius}
|
||||
stroke="currentColor"
|
||||
strokeWidth={strokeWidth}
|
||||
fill="none"
|
||||
strokeDasharray={circumference}
|
||||
strokeDashoffset={offset}
|
||||
></circle>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProgressCircle
|
||||
@ -8,16 +8,19 @@ import { useAtom, useAtomValue, useSetAtom } from 'jotai'
|
||||
import { ChevronDownIcon, DownloadCloudIcon, XIcon } from 'lucide-react'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
import ProgressCircle from '@/containers/Loader/ProgressCircle'
|
||||
|
||||
import ModelLabel from '@/containers/ModelLabel'
|
||||
|
||||
import SetupRemoteModel from '@/containers/SetupRemoteModel'
|
||||
|
||||
import useDownloadModel from '@/hooks/useDownloadModel'
|
||||
import { modelDownloadStateAtom } from '@/hooks/useDownloadState'
|
||||
import useRecommendedModel from '@/hooks/useRecommendedModel'
|
||||
|
||||
import useUpdateModelParameters from '@/hooks/useUpdateModelParameters'
|
||||
|
||||
import { toGibibytes } from '@/utils/converter'
|
||||
import { formatDownloadPercentage, toGibibytes } from '@/utils/converter'
|
||||
|
||||
import { extensionManager } from '@/extension'
|
||||
|
||||
@ -64,6 +67,7 @@ const ModelDropdown = ({
|
||||
const [dropdownOptions, setDropdownOptions] = useState<HTMLDivElement | null>(
|
||||
null
|
||||
)
|
||||
const downloadStates = useAtomValue(modelDownloadStateAtom)
|
||||
const setThreadModelParams = useSetAtom(setThreadModelParamsAtom)
|
||||
const { updateModelParameter } = useUpdateModelParameters()
|
||||
|
||||
@ -351,12 +355,29 @@ const ModelDropdown = ({
|
||||
<span className="font-medium">
|
||||
{toGibibytes(model.metadata.size)}
|
||||
</span>
|
||||
{!isDownloading && (
|
||||
{!isDownloading ? (
|
||||
<DownloadCloudIcon
|
||||
size={18}
|
||||
className="cursor-pointer text-[hsla(var(--app-link))]"
|
||||
onClick={() => downloadModel(model)}
|
||||
/>
|
||||
) : (
|
||||
Object.values(downloadStates)
|
||||
.filter((x) => x.modelId === model.id)
|
||||
.map((item) => (
|
||||
<ProgressCircle
|
||||
key={item.modelId}
|
||||
percentage={
|
||||
formatDownloadPercentage(
|
||||
item?.percent,
|
||||
{
|
||||
hidePercentage: true,
|
||||
}
|
||||
) as number
|
||||
}
|
||||
size={100}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
@ -397,12 +418,29 @@ const ModelDropdown = ({
|
||||
<span className="font-medium">
|
||||
{toGibibytes(model.metadata.size)}
|
||||
</span>
|
||||
{!isDownloading && (
|
||||
{!isDownloading ? (
|
||||
<DownloadCloudIcon
|
||||
size={18}
|
||||
className="cursor-pointer text-[hsla(var(--app-link))]"
|
||||
onClick={() => downloadModel(model)}
|
||||
/>
|
||||
) : (
|
||||
Object.values(downloadStates)
|
||||
.filter((x) => x.modelId === model.id)
|
||||
.map((item) => (
|
||||
<ProgressCircle
|
||||
key={item.modelId}
|
||||
percentage={
|
||||
formatDownloadPercentage(
|
||||
item?.percent,
|
||||
{
|
||||
hidePercentage: true,
|
||||
}
|
||||
) as number
|
||||
}
|
||||
size={100}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@ -1,32 +1,49 @@
|
||||
import { memo } from 'react'
|
||||
import { Fragment, memo } from 'react'
|
||||
|
||||
import { Badge, Tooltip } from '@janhq/joi'
|
||||
import { InfoIcon } from 'lucide-react'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { AlertTriangleIcon, InfoIcon } from 'lucide-react'
|
||||
|
||||
type Props = {
|
||||
compact?: boolean
|
||||
unit: string
|
||||
}
|
||||
|
||||
const tooltipContent = `Your device doesn't have enough RAM to run this model. Consider upgrading your RAM or using a device with more memory capacity.`
|
||||
|
||||
const NotEnoughMemoryLabel = ({ unit, compact }: Props) => (
|
||||
<Badge
|
||||
theme="destructive"
|
||||
variant="soft"
|
||||
className={twMerge(compact && 'h-5 w-5 p-1')}
|
||||
>
|
||||
{!compact && <span className="line-clamp-1">Not enough {unit}</span>}
|
||||
<>
|
||||
{compact ? (
|
||||
<div className="flex h-5 w-5 items-center">
|
||||
<Tooltip
|
||||
trigger={
|
||||
compact ? (
|
||||
<div className="h-2 w-2 cursor-pointer rounded-full bg-[hsla(var(--destructive-bg))]" />
|
||||
) : (
|
||||
<InfoIcon size={14} className="ml-2 flex-shrink-0 cursor-pointer" />
|
||||
)
|
||||
<AlertTriangleIcon
|
||||
size={14}
|
||||
className="cursor-pointer text-[hsla(var(--destructive-bg))]"
|
||||
/>
|
||||
}
|
||||
content={
|
||||
<Fragment>
|
||||
<b>Not enough RAM:</b> <span>{tooltipContent}</span>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Badge theme="destructive" variant="soft">
|
||||
<span className="line-clamp-1">Not enough {unit}</span>
|
||||
<Tooltip
|
||||
trigger={
|
||||
<InfoIcon size={14} className="ml-2 flex-shrink-0 cursor-pointer" />
|
||||
}
|
||||
content={
|
||||
<Fragment>
|
||||
<b>Not enough RAM:</b> <span>{tooltipContent}</span>
|
||||
</Fragment>
|
||||
}
|
||||
content="This tag signals insufficient RAM for optimal model performance. It's dynamic and may change with your system's RAM availability."
|
||||
/>
|
||||
</Badge>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
export default memo(NotEnoughMemoryLabel)
|
||||
|
||||
@ -1,32 +1,49 @@
|
||||
import { memo } from 'react'
|
||||
import { Fragment, memo } from 'react'
|
||||
|
||||
import { Badge, Tooltip } from '@janhq/joi'
|
||||
|
||||
import { InfoIcon } from 'lucide-react'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
import { AlertTriangleIcon, InfoIcon } from 'lucide-react'
|
||||
|
||||
type Props = {
|
||||
compact?: boolean
|
||||
}
|
||||
|
||||
const tooltipContent = `Your device may be running low on available RAM, which can affect the speed of this model. Try closing any unnecessary applications to free up system memory.`
|
||||
|
||||
const SlowOnYourDeviceLabel = ({ compact }: Props) => (
|
||||
<Badge
|
||||
theme="warning"
|
||||
variant="soft"
|
||||
className={twMerge(compact && 'h-5 w-5 p-1')}
|
||||
>
|
||||
{!compact && <span className="line-clamp-1">Slow on your device</span>}
|
||||
<>
|
||||
{compact ? (
|
||||
<div className="flex h-5 w-5 items-center">
|
||||
<Tooltip
|
||||
trigger={
|
||||
compact ? (
|
||||
<div className="h-2 w-2 cursor-pointer rounded-full bg-[hsla(var(--warning-bg))] p-0" />
|
||||
) : (
|
||||
<InfoIcon size={14} className="ml-2 flex-shrink-0 cursor-pointer" />
|
||||
)
|
||||
<AlertTriangleIcon
|
||||
size={14}
|
||||
className="cursor-pointer text-[hsla(var(--warning-bg))]"
|
||||
/>
|
||||
}
|
||||
content={
|
||||
<Fragment>
|
||||
<b>Slow on your device:</b> <span>{tooltipContent}</span>
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Badge theme="warning" variant="soft">
|
||||
<span className="line-clamp-1">Slow on your device</span>
|
||||
<Tooltip
|
||||
trigger={
|
||||
<InfoIcon size={14} className="ml-2 flex-shrink-0 cursor-pointer" />
|
||||
}
|
||||
content={
|
||||
<Fragment>
|
||||
<b>Slow on your device:</b> <span>{tooltipContent}</span>
|
||||
</Fragment>
|
||||
}
|
||||
content="This tag indicates that your current RAM performance may affect model speed. It can change based on other active apps. To improve, consider closing unnecessary applications to free up RAM."
|
||||
/>
|
||||
</Badge>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
export default memo(SlowOnYourDeviceLabel)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user