From 416a9949676c29024ae1ab16f26c1802b3ebc01f Mon Sep 17 00:00:00 2001 From: wisecolt Date: Tue, 17 Mar 2026 00:41:07 +0300 Subject: [PATCH] fix: ekip panosu ve ust arayuzu rafine et --- web/src/App.jsx | 28 +++++++++++++++++----- web/src/components/SessionToolbar.jsx | 12 ++++------ web/src/components/TeamBoard.jsx | 2 +- web/src/lib/teamFeed.js | 30 +++++++++++++++++++---- web/src/styles/app.css | 34 +++++++++++++++++++++++---- 5 files changed, 82 insertions(+), 24 deletions(-) diff --git a/web/src/App.jsx b/web/src/App.jsx index 2341512..fc47dd7 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import ShellFrame from "./components/ShellFrame.jsx"; import SessionToolbar from "./components/SessionToolbar.jsx"; import ChatStream from "./components/ChatStream.jsx"; @@ -9,8 +9,9 @@ import { useSession } from "./hooks/useSession.js"; export default function App() { const { socket, connected } = useSocket(); - const { session, chat, error, startSession, stopSession, activateTeam, sendPrompt, clearError } = useSession(socket); + const { session, chat, error, startSession, stopSession, sendPrompt, selectProject, clearError } = useSession(socket); const [busy, setBusy] = useState(false); + const autoStartedRef = useRef(false); async function runAction(action) { setBusy(true); @@ -23,12 +24,28 @@ export default function App() { } } + useEffect(() => { + if (!connected || autoStartedRef.current) { + return; + } + + if (session.status === "idle") { + autoStartedRef.current = true; + runAction(startSession).catch(() => { + autoStartedRef.current = false; + }); + } + }, [connected, session.status]); + return (
-
+

1996 COMMAND CENTER

Retro Claude Team Console

+

+ Current Project: {session.currentProjectPath ?? "None"} +

LINK: {connected ? "ONLINE" : "OFFLINE"} @@ -54,14 +71,13 @@ export default function App() { runAction(startSession)} - onActivate={() => runAction(activateTeam)} onStop={() => runAction(stopSession)} + onSelectProject={() => runAction(selectProject)} /> } /> runAction(() => sendPrompt(prompt))} />
diff --git a/web/src/components/SessionToolbar.jsx b/web/src/components/SessionToolbar.jsx index 563e242..507d71f 100644 --- a/web/src/components/SessionToolbar.jsx +++ b/web/src/components/SessionToolbar.jsx @@ -1,20 +1,16 @@ import PixelButton from "./PixelButton.jsx"; -export default function SessionToolbar({ session, busy, onStart, onActivate, onStop }) { +export default function SessionToolbar({ session, busy, onStop, onSelectProject }) { const isRunning = session.status === "running"; - const isStarting = session.status === "starting"; return (
- - Start Session - - - Activate Team - Stop Session + + Select Project +
); } diff --git a/web/src/components/TeamBoard.jsx b/web/src/components/TeamBoard.jsx index baee3e7..496146a 100644 --- a/web/src/components/TeamBoard.jsx +++ b/web/src/components/TeamBoard.jsx @@ -21,7 +21,7 @@ function TeamCard({ member }) { NO SIGNAL YET
) : ( - member.messages.slice(-4).map((message) => ( + [...member.messages].slice(-4).reverse().map((message) => (
{message.speaker}:
{message.text}
diff --git a/web/src/lib/teamFeed.js b/web/src/lib/teamFeed.js index 6b9e6ec..d7d26a4 100644 --- a/web/src/lib/teamFeed.js +++ b/web/src/lib/teamFeed.js @@ -69,8 +69,7 @@ function shouldBreakCurrentEntry(line) { /^[-=]{4,}$/.test(trimmed), /^>/.test(trimmed), /^Kullanici /i.test(trimmed), - /^Mazlum nasilsin\?/i.test(trimmed), - /^[A-Za-zÀ-ÿ]+,/.test(trimmed) + /^Mazlum nasilsin\?/i.test(trimmed) ].some(Boolean); } @@ -94,11 +93,34 @@ function dedupeMessages(messages) { const result = []; for (const message of messages) { - const key = `${message.speaker}::${message.text}`; + const normalizedText = String(message.text ?? "").replace(/\s+/g, " ").trim(); + const firstLine = normalizedText.split("\n")[0]?.trim() ?? ""; + const key = `${message.speaker}::${normalizedText}`; + if (seen.has(key)) { continue; } + const lastMessage = result[result.length - 1]; + if (lastMessage) { + const lastNormalized = String(lastMessage.text ?? "").replace(/\s+/g, " ").trim(); + const lastFirstLine = lastNormalized.split("\n")[0]?.trim() ?? ""; + + if ( + lastMessage.speaker === message.speaker && + firstLine && + lastFirstLine === firstLine + ) { + const mergedText = lastNormalized.length >= normalizedText.length ? lastMessage.text : message.text; + result[result.length - 1] = { + ...lastMessage, + text: mergedText + }; + seen.add(key); + continue; + } + } + seen.add(key); result.push(message); } @@ -112,7 +134,7 @@ export function parseTeamFeed(chat) { for (const rawLine of String(chat ?? "").split("\n")) { const line = rawLine.trim(); - const speakerMatch = line.match(/^[•*\-⏺]?\s*([A-Za-zÀ-ÿ]+):\s*(.*)$/); + const speakerMatch = line.match(/^(?:[•*⏺]\s*)?([A-Za-zÀ-ÿ]+):\s*(.*)$/); if (speakerMatch) { const member = memberMap.get(normalizeSpeaker(speakerMatch[1])); diff --git a/web/src/styles/app.css b/web/src/styles/app.css index 1bf2121..61793ca 100644 --- a/web/src/styles/app.css +++ b/web/src/styles/app.css @@ -35,6 +35,24 @@ font-size: clamp(1.3rem, 2vw, 2rem); } +.app-shell__title { + min-width: 0; +} + +.app-shell__project { + margin: 10px 0 0; + max-width: min(70vw, 760px); + color: var(--text-dim); + font-size: 0.78rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.app-shell__project span { + color: var(--accent-amber); +} + .app-shell__meta { display: flex; gap: 10px; @@ -107,13 +125,14 @@ .session-toolbar { display: flex; - gap: 12px; + gap: 8px; flex-wrap: wrap; } .session-toolbar--inline { justify-content: flex-end; margin-bottom: 0; + flex-wrap: nowrap; } .pixel-button { @@ -123,17 +142,17 @@ cursor: pointer; text-transform: uppercase; background: transparent; - min-width: 156px; + min-width: 128px; } .pixel-button span { display: block; - padding: 14px 16px; + padding: 12px 12px; border: 3px solid var(--border-dark); box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.06); font-family: var(--font-display); - font-size: 0.62rem; - letter-spacing: 0.14em; + font-size: 0.56rem; + letter-spacing: 0.12em; } .pixel-button:hover span { @@ -401,6 +420,10 @@ align-items: stretch; } + .app-shell__project { + max-width: 100%; + } + .shell-frame__screen { min-height: auto; padding: 12px; @@ -413,5 +436,6 @@ .session-toolbar--inline { justify-content: stretch; + flex-wrap: wrap; } }