defluff (frontend + backend): strip em-dashes + shorten docstrings + drop dead UI files (cosmetic only, no schedule code)

This commit is contained in:
ciregenz
2026-05-20 05:36:17 -07:00
parent 5b0c6e1df3
commit f59bf0db9b
118 changed files with 853 additions and 4202 deletions
@@ -1,17 +1,6 @@
import React, { createContext, useContext } from 'react';
/**
* React context that signals whether the Dashboard is currently the active
* route (i.e. visible to the user) vs hidden in the background.
*
* Defaults to `true` so any standalone usage of dashboard children outside
* the DashboardHost wrapper just behaves normally.
*
* Heavy/expensive Dashboard children read this via `useDashboardActive()`
* and short-circuit their work when the dashboard is hidden — that's how
* we keep CPU usage near-zero while the user is on /actions or /settings
* with the Dashboard mounted but invisible.
*/
/** True when Dashboard is the visible route; heavy children short-circuit when false. */
const DashboardActiveContext = createContext<boolean>(true);
export const DashboardActiveProvider = DashboardActiveContext.Provider;
+5 -25
View File
@@ -6,30 +6,17 @@ import { fetchTools } from '@/shared/state/toolsSlice';
import { API_BASE } from '@/shared/config';
import { report } from '@/shared/serviceClient';
// Listens for openswarm://auth?token=...&plan=...&expires=... URLs coming
// from the Electron main process via window.openswarm.onAuthUrl. Parses the
// payload and dispatches activateSubscription so the backend validates and
// persists the bearer.
//
// Safe no-op in web/browser contexts where window.openswarm isn't defined.
/** Subscribe to openswarm:// auth/oauth deep-links from Electron main; no-op in browser. */
export function useDeepLink(): void {
const dispatch = useAppDispatch();
useEffect(() => {
const api = (window as any).openswarm as OpenSwarmAPI | undefined;
// Both listeners are optional — useDeepLink no-ops in browser/web context
// where window.openswarm is undefined.
if (!api) return;
const unsubscribe = api.onAuthUrl?.((rawUrl: string) => {
try {
// openswarm://auth?token=... (host = "auth", search carries fields).
// Two flavors land here, distinguished by the `signin` flag:
// - signin=true → free-tier sign-in (Google OAuth / magic link)
// - (default) → Stripe checkout subscription activation
// Note: the bearer-handoff page in lib/authMint.ts (cloud) POSTs
// directly to localhost so this deep-link path is currently a
// backstop for older flows. Both branches here remain wired up.
// openswarm://auth?token=... ; signin=true => free sign-in, else Stripe activation.
const url = new URL(rawUrl);
if (url.host !== 'auth' && url.pathname !== '//auth' && url.pathname !== '/auth') {
console.warn('[deep-link] Unknown openswarm:// host:', url.host);
@@ -47,9 +34,7 @@ export function useDeepLink(): void {
const expires = url.searchParams.get('expires');
if (isSignin) {
// v1.0.29 only supports Google sign-in. signinMethodRaw is read
// for forward compatibility / analytics if other methods are
// added later.
// 1.0.29 only ships Google sign-in; read for forward compat.
void signinMethodRaw;
report('signin', 'deep_link_received', { method: 'google' });
@@ -82,8 +67,7 @@ export function useDeepLink(): void {
.unwrap()
.then((res) => {
report('subscription', 'activated', { plan: res.plan });
// Re-fetch the model list so the Claude models (via OpenSwarm
// Pro proxy) show up in the chat picker right away.
// Refresh models so Pro-proxy Claude models appear in the picker immediately.
dispatch(fetchModels());
})
.catch((err) => {
@@ -97,15 +81,12 @@ export function useDeepLink(): void {
}
});
// OAuth claim deep-link listener. The Electron main process routes
// openswarm://oauth/{provider}/complete to its own IPC channel so we
// can claim tokens immediately rather than routing through Settings.
let unsubscribeOauth: (() => void) | undefined;
if (api?.onOauthClaim) {
unsubscribeOauth = api.onOauthClaim(async (rawUrl: string) => {
try {
// openswarm://oauth/{provider}/complete?session_id=...&tool_id=...
const url = new URL(rawUrl);
// Expected: openswarm://oauth/{provider}/complete?session_id=...&tool_id=...
if (url.host !== 'oauth' || !url.pathname.endsWith('/complete')) {
console.warn('[deep-link] Unexpected oauth-claim URL:', rawUrl);
return;
@@ -131,7 +112,6 @@ export function useDeepLink(): void {
return;
}
report('oauth', 'claim_succeeded');
// Refresh tools so the UI reflects the newly-connected tool.
dispatch(fetchTools());
} catch (e) {
console.error('[deep-link] OAuth claim threw:', e);
@@ -1,10 +1,4 @@
// Mounts a single global listener that records each user interaction
// timestamp into Redux. One installer per app — call from Main.tsx after
// the store is provided.
//
// Debounces at 1-second granularity so we don't spam Redux on every
// keystroke. Coarse enough for "idle dim after N minutes" UX; fine enough
// that the timestamp on session close is accurate to the second.
// Records user-interaction timestamps into Redux, 1s-debounced. Mount once from Main.tsx.
import { useEffect } from 'react';
import { useAppDispatch } from '@/shared/hooks';
@@ -4,23 +4,7 @@ import { useLocation } from 'react-router-dom';
const STORAGE_KEY = 'openswarm_last_dashboard_id';
const WINDOW_KEY = '__openswarm_last_dashboard_id';
/**
* Tracks the last visited dashboard id in a "sticky" way: once a dashboard
* has been visited, the id stays set even when the user navigates to other
* routes. This is the foundation for keeping the Dashboard component mounted
* across non-dashboard route navigation (hide-don't-unmount pattern).
*
* The Dashboard component reads its dashboardId from this hook (via a prop
* passed by AppShell) instead of from `useParams()`, so the id never goes
* undefined when the URL changes to /actions etc. This prevents the
* dashboardId useEffect from re-firing on every incidental route change,
* which would cause `resetLayout` + `fetchLayout` and visibly reload the
* browser cards.
*
* Returns a tuple of `[lastDashboardId, setLastDashboardId]`. The setter
* is exposed so explicit dashboard close/delete handlers can clear it
* (which causes the Dashboard to fully unmount and tear down its webviews).
*/
/** Sticky last-visited dashboard id so Dashboard stays mounted across non-dashboard nav. */
export function useLastDashboardId(): [string | null, (id: string | null) => void] {
const location = useLocation();
const [lastId, setLastIdState] = useState<string | null>(() => {
@@ -31,8 +15,7 @@ export function useLastDashboardId(): [string | null, (id: string | null) => voi
}
});
// Watch the URL — when it matches /dashboard/:id, update the sticky id.
// Critically: do NOT clear the sticky id when the URL stops matching.
// Watch URL; update sticky id on /dashboard/:id. Do NOT clear when URL stops matching.
useEffect(() => {
const match = location.pathname.match(/^\/dashboard\/([^/]+)/);
if (match && match[1] && match[1] !== lastId) {
+2 -21
View File
@@ -5,7 +5,6 @@ const QUERY = '(prefers-reduced-motion: reduce)';
function subscribe(callback: () => void): () => void {
if (typeof window === 'undefined' || !window.matchMedia) return () => {};
const mql = window.matchMedia(QUERY);
// Modern + legacy event names both supported.
mql.addEventListener('change', callback);
return () => mql.removeEventListener('change', callback);
}
@@ -19,30 +18,12 @@ function getServerSnapshot(): boolean {
return false;
}
/**
* True when the OS-level "Reduce motion" preference is on.
* Mac: System Settings → Accessibility → Display → Reduce Motion.
* Windows: Settings → Ease of Access → Display → Show animations.
*
* Reactive — flips immediately if the user toggles the OS setting
* mid-session (rare but supported).
*/
/** True when the OS "Reduce motion" preference is on; reactive to OS toggles. */
export function useReducedMotion(): boolean {
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
}
/**
* Convenience: returns 0 when reduced-motion is on, otherwise the supplied
* duration. Use inline at animation sites:
*
* const dur = useMotionDuration(DURATION_MS.quick);
* <Fade timeout={dur}>...</Fade>
*
* For animations that convey causality (modal open, drawer slide), prefer a
* tiny non-zero floor so the user still perceives the transition:
*
* const dur = useMotionDuration(DURATION_MS.standard, { floor: 40 });
*/
/** Returns 0 (or `opts.floor`) when reduced-motion is on, else `ms`. */
export function useMotionDuration(ms: number, opts: { floor?: number } = {}): number {
const reduced = useReducedMotion();
if (!reduced) return ms;
+2 -13
View File
@@ -1,12 +1,4 @@
// Route-change tracker.
//
// Reports a `nav.route_changed` event on every React Router location
// change so the cloud can aggregate visits per route. Reuses the
// existing report() surface — no new outbound paths added. The desktop
// just sends the path; the cloud counts.
//
// Mount inside a Router (must be a child of HashRouter / BrowserRouter)
// so useLocation() resolves.
// Reports nav.route_changed on each React Router location change. Mount inside a Router.
import { useEffect, useRef } from 'react';
import { useLocation } from 'react-router-dom';
@@ -14,8 +6,7 @@ import { report } from '@/shared/serviceClient';
export function useRouteTracker(): void {
const location = useLocation();
// Skip the very first render the App opens at "/" and we don't want
// to report a phantom navigation that didn't happen.
// Skip first render so the App's "/" open doesn't fire a phantom nav.
const skippedFirst = useRef(false);
const lastPath = useRef<string>('');
@@ -28,8 +19,6 @@ export function useRouteTracker(): void {
}
if (path === lastPath.current) return;
lastPath.current = path;
// The path is a route name (e.g. /dashboard, /settings) — never the
// full URL. No query strings, no hash fragments beyond the route id.
report('nav', 'route_changed', { path });
}, [location.hash, location.pathname]);
}
@@ -1,19 +1,4 @@
// Single source of truth for "what URL should the preview webview point at?"
//
// New-mode webapp_template workspaces have no root index.html — the live
// preview lives behind the workspace's own Vite dev server, whose port is
// announced by the backend's runtime:status WS frame. Old-mode flat
// workspaces still serve files through the legacy /api/outputs/.../serve/
// endpoints. This hook hides the difference: it attaches to the runtime
// (ref-counted server-side, so multiple subscribers share one process),
// listens for status, and exposes the live frontend_url + new-mode flag.
// Consumers compute their final URL with `pickPreviewUrl()` below.
//
// Used by both ViewEditor (editor tab) and DashboardViewCard (dashboard
// canvas). Earlier each component had its own copy of this effect and
// only the editor had the new-mode logic — that's why dashboard cards
// for webapp_template apps were rendering the literal "File not found
// in output" JSON. One hook now, both consumers stay in sync.
// Hides legacy /serve/ vs new-mode Vite-runtime split for preview URLs; ref-counted spawn.
import { useEffect, useRef, useState } from 'react';
import { API_BASE, getAuthToken } from '@/shared/config';
@@ -27,25 +12,14 @@ export interface RuntimeLogLine {
export interface RuntimePreviewState {
frontendUrl: string | null;
isNewMode: boolean;
// True for the first ~400ms after subscribing — gives the runtime WS a
// chance to send its initial runtime:status frame before consumers
// decide to render a "Starting preview…" placeholder. Without this
// gate, dashboard cards flashed the placeholder every remount even
// when Vite was already up, because frontendUrl resets to null on
// mount and arrives one tick later.
// True until the runtime:status frame lands; prevents placeholder flash on remount when Vite is up.
isHydrating: boolean;
}
export interface RuntimePreviewOptions {
// Workspace to attach to. null/undefined → no-op (no spawn, no WS).
workspaceId: string | null | undefined;
// Gate the spawn. Lets callers defer paying the runtime cost until
// the user actually wants the preview (ViewEditor only spawns once
// the user clicks Preview or Terminal). Dashboard cards default to
// true since the preview pane is always visible.
/** Gate the spawn so callers can defer paying runtime cost until preview is wanted. */
enabled?: boolean;
// Optional sink for log lines. Editor's terminal panel uses this;
// dashboard cards don't need it and can omit.
onLog?: (line: RuntimeLogLine) => void;
}
@@ -54,9 +28,7 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
const [frontendUrl, setFrontendUrl] = useState<string | null>(null);
const [isNewMode, setIsNewMode] = useState(false);
const [isHydrating, setIsHydrating] = useState(true);
// Pin the latest onLog so we don't tear down + respawn the runtime
// every time the callback identity changes. The effect only depends
// on workspaceId + enabled.
// Pin latest onLog so callback identity changes don't tear down/respawn the runtime.
const onLogRef = useRef(onLog);
onLogRef.current = onLog;
@@ -70,12 +42,7 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
setFrontendUrl(null);
setIsNewMode(false);
setIsHydrating(true);
// Drop the hydrating flag after the WS has had time to deliver its
// initial runtime:status frame. With the backend's 80ms poll
// interval, status almost always arrives in 20-100ms; 150ms is
// generous enough that warm starts never flash the booting
// placeholder, while not making genuinely-cold runtimes wait an
// extra half second before showing "Starting preview…".
// 150ms: warm starts deliver status in 20-100ms; long enough to skip placeholder flash, short enough to not stall cold starts.
const hydrationTimer = setTimeout(() => {
if (!cancelled) setIsHydrating(false);
}, 150);
@@ -91,7 +58,7 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
headers,
});
} catch (_) {
// Spawn errors surface via the log WS. Don't double-report.
// Spawn errors surface via the log WS; don't double-report.
}
if (cancelled) return;
try {
@@ -105,7 +72,6 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
const fu = msg.data?.frontend_url ?? null;
setFrontendUrl(fu || null);
setIsNewMode(!!msg.data?.is_new_mode);
// Status arrived; hand off to the real ready/booting gate.
setIsHydrating(false);
} else if (msg.event === 'runtime:log') {
const stream = msg.data?.stream || 'stdout';
@@ -118,8 +84,7 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
}
};
} catch (_) {
// WS construction failed (CSP, bad URL, etc). Caller stays in
// its "no preview yet" state — same shape as a slow Vite cold start.
// WS construction failed; caller stays in "no preview yet" state.
}
})();
@@ -130,9 +95,7 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
setFrontendUrl(null);
setIsNewMode(false);
setIsHydrating(true);
// detach is ref-counted on the backend — only the last subscriber
// actually tears down the runtime, the rest are no-ops. We fire
// and forget; errors here would be transient and don't affect UX.
// detach is ref-counted on the backend; fire-and-forget.
fetch(`${API_BASE}/outputs/workspace/${workspaceId}/runtime/stop`, {
method: 'POST',
headers,
@@ -145,40 +108,25 @@ export function useRuntimePreviewUrl(opts: RuntimePreviewOptions): RuntimePrevie
export interface PickPreviewUrlOptions {
workspaceId: string | null | undefined;
// Legacy fallback URL for old-mode flat workspaces. Pass the URL the
// component used BEFORE the new-mode split (ViewEditor uses
// `${SERVE_BASE}/workspace/${ws}/serve/index.html`, dashboard cards
// use `${SERVE_BASE}/${output_id}/serve/index.html`). When the runtime
// says we're in new-mode AND Vite is up, we override with frontendUrl.
/** Pre-new-mode URL the component used (serve/index.html); overridden by frontendUrl when ready. */
legacyUrl: string | undefined;
frontendUrl: string | null;
isNewMode: boolean;
}
export interface PickPreviewUrlResult {
// Final URL the preview should load. `undefined` means "show placeholder
// instead" — happens when the workspace is new-mode but Vite hasn't
// bound yet (cold start, npm install in progress, runtime crashed).
/** undefined => render placeholder (new-mode and Vite not bound yet). */
url: string | undefined;
// True iff we're in new-mode and frontendUrl hasn't arrived. UI uses
// this to render a "Starting preview…" affordance instead of letting
// the webview attempt the legacy URL (which 404s in new-mode).
isBooting: boolean;
}
export function pickPreviewUrl(opts: PickPreviewUrlOptions): PickPreviewUrlResult {
const { legacyUrl, frontendUrl, isNewMode, workspaceId } = opts;
if (!workspaceId) {
// No workspace id at all (output never seeded one). Use whatever
// legacy URL the caller computed — typical for old flat outputs
// that were created before workspace_id became standard.
return { url: legacyUrl, isBooting: false };
}
if (isNewMode && !frontendUrl) {
return { url: undefined, isBooting: true };
}
// Prefer frontendUrl when present (works for both new-mode that's up
// AND any future caller that gives us a Vite URL). Fall back to the
// legacy serve URL for old-mode workspaces.
return { url: frontendUrl ?? legacyUrl, isBooting: false };
}
+1 -12
View File
@@ -1,15 +1,4 @@
// Window blur/focus tracking — analytics signal for "user switched to
// another app" (temp-churn measurement).
//
// Wires the IPC channel that electron/main.js fires on the BrowserWindow's
// blur/focus events into the existing `report()` analytics pipeline. Each
// blur emits `app focus_lost` with the elapsed-ms-since-last-focus, and
// each focus emits `app focus_gained` with elapsed-ms-since-last-blur.
//
// Together these answer: how often do users leave OpenSwarm mid-session,
// for how long, and at what cadence?
//
// No-op in browser/web context where window.openswarm is undefined.
// Reports app focus_lost/focus_gained from Electron blur/focus IPC; no-op in browser.
import { useEffect } from 'react';
import { report } from '@/shared/serviceClient';