дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(plugins): import IntelliJ theme plugins (#1184)
Settings › Plugins (gear menu) gets Import Theme from IntelliJ IDE… (theme plugins of the JetBrains IDEs on this machine, the one each IDE uses first) and Import IntelliJ Theme from File… (a Marketplace .jar / .zip or a .theme.json). The host reads the plugin with size limits; the UI converts it with the IntelliJ mapping (moved from scripts/theme to src/features/plugins/intellijTheme.ts, still used by pnpm theme:import-intellij) into one OpenIDEA theme plugin (engines.openidea ^1.0) with all of its themes, installed through the usual install page, and applies the chosen theme. Theme pickers separate each plugin's themes, and Quick Switch Scheme › Theme previews the theme under the pointer or keyboard after 500 ms and restores the selected one when closed without a choice. Co-authored-by: ldg030201 <[email protected]>
Цей коміт міститься в:
1 джерело
a610982655
коміт
6dec1252db
33 files changed
+2284
-87
No files matched your search
@@ -7,9 +7,9 @@ import { listSchemes } from "@/platform/colorScheme";
|
||||
import { editorPrefs } from "@/platform/editorSettings";
|
||||
import { PRESET_TITLES, useKeymap } from "@/platform/keymap";
|
||||
import { useProject } from "@/platform/project";
|
||||
import type { MenuItem } from "@/ui";
|
||||
import { themeChoices } from "@/platform/themes";
|
||||
import { currentThemeChoice, setTheme } from "./theme";
|
||||
import { showContextMenu, useContextMenuStore, type MenuItem } from "@/ui";
|
||||
import { themeGroups, type ThemeChoiceId } from "@/platform/themes";
|
||||
import { currentThemeChoice, previewTheme, setTheme } from "./theme";
|
||||
|
||||
async function setGlobal(key: string, value: unknown, what: string) {
|
||||
if (!isTauri()) return;
|
||||
@@ -22,15 +22,67 @@ async function setGlobal(key: string, value: unknown, what: string) {
|
||||
|
||||
export const selectKeymap = (id: string) => setGlobal("keymap", id, "keymap");
|
||||
|
||||
export function themeItems(themeId: string = currentThemeChoice()): MenuItem[] {
|
||||
return themeChoices().map<MenuItem>((c) => ({
|
||||
id: `theme.${c.id}`,
|
||||
label: c.label,
|
||||
// Plugin themes keep their own names.
|
||||
verbatim: !!c.origin,
|
||||
checked: c.id === themeId,
|
||||
run: () => void setTheme(c.id),
|
||||
}));
|
||||
/** How long a theme stays under the pointer or keyboard before Quick Switch shows it (IDEA's delay). */
|
||||
export const THEME_PREVIEW_DELAY = 500;
|
||||
|
||||
/**
|
||||
* IDEA's instant theme switch (`ide.instant.theme.switch`): in Quick Switch
|
||||
* the active theme shows after a moment, in this window only; choosing one
|
||||
* selects it, and closing the menu without a choice brings the selected
|
||||
* theme back.
|
||||
*/
|
||||
export interface ThemePreview {
|
||||
preview(id: ThemeChoiceId): void;
|
||||
/** Back to the selected theme (another Quick Switch entry became active). */
|
||||
restore(): void;
|
||||
choose(id: ThemeChoiceId): void;
|
||||
/** The menu closed. */
|
||||
end(): void;
|
||||
}
|
||||
|
||||
export function themePreview(): ThemePreview {
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
let shown: ThemeChoiceId | null = null;
|
||||
let chosen = false;
|
||||
const restore = () => {
|
||||
clearTimeout(timer);
|
||||
if (shown !== null && !chosen) previewTheme(null);
|
||||
shown = null;
|
||||
};
|
||||
return {
|
||||
preview(id) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
shown = id;
|
||||
previewTheme(id);
|
||||
}, THEME_PREVIEW_DELAY);
|
||||
},
|
||||
restore,
|
||||
choose(id) {
|
||||
clearTimeout(timer);
|
||||
chosen = true;
|
||||
// Shown right away; selecting it then changes nothing visible.
|
||||
if (shown !== id) previewTheme(id);
|
||||
void setTheme(id);
|
||||
},
|
||||
end: restore,
|
||||
};
|
||||
}
|
||||
|
||||
/** The built-in themes, then each plugin's, a separator between them (as IDEA's Theme list). */
|
||||
export function themeItems(themeId: string = currentThemeChoice(), preview?: ThemePreview): MenuItem[] {
|
||||
return themeGroups().flatMap<MenuItem>((group, i) => [
|
||||
...(i > 0 ? [{ kind: "separator" as const }] : []),
|
||||
...group.themes.map<MenuItem>((c) => ({
|
||||
id: `theme.${c.id}`,
|
||||
label: c.label,
|
||||
// Plugin themes keep their own names.
|
||||
verbatim: !!c.origin,
|
||||
checked: c.id === themeId,
|
||||
onActive: preview && (() => preview.preview(c.id)),
|
||||
run: () => (preview ? preview.choose(c.id) : void setTheme(c.id)),
|
||||
})),
|
||||
]);
|
||||
}
|
||||
|
||||
export function keymapItems(keymapId: string, customKeymaps: string[]): MenuItem[] {
|
||||
@@ -78,17 +130,32 @@ export function keymapState(): { keymapId: string; customs: string[] } {
|
||||
};
|
||||
}
|
||||
|
||||
/** View › Quick Switch Scheme…: IDEA's popup of the switchable schemes. */
|
||||
export function quickSwitchItems(): MenuItem[] {
|
||||
/** View › Quick Switch Scheme…: IDEA's popup of the switchable schemes, its themes previewed. */
|
||||
export function quickSwitchItems(preview?: ThemePreview): MenuItem[] {
|
||||
const { keymapId, customs } = keymapState();
|
||||
const restore = preview && (() => preview.restore());
|
||||
return [
|
||||
{
|
||||
id: "qs.scheme",
|
||||
label: "Editor Color Scheme",
|
||||
onActive: restore,
|
||||
submenu: colorSchemeItems(useProject.getState().settings?.editor?.colorScheme),
|
||||
},
|
||||
{ id: "qs.keymap", label: "Keymap", submenu: keymapItems(keymapId, customs) },
|
||||
{ id: "qs.viewMode", label: "View Mode", submenu: VIEW_MODE_ITEMS },
|
||||
{ id: "qs.theme", label: "Theme", submenu: themeItems() },
|
||||
{ id: "qs.keymap", label: "Keymap", onActive: restore, submenu: keymapItems(keymapId, customs) },
|
||||
{ id: "qs.viewMode", label: "View Mode", onActive: restore, submenu: VIEW_MODE_ITEMS },
|
||||
{ id: "qs.theme", label: "Theme", submenu: themeItems(undefined, preview) },
|
||||
];
|
||||
}
|
||||
|
||||
/** Opens Quick Switch Scheme; a theme previewed there goes away with the menu unless chosen. */
|
||||
export function showQuickSwitch(at: { x: number; y: number }) {
|
||||
const preview = themePreview();
|
||||
showContextMenu(at, quickSwitchItems(preview));
|
||||
const menu = useContextMenuStore.getState().menu;
|
||||
const unsubscribe = useContextMenuStore.subscribe((s) => {
|
||||
if (s.menu === menu) return;
|
||||
unsubscribe();
|
||||
// A chosen item runs right after the menu closes: let it choose first.
|
||||
queueMicrotask(() => preview.end());
|
||||
});
|
||||
}
|
||||
Reference in new issue
Заблокувати користувача