refactor(ui): trim unused control UI helpers (#101632)

This commit is contained in:
Vincent Koc
2026-07-07 04:55:28 -07:00
committed by GitHub
parent 4d5cd05a64
commit 2ba622ca30
6 changed files with 12 additions and 58 deletions

View File

@@ -4,7 +4,7 @@ import {
navigateChatInputHistory,
type ChatInputHistoryState,
} from "../pages/chat/input-history.ts";
import { createNativeChatDrafts, isWebView2, sendToNative } from "./native-bridge.ts";
import { createNativeChatDrafts } from "./native-bridge.ts";
type FakeBridge = {
postMessage: ReturnType<typeof vi.fn>;
@@ -46,14 +46,6 @@ afterEach(() => {
});
describe("native chat drafts", () => {
it("detects WebView2 and sends native messages", () => {
expect(isWebView2()).toBe(false);
const bridge = makeBridge();
expect(isWebView2()).toBe(true);
sendToNative({ type: "ready" });
expect(bridge.posted).toEqual([{ type: "ready" }]);
});
it("registers the listener before the ready handshake", () => {
const callOrder: string[] = [];
vi.stubGlobal("chrome", {

View File

@@ -5,10 +5,6 @@ type WebView2Bridge = {
removeEventListener(type: "message", listener: (event: MessageEvent) => void): void;
};
type NativeBridgeMessage =
| { type: "draft-text"; payload: { text: string } }
| { type: "ready"; payload?: Record<string, unknown> };
export type NativeChatDrafts = {
subscribe: (listener: (draft: string) => void) => () => void;
dispose: () => void;
@@ -19,12 +15,9 @@ function getWebview(): WebView2Bridge | undefined {
return webview;
}
export function isWebView2(): boolean {
return getWebview() !== undefined;
}
export function sendToNative(msg: NativeBridgeMessage): void {
getWebview()?.postMessage(msg);
// Keep WebView2 messaging distinct from the DOM Window.postMessage contract.
function sendToNative(message: unknown): void {
getWebview()?.postMessage(message);
}
function readNativeDraft(raw: unknown): string | null {

View File

@@ -6,7 +6,6 @@ import {
loadGatewaySessionSelection,
loadLocalUserIdentity,
loadSettings,
saveLocalUserIdentity,
saveSettings,
type UiSettings,
} from "./settings.ts";
@@ -837,14 +836,16 @@ describe("loadSettings default gateway URL derivation", () => {
});
});
it("persists local user identity separately from gateway settings", () => {
it("loads local user identity separately from gateway settings", () => {
setTestLocation({
protocol: "https:",
host: "gateway.example:8443",
pathname: "/",
});
saveLocalUserIdentity({ name: "Buns", avatar: "🦞" });
localStorage.setItem(
"openclaw.control.user.v1",
JSON.stringify({ name: "Buns", avatar: "🦞" }),
);
expect(loadLocalUserIdentity()).toEqual({
name: "Buns",
@@ -870,15 +871,4 @@ describe("loadSettings default gateway URL derivation", () => {
avatar: null,
});
});
it("removes the persisted local user identity when cleared", () => {
saveLocalUserIdentity({ name: "Buns", avatar: "data:image/png;base64,AAA" });
saveLocalUserIdentity({ name: null, avatar: null });
expect(loadLocalUserIdentity()).toEqual({
name: null,
avatar: null,
});
expect(localStorage.getItem("openclaw.control.user.v1")).toBeNull();
});
});

View File

@@ -45,11 +45,7 @@ import { normalizeChatSplitLayout, type ChatSplitLayout } from "../pages/chat/sp
import { parseImportedCustomTheme, type ImportedCustomTheme } from "./custom-theme.ts";
import { normalizeGatewayTokenScope } from "./gateway-scope.ts";
import { parseThemeSelection, type ThemeMode, type ThemeName } from "./theme.ts";
import {
hasLocalUserIdentity,
normalizeLocalUserIdentity,
type LocalUserIdentity,
} from "./user-identity.ts";
import { normalizeLocalUserIdentity, type LocalUserIdentity } from "./user-identity.ts";
export const BORDER_RADIUS_STOPS = [0, 25, 50, 75, 100] as const;
export type BorderRadiusStop = (typeof BORDER_RADIUS_STOPS)[number];
@@ -129,8 +125,6 @@ export type UiSettings = {
locale?: string;
};
export type { LocalUserIdentity } from "./user-identity.ts";
type LastActiveSessionHost = {
settings: UiSettings;
applySettings(next: UiSettings): void;
@@ -668,21 +662,6 @@ export function loadLocalUserIdentity(): LocalUserIdentity {
}
}
export function saveLocalUserIdentity(next: LocalUserIdentity) {
const storage = getSafeLocalStorage();
const normalized = normalizeLocalUserIdentity(next);
try {
if (!hasLocalUserIdentity(normalized)) {
storage?.removeItem(LOCAL_USER_IDENTITY_KEY);
return;
}
storage?.setItem(LOCAL_USER_IDENTITY_KEY, JSON.stringify(normalized));
} catch {
// best-effort — quota exceeded or security restrictions should not
// prevent in-memory identity updates from being applied
}
}
function persistSettings(next: UiSettings, options: { selectGateway?: boolean } = {}) {
persistSessionToken(next.gatewayUrl, next.token);
const storage = getSafeLocalStorage();

View File

@@ -1,3 +1,4 @@
// Private MIME keeps stray text and file drags from becoming session actions.
export const SESSION_DRAG_MIME = "application/x-openclaw-session-key";
export function writeSessionDragData(dataTransfer: DataTransfer, sessionKey: string): void {

View File

@@ -24,6 +24,7 @@ import { formatSessionTokens } from "../../lib/presenter.ts";
import { formatGoalDetail, formatGoalSummary } from "../../lib/session-goal.ts";
import { sessionModelMatchesDefaults } from "../../lib/session-model-defaults.ts";
import { isSessionRunActive } from "../../lib/session-run-state.ts";
import { SESSION_DRAG_MIME } from "../../lib/sessions/drag.ts";
import {
groupSessionRows,
SESSION_GROUP_MODES,
@@ -484,8 +485,6 @@ function sessionDetailItems(params: {
}
const NEW_GROUP_OPTION = "__new-group__";
// Private MIME so stray text/file drags never become sessions.patch calls.
const SESSION_DRAG_MIME = "application/x-openclaw-session-key";
function sessionsTableColumnCount(props: SessionsProps): number {
return props.groupBy === "category" ? 9 : 8;