diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/ChatInterface.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/ChatInterface.tsx
index 147cf80e0..e5b3a6eb0 100644
--- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/ChatInterface.tsx
+++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/ChatInterface.tsx
@@ -45,6 +45,7 @@ import { generateAndUpdateChatTitle } from "../../utils/titleGeneration"
import { GlobalFileDropZone } from "../file/GlobalFileDropZone"
import { AIErrorFallback } from "./AIErrorFallback"
import { ChatInput } from "./ChatInput"
+import { ChatShortcutsRow } from "./ChatShortcutsRow"
import { CollapsibleError } from "./CollapsibleError"
import { WelcomeScreen } from "./WelcomeScreen"
@@ -311,7 +312,7 @@ const ChatInterfaceContent = ({ centerInputOnEmpty }: ChatInterfaceProps) => {
{!hasMessages && !isLoadingHistory ? (
-
+
) : (
<>
{
)}
>
{error && }
+ handleSendMessage(prompt)} />
void
+}
+
+export const ChatShortcutsRow: React.FC = ({ onSelect }) => {
+ const { t } = useTranslation("ai")
+ const aiSettings = useAISettingValue()
+ const mainEntryId = useMainEntryId()
+ const showSettings = useSettingModal()
+
+ const shortcutsToDisplay = useMemo(() => {
+ const shortcuts = aiSettings.shortcuts ?? []
+ const list: typeof shortcuts = []
+ const entry: typeof shortcuts = []
+
+ for (const shortcut of shortcuts) {
+ if (!shortcut.enabled) continue
+ const targets =
+ shortcut.displayTargets && shortcut.displayTargets.length > 0
+ ? shortcut.displayTargets
+ : DEFAULT_SHORTCUT_TARGETS
+ if (targets.includes("list")) {
+ list.push(shortcut)
+ }
+ if (targets.includes("entry")) {
+ entry.push(shortcut)
+ }
+ }
+
+ return (mainEntryId ? entry : list) ?? []
+ }, [aiSettings.shortcuts, mainEntryId])
+
+ const handleCustomize = useCallback(() => {
+ showSettings("ai")
+ }, [showSettings])
+
+ return (
+
+
+
+
+
+ {shortcutsToDisplay.map((shortcut) => (
+
onSelect(shortcut.prompt)}
+ animationDelay={0}
+ size="sm"
+ title={shortcut.hotkey ? `${shortcut.name} (${shortcut.hotkey})` : shortcut.name}
+ >
+ {shortcut.name}
+
+ ))}
+
+
+ )
+}
diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/WelcomeScreen.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/WelcomeScreen.tsx
index 7bb9001f9..7002effb6 100644
--- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/WelcomeScreen.tsx
+++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/layouts/WelcomeScreen.tsx
@@ -1,14 +1,11 @@
import { Folo } from "@follow/components/icons/folo.js"
import { ScrollArea } from "@follow/components/ui/scroll-area/ScrollArea.js"
import { useElementWidth } from "@follow/hooks"
-import { DEFAULT_SHORTCUT_TARGETS } from "@follow/shared/settings/interface"
import { clsx } from "@follow/utils"
-import type { EditorState } from "lexical"
import { AnimatePresence, m } from "motion/react"
-import { useEffect, useMemo, useRef } from "react"
+import { useEffect, useRef } from "react"
import { useTranslation } from "react-i18next"
-import { useAISettingValue } from "~/atoms/settings/ai"
import { AISpline } from "~/modules/ai-chat/components/3d-models/AISpline"
import { useAttachScrollBeyond } from "../../hooks/useAttachScrollBeyond"
@@ -20,38 +17,16 @@ import { DefaultWelcomeContent, EntryWelcomeContent } from "../welcome"
import { AIChatRoot } from "./AIChatRoot"
interface WelcomeScreenProps {
- onSend: (message: EditorState | string) => void
centerInputOnEmpty?: boolean
}
-export const WelcomeScreen = ({ onSend, centerInputOnEmpty }: WelcomeScreenProps) => {
+export const WelcomeScreen = ({ centerInputOnEmpty }: WelcomeScreenProps) => {
const { t } = useTranslation("ai")
- const aiSettings = useAISettingValue()
const mainEntryId = useMainEntryId()
const { todayTimelineSummaryId, canReuseTimelineSummary, hasEntryContext } =
useTimelineSummarySession()
- const enabledShortcuts = aiSettings.shortcuts || []
const shouldFetchTimelineSummary = canReuseTimelineSummary
- const { list: listShortcuts, entry: entryShortcuts } = useMemo(() => {
- const list: typeof enabledShortcuts = []
- const entry: typeof enabledShortcuts = []
- for (const shortcut of enabledShortcuts) {
- if (!shortcut.enabled) continue
- const targets =
- shortcut.displayTargets && shortcut.displayTargets.length > 0
- ? shortcut.displayTargets
- : DEFAULT_SHORTCUT_TARGETS
- if (targets.includes("list")) {
- list.push(shortcut)
- }
- if (targets.includes("entry")) {
- entry.push(shortcut)
- }
- }
- return { list, entry }
- }, [enabledShortcuts])
-
const { handleScroll } = useAttachScrollBeyond()
const showTimelineSummary = shouldFetchTimelineSummary
@@ -87,18 +62,9 @@ export const WelcomeScreen = ({ onSend, centerInputOnEmpty }: WelcomeScreenProps
>
{hasEntryContext && mainEntryId ? (
-
+
) : (
-
+
)}
diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/DefaultWelcomeContent.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/DefaultWelcomeContent.tsx
index 3232131e6..890bfaa7b 100644
--- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/DefaultWelcomeContent.tsx
+++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/DefaultWelcomeContent.tsx
@@ -1,38 +1 @@
-import type { AIShortcut } from "@follow/shared/settings/interface"
-import type { EditorState } from "lexical"
-import { m } from "motion/react"
-import { useTranslation } from "react-i18next"
-
-import { useSettingModal } from "~/modules/settings/modal/use-setting-modal-hack"
-
-import { ShortcutButtonGrid } from "./ShortcutButtonGrid"
-
-interface DefaultWelcomeContentProps {
- onSend: (message: EditorState | string) => void
- shortcuts: AIShortcut[]
-}
-
-export const DefaultWelcomeContent: React.FC = ({
- onSend,
- shortcuts,
-}) => {
- const { t } = useTranslation("ai")
- const showSettings = useSettingModal()
-
- return (
-
- showSettings("ai")}
- customizeLabel={t("customize_shortcuts")}
- customizeTitle={t("customize_shortcuts_title")}
- />
-
- )
-}
+export const DefaultWelcomeContent: React.FC = () => null
diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/EntryWelcomeContent.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/EntryWelcomeContent.tsx
index c4fa6ab4b..a83a0be3c 100644
--- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/EntryWelcomeContent.tsx
+++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/EntryWelcomeContent.tsx
@@ -1,44 +1,20 @@
-import type { AIShortcut } from "@follow/shared/settings/interface"
-import type { EditorState } from "lexical"
import { m } from "motion/react"
-import { useTranslation } from "react-i18next"
-
-import { useSettingModal } from "~/modules/settings/modal/use-setting-modal-hack"
import { EntrySummaryCard } from "./EntrySummaryCard"
-import { ShortcutButtonGrid } from "./ShortcutButtonGrid"
interface EntryWelcomeContentProps {
entryId: string
- onSend: (message: EditorState | string) => void
- shortcuts: AIShortcut[]
}
-export const EntryWelcomeContent: React.FC = ({
- entryId,
- onSend,
- shortcuts,
-}) => {
- const { t } = useTranslation("ai")
- const showSettings = useSettingModal()
-
- return (
-
+export const EntryWelcomeContent: React.FC
= ({ entryId }) => (
+
+
-
- showSettings("ai")}
- customizeLabel={t("customize_shortcuts")}
- customizeTitle={t("customize_shortcuts_title")}
- />
-
-
- )
-}
+
+
+)
diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/ShortcutButtonGrid.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/ShortcutButtonGrid.tsx
deleted file mode 100644
index 37e9ac9d3..000000000
--- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/welcome/ShortcutButtonGrid.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { AIShortcutButton } from "@follow/components/ui/ai-shortcut-button/index.js"
-import type { AIShortcut } from "@follow/shared/settings/interface"
-import type { EditorState } from "lexical"
-import { useMemo } from "react"
-
-interface ShortcutButtonGridProps {
- shortcuts: AIShortcut[]
- onSend: (message: EditorState | string) => void
- onCustomize: () => void
- customizeLabel: string
- customizeTitle: string
- className?: string
- limit?: number
-}
-
-const baseClassName = "relative flex flex-wrap items-center justify-center gap-2"
-
-export const ShortcutButtonGrid: React.FC = ({
- shortcuts,
- onSend,
- onCustomize,
- customizeLabel,
- customizeTitle,
- className,
- limit = 6,
-}) => {
- const enabledShortcuts = useMemo(
- () => shortcuts.filter((shortcut) => shortcut.enabled),
- [shortcuts],
- )
- const displayShortcuts = useMemo(
- () => enabledShortcuts.slice(0, limit),
- [enabledShortcuts, limit],
- )
- const wrapperClassName = className ? `${baseClassName} ${className}` : baseClassName
-
- return (
-
- {displayShortcuts.map((shortcut, index) => (
-
onSend(shortcut.prompt)}
- animationDelay={index * 0.1}
- title={shortcut.hotkey ? `${shortcut.name} (${shortcut.hotkey})` : shortcut.name}
- >
- {shortcut.name}
-
- ))}
-
- {enabledShortcuts.length === 0 && (
-
- {customizeLabel}
-
- )}
-
- )
-}