mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[Haik]: fix case-sensitive Button import paths across 7 adapter files, replace React use() with useContext in CodeDiff for broader compat, remove unused useResolvedTheme/getSystemTheme/getDocumentTheme from CodeBlockRoot helpers, fix useFileSrc object URL race condition with revocation flag and queueMicrotask, replace OptionList useEffect-based activeIndex with useMemo derivation, swap process.env NODE_ENV check for import.meta.env.DEV, and wrap ElementSelectionProvider ref assignment in useEffect to avoid render-phase side effects
This commit is contained in:
@@ -6,7 +6,7 @@ import {
|
||||
AuiIf,
|
||||
} from '@assistant-ui/react';
|
||||
import { ArrowDownIcon } from 'lucide-react';
|
||||
import { Button } from '@/app/pages/AgentChat/_shared/button';
|
||||
import { Button } from '@/app/pages/AgentChat/_shared/Button';
|
||||
import { TooltipProvider } from './components/tooltip';
|
||||
import { TooltipIconButton } from './components/TooltipIconButton';
|
||||
import { UserMessage } from './components/UserMessage/UserMessage';
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "./tooltip";
|
||||
import { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
import { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type TooltipIconButtonProps = ComponentPropsWithRef<typeof Button> & {
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ function useOriginalMessage(): AgentMessage | undefined {
|
||||
try {
|
||||
messageId = aui.message().getState().id;
|
||||
} catch {
|
||||
return undefined;
|
||||
// intentionally empty — messageId stays undefined
|
||||
}
|
||||
|
||||
return useAppSelector((state) => {
|
||||
|
||||
+7
-3
@@ -29,19 +29,23 @@ const useFileSrc = (file: File | undefined) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (!file) {
|
||||
setSrc(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
let revoked = false;
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
setSrc(objectUrl);
|
||||
queueMicrotask(() => {
|
||||
if (!revoked) setSrc(objectUrl);
|
||||
});
|
||||
|
||||
return () => {
|
||||
revoked = true;
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
queueMicrotask(() => setSrc(undefined));
|
||||
};
|
||||
}, [file]);
|
||||
|
||||
return src;
|
||||
return file ? src : undefined;
|
||||
};
|
||||
|
||||
const useAttachmentSrc = () => {
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
import type { Action } from "../../utils/types";
|
||||
import { useActionButtons } from "./useActionButtons";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
import { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
|
||||
interface ActionButtonsProps {
|
||||
actions: Action[];
|
||||
|
||||
+14
-17
@@ -4,7 +4,6 @@ import {
|
||||
useMemo,
|
||||
useState,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
Fragment,
|
||||
} from "react";
|
||||
@@ -229,7 +228,7 @@ export function OptionList({
|
||||
onBeforeAction,
|
||||
className,
|
||||
}: OptionListProps) {
|
||||
if (process.env["NODE_ENV"] !== "production") {
|
||||
if (import.meta.env.DEV) {
|
||||
if (value !== undefined && defaultValue !== undefined) {
|
||||
console.warn(
|
||||
"[OptionList] Both `value` (controlled) and `defaultValue` (uncontrolled) were provided. `defaultValue` is ignored when `value` is set.",
|
||||
@@ -297,7 +296,7 @@ export function OptionList({
|
||||
]);
|
||||
|
||||
const optionRefs = useRef<Array<HTMLButtonElement | null>>([]);
|
||||
const [activeIndex, setActiveIndex] = useState(() => {
|
||||
const [rawActiveIndex, setActiveIndex] = useState(() => {
|
||||
const firstSelected = optionStates.findIndex(
|
||||
(s) => s.isSelected && !s.isDisabled,
|
||||
);
|
||||
@@ -306,20 +305,18 @@ export function OptionList({
|
||||
return firstEnabled >= 0 ? firstEnabled : 0;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (optionStates.length === 0) return;
|
||||
setActiveIndex((prev) => {
|
||||
if (
|
||||
prev < 0 ||
|
||||
prev >= optionStates.length ||
|
||||
optionStates[prev].isDisabled
|
||||
) {
|
||||
const firstEnabled = optionStates.findIndex((s) => !s.isDisabled);
|
||||
return firstEnabled >= 0 ? firstEnabled : 0;
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
}, [optionStates]);
|
||||
const activeIndex = useMemo(() => {
|
||||
if (
|
||||
optionStates.length === 0 ||
|
||||
(rawActiveIndex >= 0 &&
|
||||
rawActiveIndex < optionStates.length &&
|
||||
!optionStates[rawActiveIndex].isDisabled)
|
||||
) {
|
||||
return rawActiveIndex;
|
||||
}
|
||||
const firstEnabled = optionStates.findIndex((s) => !s.isDisabled);
|
||||
return firstEnabled >= 0 ? firstEnabled : 0;
|
||||
}, [rawActiveIndex, optionStates]);
|
||||
|
||||
const updateSelection = useCallback(
|
||||
(next: Set<string>) => {
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
export { cn } from "@/lib/utils";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
export { Separator } from "../../separator";
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import type { Action, ActionsConfig } from "./schema";
|
||||
import type { Action, ActionsConfig } from "@/app/pages/AgentChat/toolkit/approvalToolkit/utils/types";
|
||||
|
||||
export type ActionsProp = ActionsConfig | Action[];
|
||||
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
export { cn } from "@/lib/utils";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
export { Separator } from "../../separator";
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
export { cn } from "@/lib/utils";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
export { Collapsible, CollapsibleTrigger } from "@/app/pages/AgentChat/_shared/collapsible";
|
||||
|
||||
-52
@@ -1,9 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
useState,
|
||||
useEffect,
|
||||
} from "react";
|
||||
import { createHighlighter, type Highlighter } from "shiki/bundle/web";
|
||||
import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
|
||||
import pierreDarkTheme from "../../../_shared/pierre-dark-theme.js";
|
||||
@@ -57,52 +53,4 @@ export function setCachedHtml(cacheKey: string, html: string): void {
|
||||
}
|
||||
|
||||
htmlCache.set(cacheKey, html);
|
||||
}
|
||||
|
||||
export function getSystemTheme(): "light" | "dark" {
|
||||
if (typeof window === "undefined") return "light";
|
||||
return window.matchMedia?.("(prefers-color-scheme: dark)").matches
|
||||
? "dark"
|
||||
: "light";
|
||||
}
|
||||
|
||||
export function getDocumentTheme(): "light" | "dark" | null {
|
||||
if (typeof document === "undefined") return null;
|
||||
const root = document.documentElement;
|
||||
const dataTheme = root.getAttribute("data-theme")?.toLowerCase();
|
||||
if (dataTheme === "dark") return "dark";
|
||||
if (dataTheme === "light") return "light";
|
||||
if (root.classList.contains("dark")) return "dark";
|
||||
if (root.classList.contains("light")) return "light";
|
||||
return null;
|
||||
}
|
||||
|
||||
export function useResolvedTheme(): "light" | "dark" {
|
||||
const [theme, setTheme] = useState<"light" | "dark">(() => {
|
||||
return getDocumentTheme() ?? getSystemTheme();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined" || typeof document === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
const update = () => setTheme(getDocumentTheme() ?? getSystemTheme());
|
||||
|
||||
const mql = window.matchMedia?.("(prefers-color-scheme: dark)");
|
||||
mql?.addEventListener("change", update);
|
||||
|
||||
const observer = new MutationObserver(update);
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ["class", "data-theme"],
|
||||
});
|
||||
|
||||
return () => {
|
||||
mql?.removeEventListener("change", update);
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return theme;
|
||||
}
|
||||
+2
-2
@@ -6,7 +6,7 @@ import {
|
||||
useEffect,
|
||||
useMemo,
|
||||
createContext,
|
||||
use,
|
||||
useContext,
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import {
|
||||
@@ -137,7 +137,7 @@ type CodeDiffSharedState = {
|
||||
const CodeDiffContext = createContext<CodeDiffSharedState | null>(null);
|
||||
|
||||
function useCodeDiff(): CodeDiffSharedState {
|
||||
const context = use(CodeDiffContext);
|
||||
const context = useContext(CodeDiffContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"CodeDiff subcomponents must be used within <CodeDiff.Root>.",
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
export { cn } from "@/lib/utils";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
export { Collapsible, CollapsibleTrigger } from "@/app/pages/AgentChat/_shared/collapsible";
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
export { cn } from "@/lib/utils";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/button";
|
||||
export { Button } from "@/app/pages/AgentChat/_shared/Button";
|
||||
export { Collapsible, CollapsibleTrigger } from "@/app/pages/AgentChat/_shared/collapsible";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useCallback, useMemo } from 'react';
|
||||
import React, { useState, useRef, useCallback, useMemo, useEffect } from 'react';
|
||||
import { type SelectedElement } from './SelectedElement';
|
||||
import { ElementSelectionContext } from './useElementSelection';
|
||||
|
||||
@@ -10,7 +10,9 @@ export const ElementSelectionProvider: React.FC<{ children: React.ReactNode }> =
|
||||
const iframeRef = useRef<HTMLIFrameElement | null>(null);
|
||||
|
||||
const activeOwnerIdRef = useRef(activeOwnerId);
|
||||
activeOwnerIdRef.current = activeOwnerId;
|
||||
useEffect(() => {
|
||||
activeOwnerIdRef.current = activeOwnerId;
|
||||
}, [activeOwnerId]);
|
||||
|
||||
const selectedElements = useMemo(
|
||||
() => (activeOwnerId ? elementsByOwner[activeOwnerId] ?? [] : []),
|
||||
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
Reference in New Issue
Block a user