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:
Faisal Amir 2024-05-30 18:14:16 +07:00 committed by GitHub
parent bd5a0ea8ab
commit 93ce01051c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 83 additions and 32 deletions

View File

@ -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()

View File

@ -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%;

View File

@ -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

View File

@ -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>

View File

@ -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}

View File

@ -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>
) )

View File

@ -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>

View File

@ -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"

View File

@ -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"

View File

@ -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>

View File

@ -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">

View File

@ -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"

View File

@ -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">

View File

@ -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 {