Commit Graph
13617 Commits
Author SHA1 Message Date
Georges-Antoine Assi 7995faa524 Merge pull request #4896 from rommapp/fix/bulk-actions-whole-selection-4460
Size gallery bulk actions for whole-result selections
2026-10-01 16:42:43 -04:00
Georges-Antoine Assi 77508abfa7 Merge remote-tracking branch 'origin/master' into revert-download-4460
# Conflicts:
#	frontend/src/v2/components/Gallery/SelectionBar.vue
2026-10-01 16:34:32 -04:00
Georges-Antoine AssiandClaude Opus 5.5 36b8560f2c revert(download): drop the stored download selection endpoint
Bulk downloads only ever name a couple dozen ROMs, so the id list fits
in the URL and `GET /roms/download?rom_ids=` stays as it was. Removes
`POST /roms/download/selection`, the Redis-backed selection handler,
the `selection` query param, and the download-failure snackbar.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 16:31:58 -04:00
Georges-Antoine Assi 93d6dbb508 Merge pull request #4993 from rommapp/feat/pad-text-field-exit
feat(input): let the D-pad move through and out of text fields
2026-10-01 16:05:14 -04:00
Georges-Antoine AssiandClaude Opus 5.5 2e0de3d193 refactor: simplify pass (pr-ready step 3)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 15:52:41 -04:00
Georges-Antoine AssiandClaude Opus 5.5 fffee29923 fix: address code-review findings (pr-ready step 2)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 15:51:01 -04:00
Georges-Antoine Assi db0efd213d Merge remote-tracking branch 'origin/master' into feat/pad-text-field-exit
# Conflicts:
#	frontend/src/v2/composables/useGamepad/index.test.ts
#	frontend/src/v2/composables/useGamepad/index.ts
#	frontend/src/v2/composables/useSpatialNav/index.test.ts
#	frontend/src/v2/composables/useSpatialNav/index.ts
2026-10-01 15:40:26 -04:00
Georges-Antoine Assi 5faa695987 Merge pull request #4991 from rommapp/claude/ecstatic-wozniak-1xpe7c
fix: eight bugs from hand-maintained lists drifting apart
2026-10-01 15:37:30 -04:00
Georges-Antoine AssiandClaude Opus 5.5 828954d2a6 fix(streaming): keep an adopted memory card when its claim aborts
An aborted claim deleted the blank it created even after adoption had
stored the container card on it, while the adoption record stayed. The
next claim then skipped the prompt, created a new blank and hydrated
it, wiping the container's original card. The new catch-all in
claim_session made any late failure hit this, not only a failed
hydrate or launch. discard_blank_card now keeps a card that holds a
version, so the next claim mounts it.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 15:29:52 -04:00
Georges-Antoine AssiandClaude Opus 5.5 2c65a0fd2e chore: review-polish pass (pr-ready step 4)
Trim a two-line test docstring to one sentence.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 15:16:03 -04:00
Georges-Antoine AssiandClaude Opus 5.5 b2b7904b51 refactor: simplify pass (pr-ready step 3)
- Validate each exclude list where it is read, so a new path cannot skip
  validation and the rule has one home.
- Move useEscapable to composables/ and use it in RMenu and
  MatchRomBodyGrid, which hand-rolled the same stack wiring.
- Drop the Escape branches in RSelect and RDateField that the escape
  stack's capture listener now preempts.
- Debounce the gallery search with lodash like the rest of v2.
- Drop a cached-client assertion that held by construction.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 15:10:39 -04:00
Georges-Antoine AssiandClaude Opus 5.5 c92d665c6c fix: address code-review findings (pr-ready step 2)
- Time stream play sessions only for joiners; the backend records the
  claim holder's session on release, so timing it here counted it twice.
