From 96af5fb85af017f8fe5b43363311a02d5981b7d4 Mon Sep 17 00:00:00 2001 From: NamH Date: Sat, 30 Mar 2024 08:59:52 +0700 Subject: [PATCH] fix: quick ask improvement (#2543) * docs: Update README.md * fix: quick ask improvement Signed-off-by: James --------- Signed-off-by: James Co-authored-by: hieu-jan <150573299+henryh0x1@users.noreply.github.com> Co-authored-by: James --- README.md | 20 ++++----- web/app/layout.tsx | 5 +-- web/app/page.tsx | 41 +++---------------- web/app/search/SelectedText.tsx | 1 + web/app/search/layout.tsx | 32 +++++++++++++++ web/containers/Layout/TopBar/index.tsx | 2 +- web/containers/Layout/index.tsx | 10 +++-- web/containers/MainViewContainer/index.tsx | 37 +++++++++++++++++ .../Providers/ClipboardListener.tsx | 8 ++-- web/containers/Providers/QuickAskListener.tsx | 22 ++++------ web/containers/Providers/index.tsx | 14 +------ web/package.json | 1 + web/services/extensionService.ts | 3 +- web/styles/base/global.scss | 6 --- 14 files changed, 111 insertions(+), 91 deletions(-) create mode 100644 web/app/search/layout.tsx create mode 100644 web/containers/MainViewContainer/index.tsx diff --git a/README.md b/README.md index cf307cfbc..eda108b35 100644 --- a/README.md +++ b/README.md @@ -44,31 +44,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Stable (Recommended) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage @@ -77,31 +77,31 @@ Jan is an open-source ChatGPT alternative that runs 100% offline on your compute Experimental (Nightly Build) - + jan.exe - + Intel - + M1/M2 - + jan.deb - + jan.AppImage diff --git a/web/app/layout.tsx b/web/app/layout.tsx index 6c6fc65ab..a5b227445 100644 --- a/web/app/layout.tsx +++ b/web/app/layout.tsx @@ -2,8 +2,6 @@ import { PropsWithChildren } from 'react' import { Metadata } from 'next' -import Providers from '@/containers/Providers' - import '@/styles/main.scss' export const metadata: Metadata = { @@ -16,8 +14,7 @@ export default function RootLayout({ children }: PropsWithChildren) { return ( -
- {children} + {children} ) diff --git a/web/app/page.tsx b/web/app/page.tsx index ab619f061..363ca2de4 100644 --- a/web/app/page.tsx +++ b/web/app/page.tsx @@ -1,40 +1,11 @@ -'use client' - -import { useAtomValue } from 'jotai' - import BaseLayout from '@/containers/Layout' -import { MainViewState } from '@/constants/screens' - -import ChatScreen from '@/screens/Chat' -import ExploreModelsScreen from '@/screens/ExploreModels' - -import LocalServerScreen from '@/screens/LocalServer' -import SettingsScreen from '@/screens/Settings' - -import { mainViewStateAtom } from '@/helpers/atoms/App.atom' +import Providers from '@/containers/Providers' export default function Page() { - const mainViewState = useAtomValue(mainViewStateAtom) - - let children = null - switch (mainViewState) { - case MainViewState.Hub: - children = - break - - case MainViewState.Settings: - children = - break - - case MainViewState.LocalServer: - children = - break - - default: - children = - break - } - - return {children} + return ( + + + + ) } diff --git a/web/app/search/SelectedText.tsx b/web/app/search/SelectedText.tsx index 2bb90775e..db2209a21 100644 --- a/web/app/search/SelectedText.tsx +++ b/web/app/search/SelectedText.tsx @@ -10,6 +10,7 @@ const SelectedText = ({ onCleared }: { onCleared?: () => void }) => { const containerRef = useRef(null) useEffect(() => { + if (window.core?.api?.quickAskSizeUpdated !== 'function') return if (text.trim().length === 0) { window.core?.api?.quickAskSizeUpdated(0) } else { diff --git a/web/app/search/layout.tsx b/web/app/search/layout.tsx new file mode 100644 index 000000000..f6125f8d2 --- /dev/null +++ b/web/app/search/layout.tsx @@ -0,0 +1,32 @@ +'use client' + +import { useEffect } from 'react' + +import ClipboardListener from '@/containers/Providers/ClipboardListener' + +import JotaiWrapper from '@/containers/Providers/Jotai' +import ThemeWrapper from '@/containers/Providers/Theme' + +import { setupCoreServices } from '@/services/coreService' + +import Search from './page' + +export default function RootLayout() { + useEffect(() => { + setupCoreServices() + }, []) + + return ( + + + + + + + + + + + + ) +} diff --git a/web/containers/Layout/TopBar/index.tsx b/web/containers/Layout/TopBar/index.tsx index 605d8e44d..7f108f15a 100644 --- a/web/containers/Layout/TopBar/index.tsx +++ b/web/containers/Layout/TopBar/index.tsx @@ -68,7 +68,7 @@ const TopBar = () => { } return ( -
+
{mainViewState !== MainViewState.Thread && mainViewState !== MainViewState.LocalServer ? (
diff --git a/web/containers/Layout/index.tsx b/web/containers/Layout/index.tsx index c87b6cacc..ed4a30477 100644 --- a/web/containers/Layout/index.tsx +++ b/web/containers/Layout/index.tsx @@ -1,4 +1,5 @@ -import React, { PropsWithChildren, useEffect } from 'react' +'use client' +import React, { useEffect } from 'react' import { useTheme } from 'next-themes' @@ -23,12 +24,13 @@ import ImportModelOptionModal from '@/screens/Settings/ImportModelOptionModal' import ImportingModelModal from '@/screens/Settings/ImportingModelModal' import SelectingModelModal from '@/screens/Settings/SelectingModelModal' +import MainViewContainer from '../MainViewContainer' + import InstallingExtensionModal from './BottomBar/InstallingExtension/InstallingExtensionModal' import { mainViewStateAtom } from '@/helpers/atoms/App.atom' -const BaseLayout = (props: PropsWithChildren) => { - const { children } = props +const BaseLayout = () => { const [mainViewState, setMainViewState] = useAtom(mainViewStateAtom) const importModelStage = useAtomValue(getImportModelStageAtom) const { theme, setTheme } = useTheme() @@ -61,7 +63,7 @@ const BaseLayout = (props: PropsWithChildren) => { }, }} > - {children} +
diff --git a/web/containers/MainViewContainer/index.tsx b/web/containers/MainViewContainer/index.tsx new file mode 100644 index 000000000..1de48642a --- /dev/null +++ b/web/containers/MainViewContainer/index.tsx @@ -0,0 +1,37 @@ +import { useAtomValue } from 'jotai' + +import { MainViewState } from '@/constants/screens' + +import ChatScreen from '@/screens/Chat' +import ExploreModelsScreen from '@/screens/ExploreModels' +import LocalServerScreen from '@/screens/LocalServer' +import SettingsScreen from '@/screens/Settings' + +import { mainViewStateAtom } from '@/helpers/atoms/App.atom' + +const MainViewContainer: React.FC = () => { + const mainViewState = useAtomValue(mainViewStateAtom) + + let children = null + switch (mainViewState) { + case MainViewState.Hub: + children = + break + + case MainViewState.Settings: + children = + break + + case MainViewState.LocalServer: + children = + break + + default: + children = + break + } + + return children +} + +export default MainViewContainer diff --git a/web/containers/Providers/ClipboardListener.tsx b/web/containers/Providers/ClipboardListener.tsx index 780515461..2d9910b9b 100644 --- a/web/containers/Providers/ClipboardListener.tsx +++ b/web/containers/Providers/ClipboardListener.tsx @@ -7,9 +7,11 @@ import { selectedTextAtom } from './Jotai' const ClipboardListener = ({ children }: PropsWithChildren) => { const setSelectedText = useSetAtom(selectedTextAtom) - window?.electronAPI?.onSelectedText((_event: string, text: string) => { - setSelectedText(text) - }) + if (typeof window !== 'undefined') { + window?.electronAPI?.onSelectedText((_event: string, text: string) => { + setSelectedText(text) + }) + } return {children} } diff --git a/web/containers/Providers/QuickAskListener.tsx b/web/containers/Providers/QuickAskListener.tsx index 1aacd2e29..415fc19a6 100644 --- a/web/containers/Providers/QuickAskListener.tsx +++ b/web/containers/Providers/QuickAskListener.tsx @@ -1,15 +1,13 @@ -import { Fragment, ReactNode, useRef } from 'react' +import { Fragment, ReactNode } from 'react' import { useSetAtom } from 'jotai' +import { useDebouncedCallback } from 'use-debounce' + import { MainViewState } from '@/constants/screens' import useSendChatMessage from '@/hooks/useSendChatMessage' -import { showRightSideBarAtom } from '@/screens/Chat/Sidebar' - -import { showLeftSideBarAtom } from './KeyListener' - import { mainViewStateAtom } from '@/helpers/atoms/App.atom' type Props = { @@ -18,19 +16,15 @@ type Props = { const QuickAskListener: React.FC = ({ children }) => { const { sendChatMessage } = useSendChatMessage() - const setShowRightSideBar = useSetAtom(showRightSideBarAtom) - const setShowLeftSideBar = useSetAtom(showLeftSideBarAtom) const setMainState = useSetAtom(mainViewStateAtom) - const previousMessage = useRef('') + const debounced = useDebouncedCallback((value) => { + setMainState(MainViewState.Thread) + sendChatMessage(value) + }, 300) window.electronAPI?.onUserSubmitQuickAsk((_event: string, input: string) => { - if (previousMessage.current === input) return - setMainState(MainViewState.Thread) - setShowRightSideBar(false) - setShowLeftSideBar(false) - sendChatMessage(input) - previousMessage.current = input + debounced(input) }) return {children} diff --git a/web/containers/Providers/index.tsx b/web/containers/Providers/index.tsx index 10c6c7547..999979758 100644 --- a/web/containers/Providers/index.tsx +++ b/web/containers/Providers/index.tsx @@ -4,8 +4,6 @@ import { PropsWithChildren, useCallback, useEffect, useState } from 'react' import { Toaster } from 'react-hot-toast' -import { usePathname } from 'next/navigation' - import { TooltipProvider } from '@janhq/uikit' import GPUDriverPrompt from '@/containers/GPUDriverPromptModal' @@ -29,10 +27,7 @@ import KeyListener from './KeyListener' import { extensionManager } from '@/extension' -const Providers = (props: PropsWithChildren) => { - const { children } = props - const pathname = usePathname() - +const Providers = ({ children }: PropsWithChildren) => { const [setupCore, setSetupCore] = useState(false) const [activated, setActivated] = useState(false) const [settingUp, setSettingUp] = useState(false) @@ -43,11 +38,6 @@ const Providers = (props: PropsWithChildren) => { setTimeout(async () => { if (!isCoreExtensionInstalled()) { - // TODO: Proper window handle - // Do not migrate extension from quick ask window - if (pathname === '/search') { - return - } setSettingUp(true) await setupBaseExtensions() return @@ -57,7 +47,7 @@ const Providers = (props: PropsWithChildren) => { setSettingUp(false) setActivated(true) }, 500) - }, [pathname]) + }, []) // Services Setup useEffect(() => { diff --git a/web/package.json b/web/package.json index 94675151e..de42f053c 100644 --- a/web/package.json +++ b/web/package.json @@ -46,6 +46,7 @@ "tailwindcss": "3.3.5", "ulidx": "^2.3.0", "uuid": "^9.0.1", + "use-debounce": "^10.0.0", "zod": "^3.22.4" }, "devDependencies": { diff --git a/web/services/extensionService.ts b/web/services/extensionService.ts index 975b226b9..32fb49c22 100644 --- a/web/services/extensionService.ts +++ b/web/services/extensionService.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -'use client' import { ExtensionTypeEnum } from '@janhq/core' import { extensionManager } from '@/extension/ExtensionManager' @@ -13,6 +11,7 @@ export const isCoreExtensionInstalled = () => { } return true } + export const setupBaseExtensions = async () => { if (typeof window === 'undefined') { return diff --git a/web/styles/base/global.scss b/web/styles/base/global.scss index f1b7c3537..c830d0ecf 100644 --- a/web/styles/base/global.scss +++ b/web/styles/base/global.scss @@ -8,12 +8,6 @@ } .title-bar { - position: absolute; - left: 0px; - top: 0px; - width: 100%; - height: 24px; - user-select: none; -webkit-app-region: drag; }