Show empty asset groups on request, and add by the heading (#361)
game-maker / gate (push) Successful in 3m47s
game-maker / suite (push) Successful in 15m1s

The asset panel only listed the categories and types that hold assets.
To make the first asset of a kind you had to know its category in the
`+` menu. A switch now lists all of them, and a right-click on a
heading offers just what sits under it.

- General settings has "Show empty asset categories and types", off by
  default and kept in this browser. Applying it refreshes the panel at
  once through a new `onGeneralSettings` listener.
- `groupAssets(assets, empty)` gives every category and type when
  asked. The empty ones stand faint with a count of 0, and an empty
  type has no chevron, since there is nothing to unfold.
- `ListItem.faint` draws a row's label, hint and icons at half opacity,
  like a disabled widget.
- A right-click on a category heading offers the types of that
  category without a submenu, on a type heading only that type. The
  empty space below the rows still opens the whole `+` menu.
  `ListView.onListMenu` passes the heading's id for this.
- Every menu of new assets says "Create asset" above its entries, so a
  click on a type reads as making one. `MenuOptions.title` draws that
  muted line. It is not an entry and matches no search.

Tests:
- Unit asset-groups and view-tween: 23 green, 2 new. Counter-test
  with the empty flag ignored: the new groups test fails.
- e2e 04 (melektaus-atx): ALL PASSED, 67 checks, 4 new and 1
  rewritten. Counter-test with the heading id dropped: the 3 menu
  checks fail. The title is checked on the `+` button and on a type
  heading (2 checks extended), the rerun passed with 67 checks.
- Gate (melektaus-atx): CHECK EXIT 0, 272 files, 4212 tests. It ran
  before the menu title. Afterwards only the menu and asset-groups
  units, typecheck and lint ran, all clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-09 06:51:59 +02:00
1 parent cf96442835
commit 5cb7ef7bed
11 files changed
+269 -38

No files matched your search

+12
View File
@@ -63,6 +63,18 @@ describe('groupAssets (#176)', () => {
expect(groupsOf([second, first])[0]!.assets).toEqual([second, first]);
});
it('lists every category and type when asked to, the empty ones with no assets (#361)', () => {
const categories = groupAssets([asset('sprite', 'Hero')], true);
expect(categories.map((c) => c.category)).toEqual([...ASSET_CATEGORIES]);
const groups = categories.flatMap((c) => c.groups);
expect(groups.map((g) => g.type).sort()).toEqual([...ASSET_TYPES].sort());
expect(groups.filter((g) => g.assets.length > 0).map((g) => g.type)).toEqual(['sprite']);
for (const { category, groups } of categories)
for (const { type } of groups) expect(ASSET_GROUPS[type].category).toBe(category);
expect(groupAssets([], true).flatMap((c) => c.groups)).toHaveLength(ASSET_TYPES.length);
expect(groupAssets([])).toEqual([]);
});
it('leaves the project list alone', () => {
const assets = [asset('sprite', 'B'), asset('sprite', 'A')];
groupAssets(assets);
+15
View File
@@ -3,6 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import {
generalSettings,
keepGeneralSettings,
onGeneralSettings,
resetGeneralSettings,
zoomTransitionMs,
} from '../../src/editor/generalSettings';
@@ -215,9 +216,23 @@ describe('the general settings', () => {
expect(generalSettings().zoomTransitionMs).toBe(350);
expect(JSON.parse(store.items.get('game-maker.general-settings') ?? '')).toEqual({
zoomTransitionMs: 350,
showEmptyAssetGroups: false,
});
});
it('hides empty asset groups until switched on, keeps the switch and tells listeners (#361)', () => {
vi.stubGlobal('window', { localStorage: memoryStore() });
expect(generalSettings().showEmptyAssetGroups).toBe(false);
let told = 0;
const stop = onGeneralSettings(() => (told += 1));
keepGeneralSettings({ showEmptyAssetGroups: true });
resetGeneralSettings();
expect(generalSettings()).toEqual({ zoomTransitionMs: 200, showEmptyAssetGroups: true });
stop();
keepGeneralSettings({ showEmptyAssetGroups: false });
expect(told).toBe(1);
});
it('holds the transition to whole ms from 0 to 1000', () => {
expect([zoomTransitionMs(5000), zoomTransitionMs(-3), zoomTransitionMs(12.6)]).toEqual([1000, 0, 13]);
expect(zoomTransitionMs('fast')).toBe(200);