fix(chat): '생각하는 중'과 '작성 중'이 둘 다 보이던 것 — 상태줄 하나로 합치고 첫 글자 전/후로 라벨만 바뀜. 0.1.3

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
lee-hyeon-cheol
2026-09-22 10:47:25 +09:00
co-authored by Claude Fable 5.1
parent 69d4dd340f
commit 596c7e52a8
8 changed files with 19 additions and 21 deletions
@@ -1,7 +1,7 @@
import type { ReactNode } from "react"
/** 답변 자리(첫 토큰 전·재진입 대기·세션 생성 중). Message 의 assistant 모양과 똑같이 —
* AI 배지 + CODEASSIST 라벨, 본문은 상자 없이. 안에 시머 텍스트나 스트리밍 본문을 넣는다. */
* AI 배지 + CODEASSIST 라벨, 본문은 상자 없이. "생각하는 중" 표시는 아래 WorkingRow 가 맡음. */
export function ThinkingBubble({ children }: { children?: ReactNode }) {
return (
<div className="flex flex-col items-start gap-1">
@@ -13,9 +13,7 @@ export function ThinkingBubble({ children }: { children?: ReactNode }) {
CODEASSIST
</span>
</div>
<div className="text-foreground w-full text-sm leading-[1.9]">
{children ?? <span className="shimmer-text text-sm"> </span>}
</div>
<div className="text-foreground w-full text-sm leading-[1.9]">{children}</div>
</div>
)
}
@@ -66,8 +66,8 @@ export function ThinkingSteps({
)
}
/** 하단 "작성 중… · N초" — 스피너 + 경과 초. busy 가 true 인 동안만 그림. */
export function WorkingRow({ busy }: { busy: boolean }) {
/** 하단 상태줄 — 스피너 + 경과 초. 답변 글자 오기 전엔 "생각하는 중", 오기 시작하면 "작성 중". */
export function WorkingRow({ busy, label = "작성 중…" }: { busy: boolean; label?: string }) {
const [elapsed, setElapsed] = useState(0)
useEffect(() => {
if (!busy) return
@@ -80,7 +80,7 @@ export function WorkingRow({ busy }: { busy: boolean }) {
return (
<div className="text-muted-foreground flex items-center gap-2 text-[12.5px]">
<Loader2 size={14} className="animate-spin" />
· {elapsed}
{label} · {elapsed}
</div>
)
}
@@ -30,7 +30,7 @@ describe("NewChatPage 전송", () => {
mount()
fireEvent.click(screen.getByText("MARA 에서 자재번호로 자재유형(MTART) 읽는 SELECT SINGLE"))
expect(mutate).toHaveBeenCalledOnce()
expect(await screen.findByText("생각하는 중…")).toBeTruthy()
expect(await screen.findByText(/생각하는 중…/)).toBeTruthy()
expect(screen.getByText("MARA 에서 자재번호로 자재유형(MTART) 읽는 SELECT SINGLE")).toBeTruthy()
expect(screen.queryByText("무엇을 도와드릴까요?")).toBeNull()
act(() => lastCallbacks().onSuccess({ id: "ses_new" }))
@@ -40,10 +40,10 @@ describe("NewChatPage 전송", () => {
it("세션 생성 실패면 헤로로 돌아온다", async () => {
mount()
fireEvent.click(screen.getByText("내부 테이블 LOOP 에서 그룹 소계 구하는 관용구"))
expect(await screen.findByText("생각하는 중…")).toBeTruthy()
expect(await screen.findByText(/생각하는 중…/)).toBeTruthy()
act(() => lastCallbacks().onError())
expect(await screen.findByText("무엇을 도와드릴까요?")).toBeTruthy()
expect(screen.queryByText("생각하는 중…")).toBeNull()
expect(screen.queryByText(/생각하는 중…/)).toBeNull()
})
it("생성 중엔 두 번째 전송을 무시한다", () => {
@@ -9,6 +9,7 @@ import { Hero } from "../components/Hero"
import { Composer } from "../components/Composer"
import { Message } from "../components/Message"
import { ThinkingBubble } from "../components/ThinkingBubble"
import { WorkingRow } from "../components/ThinkingSteps"
import { useEscapeKey } from "../hooks/useEscapeKey"
import type { SnapImageInput } from "../contract/types"
@@ -61,6 +62,7 @@ export default function NewChatPage() {
{/* eslint-disable-next-line jsx-a11y/aria-role -- Message 의 role 은 ARIA 아니고 화자 */}
<Message role="user" content={pending} />
<ThinkingBubble />
<WorkingRow busy label="생각하는 중…" />
</div>
)}
<Composer
@@ -174,12 +174,7 @@ export default function SessionChatPage() {
isDone={!isStreaming}
answerStarted={m.content !== ""}
/>
{m.content === "" ? (
// 첫 토큰 오기 전 빈 시간 메움 — 과정도 아직 없으면 시머로 "생각 중" 신호
steps.length === 0 && (
<span className="shimmer-text text-sm"> </span>
)
) : (
{m.content !== "" && (
<StreamingText
text={m.content}
isStreaming={isStreaming}
@@ -188,7 +183,10 @@ export default function SessionChatPage() {
/>
)}
</ThinkingBubble>
<WorkingRow busy={isStreaming} />
<WorkingRow
busy={isStreaming}
label={m.content === "" ? "생각하는 중…" : "작성 중…"}
/>
</div>
)
}
@@ -222,7 +220,7 @@ export default function SessionChatPage() {
{generatingRemotely && (
<div className="flex flex-col gap-2">
<ThinkingBubble />
<WorkingRow busy />
<WorkingRow busy label="생각하는 중…" />
</div>
)}
</div>
+1 -1
View File
@@ -485,7 +485,7 @@ dependencies = [
[[package]]
name = "codeassist-tauri"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"base64 0.22.1",
"png 0.17.16",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "codeassist-tauri"
version = "0.1.2"
version = "0.1.3"
description = "CodeAssist 표준 Rust/Tauri 데스크톱 앱"
authors = ["justdodev"]
edition = "2021"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "CodeAssist",
"version": "0.1.2",
"version": "0.1.3",
"identifier": "com.codeassist.app",
"build": {
"beforeDevCommand": { "cwd": "../../2_frontend", "script": "npm run dev" },