refactor(web): unify form controls, one notification rule, dedupe i18n copy (#54)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
c7465625a4
commit
3f868ac385
50 files changed
+2391
-1190
No files matched your search
@@ -26,6 +26,7 @@ import { S } from "../../lib/strings";
|
||||
import { apiErrorText } from "../../lib/api-error";
|
||||
import { useDocumentTitle } from "../../lib/use-document-title";
|
||||
import { formatDateTime, formatMoney, humanizeDuration, humanizeTokens } from "../../lib/format";
|
||||
import { latestConversation } from "../../lib/session-grouping";
|
||||
import { approvalKey } from "../../lib/omni/stream-model";
|
||||
import { useTheme } from "../../state/theme";
|
||||
import { useProject } from "../../state/project";
|
||||
@@ -203,14 +204,17 @@ export function ChatPage() {
|
||||
};
|
||||
}, [draft, routeSessionId, sessionsLoading, sessions, addSession]);
|
||||
|
||||
// Auto-select the most recent Session when the route doesn't select one; if there are none at all, fall back to draft state (instead of auto-creating one).
|
||||
// Auto-select the most recent conversation when the route doesn't select one (newest loaded
|
||||
// active/schedule Session — archived rows are hidden by choice and subagent Sessions belong
|
||||
// to their parent, so neither is auto-opened); if there is none, fall back to draft state
|
||||
// (instead of auto-creating one).
|
||||
useEffect(() => {
|
||||
if (sessionsLoading || draft) return;
|
||||
if (routeSessionId && sessions.some((s) => s.sessionId === routeSessionId)) return;
|
||||
// A routed id missing from the paged list isn't gone until the direct lookup fails.
|
||||
if (routeSessionId && probeFailedId !== routeSessionId) return;
|
||||
const first = sessions[0];
|
||||
navigate(first ? `/chat/${first.sessionId}` : `/chat/${DRAFT_SESSION_ID}`, { replace: true });
|
||||
const last = latestConversation(sessions);
|
||||
navigate(last ? `/chat/${last.sessionId}` : `/chat/${DRAFT_SESSION_ID}`, { replace: true });
|
||||
}, [sessionsLoading, draft, routeSessionId, probeFailedId, sessions, navigate]);
|
||||
|
||||
// Sync task_state to the sidebar list badge.
|
||||
@@ -574,7 +578,7 @@ export function ChatPage() {
|
||||
<StatChip
|
||||
icon={STAT_ICONS.cost}
|
||||
value={`${formatMoney(sessionCost, currency)}${costUncosted ? " *" : ""}`}
|
||||
label={`${S.chat.statCost}(${currency})${costUncosted ? ` · ${S.usage.uncostedNote}` : ""}`}
|
||||
label={`${S.common.cost}(${currency})${costUncosted ? ` · ${S.usage.uncostedNote}` : ""}`}
|
||||
/>
|
||||
)}
|
||||
<StatChip
|
||||
@@ -660,7 +664,7 @@ export function ChatPage() {
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-medium text-gray-500 dark:text-gray-400">
|
||||
{S.models.createdAt}
|
||||
{S.common.created}
|
||||
</p>
|
||||
<p className="font-mono text-xs">{formatDateTime(selected.createdAt)}</p>
|
||||
</div>
|
||||
@@ -672,7 +676,7 @@ export function ChatPage() {
|
||||
<p className="font-mono text-xs">
|
||||
{S.chat.statTokens} {humanizeTokens(totalTokens)}
|
||||
{sessionCost != null &&
|
||||
` · ${S.chat.statCost} ${formatMoney(sessionCost, currency)}`}{" "}
|
||||
` · ${S.common.cost} ${formatMoney(sessionCost, currency)}`}{" "}
|
||||
· {S.chat.statElapsed} {humanizeDuration(stream.model.stats.sessionElapsedMs)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user