Files
openchamber/packages/ui/src/lib/utils.ts
T
00821700de chore: remove dead code (59 unused files + ~125 unused exports) (#1835)
* chore: remove dead/unreferenced files across ui, vscode

Remove 59 unused source files (components, hooks, lib utils, stores,
barrels, and orphaned vscode github modules) that are not imported by
any entry-reachable code. Also drop a stale test mock for the removed
execCommands module.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor: remove unused exported symbols (types, functions, consts, hooks)

Remove exported symbols whose identifier is referenced nowhere in the
repository (verified via repo-wide search), across ui types/contracts,
lib utilities, sync layer, stores, and components. Also drop the few
imports/private helpers orphaned by these removals.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* refactor: remove more unused exports (desktop, shortcuts, worktree, vscode)

Continue removing repo-wide unreferenced exported functions, consts and
types across lib/desktop, shortcuts, worktreeSessionCreator, sync, and
vscode gitService, with cascading orphaned helpers/imports cleaned up.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* chore: add dead-code cleanup tooling

* refactor: checkpoint dead-code cleanup

* refactor: remove dead-code suppressions

---------

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-26 19:27:53 +03:00

152 lines
4.2 KiB
TypeScript

import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
import { isDesktopShell } from "@/lib/desktop";
import { matchesFuzzyQuery } from "@/lib/search/fuzzySearch";
import type { I18nKey } from "@/lib/i18n";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
/**
* Detects if the current platform is macOS.
* Uses navigator.userAgent in browser environments.
*/
export const isMacOS = (): boolean => {
if (typeof navigator === 'undefined') return false;
return /Macintosh|Mac OS X/.test(navigator.userAgent || '');
};
const isWindows = (): boolean => {
if (typeof navigator === 'undefined') return false;
return /Windows/.test(navigator.userAgent || '');
};
export const getRevealLabelKey = (): I18nKey => {
if (isMacOS()) return 'common.revealPath.finder';
if (isWindows()) return 'common.revealPath.fileExplorer';
return 'common.revealPath.fileManager';
};
/**
* Checks if the platform-appropriate modifier key is pressed.
* On macOS desktop app: Cmd (metaKey), on other platforms or web: Ctrl (ctrlKey).
* Browser intercepts Cmd shortcuts, so we only use Cmd in the desktop app.
*/
export const hasModifier = (e: KeyboardEvent | React.KeyboardEvent): boolean => {
return isMacOS() && isDesktopShell() ? e.metaKey : e.ctrlKey;
};
/**
* Returns the platform-appropriate modifier key label.
* On macOS desktop app: "⌘", on other platforms or web: "Ctrl"
* Browser intercepts Cmd shortcuts, so we only show Cmd in the desktop app.
*/
export const getModifierLabel = (): string => {
return isMacOS() && isDesktopShell() ? '⌘' : 'Ctrl';
};
export const truncatePathMiddle = (
value: string,
options?: { maxLength?: number }
): string => {
const source = value ?? "";
const maxLength = Math.max(16, options?.maxLength ?? 45);
if (source.length <= maxLength) {
return source;
}
const segments = source.split('/');
if (segments.length <= 1) {
return source;
}
const fileName = segments.pop() ?? '';
if (!fileName) {
return source;
}
const prefixBudget = Math.max(0, maxLength - (fileName.length + 2));
if (prefixBudget <= 0) {
return `…/${fileName}`;
}
let prefix = '';
for (const segment of segments) {
if (!segment) {
continue;
}
const candidate = prefix ? `${prefix}/${segment}` : segment;
if (candidate.length > prefixBudget) {
break;
}
prefix = candidate;
}
if (!prefix) {
const first = segments[0] ?? '';
prefix = first ? first.slice(0, prefixBudget) : '';
}
return prefix ? `${prefix}…/${fileName}` : `…/${fileName}`;
};
const normalizePath = (value: string) => {
if (!value) return "";
if (value === "/") return "/";
return value.replace(/\/+$/, "");
};
export function formatPathForDisplay(path: string | null | undefined, homeDirectory?: string | null): string {
if (!path) {
return "";
}
const normalizedPath = normalizePath(path);
if (normalizedPath === "/") {
return "/";
}
const normalizedHome = homeDirectory ? normalizePath(homeDirectory) : undefined;
if (normalizedHome && normalizedHome !== "/") {
if (normalizedPath === normalizedHome) {
return "~";
}
if (normalizedPath.startsWith(`${normalizedHome}/`)) {
const relative = normalizedPath.slice(normalizedHome.length + 1);
return relative ? `~/${relative}` : "~";
}
}
return normalizedPath;
}
export function formatDirectoryName(path: string | null | undefined, homeDirectory?: string | null): string {
if (!path) {
return "/";
}
const normalizedPath = normalizePath(path);
if (!normalizedPath || normalizedPath === "/") {
return "/";
}
const normalizedHome = homeDirectory ? normalizePath(homeDirectory) : undefined;
if (normalizedHome && normalizedHome !== "/" && normalizedPath === normalizedHome) {
return "~";
}
const segments = normalizedPath.split("/");
const name = segments.pop() || normalizedPath;
return name || "/";
}
/**
* Fuzzy search using Fuse.js with typo tolerance.
* Returns true if query fuzzy-matches target (e.g. "coude" matches "claude")
*/
export function fuzzyMatch(target: string, query: string): boolean {
return matchesFuzzyQuery(target, query);
}