дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
Project & files - Project view modes (Project Files / Open Files / All Changed Files / Scratches); External Libraries for Python, JDK (src.zip), Node, Cargo, Go, Maven/Gradle jars; read-only jar/zip browsing - ⌘N New popup with type search and more file kinds; New Project, Rename Project, Reload All from Disk, Export/Import Settings, Power Save Mode - File type associations, extra content roots and exclude patterns (indexed and watched without reopening the project) Editor & navigation - Find bar: search scope (comments/strings), Preserve Case, Exclude, multiline, history; Find in Files: Module scope, custom pattern scopes, multiline - Search Everywhere filters, Assign Shortcut, settings results; named bookmark lists, file/folder bookmarks; Structure filters and Show Inherited; Recent Locations timestamps and breadcrumbs; Code Vision author - Completion options, editor tab placement/layout, inline completion (LSP 3.18) - Spell checking (Typo inspection, ide-spell) and Inspections settings with custom profiles; Code Style schemes, formatter markers, Do not format Run, VCS, services, database - Typed run configurations (Shell, Program, npm, Gradle, Maven, Docker, Compound), Modify options, Before launch, env dialog, Current File, Emulate terminal (PTY) - Git log graph/view options, Go to Hash/Branch/Tag, date filter keeps the graph; Pull/Merge/Rebase dialogs, Manage Remotes, Worktrees - Generic Services host (Docker connections/registries, run sessions); TODO scope/changes tabs with changelists; Coverage report import - Data sources: wire-compatible vendors, URL import, SSL certs, Options, Schemas and Advanced tabs, color and comment Workbench - Run Anything, Customize Main Toolbar, named tool window layouts, menu completeness, Code Cleanup, macros, "Don't Show Again", editor banners - Chinese translations for the new UI Claude-Session: https://claude.ai/code/session_01SaPPsVPuk6ZTNsoUCNCbMv
101 рядки
4.4 KiB
TypeScript
101 рядки
4.4 KiB
TypeScript
/**
|
|
* Customize Main Toolbar: which widgets (project, VCS, run…) and actions the
|
|
* title bar shows on each side, in which order. Stored in
|
|
* `appearance.mainToolbar` (global settings); unset = the default toolbar.
|
|
*/
|
|
import type { MainToolbarSettings } from "@/bindings";
|
|
import { getAction } from "@/platform/actions";
|
|
import { call, commands, isTauri } from "@/platform/ipc";
|
|
import { useProject } from "@/platform/project";
|
|
import type { TitleItemContribution } from "./contributions";
|
|
|
|
export const PROJECT_WIDGET = "project";
|
|
/** Shown as "Version Control ▾" while the project has no repository. */
|
|
export const VCS_WIDGET = "vcs.branch";
|
|
export const ACTION_PREFIX = "action:";
|
|
export const SEARCH_ENTRY = `${ACTION_PREFIX}navigate.searchEverywhere`;
|
|
|
|
export interface ToolbarLayout {
|
|
left: string[];
|
|
right: string[];
|
|
hidden: string[];
|
|
}
|
|
|
|
export const isActionEntry = (id: string) => id.startsWith(ACTION_PREFIX);
|
|
export const entryAction = (id: string) => id.slice(ACTION_PREFIX.length);
|
|
|
|
const byPriority = (a: TitleItemContribution, b: TitleItemContribution) => a.priority - b.priority || a.id.localeCompare(b.id);
|
|
|
|
/** Widgets in their default place (built-ins included), by side. */
|
|
function defaultWidgets(items: Iterable<TitleItemContribution>): { left: string[]; right: string[] } {
|
|
const all = [...items];
|
|
const left = all.filter((i) => i.align === "left").sort(byPriority).map((i) => i.id);
|
|
const right = all.filter((i) => i.align === "right").sort(byPriority).map((i) => i.id);
|
|
return { left: [PROJECT_WIDGET, ...(left.includes(VCS_WIDGET) ? [] : [VCS_WIDGET]), ...left], right };
|
|
}
|
|
|
|
export function defaultToolbar(items: Iterable<TitleItemContribution>): ToolbarLayout {
|
|
const { left, right } = defaultWidgets(items);
|
|
return { left, right: [...right, SEARCH_ENTRY], hidden: [] };
|
|
}
|
|
|
|
/**
|
|
* The entries to show per side: the saved order, plus widgets registered since
|
|
* (not listed, not removed) at their default side's end.
|
|
*/
|
|
export function resolveToolbar(
|
|
saved: MainToolbarSettings | null | undefined,
|
|
items: Iterable<TitleItemContribution>,
|
|
): { left: string[]; right: string[] } {
|
|
const list = [...items];
|
|
if (!saved) {
|
|
const d = defaultToolbar(list);
|
|
return { left: d.left, right: d.right };
|
|
}
|
|
const left = [...(saved.left ?? [])];
|
|
const right = [...(saved.right ?? [])];
|
|
const known = new Set([...left, ...right, ...(saved.hidden ?? [])]);
|
|
const d = defaultWidgets(list);
|
|
for (const id of d.left) if (!known.has(id)) left.push(id);
|
|
for (const id of d.right) if (!known.has(id)) right.push(id);
|
|
return { left, right };
|
|
}
|
|
|
|
/** The full editable layout (Customize Main Toolbar dialog). */
|
|
export function editableToolbar(saved: MainToolbarSettings | null | undefined, items: Iterable<TitleItemContribution>): ToolbarLayout {
|
|
const list = [...items];
|
|
const { left, right } = resolveToolbar(saved, list);
|
|
return { left, right, hidden: saved ? [...(saved.hidden ?? [])] : [] };
|
|
}
|
|
|
|
export function widgetTitle(id: string, items: ReadonlyMap<string, TitleItemContribution>): string {
|
|
if (id === PROJECT_WIDGET) return "Project Widget";
|
|
if (id === VCS_WIDGET && !items.has(id)) return "VCS Widget";
|
|
if (isActionEntry(id)) return getAction(entryAction(id))?.title ?? entryAction(id);
|
|
return items.get(id)?.title ?? id;
|
|
}
|
|
|
|
/** Shows or removes a widget, keeping the rest of the layout. */
|
|
export function toggleWidget(layout: ToolbarLayout, id: string, defaultSide: "left" | "right"): ToolbarLayout {
|
|
const shown = layout.left.includes(id) || layout.right.includes(id);
|
|
if (shown)
|
|
return {
|
|
left: layout.left.filter((x) => x !== id),
|
|
right: layout.right.filter((x) => x !== id),
|
|
hidden: [...layout.hidden.filter((x) => x !== id), ...(isActionEntry(id) ? [] : [id])],
|
|
};
|
|
const side = defaultSide === "left" ? { left: [...layout.left, id], right: layout.right } : { left: layout.left, right: [...layout.right, id] };
|
|
return { ...side, hidden: layout.hidden.filter((x) => x !== id) };
|
|
}
|
|
|
|
export function useMainToolbarSettings(): MainToolbarSettings | null | undefined {
|
|
return useProject((s) => s.settings?.appearance?.mainToolbar);
|
|
}
|
|
|
|
/** Saves `layout`; `null` restores the default toolbar. */
|
|
export async function saveToolbar(layout: ToolbarLayout | null): Promise<void> {
|
|
if (!isTauri()) return;
|
|
const settings = await call(commands.settingsSet("global", "appearance.mainToolbar", JSON.stringify(layout)));
|
|
useProject.setState({ settings });
|
|
}
|