Files
NetMesh/domain/customKeyBindings.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

134 lines
3.3 KiB
TypeScript

import { CustomKeyBindings } from './models';
const SYNC_VERSION_FIELD = '__netcattySyncVersion';
const SYNC_ORIGIN_FIELD = '__netcattySyncOrigin';
export interface CustomKeyBindingsStorageRecord {
bindings: CustomKeyBindings;
version: number;
origin: string;
}
export const serializeCustomKeyBindings = (bindings: CustomKeyBindings): string =>
JSON.stringify(bindings);
export const areCustomKeyBindingsEqual = (a: CustomKeyBindings, b: CustomKeyBindings): boolean =>
serializeCustomKeyBindings(a) === serializeCustomKeyBindings(b);
export const parseCustomKeyBindingsStorageRecord = (
value: unknown,
): CustomKeyBindingsStorageRecord | null => {
let candidate = value;
if (typeof candidate === 'string') {
try {
candidate = JSON.parse(candidate);
} catch {
return null;
}
}
if (!candidate || typeof candidate !== 'object') {
return null;
}
const record = candidate as Record<string, unknown>;
if (
typeof record.version === 'number' &&
typeof record.origin === 'string' &&
record.bindings &&
typeof record.bindings === 'object'
) {
return {
version: record.version,
origin: record.origin,
bindings: record.bindings as CustomKeyBindings,
};
}
if (
typeof record[SYNC_VERSION_FIELD] === 'number' &&
typeof record[SYNC_ORIGIN_FIELD] === 'string' &&
record.bindings &&
typeof record.bindings === 'object'
) {
return {
version: record[SYNC_VERSION_FIELD] as number,
origin: record[SYNC_ORIGIN_FIELD] as string,
bindings: record.bindings as CustomKeyBindings,
};
}
return {
version: 0,
origin: 'legacy',
bindings: candidate as CustomKeyBindings,
};
};
export const serializeCustomKeyBindingsStorageRecord = (
record: CustomKeyBindingsStorageRecord,
): string =>
JSON.stringify({
[SYNC_VERSION_FIELD]: record.version,
[SYNC_ORIGIN_FIELD]: record.origin,
bindings: record.bindings,
});
export const nextCustomKeyBindingsSyncVersion = (
currentVersion: number,
now: number = Date.now(),
): number => Math.max(now, currentVersion + 1);
export const shouldApplyIncomingCustomKeyBindingsRecord = (
current: Pick<CustomKeyBindingsStorageRecord, 'version' | 'origin'>,
incoming: Pick<CustomKeyBindingsStorageRecord, 'version' | 'origin'>,
): boolean => {
if (incoming.version !== current.version) {
return incoming.version > current.version;
}
return incoming.origin > current.origin;
};
export const updateCustomKeyBinding = (
bindings: CustomKeyBindings,
bindingId: string,
scheme: 'mac' | 'pc',
newKey: string,
): CustomKeyBindings => ({
...bindings,
[bindingId]: {
...bindings[bindingId],
[scheme]: newKey,
},
});
export const resetCustomKeyBinding = (
bindings: CustomKeyBindings,
bindingId: string,
scheme?: 'mac' | 'pc',
): CustomKeyBindings => {
if (!scheme) {
const { [bindingId]: _removed, ...rest } = bindings;
return rest;
}
const existing = bindings[bindingId];
if (!existing) {
return bindings;
}
const nextBinding = { ...existing };
delete nextBinding[scheme];
if (Object.keys(nextBinding).length === 0) {
const { [bindingId]: _removed, ...rest } = bindings;
return rest;
}
return {
...bindings,
[bindingId]: nextBinding,
};
};