- Reject non-string exclude-list entries (YAML reads 001 as an int).
- Clear the shared dialog close mock between combobox tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 15:03:08 -04:00
Georges-Antoine Assi a22480bef9 Merge pull request #4990 from rommapp/renovate/backend-dependencies
chore(deps): update backend dependencies
2026-10-01 14:32:20 -04:00
Georges-Antoine AssiandClaude Opus 5.5 97ba10f7bd test: stack parametrize decorators instead of itertools.product (simplify)
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 14:14:00 -04:00
Georges-Antoine AssiandClaude Opus 5.5 6842188c6a test: materialize parametrize product for pytest 9.1 (code-review)
pytest 9.1 deprecates passing a non-Collection iterable to parametrize.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 14:12:40 -04:00
Sam DornanandClaude Opus 5.5 97a5f80eef Check the active sort in the gallery sort menu (#4998)
* Check the active sort in the gallery sort menu

The grid toolbar's sort menu (and its phone-width mirror) marked the
active axis by colour alone. It now also shows a leading check, the same
way the version switcher and sibling menus mark the current item.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015iCApu4gYrGBWDX8JD9JH6

* Share the sort menu's selection mark and test the phone menu

Both sort menus now take their active variant and check from one
selectionMark helper, and the toolbar test covers the phone-width menu
as well as the inline one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015iCApu4gYrGBWDX8JD9JH6

* Reset the toolbar test's breakpoint in teardown and drop a restating comment

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015iCApu4gYrGBWDX8JD9JH6

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-01 12:54:05 -05:00
Georges-Antoine Assi bf42ac0422 Merge pull request #4989 from rommapp/renovate/frontend-dependencies
chore(deps): update frontend dependencies
2026-10-01 13:50:34 -04:00
Georges-Antoine AssiandClaude Opus 5.5 f783f7a846 chore(deps): apply the in-range frontend updates to the lockfile
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 13:42:00 -04:00
Georges-Antoine AssiandClaude Opus 5.5 7dc89a4ab1 chore(deps): hold openapi-typescript-codegen below 0.30
0.30 moved to json-schema-ref-parser 14, whose safe URL resolver
refuses localhost, so `npm run generate` failed in the api-types check.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 13:26:50 -04:00
renovate[bot] b535ed0e6f chore(deps): update backend dependencies 2026-10-01 17:03:30 +00:00
Georges-Antoine AssiandClaude Opus 5.5 48d4a90220 chore(deps): bump vite to match the rolldown override and refresh the lockfile
Vite 8.0.16 pins rolldown 1.0.3, so the rolldown 1.2.11 override broke
the build. Vite 8.3.1 needs rolldown ~1.2.9 and clears min-release-age.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 13:01:47 -04:00
Georges-Antoine Assi bb09e59c44 Merge remote-tracking branch 'origin/master' into renovate/frontend-dependencies 2026-10-01 12:35:12 -04:00
Georges-Antoine Assi b8650d230b Merge pull request #4986 from LoneAngelFayt/fix/firmware-upload-filename
fix(firmware): store uploads under the name written to disk
2026-10-01 12:28:01 -04:00
renovate[bot] 1ed1dfff3b chore(deps): update frontend dependencies 2026-10-01 16:18:25 +00:00
Georges-Antoine Assi 54e377ca9d Merge pull request #4982 from rommapp/claude/rq-slim-imports-7m0jrn
perf: keep task code out of the cron scheduler and idle RQ workers
2026-10-01 12:16:26 -04:00
Georges-Antoine AssiandClaude Opus 5.5 17765df6b2 fix(tasks): keep failure reports and queue choice on the task spec
report_task_failure can run in the worker parent when a work horse is
killed, so it now enqueues notify_task_failure on the default queue
instead of loading the notification stack there.

enqueue_task defaults to the queue its spec names. The streaming worker
runs as PreloadingWorker, which imports the enabled scheduled tasks of
its queues, so the reaper's per-minute horse inherits its stack. Spec
tests now read config in a fresh interpreter instead of comparing a
value with itself.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 11:29:52 -04:00
Georges-Antoine AssiandClaude Opus 5.5 c21f2c3905 test(recommendation): patch enqueue_task where the builder imports it
Review-polish pass: the builder now imports enqueue_task at module level.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 11:08:30 -04:00
Georges-Antoine AssiandClaude Opus 5.5 656c85bc46 refactor(tasks): simplify pass on the task catalog split
Loads every model where the engine is built rather than per job, so only
processes that touch the ORM pay for it. Resolves task paths with RQ's
import_attribute, references the scan failure callback by path, hoists
the recommendations builder's registry import now that the registry
loads no task modules, and gates push-pull on its spec.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 11:06:27 -04:00
Georges-Antoine AssiandClaude Opus 5.5 e62c452ea9 fix(tasks): code-review pass on the task catalog split
Loads every model before a job resolves its task, so the mappers
configure in a work horse that imported a single task module. Moves the
httpx2 import into RemoteFilePullTask.run, builds the push-pull job meta
from its spec, gates the scheduled scan on its spec, and widens the
loaded-modules test to cover task modules and httpx2.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 11:00:39 -04:00
Georges-Antoine Assi d3c7be82e3 Merge pull request #4981 from rommapp/claude/rom-lazy-load-memory-7m0jrn
perf: trim idle memory of the backend processes
2026-10-01 10:34:29 -04:00
Georges-Antoine Assi 704dd6cf84 Merge pull request #4980 from rommapp/fix/v2-pair-route
Render the v2 pair page and share the auth footer
2026-10-01 10:28:50 -04:00
Georges-Antoine Assi 36c53a32eb Merge remote-tracking branch 'origin/master' into fix/v2-pair-route
# Conflicts:
#	frontend/src/v2/layouts/AuthLayout.vue
#	frontend/src/v2/views/DevicePairShell.vue
#	frontend/src/v2/views/PairShell.vue
2026-10-01 10:19:02 -04:00
Georges-Antoine Assi 9b9217ceae Merge pull request #4974 from LoneAngelFayt/fix/streaming-desktop-pad-nav
fix(streaming): let the desktop session own the controller
2026-10-01 09:09:04 -04:00
Georges-Antoine Assi 1f2abb6974 Merge pull request #4971 from andest01/fix/wcag-aa-misc-fixes
chore(wcag): AA misc fixes
2026-10-01 08:36:12 -04:00
Georges-Antoine AssiandClaude Opus 5.5 84e595cac1 feat(input): let the D-pad move through and out of text fields
A text field claimed every arrow, and a synthetic key never moves the caret,
so a D-pad that landed in one was stuck there. useGamepad now flags the arrows
it dispatches, and for those useSpatialNav steps the caret itself, moving
focus on up and down and once the caret reaches the text's edge. Keyboard
arrows, number fields, and open popups keep their arrows.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 08:09:54 -04:00
Georges-Antoine AssiandClaude Opus 5.5 c6fd1bd130 fix(confirm): open confirm dialogs on Cancel
ConfirmDialog focused Cancel on the next tick, but RDialog's own initial focus
ran after it and landed on the header's close button. Mark Cancel autofocus,
which RDialog already prefers, so a stray A or Enter cancels as intended.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 07:54:24 -04:00
Claude f5ce0af4f9 style: use alias imports for useEscapable and trim new comments
Addresses review: v2 imports go through the @/v2 alias, and comments
stay within two lines with docstrings in one sentence.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 11:20:58 +00:00
Claude d91af962d2 style: sort the useEscapable import in RComboboxField
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 11:17:53 +00:00
Georges-Antoine AssiandClaude Opus 5.5 77cf9f6cb0 fix(a11y): floor aria-valuenow so progress bars never announce 100 early
Addresses Greptile's review on #4971: rounding reported 100 at 99.6%.
Flooring keeps the value a whole number.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 07:16:32 -04:00
Claude cb7bb1a0aa fix(v2): time stream play sessions from the moment the stream is live
onPlay started the play session only if the state was already 'playing'
when it returned, but a claim stays 'loading' until the launch-ready socket
push, which usually lands later. Start the session when the game starts
running and flush it when it stops.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:17 +00:00
Claude b57cbd3e51 fix(v2): keep the gallery search box in sync with the URL
The search box was only written by typing, and the refetch only ran from
the debounce, so a search term changed by navigation (the platform view
reuses the shell across /platform/:id) left a stale query in the box.
Move the debounced search into useDebouncedSearch, which mirrors the store
term into the box, and refetch from the shell's filter watch.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:17 +00:00
Claude 2be99ae170 fix(v2): close select, combobox and date popovers before their overlay
RSelect, RComboboxField and RDateField never registered on the escape
stack, whose window capture listener runs first. Escape (or pad B) with
one of them open inside a dialog closed the dialog and left the popover
open; outside an overlay, pad B navigated back. Add useEscapable and
register each popover while its panel is shown.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:17 +00:00
Claude cc20146049 fix(streaming): release the claim when a claim fails unexpectedly
claim_session released the container only at the hand-placed abort_claim
calls before each planned refusal. Any other error after the claim was won
(a DB or Redis error, say) left the container reserved for every player
until the claim went stale, and could orphan the blank memory card.
Release the claim, and the blank card it created, on any such error.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:17 +00:00
Claude a846b7edc1 fix(frontend): build the cached /roms query with the shared mapping
The cached client kept its own copy of the GetRomsParams to query mapping,
which had drifted: it dropped publishers, developers, physical,
has_soundtrack, the HLTB length bounds, released_days and the with_* flags.
Export buildGetRomsQuery from the API client and use it in both.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:17 +00:00
Claude b2c628093d fix(config): reject exclude lists that are not lists
The exclude lists were spread into a set before validation ran, so the
isinstance checks could never fail: 'exclude.platforms: ps2' excluded the
folders 'p', 's' and '2', and a number crashed startup with a TypeError.
Validate the raw YAML values instead, and read only list values.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:16 +00:00
Claude 500728708c fix(roms): clear every match id when unmatching a ROM
The unmatch branch of update_rom nulled 15 ids but not gamelist_id, while
clearing gamelist_metadata, so an unmatched ROM that came from a
gamelist.xml still counted as identified. Build the reset (and the audit
record of what was unmatched) from METADATA_SOURCE_COLUMNS plus sgdb_id.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:16 +00:00
Claude ef57ee300d fix(scan): count every metadata source when deciding a ROM is identified
The not-identified check in scan_rom listed 13 provider ids by hand and
missed tgdb_id and libretro_id, so a ROM matched only by Libretro (or by a
TGDB id from Hasheous) took the early return: it skipped the SteamGridDB
lookup and missing_from_fs reset, while Rom.is_identified counted it as
matched. Derive the check from METADATA_SOURCE_COLUMNS instead.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01XZW9ChvmiTKXYYWY6JvTKU
2026-10-01 04:12:16 +00:00
Georges-Antoine AssiandClaude Opus 5.5 cfbf78d7c8 Move through the gallery grid with Home, End and the page keys
Home and End go to the ends of the row, and with Ctrl to the first and
last item of the grid. A row of one cell (list view) has nowhere to go
inside it, so there Home and End move through the grid too. PageUp and
PageDown move about one viewport of rows, keeping the column. The
gallery and Missing games scroll the virtualised list to the edge row
and wait for it to load before focusing it.

The list row's click, Space and context-menu handlers move onto its
name link, which already takes every click on the row, so the row
element carries no handlers of its own.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-30 23:12:31 -04:00
Georges-Antoine AssiandClaude Opus 5.5 23fe4e7c12 refactor(player): drive the playing flag through usePlayingWhile
Pico8, Ruffle, JsDos and EmulatorJS each set and cleared the flag by hand next
to gameRunning, with their own unmount resets. Each now mirrors gameRunning
through usePlayingWhile, which clears the flag on dispose. JsDos hands input
back at unmount rather than in teardown; every exit from a running JsDos
replaces the document, so the difference is not observable.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-30 23:03:50 -04:00
Georges-Antoine AssiandClaude Opus 5.5 a00b0cb0cb fix(input): move focus by arrow and D-pad inside open overlays
Spatial nav used to bail whenever an overlay was open, and no dialog moves
focus on arrows, so a pad could only reach a dialog's first control:
ConfirmDialog's Confirm was unreachable app-wide. It now moves focus among the
controls of the topmost overlay's panel, including a dialog over a running
game, which replaces Stream's own exit-dialog arrow handler.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-30 23:03:47 -04:00