* refactor: clear no-unnecessary-type-conversion + unbound-method (T3.b partial)
Fixes 15 files within the hard cap:
unbound-method (interface method shorthand → property function syntax):
- pane-context.tsx: PaneContextValue + PaneFocusContextValue (fixes agent-panel, browser-panel, draft-panel)
- provider-runner.ts: ProviderTurnRunner interface
- process-tree.ts: process.kill.bind(process)
no-unnecessary-type-conversion (remove redundant Boolean()/String() wraps):
- agent-timeline-store.ts, worktree-session.ts, pairing-qr.ts
- sherpa-realtime-session.ts, sherpa-stt.ts (String() → direct call chain)
- workspace-execution.ts, confirm-dialog.ts, use-archive-agent.ts
- use-agent-history.ts, left-sidebar.tsx, autocomplete.tsx, dropdown-menu.tsx
Deferred (9 errors across 7 files, all single-line Boolean(hovered) removals):
project-picker-modal.tsx, agent-list.tsx, branch-switcher.tsx,
file-explorer-pane.tsx, workspace-open-in-editor-button.tsx,
browser-pane.electron.tsx, sortable-inline-list.web.tsx
* fix(app): preserve Boolean coercion fallback in archive state lookups
readPendingState(...)[key] and (pendingQuery.data ?? {})[key] return
boolean | undefined at runtime — noUncheckedIndexedAccess is off so
TypeScript types this as boolean but the actual value can be undefined.
Add ?? false to maintain the explicit boolean return contract.
123 lines
3.0 KiB
TypeScript
123 lines
3.0 KiB
TypeScript
import { Alert } from "react-native";
|
|
import { getDesktopHost, type DesktopDialogAskOptions } from "@/desktop/host";
|
|
import { isNative } from "@/constants/platform";
|
|
|
|
export interface ConfirmDialogInput {
|
|
title: string;
|
|
message: string;
|
|
confirmLabel?: string;
|
|
cancelLabel?: string;
|
|
destructive?: boolean;
|
|
}
|
|
|
|
interface ConfirmButtonConfig {
|
|
confirmLabel: string;
|
|
cancelLabel: string;
|
|
}
|
|
|
|
function resolveButtonLabels(input: ConfirmDialogInput): ConfirmButtonConfig {
|
|
return {
|
|
confirmLabel: input.confirmLabel ?? "Confirm",
|
|
cancelLabel: input.cancelLabel ?? "Cancel",
|
|
};
|
|
}
|
|
|
|
async function showNativeConfirmDialog(input: ConfirmDialogInput): Promise<boolean> {
|
|
const labels = resolveButtonLabels(input);
|
|
|
|
return new Promise<boolean>((resolve) => {
|
|
Alert.alert(
|
|
input.title,
|
|
input.message,
|
|
[
|
|
{
|
|
text: labels.cancelLabel,
|
|
style: "cancel",
|
|
onPress: () => resolve(false),
|
|
},
|
|
{
|
|
text: labels.confirmLabel,
|
|
style: input.destructive ? "destructive" : "default",
|
|
onPress: () => resolve(true),
|
|
},
|
|
],
|
|
{
|
|
cancelable: true,
|
|
onDismiss: () => resolve(false),
|
|
},
|
|
);
|
|
});
|
|
}
|
|
|
|
function getDesktopApi() {
|
|
if (isNative) {
|
|
return null;
|
|
}
|
|
return getDesktopHost();
|
|
}
|
|
|
|
function buildDesktopAskOptions(input: ConfirmDialogInput): DesktopDialogAskOptions {
|
|
const labels = resolveButtonLabels(input);
|
|
|
|
return {
|
|
title: input.title,
|
|
okLabel: labels.confirmLabel,
|
|
cancelLabel: labels.cancelLabel,
|
|
kind: input.destructive ? "warning" : "info",
|
|
};
|
|
}
|
|
|
|
function blurActiveWebElement(): void {
|
|
if (isNative) {
|
|
return;
|
|
}
|
|
const activeElement = (globalThis as { document?: Document }).document?.activeElement;
|
|
(activeElement as HTMLElement | null)?.blur?.();
|
|
}
|
|
|
|
async function showDesktopConfirmDialog(input: ConfirmDialogInput): Promise<boolean | null> {
|
|
const desktopApi = getDesktopApi();
|
|
if (!desktopApi) {
|
|
return null;
|
|
}
|
|
|
|
blurActiveWebElement();
|
|
const options = buildDesktopAskOptions(input);
|
|
const desktopAsk = desktopApi.dialog?.ask;
|
|
|
|
if (typeof desktopAsk === "function") {
|
|
return await desktopAsk(input.message, options);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function showWebConfirmDialog(input: ConfirmDialogInput): boolean {
|
|
const browserConfirm = (globalThis as { confirm?: (message?: string) => boolean }).confirm;
|
|
if (typeof browserConfirm !== "function") {
|
|
throw new Error("[ConfirmDialog] No web confirmation backend is available.");
|
|
}
|
|
|
|
blurActiveWebElement();
|
|
const promptMessage = `${input.title}\n\n${input.message}`;
|
|
return browserConfirm(promptMessage);
|
|
}
|
|
|
|
export async function confirmDialog(input: ConfirmDialogInput): Promise<boolean> {
|
|
if (isNative) {
|
|
return showNativeConfirmDialog(input);
|
|
}
|
|
|
|
const desktopResult = await showDesktopConfirmDialog(input);
|
|
if (desktopResult !== null) {
|
|
return desktopResult;
|
|
}
|
|
|
|
return showWebConfirmDialog(input);
|
|
}
|
|
|
|
export const __private__ = {
|
|
blurActiveWebElement,
|
|
buildDesktopAskOptions,
|
|
};
|