优化新会话页面显示布局
This commit is contained in:
@@ -32,6 +32,7 @@ interface ConversationShellProps {
|
||||
availableCommands?: AvailableCommandInfo[] | null
|
||||
attachmentTabId?: string | null
|
||||
draftStorageKey?: string | null
|
||||
hideInput?: boolean
|
||||
}
|
||||
|
||||
export function ConversationShell({
|
||||
@@ -55,6 +56,7 @@ export function ConversationShell({
|
||||
availableCommands,
|
||||
attachmentTabId,
|
||||
draftStorageKey,
|
||||
hideInput = false,
|
||||
}: ConversationShellProps) {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
@@ -65,24 +67,26 @@ export function ConversationShell({
|
||||
onRespond={onRespondPermission}
|
||||
/>
|
||||
|
||||
<ChatInput
|
||||
status={status}
|
||||
promptCapabilities={promptCapabilities}
|
||||
defaultPath={defaultPath}
|
||||
onFocus={onFocus}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
modes={modes}
|
||||
configOptions={configOptions}
|
||||
modeLoading={modeLoading}
|
||||
configOptionsLoading={configOptionsLoading}
|
||||
selectedModeId={selectedModeId}
|
||||
onModeChange={onModeChange}
|
||||
onConfigOptionChange={onConfigOptionChange}
|
||||
availableCommands={availableCommands}
|
||||
attachmentTabId={attachmentTabId}
|
||||
draftStorageKey={draftStorageKey}
|
||||
/>
|
||||
{!hideInput && (
|
||||
<ChatInput
|
||||
status={status}
|
||||
promptCapabilities={promptCapabilities}
|
||||
defaultPath={defaultPath}
|
||||
onFocus={onFocus}
|
||||
onSend={onSend}
|
||||
onCancel={onCancel}
|
||||
modes={modes}
|
||||
configOptions={configOptions}
|
||||
modeLoading={modeLoading}
|
||||
configOptionsLoading={configOptionsLoading}
|
||||
selectedModeId={selectedModeId}
|
||||
onModeChange={onModeChange}
|
||||
onConfigOptionChange={onConfigOptionChange}
|
||||
availableCommands={availableCommands}
|
||||
attachmentTabId={attachmentTabId}
|
||||
draftStorageKey={draftStorageKey}
|
||||
/>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="px-4 py-2 text-xs text-destructive bg-destructive/5 border-t border-destructive/20">
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useConnectionLifecycle } from "@/hooks/use-connection-lifecycle"
|
||||
import { MessageListView } from "@/components/message/message-list-view"
|
||||
import { ConversationShell } from "@/components/chat/conversation-shell"
|
||||
import { AgentSelector } from "@/components/chat/agent-selector"
|
||||
import { ChatInput } from "@/components/chat/chat-input"
|
||||
import {
|
||||
createConversation,
|
||||
openSettingsWindow,
|
||||
@@ -151,6 +152,7 @@ const ConversationTabView = memo(function ConversationTabView({
|
||||
const [agentConnectError, setAgentConnectError] = useState<string | null>(
|
||||
null
|
||||
)
|
||||
const [hasSentMessage, setHasSentMessage] = useState(false)
|
||||
|
||||
const hasPersistedConversation = dbConversationId != null
|
||||
const canAutoConnect =
|
||||
@@ -425,6 +427,7 @@ const ConversationTabView = memo(function ConversationTabView({
|
||||
)
|
||||
setSendSignal((prev) => prev + 1)
|
||||
setSyncState(effectiveConversationId, "awaiting_persist")
|
||||
setHasSentMessage(true)
|
||||
lifecycleSend(draft, selectedModeIdArg)
|
||||
|
||||
const persistedId = dbConvIdRef.current
|
||||
@@ -534,6 +537,9 @@ const ConversationTabView = memo(function ConversationTabView({
|
||||
[connConnect, connDisconnect, workingDirForConnection]
|
||||
)
|
||||
|
||||
const showDraftHeader = !hasPersistedConversation
|
||||
const isWelcomeMode = showDraftHeader && !hasSentMessage
|
||||
|
||||
const messageListNode = (
|
||||
<MessageListView
|
||||
conversationId={effectiveConversationId}
|
||||
@@ -543,11 +549,10 @@ const ConversationTabView = memo(function ConversationTabView({
|
||||
sessionStats={detail?.session_stats ?? null}
|
||||
detailLoading={detailLoading}
|
||||
detailError={detailError}
|
||||
hideEmptyState={showDraftHeader}
|
||||
/>
|
||||
)
|
||||
|
||||
const showDraftHeader = !hasPersistedConversation
|
||||
|
||||
return (
|
||||
<ConversationShell
|
||||
status={connStatus}
|
||||
@@ -569,8 +574,59 @@ const ConversationTabView = memo(function ConversationTabView({
|
||||
availableCommands={connectionCommands}
|
||||
attachmentTabId={tabId}
|
||||
draftStorageKey={draftStorageKey}
|
||||
hideInput={isWelcomeMode}
|
||||
>
|
||||
{showDraftHeader ? (
|
||||
{isWelcomeMode ? (
|
||||
<div className="flex h-full min-h-0 flex-col items-center justify-center">
|
||||
<div className="flex w-full max-w-2xl flex-col gap-4 px-4">
|
||||
<AgentSelector
|
||||
defaultAgentType={selectedAgent}
|
||||
onSelect={handleAgentSelect}
|
||||
onAgentsLoaded={(agents) => {
|
||||
setAgentsLoaded(true)
|
||||
setUsableAgentCount(
|
||||
agents.filter((agent) => agent.enabled && agent.available)
|
||||
.length
|
||||
)
|
||||
}}
|
||||
onOpenAgentsSettings={handleOpenAgentsSettings}
|
||||
disabled={isConnecting || dbConversationId != null}
|
||||
/>
|
||||
{autoConnectError || agentConnectError ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleOpenAgentsSettings}
|
||||
className="w-full cursor-pointer rounded-lg border border-destructive/30 bg-destructive/5 px-3 py-2 text-center text-xs text-destructive transition-colors hover:bg-destructive/10"
|
||||
>
|
||||
<div
|
||||
className="overflow-hidden text-ellipsis whitespace-nowrap text-center"
|
||||
title={autoConnectError ?? agentConnectError ?? ""}
|
||||
>
|
||||
{autoConnectError ?? agentConnectError}
|
||||
</div>
|
||||
</button>
|
||||
) : null}
|
||||
<ChatInput
|
||||
status={connStatus}
|
||||
promptCapabilities={conn.promptCapabilities}
|
||||
defaultPath={workingDirForConnection}
|
||||
onFocus={handleFocus}
|
||||
onSend={handleSend}
|
||||
onCancel={handleCancel}
|
||||
modes={connectionModes}
|
||||
configOptions={connectionConfigOptions}
|
||||
modeLoading={modeLoading}
|
||||
configOptionsLoading={configOptionsLoading}
|
||||
selectedModeId={selectedModeId}
|
||||
onModeChange={setModeId}
|
||||
onConfigOptionChange={handleSetConfigOption}
|
||||
availableCommands={connectionCommands}
|
||||
attachmentTabId={tabId}
|
||||
draftStorageKey={draftStorageKey}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : showDraftHeader ? (
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
<div className="px-4 pt-3 pb-2">
|
||||
<AgentSelector
|
||||
|
||||
@@ -36,6 +36,7 @@ interface MessageListViewProps {
|
||||
sessionStats?: SessionStats | null
|
||||
detailLoading?: boolean
|
||||
detailError?: string | null
|
||||
hideEmptyState?: boolean
|
||||
}
|
||||
|
||||
interface ResolvedMessageGroup extends MessageGroup {
|
||||
@@ -133,6 +134,7 @@ export function MessageListView({
|
||||
sessionStats = null,
|
||||
detailLoading = false,
|
||||
detailError = null,
|
||||
hideEmptyState = false,
|
||||
}: MessageListViewProps) {
|
||||
const t = useTranslations("Folder.chat.messageList")
|
||||
const sharedT = useTranslations("Folder.chat.shared")
|
||||
@@ -237,14 +239,15 @@ export function MessageListView({
|
||||
}, [])
|
||||
|
||||
const emptyState = useMemo(
|
||||
() => (
|
||||
<div className="px-4 py-12 text-center">
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("emptyConversation")}
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
[t]
|
||||
() =>
|
||||
hideEmptyState ? null : (
|
||||
<div className="px-4 py-12 text-center">
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("emptyConversation")}
|
||||
</p>
|
||||
</div>
|
||||
),
|
||||
[hideEmptyState, t]
|
||||
)
|
||||
|
||||
const agentPlanOverlayKey = liveMessage?.id ?? `history-${conversationId}`
|
||||
|
||||
Reference in New Issue
Block a user