Commit 2e26ac93 authored by Kantz's avatar Kantz
Browse files

chat deaktiviert während das LLM läd

parent 2fbf0a51
......@@ -9,6 +9,7 @@ type ChatWindowProps = {
draft: string;
onDraftChange: (value: string) => void;
onSend: () => void;
isSending?: boolean;
onHistoryNavigate?: (direction: "older" | "newer") => boolean;
onToggleCanvas?: () => void;
onUploadSolution?: (file: File) => void | Promise<void>;
......@@ -22,6 +23,7 @@ export default function ChatWindow({
draft,
onDraftChange,
onSend,
isSending = false,
onHistoryNavigate,
onToggleCanvas,
onUploadSolution,
......@@ -42,6 +44,7 @@ export default function ChatWindow({
value={draft}
onChange={onDraftChange}
onSend={onSend}
isSending={isSending}
onHistoryNavigate={onHistoryNavigate}
onToggleCanvas={onToggleCanvas}
onUploadSolution={onUploadSolution}
......
......@@ -50,10 +50,6 @@ export default function MessageBubble({
const hasThinking = Boolean(thinkingText);
useEffect(() => {
setIsThinkingExpanded(false);
}, [text]);
const renderMarkdown = (value: string) => (
<ReactMarkdown
urlTransform={(url) => {
......
......@@ -6,6 +6,7 @@ type MessageInputProps = {
value: string;
onChange: (value: string) => void;
onSend: () => void;
isSending?: boolean;
onHistoryNavigate?: (direction: "older" | "newer") => boolean;
onToggleCanvas?: () => void;
onUploadSolution?: (file: File) => void | Promise<void>;
......@@ -15,6 +16,7 @@ export default function MessageInput({
value,
onChange,
onSend,
isSending = false,
onHistoryNavigate,
onToggleCanvas,
onUploadSolution,
......@@ -44,6 +46,7 @@ export default function MessageInput({
className="btn"
type="button"
onClick={onToggleCanvas}
disabled={isSending}
aria-label={t("draw")}
title={t("draw")}
>
......@@ -53,6 +56,7 @@ export default function MessageInput({
className="btn"
type="button"
onClick={handleUploadClick}
disabled={isSending}
aria-label={t("uploadSolution")}
title={t("uploadSolution")}
>
......@@ -69,11 +73,19 @@ export default function MessageInput({
className="btn primary"
type="button"
onClick={onSend}
disabled={!canSend}
disabled={!canSend || isSending}
aria-label={t("send")}
title={t("send")}
>
<Send width={18} height={18} aria-hidden="true" />
{isSending ? (
<span className="composer-loading" aria-hidden="true">
<span />
<span />
<span />
</span>
) : (
<Send width={18} height={18} aria-hidden="true" />
)}
</button>
</div>
<textarea
......@@ -81,8 +93,14 @@ export default function MessageInput({
placeholder={t("typeQuestionOrLatex")}
rows={3}
value={value}
disabled={isSending}
onChange={(event) => onChange(event.target.value)}
onKeyDown={(event) => {
if (isSending) {
event.preventDefault();
return;
}
const isCursorAtStart =
event.currentTarget.selectionStart === 0 && event.currentTarget.selectionEnd === 0;
......
......@@ -200,6 +200,7 @@ export default function ChatPage() {
const [draftHistoryIndex, setDraftHistoryIndex] = useState<number | null>(null);
const [draftBeforeHistory, setDraftBeforeHistory] = useState<string | null>(null);
const [isArchiving, setIsArchiving] = useState(false);
const [isSending, setIsSending] = useState(false);
const [archivedChats, setArchivedChats] = useState<ArchivedChatSummary[]>([]);
const [selectedArchiveId, setSelectedArchiveId] = useState("");
const [archiveError, setArchiveError] = useState<string | null>(null);
......@@ -367,6 +368,7 @@ export default function ChatPage() {
deepLinkTarget,
isTasksInitialized,
navigate,
searchParams,
setSelectedOrchestrator,
setTaskRef,
setSubsectionRef,
......@@ -447,7 +449,6 @@ export default function ChatPage() {
cancelled = true;
};
}, [
applyRetrievedSources,
chatSessionId,
isTasksInitialized,
messages.length,
......@@ -612,6 +613,10 @@ export default function ChatPage() {
};
const handleSend = async () => {
if (isSending) {
return;
}
const trimmed = draft.trim();
if (!trimmed) {
return;
......@@ -626,10 +631,12 @@ export default function ChatPage() {
setMessages((prev) => [...prev, userMessage]);
setDraft("");
resetDraftHistoryNavigation();
setIsSending(true);
setRetrievalLoading(true);
setRetrievalError(null);
let chatRequestSucceeded = false;
try {
const chatPayload: {
messages: Array<{ role: "user" | "assistant"; text: string }>;
......@@ -680,6 +687,7 @@ export default function ChatPage() {
},
]);
}
chatRequestSucceeded = true;
} catch (error) {
setMessages((prev) => [
...prev,
......@@ -690,8 +698,13 @@ export default function ChatPage() {
},
]);
setRetrievalError(t("retrievalFailed"));
setRetrievalLoading(false);
void error;
} finally {
setIsSending(false);
}
if (!chatRequestSucceeded) {
setRetrievalLoading(false);
return;
}
......@@ -723,9 +736,8 @@ export default function ChatPage() {
} catch (error) {
setRetrievalError(t("retrievalFailed"));
void error;
} finally {
setRetrievalLoading(false);
}
setRetrievalLoading(false);
};
const handleToggleCanvas = () => {
......@@ -1161,6 +1173,7 @@ export default function ChatPage() {
draft={draft}
onDraftChange={handleDraftChange}
onSend={handleSend}
isSending={isSending}
onHistoryNavigate={handleHistoryNavigate}
onToggleCanvas={handleToggleCanvas}
onUploadSolution={handleCanvasUpload}
......
......@@ -510,6 +510,33 @@ body {
margin-left: auto;
}
.composer-loading {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 4px;
min-width: 28px;
min-height: 18px;
}
.composer-loading span {
display: inline-block;
width: 5px;
height: 5px;
border-radius: 999px;
background: currentColor;
opacity: 0.55;
animation: composer-dot-bounce 1s infinite ease-in-out;
}
.composer-loading span:nth-child(2) {
animation-delay: 0.15s;
}
.composer-loading span:nth-child(3) {
animation-delay: 0.3s;
}
.composer-input {
width: 100%;
resize: vertical;
......@@ -519,6 +546,12 @@ body {
font-family: inherit;
}
.composer-input:disabled {
background: #f7f3ec;
color: #8b857b;
cursor: not-allowed;
}
.btn {
border: 1px solid #b9b2a4;
background: #ffffff;
......@@ -539,6 +572,19 @@ body {
cursor: not-allowed;
}
@keyframes composer-dot-bounce {
0%,
80%,
100% {
transform: translateY(0);
opacity: 0.45;
}
40% {
transform: translateY(-3px);
opacity: 1;
}
}
.btn.small {
padding: 4px 10px;
font-size: 11px;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment