mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-13 04:34:21 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1d2863543 | ||
|
|
4a1fec369f |
No files matched your search
@@ -578,6 +578,8 @@ pub struct AppearanceSettings {
|
||||
pub main_menu_style: String,
|
||||
/// A lone Alt press focuses or opens the main menu (IDEA `ide.windows.main.menu.focus.on.alt`).
|
||||
pub main_menu_alt: bool,
|
||||
/// Always show the main menu titles instead of the hamburger button (#1521).
|
||||
pub always_show_main_menu: bool,
|
||||
/// `subpixel` | `greyscale` | `none`
|
||||
pub ide_antialiasing: String,
|
||||
pub editor_antialiasing: String,
|
||||
@@ -655,6 +657,7 @@ impl Default for AppearanceSettings {
|
||||
menu_icons: true,
|
||||
main_menu_style: "hamburger".into(),
|
||||
main_menu_alt: true,
|
||||
always_show_main_menu: false,
|
||||
ide_antialiasing: "greyscale".into(),
|
||||
editor_antialiasing: "greyscale".into(),
|
||||
show_tool_window_bars: true,
|
||||
@@ -1570,6 +1573,11 @@ mod tests {
|
||||
let off: Settings = serde_json::from_str(r#"{"appearance":{"mainMenuAlt":false}}"#).unwrap();
|
||||
assert!(!off.appearance.main_menu_alt);
|
||||
assert_eq!(serde_json::to_value(off).unwrap()["appearance"]["mainMenuAlt"], false);
|
||||
let old: Settings = serde_json::from_str(r#"{"appearance":{"compactMode":true}}"#).unwrap();
|
||||
assert!(!old.appearance.always_show_main_menu);
|
||||
let shown: Settings = serde_json::from_str(r#"{"appearance":{"alwaysShowMainMenu":true}}"#).unwrap();
|
||||
assert!(shown.appearance.always_show_main_menu);
|
||||
assert_eq!(serde_json::to_value(shown).unwrap()["appearance"]["alwaysShowMainMenu"], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -2110,6 +2110,8 @@ export type AppearanceSettings = {
|
||||
mainMenuStyle?: string,
|
||||
/** A lone Alt press focuses or opens the main menu (IDEA `ide.windows.main.menu.focus.on.alt`). */
|
||||
mainMenuAlt?: boolean,
|
||||
/** Always show the main menu titles instead of the hamburger button (#1521). */
|
||||
alwaysShowMainMenu?: boolean,
|
||||
/** `subpixel` | `greyscale` | `none` */
|
||||
ideAntialiasing?: string,
|
||||
editorAntialiasing?: string,
|
||||
|
||||
@@ -43,4 +43,9 @@ describe("Main menu appearance setting", () => {
|
||||
expect(validateAppearanceExtras({ mainMenuStyle: "unknown" }).mainMenuStyle).toBe("hamburger");
|
||||
expect(validateAppearanceExtras({ mainMenuStyle: "merged" }).mainMenuStyle).toBe("merged");
|
||||
});
|
||||
|
||||
it("defaults to hiding the hamburger override and round-trips it (#1521)", () => {
|
||||
expect(validateAppearanceExtras({}).alwaysShowMainMenu).toBe(false);
|
||||
expect(validateAppearanceExtras({ alwaysShowMainMenu: true }).alwaysShowMainMenu).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -40,6 +40,8 @@ export interface AppearanceExtras {
|
||||
mainMenuStyle: "hamburger" | "merged";
|
||||
/** A lone Alt press focuses or opens the main menu (IDEA `ide.windows.main.menu.focus.on.alt`). */
|
||||
mainMenuAlt: boolean;
|
||||
/** Always show the main menu titles instead of the hamburger button (#1521). */
|
||||
alwaysShowMainMenu: boolean;
|
||||
ideAntialiasing: Antialiasing;
|
||||
editorAntialiasing: Antialiasing;
|
||||
showToolWindowBars: boolean;
|
||||
@@ -107,6 +109,7 @@ export const DEFAULT_APPEARANCE_EXTRAS: AppearanceExtras = {
|
||||
menuIcons: true,
|
||||
mainMenuStyle: "hamburger",
|
||||
mainMenuAlt: true,
|
||||
alwaysShowMainMenu: false,
|
||||
ideAntialiasing: "greyscale",
|
||||
editorAntialiasing: "greyscale",
|
||||
showToolWindowBars: true,
|
||||
@@ -171,6 +174,7 @@ export function validateAppearanceExtras(raw: unknown): AppearanceExtras {
|
||||
menuIcons: b("menuIcons"),
|
||||
mainMenuStyle: oneOf(a.mainMenuStyle, ["hamburger", "merged"], d.mainMenuStyle),
|
||||
mainMenuAlt: b("mainMenuAlt"),
|
||||
alwaysShowMainMenu: b("alwaysShowMainMenu"),
|
||||
ideAntialiasing: oneOf(a.ideAntialiasing, AA, d.ideAntialiasing),
|
||||
editorAntialiasing: oneOf(a.editorAntialiasing, AA, d.editorAntialiasing),
|
||||
showToolWindowBars: b("showToolWindowBars"),
|
||||
|
||||
@@ -358,6 +358,11 @@ function UiOptionsGrid() {
|
||||
label="Open main menu with a lone Alt press"
|
||||
hint="When off, Alt key combinations still work but pressing Alt alone does not focus the main menu"
|
||||
/>
|
||||
<BoundToggle
|
||||
k="appearance.alwaysShowMainMenu"
|
||||
label="Always show the main menu"
|
||||
hint="Show menu titles instead of the hamburger button, even when the window is narrow"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -6985,6 +6985,8 @@
|
||||
"Servers": "服务器",
|
||||
"Open main menu with a lone Alt press": "单独按下 Alt 打开主菜单",
|
||||
"When off, Alt key combinations still work but pressing Alt alone does not focus the main menu": "关闭后,Alt 组合键仍然可用,但单独按下 Alt 不会聚焦主菜单",
|
||||
"Always show the main menu": "始终显示主菜单",
|
||||
"Show menu titles instead of the hamburger button, even when the window is narrow": "显示菜单标题而不是汉堡菜单按钮,即使窗口较窄",
|
||||
"the bundle of {gemfile} has no `debug` gem. Add `gem \"debug\"` to the Gemfile and run `bundle install`": "{gemfile} 的 bundle 中没有 `debug` gem。请在 Gemfile 中添加 `gem \"debug\"`,然后运行 `bundle install`",
|
||||
"No background tasks": "没有后台任务",
|
||||
"Status Bar Widgets": "状态栏微件",
|
||||
|
||||
@@ -253,6 +253,30 @@ describe("main menu presentation", () => {
|
||||
expect(screen.getByRole("button", { name: "Main Menu" })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each(["hamburger", "merged"] as const)(
|
||||
"%s shows titles instead of the hamburger button when always showing the main menu",
|
||||
async (style) => {
|
||||
// A narrow window where merged titles would not fit: the flag keeps them visible anyway.
|
||||
if (style === "merged") available = 100;
|
||||
act(() =>
|
||||
useProject.setState({
|
||||
settings: { appearance: { mainMenuStyle: style, alwaysShowMainMenu: true } } as Settings,
|
||||
}),
|
||||
);
|
||||
render(<MainMenu />);
|
||||
await screen.findByRole("menubar");
|
||||
expect(screen.queryByRole("button", { name: "Main Menu" })).toBeNull();
|
||||
expect(titles().getByRole("menuitem", { name: "File" })).toBeInTheDocument();
|
||||
// Dismissing a menu keeps the titles instead of collapsing back to the button.
|
||||
fireEvent.click(titles().getByRole("menuitem", { name: "File" }));
|
||||
expect(await screen.findByRole("menu", { name: "File" })).toBeInTheDocument();
|
||||
fireEvent.keyDown(document.activeElement!, { key: "Escape" });
|
||||
expect(screen.queryByRole("menu")).toBeNull();
|
||||
expect(screen.getByRole("menubar")).toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "Main Menu" })).toBeNull();
|
||||
},
|
||||
);
|
||||
|
||||
it("applies the setting immediately and restores toolbar visibility when switching from an expanded hamburger", async () => {
|
||||
const expanded = vi.fn();
|
||||
render(<MainMenu onExpandedChange={expanded} />);
|
||||
|
||||
@@ -96,19 +96,22 @@ function MainMenuBar({ merged, onExpandedChange }: MainMenuProps & { merged: boo
|
||||
const previousFocus = useRef<HTMLElement | null>(null);
|
||||
const [fits, setFits] = useState(false);
|
||||
const pressedTitle = useRef(false);
|
||||
const persistent = merged && fits;
|
||||
// #1521: always show the menu titles instead of the hamburger button,
|
||||
// even when the window is too narrow for the merged titles to fit.
|
||||
const alwaysShow = useProject((s) => s.settings?.appearance?.alwaysShowMainMenu === true);
|
||||
const persistent = (merged && fits) || alwaysShow;
|
||||
const showTitles = persistent || (!merged && expanded);
|
||||
|
||||
useEffect(() => {
|
||||
let disposed = false;
|
||||
if (merged)
|
||||
if (merged || alwaysShow)
|
||||
void loadMenus().then((top) => {
|
||||
if (!disposed) setMenus(top);
|
||||
});
|
||||
return () => {
|
||||
disposed = true;
|
||||
};
|
||||
}, [merged]);
|
||||
}, [merged, alwaysShow]);
|
||||
useEffect(() => {
|
||||
if (!merged || open === null) return;
|
||||
let disposed = false;
|
||||
@@ -132,15 +135,16 @@ function MainMenuBar({ merged, onExpandedChange }: MainMenuProps & { merged: boo
|
||||
const next = menus.length > 0 && slot.current!.clientWidth >= measure.current!.scrollWidth;
|
||||
setFits(next);
|
||||
// Each presentation's menu closes with it, and must not reopen when it returns.
|
||||
// With "always show" the titles never collapse, so an open menu stays open.
|
||||
if (next) setExpanded(false);
|
||||
else setOpen(null);
|
||||
else if (!alwaysShow) setOpen(null);
|
||||
};
|
||||
const observer = new ResizeObserver(update);
|
||||
observer.observe(slot.current);
|
||||
observer.observe(measure.current);
|
||||
update();
|
||||
return () => observer.disconnect();
|
||||
}, [merged, menus]);
|
||||
}, [merged, menus, alwaysShow]);
|
||||
|
||||
const close = () => {
|
||||
setOpen(null);
|
||||
|
||||
Reference in new issue
Block a user