Fix lint error

This commit is contained in:
Zero Liu 2026-05-23 23:37:56 -07:00
parent 814c63d62a
commit 2537348b2d
No known key found for this signature in database
10 changed files with 21 additions and 5 deletions

View file

@ -45,6 +45,7 @@ export const BinaryPathSetting: React.FC<Props> = ({
const [busy, setBusy] = React.useState(false);
React.useEffect(() => {
// eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect -- sync the editable draft when the persisted path changes underneath us (e.g. auto-detect from another panel); a key-prop remount would drop in-flight edits
setPathInput(initialPath);
}, [initialPath]);

View file

@ -104,8 +104,10 @@ export const SkillsSettings: React.FC = () => {
// (e.g. via Reset Settings). We don't want to clobber the user's in-flight
// typing, so only sync when the persisted value changes.
useEffect(() => {
/* eslint-disable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect -- resync the local draft when persisted settings change underneath us (e.g. Reset Settings); see comment above */
setDraft(persistedFolder);
setValidationError(null);
/* eslint-enable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect */
}, [persistedFolder]);
// Trigger a discovery pass on mount and on persisted-folder change so

View file

@ -491,7 +491,11 @@ const ChatInput = React.forwardRef<ChatInputHandle, ChatInputProps>(function Cha
}
break;
case "images": {
const input = document.createElement("input");
// Use the input's own document so the file picker opens in the window
// hosting this chat view (popout-safe), not whichever window is focused.
const doc = containerRef.current?.doc;
if (!doc) break;
const input = doc.createElement("input");
input.type = "file";
input.accept = "image/*";
input.multiple = true;

View file

@ -34,11 +34,13 @@ const ChatModeInput: React.FC<ChatModeInputProps> = (props) => {
// Force off in Projects mode; otherwise mirror settings.
useEffect(() => {
/* eslint-disable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect -- mirror the persisted setting / chain into the local toggle; the toggle is also user-editable so it can't be pure derived state */
if (currentChain === ChainType.PROJECT_CHAIN) {
setAutonomousAgentToggle(false);
} else {
setAutonomousAgentToggle(settings.enableAutonomousAgent);
}
/* eslint-enable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect */
}, [settings.enableAutonomousAgent, currentChain]);
const chatInputRef = useRef<ChatInputHandle>(null);

View file

@ -53,6 +53,7 @@ jest.mock("obsidian", () => {
TFile: class {},
App: class {},
ItemView: class {
// eslint-disable-next-line obsidianmd/prefer-active-doc -- jsdom mock creating the root containerEl; single realm, no owner element to derive `.doc` from
containerEl = document.createElement("div");
},
WorkspaceLeaf: class {},

View file

@ -24,12 +24,12 @@ export const CopilotSpinner: React.FC = () => {
viewBox={`0 0 ${GRID_SIZE} ${GRID_SIZE}`}
className="copilot-spinner"
>
{SIGMA_DOTS.map((dot, index) => {
{SIGMA_DOTS.map((dot) => {
const cx = dot.col * (DOT_SIZE + DOT_GAP) + DOT_SIZE / 2;
const cy = dot.row * (DOT_SIZE + DOT_GAP) + DOT_SIZE / 2;
return (
<circle
key={index}
key={dot.animIndex}
cx={cx}
cy={cy}
r={DOT_SIZE / 2}

View file

@ -37,13 +37,13 @@ export function attachChatViewLayoutObservers(containerEl: HTMLElement): {
const isCopilotActive = !!containerEl.closest(".workspace-drawer-active-tab-content");
const kbHeight = parseFloat(
document.documentElement.style.getPropertyValue("--keyboard-height") || "0"
containerEl.doc.documentElement.style.getPropertyValue("--keyboard-height") || "0"
);
drawer.classList.toggle("copilot-keyboard-open", isCopilotActive && kbHeight > 0);
};
const keyboardObserver = new MutationObserver(syncKeyboardClass);
keyboardObserver.observe(document.documentElement, {
keyboardObserver.observe(containerEl.doc.documentElement, {
attributes: true,
attributeFilter: ["style"],
});

View file

@ -75,6 +75,7 @@ export function ModelEffortPicker({ override, className }: ModelEffortPickerProp
// on open.
useEffect(() => {
if (open) {
/* eslint-disable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect -- seed the editable draft from props when the popover opens; drafts are committed on close, so this can't be pure derived state */
const initial = value && enabledKeys.includes(value) ? value : (enabledKeys[0] ?? null);
setHighlightKey(initial);
setDraftModelKey(initial);
@ -87,6 +88,7 @@ export function ModelEffortPicker({ override, className }: ModelEffortPickerProp
: null;
setDraftEffort(initialEffort);
initialRef.current = { model: value, effort: activeEffortValue };
/* eslint-enable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect */
}
}, [open, value, enabledKeys, activeEffortValue, effortOptionsByModelKey]);

View file

@ -16,6 +16,7 @@ const mockRemoveRefs = jest.fn().mockResolvedValue(undefined);
const mockGetProvider = jest.fn();
jest.mock("@/modelManagement/ui/ModelManagementContext", () => ({
// eslint-disable-next-line @eslint-react/hooks-extra/no-unnecessary-use-prefix -- mocks the real `useModelManagement` hook; the name must match the export
useModelManagement: () => ({
adapters: { verifyCredentials: mockVerifyCredentials },
setup: { byok: { addCatalogProvider: mockAddCatalogProvider } },
@ -31,6 +32,7 @@ jest.mock("@/modelManagement/ui/ModelManagementContext", () => ({
catalogService: { getProvider: mockGetProvider },
}),
}));
// eslint-disable-next-line @eslint-react/hooks-extra/no-unnecessary-use-prefix -- mocks the real `useApp` hook; the name must match the export
jest.mock("@/context", () => ({ useApp: () => ({}) }));
jest.mock("@/modelManagement/state/atoms", () => {
const jotai = jest.requireActual<typeof import("jotai")>("jotai");

View file

@ -9,6 +9,7 @@ const mockAddProviderOpen = jest.fn();
const mockConfigureOpen = jest.fn();
jest.mock("@/modelManagement/ui/ModelManagementContext", () => ({
// eslint-disable-next-line @eslint-react/hooks-extra/no-unnecessary-use-prefix -- mocks the real `useModelManagement` hook; the name must match the export
useModelManagement: () => ({
catalogService: {
ensureLoaded: mockEnsureLoaded,
@ -19,6 +20,7 @@ jest.mock("@/modelManagement/ui/ModelManagementContext", () => ({
coordinator: { removeProvider: mockRemoveProvider },
}),
}));
// eslint-disable-next-line @eslint-react/hooks-extra/no-unnecessary-use-prefix -- mocks the real `useApp` hook; the name must match the export
jest.mock("@/context", () => ({ useApp: () => ({}) }));
jest.mock("@/modelManagement/state/atoms", () => {
const jotai = jest.requireActual<typeof import("jotai")>("jotai");