fix: wrong direction icon collapse right panel (#2967)
* fix: wrong direction icon collapse right panel * fix: add back social icon * fix: modal troubleshoot * fix: shadow transparent theme * fix: enable nitro_tensorrt_llm * fix: disabled model dropdown when local server running
This commit is contained in:
parent
bd5a0ea8ab
commit
93ce01051c
@ -2,7 +2,7 @@ import { app } from 'electron'
|
|||||||
import Store from 'electron-store'
|
import Store from 'electron-store'
|
||||||
|
|
||||||
const DEFAULT_WIDTH = 1000
|
const DEFAULT_WIDTH = 1000
|
||||||
const DEFAULT_HEIGHT = 700
|
const DEFAULT_HEIGHT = 800
|
||||||
|
|
||||||
const storage = new Store()
|
const storage = new Store()
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@ fieldset,
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: hsla(var(--modal-bg));
|
background-color: hsla(var(--modal-bg));
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 300;
|
z-index: 300;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|||||||
@ -7,13 +7,17 @@ import './styles.scss'
|
|||||||
const ScrollArea = React.forwardRef<
|
const ScrollArea = React.forwardRef<
|
||||||
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
||||||
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
||||||
>(({ className, children, ...props }, ref) => (
|
>(({ className, children, onScroll, ...props }, ref) => (
|
||||||
<ScrollAreaPrimitive.Root
|
<ScrollAreaPrimitive.Root
|
||||||
type="scroll"
|
type="scroll"
|
||||||
className={twMerge('scroll-area__root', className)}
|
className={twMerge('scroll-area__root', className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ScrollAreaPrimitive.Viewport className="scroll-area__viewport" ref={ref}>
|
<ScrollAreaPrimitive.Viewport
|
||||||
|
className="scroll-area__viewport"
|
||||||
|
ref={ref}
|
||||||
|
onScroll={onScroll}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</ScrollAreaPrimitive.Viewport>
|
</ScrollAreaPrimitive.Viewport>
|
||||||
<ScrollAreaPrimitive.Scrollbar
|
<ScrollAreaPrimitive.Scrollbar
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const metadata: Metadata = {
|
|||||||
export default function RootLayout({ children }: PropsWithChildren) {
|
export default function RootLayout({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en" suppressHydrationWarning>
|
||||||
<body className="h-screen font-sans antialiased">
|
<body className="h-screen font-sans text-sm antialiased">
|
||||||
<div className="dragable-bar" />
|
<div className="dragable-bar" />
|
||||||
{children}
|
{children}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ const CenterPanelContainer = ({ children }: PropsWithChildren) => {
|
|||||||
className={twMerge(
|
className={twMerge(
|
||||||
'h-full w-full overflow-hidden bg-[hsla(var(--center-panel-bg))]',
|
'h-full w-full overflow-hidden bg-[hsla(var(--center-panel-bg))]',
|
||||||
!reduceTransparent &&
|
!reduceTransparent &&
|
||||||
'rounded-lg border border-[hsla(var(--app-border))] shadow'
|
'rounded-lg border border-[hsla(var(--app-border))]'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
import { Button, Tooltip } from '@janhq/joi'
|
||||||
import { useAtomValue } from 'jotai'
|
import { useAtomValue } from 'jotai'
|
||||||
|
|
||||||
|
import { FaGithub, FaDiscord } from 'react-icons/fa'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
import DownloadingState from './DownloadingState'
|
import DownloadingState from './DownloadingState'
|
||||||
@ -13,6 +15,19 @@ import UpdatedFailedModal from './UpdateFailedModal'
|
|||||||
import { appDownloadProgressAtom } from '@/helpers/atoms/App.atom'
|
import { appDownloadProgressAtom } from '@/helpers/atoms/App.atom'
|
||||||
import { reduceTransparentAtom } from '@/helpers/atoms/Setting.atom'
|
import { reduceTransparentAtom } from '@/helpers/atoms/Setting.atom'
|
||||||
|
|
||||||
|
const menuLinks = [
|
||||||
|
{
|
||||||
|
name: 'Discord',
|
||||||
|
icon: <FaDiscord size={16} className="flex-shrink-0" />,
|
||||||
|
link: 'https://discord.gg/FTk2MvZwJH',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Github',
|
||||||
|
icon: <FaGithub size={14} className="flex-shrink-0" />,
|
||||||
|
link: 'https://github.com/janhq/jan',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
const BottomPanel = () => {
|
const BottomPanel = () => {
|
||||||
const progress = useAtomValue(appDownloadProgressAtom)
|
const progress = useAtomValue(appDownloadProgressAtom)
|
||||||
const reduceTransparent = useAtomValue(reduceTransparentAtom)
|
const reduceTransparent = useAtomValue(reduceTransparentAtom)
|
||||||
@ -41,6 +56,31 @@ const BottomPanel = () => {
|
|||||||
<span className="font-medium text-[hsla(var(--text-secondary))]">
|
<span className="font-medium text-[hsla(var(--text-secondary))]">
|
||||||
Jan v{VERSION ?? ''}
|
Jan v{VERSION ?? ''}
|
||||||
</span>
|
</span>
|
||||||
|
<div className="ml-2 flex items-center">
|
||||||
|
{menuLinks
|
||||||
|
.filter((link) => !!link)
|
||||||
|
.map((link, i) => (
|
||||||
|
<div className="relative" key={i}>
|
||||||
|
<Tooltip
|
||||||
|
withArrow={false}
|
||||||
|
side="top"
|
||||||
|
trigger={
|
||||||
|
<Button theme="icon">
|
||||||
|
<a
|
||||||
|
href={link.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="relative flex w-full flex-shrink-0 items-center justify-center no-underline"
|
||||||
|
>
|
||||||
|
{link.icon}
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
content={link.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -77,11 +77,11 @@ const TopPanel = () => {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
{showRightPanel ? (
|
{showRightPanel ? (
|
||||||
<Button theme="icon" onClick={() => setShowRightPanel(false)}>
|
<Button theme="icon" onClick={() => setShowRightPanel(false)}>
|
||||||
<PanelRightOpenIcon size={16} />
|
<PanelRightCloseIcon size={16} />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button theme="icon" onClick={() => setShowRightPanel(true)}>
|
<Button theme="icon" onClick={() => setShowRightPanel(true)}>
|
||||||
<PanelRightCloseIcon size={16} />
|
<PanelRightOpenIcon size={16} />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const AppLogs = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-[50vw] p-4 pb-0">
|
<div className="max-w-[50vw] p-4 pb-0">
|
||||||
<div className="absolute -top-11 right-2">
|
<div className="absolute right-2 top-7">
|
||||||
<div className="flex w-full flex-row items-center gap-2">
|
<div className="flex w-full flex-row items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
theme="ghost"
|
theme="ghost"
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const DeviceSpecs = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-[50vw] p-4 pb-0">
|
<div className="max-w-[50vw] p-4 pb-0">
|
||||||
<div className="absolute -top-11 right-2">
|
<div className="absolute right-2 top-7">
|
||||||
<Button
|
<Button
|
||||||
theme="ghost"
|
theme="ghost"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
import { Modal, ScrollArea } from '@janhq/joi'
|
import { Modal } from '@janhq/joi'
|
||||||
import { motion as m } from 'framer-motion'
|
|
||||||
import { atom, useAtom } from 'jotai'
|
import { atom, useAtom } from 'jotai'
|
||||||
import { twMerge } from 'tailwind-merge'
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ const ModalTroubleShooting = () => {
|
|||||||
onOpenChange={setModalTroubleShooting}
|
onOpenChange={setModalTroubleShooting}
|
||||||
title="Troubleshooting Assistance"
|
title="Troubleshooting Assistance"
|
||||||
content={
|
content={
|
||||||
<div className="flex h-full w-full flex-col overflow-hidden ">
|
<div className="flex h-full w-full flex-col overflow-hidden text-sm">
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
<p className="text-[hsla(var(--text-secondary)] mt-2 pr-3 leading-relaxed">
|
<p className="text-[hsla(var(--text-secondary)] mt-2 pr-3 leading-relaxed">
|
||||||
{`We're here to help! Your report is crucial for debugging and shaping
|
{`We're here to help! Your report is crucial for debugging and shaping
|
||||||
@ -78,41 +77,37 @@ const ModalTroubleShooting = () => {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex h-full w-full flex-col pt-4">
|
<div className="relative flex h-full w-full flex-col pt-4">
|
||||||
<div className="relative border-y border-[hsla(var(--app-border))] px-4 py-2 ">
|
<div className="border-y border-[hsla(var(--app-border))] px-4 py-2 ">
|
||||||
<ul className="inline-flex space-x-2 rounded-lg px-1">
|
<ul className="inline-flex space-x-2 rounded-lg px-1">
|
||||||
{logOption.map((name, i) => {
|
{logOption.map((name, i) => {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className="relative cursor-pointer px-4 py-2"
|
className={twMerge(
|
||||||
|
'relative cursor-pointer px-4 py-2',
|
||||||
|
isTabActive === i &&
|
||||||
|
'rounded-md bg-[hsla(var(--primary-bg))] font-bold text-[hsla(var(--primary-fg))]'
|
||||||
|
)}
|
||||||
key={i}
|
key={i}
|
||||||
onClick={() => setIsTabActivbe(i)}
|
onClick={() => setIsTabActivbe(i)}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'text-[hsla(var(--text-secondary)] relative z-50 font-medium',
|
'text-[hsla(var(--text-secondary)] relative z-50 font-medium'
|
||||||
isTabActive === i &&
|
|
||||||
'bg= font-bold text-[hsla(var(--primary-fg))]'
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
{isTabActive === i && (
|
|
||||||
<m.div
|
|
||||||
className="absolute left-0 top-1 h-[calc(100%-8px)] w-full rounded-md bg-[hsla(var(--primary-bg))]"
|
|
||||||
layoutId="log-state-active"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<ScrollArea className="w-full">
|
<div className="max-h-[160px] overflow-y-auto">
|
||||||
{isTabActive === 0 && <AppLogs />}
|
{isTabActive === 0 && <AppLogs />}
|
||||||
{isTabActive === 1 && <ServerLogs limit={50} withCopy />}
|
{isTabActive === 1 && <ServerLogs limit={50} withCopy />}
|
||||||
{isTabActive === 2 && <DeviceSpecs />}
|
{isTabActive === 2 && <DeviceSpecs />}
|
||||||
</ScrollArea>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import {
|
|||||||
type Props = {
|
type Props = {
|
||||||
chatInputMode?: boolean
|
chatInputMode?: boolean
|
||||||
strictedThread?: boolean
|
strictedThread?: boolean
|
||||||
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const engineHasLogo = [
|
const engineHasLogo = [
|
||||||
@ -45,7 +46,11 @@ const engineHasLogo = [
|
|||||||
InferenceEngine.openai,
|
InferenceEngine.openai,
|
||||||
]
|
]
|
||||||
|
|
||||||
const ModelDropdown = ({ chatInputMode, strictedThread = true }: Props) => {
|
const ModelDropdown = ({
|
||||||
|
disabled,
|
||||||
|
chatInputMode,
|
||||||
|
strictedThread = true,
|
||||||
|
}: Props) => {
|
||||||
const { downloadModel } = useDownloadModel()
|
const { downloadModel } = useDownloadModel()
|
||||||
const [searchFilter, setSearchFilter] = useState('all')
|
const [searchFilter, setSearchFilter] = useState('all')
|
||||||
const [filterOptionsOpen, setFilterOptionsOpen] = useState(false)
|
const [filterOptionsOpen, setFilterOptionsOpen] = useState(false)
|
||||||
@ -210,7 +215,7 @@ const ModelDropdown = ({ chatInputMode, strictedThread = true }: Props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className={twMerge('relative', disabled && 'pointer-events-none')}>
|
||||||
<div ref={setToggle}>
|
<div ref={setToggle}>
|
||||||
{chatInputMode ? (
|
{chatInputMode ? (
|
||||||
<Badge
|
<Badge
|
||||||
@ -224,6 +229,7 @@ const ModelDropdown = ({ chatInputMode, strictedThread = true }: Props) => {
|
|||||||
<Input
|
<Input
|
||||||
value={selectedModel?.name || ''}
|
value={selectedModel?.name || ''}
|
||||||
className="cursor-pointer"
|
className="cursor-pointer"
|
||||||
|
disabled={disabled}
|
||||||
readOnly
|
readOnly
|
||||||
suffixIcon={
|
suffixIcon={
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon
|
||||||
@ -387,10 +393,15 @@ const ModelDropdown = ({ chatInputMode, strictedThread = true }: Props) => {
|
|||||||
className={twMerge(
|
className={twMerge(
|
||||||
'cursor-pointer px-3 py-2 hover:bg-[hsla(var(--dropdown-menu-hover-bg))]',
|
'cursor-pointer px-3 py-2 hover:bg-[hsla(var(--dropdown-menu-hover-bg))]',
|
||||||
!apiKey &&
|
!apiKey &&
|
||||||
|
model.engine !==
|
||||||
|
InferenceEngine.nitro_tensorrt_llm &&
|
||||||
'cursor-default text-[hsla(var(--text-tertiary))]'
|
'cursor-default text-[hsla(var(--text-tertiary))]'
|
||||||
)}
|
)}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
apiKey && onClickModelItem(model.id)
|
apiKey ||
|
||||||
|
(model.engine ===
|
||||||
|
InferenceEngine.nitro_tensorrt_llm &&
|
||||||
|
onClickModelItem(model.id))
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="flex flex-shrink-0 gap-x-2">
|
<div className="flex flex-shrink-0 gap-x-2">
|
||||||
|
|||||||
@ -67,7 +67,7 @@ const ServerLogs = (props: ServerLogsProps) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{withCopy && (
|
{withCopy && (
|
||||||
<div className="absolute -top-11 right-2">
|
<div className="absolute right-2 top-7">
|
||||||
<div className="flex w-full flex-row gap-2">
|
<div className="flex w-full flex-row gap-2">
|
||||||
<Button
|
<Button
|
||||||
theme="ghost"
|
theme="ghost"
|
||||||
|
|||||||
@ -85,7 +85,7 @@ const LocalServerRightPanel = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ModelDropdown strictedThread={false} />
|
<ModelDropdown strictedThread={false} disabled={serverEnabled} />
|
||||||
|
|
||||||
{loadModelError && serverEnabled && (
|
{loadModelError && serverEnabled && (
|
||||||
<div className="mt-3 flex space-x-2">
|
<div className="mt-3 flex space-x-2">
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useCallback } from 'react'
|
|||||||
import { useTheme } from 'next-themes'
|
import { useTheme } from 'next-themes'
|
||||||
|
|
||||||
import { fs, joinPath } from '@janhq/core'
|
import { fs, joinPath } from '@janhq/core'
|
||||||
import { Button, Select, Switch } from '@janhq/joi'
|
import { Button, Select } from '@janhq/joi'
|
||||||
import { useAtom, useAtomValue } from 'jotai'
|
import { useAtom, useAtomValue } from 'jotai'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user