Skip to content

Commit af21938

Browse files
committed
Fix user control gamepad profile generation to require selected controller action - PR_26163_059-user-control-profile-generation-flow
1 parent ae44d16 commit af21938

6 files changed

Lines changed: 311 additions & 189 deletions

File tree

account/user-controls-page.js

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ export class AccountUserControlsPage {
403403
});
404404
}
405405

406-
createProfile(device) {
406+
createProfile(device, { persistImmediately = true } = {}) {
407407
const knownProfiles = new Map();
408408
this.readProfiles().forEach((profile) => {
409409
knownProfiles.set(profile.id, profile);
@@ -413,11 +413,14 @@ export class AccountUserControlsPage {
413413
});
414414
this.profiles = [...knownProfiles.values()];
415415
const profile = this.uniqueProfileForDevice(device);
416-
if (!this.saveProfiles([profile, ...this.profiles])) {
417-
this.setStatus("FAIL: User Controls could not reach the shared DB adapter.");
418-
return;
416+
let createdProfile = profile;
417+
if (persistImmediately) {
418+
if (!this.saveProfiles([profile, ...this.profiles])) {
419+
this.setStatus("FAIL: User Controls could not reach the shared DB adapter.");
420+
return;
421+
}
422+
createdProfile = this.profiles.find((candidate) => candidate.id === profile.id) || profile;
419423
}
420-
const createdProfile = this.profiles.find((candidate) => candidate.id === profile.id) || profile;
421424
this.editingProfile = { id: createdProfile.id, values: createdProfile };
422425
this.viewingDefaultFamily = "";
423426
this.renderProfiles();
@@ -514,17 +517,10 @@ export class AccountUserControlsPage {
514517
choices.push(choice);
515518
};
516519
["Keyboard", "Mouse", "Gamepad"].forEach((family) => addChoice(this.defaultSelectionChoice(family)));
517-
const profiledGamepadIds = new Set();
518520
this.profiles.forEach((profile) => {
519-
if (this.profileListFamily(profile) === "Gamepad") {
520-
profiledGamepadIds.add(profile.controllerId);
521-
}
522521
addChoice(this.profileSelectionChoice(profile));
523522
});
524523
this.deviceOptions().forEach((device) => {
525-
if (profiledGamepadIds.has(device.controllerId)) {
526-
return;
527-
}
528524
addChoice(this.detectedDeviceSelectionChoice(device));
529525
});
530526
return choices;
@@ -714,11 +710,7 @@ export class AccountUserControlsPage {
714710
rows.push(this.renderReadonlyProfileDetailsRow(defaultProfile, family));
715711
}
716712
});
717-
const profiledGamepadIds = new Set(this.profiles
718-
.filter((profile) => this.profileListFamily(profile) === "Gamepad")
719-
.map((profile) => profile.controllerId));
720713
this.deviceOptions()
721-
.filter((device) => !profiledGamepadIds.has(device.controllerId))
722714
.forEach((device) => {
723715
rowsByFamily.get("Gamepad")?.push(this.renderDetectedDeviceRow(device));
724716
});
@@ -1137,7 +1129,7 @@ export class AccountUserControlsPage {
11371129
this.setStatus("WARN: Select a detected game controller row before creating a user control profile.");
11381130
return;
11391131
}
1140-
this.createProfile(device);
1132+
this.createProfile(device, { persistImmediately: false });
11411133
}
11421134

11431135
editFamilyMappings(family) {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# PR_26163_059-user-control-profile-generation-flow
2+
3+
## Branch Validation
4+
5+
- Current branch: `main`
6+
- Expected branch: `main`
7+
- Branch validation: PASS
8+
9+
## Requirement Checklist
10+
11+
- PASS - Read `docs_build/dev/PROJECT_INSTRUCTIONS.md` before implementation.
12+
- PASS - Created PR scope `PR_26163_059-user-control-profile-generation-flow`.
13+
- PASS - Fixed `account/user-controls.html` Game Controller profile flow through the external `account/user-controls-page.js` runtime.
14+
- PASS - Connected controller detection renders detected device rows only and does not create user profiles.
15+
- PASS - User must select exactly one detected controller row before `Create User Control Profile` can generate a profile.
16+
- PASS - `Create User Control Profile` creates exactly one new profile for only the selected controller.
17+
- PASS - Newly generated game controller profile opens in edit mode.
18+
- PASS - Save persists that one profile for the current user.
19+
- PASS - A second profile for the same controller requires a second explicit select controller -> create profile -> edit -> save flow.
20+
- PASS - No behavior remains in the touched flow that auto-adds all connected gamepads as profiles.
21+
- PASS - No behavior remains in the touched flow that creates detached profiles for unselected controllers.
22+
- PASS - Scope stayed limited to account User Controls gamepad detection/profile generation behavior, targeted tests, runtime coverage, and reports.
23+
24+
## Changed Files
25+
26+
- `account/user-controls-page.js`
27+
- `tests/playwright/tools/InputMappingV2Tool.spec.mjs`
28+
- `docs_build/dev/reports/playwright_v8_coverage_report.txt`
29+
- `docs_build/dev/reports/PR_26163_059-user-control-profile-generation-flow.md`
30+
- `docs_build/dev/reports/codex_review.diff`
31+
- `docs_build/dev/reports/codex_changed_files.txt`
32+
33+
## Implementation Notes
34+
35+
- Game controller profile generation now stages the selected detected controller as an unsaved edit row.
36+
- Keyboard and Mouse profile creation keep their existing immediate DB-backed behavior; the changed persistence boundary is scoped to Game Controller generation.
37+
- Detected game controller rows remain visible after a profile is saved, allowing another explicit generation flow for the same physical controller.
38+
- Profile Save remains the DB persistence action for generated game controller profiles.
39+
- Auto-detection refreshes visible detected rows while no profile is being edited, but detection itself does not write `player_controller_profiles`.
40+
41+
## Impacted Lane
42+
43+
- Account/User Controls runtime lane.
44+
- Account/User Controls Playwright behavior lane.
45+
- Workspace V2 command lane, required by request. The command name `npm run test:workspace-v2` is legacy test-suite naming; it does not introduce user-facing Workspace V2 wording.
46+
47+
## Skipped Lanes
48+
49+
- Full samples smoke: SKIP. This PR is limited to Account/User Controls profile generation and does not touch samples, sample JSON, game runtime launch, or sample smoke behavior.
50+
- Engine lane: SKIP. No `src/engine/input` files or engine contracts changed.
51+
- Toolbox Controls lane: SKIP. Toolbox Controls source was not changed.
52+
53+
## Validation Performed
54+
55+
- PASS - Branch check: `git branch --show-current` returned `main`.
56+
- PASS - Syntax check: `node --check account/user-controls-page.js`.
57+
- PASS - Syntax check: `node --check tests/playwright/tools/InputMappingV2Tool.spec.mjs`.
58+
- PASS - Static patch check: `git diff --check -- account/user-controls-page.js tests/playwright/tools/InputMappingV2Tool.spec.mjs`.
59+
- PASS - Targeted regression: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs --grep "selected game controller row" --reporter=line` passed 1 test.
60+
- PASS - Targeted Account/User Controls slice: `npx playwright test tests/playwright/tools/InputMappingV2Tool.spec.mjs --grep "User Controls owns|selected game controller row|scopes profiles" --reporter=line` passed 3 tests.
61+
- PASS - Required workspace validation: `npm run test:workspace-v2` passed 5 tests.
62+
63+
## Playwright Result
64+
65+
- PASS - Connected controller detection renders detected device rows.
66+
- PASS - Controller detection creates zero `player_controller_profiles` records.
67+
- PASS - Selecting one controller then creating a profile opens exactly one edit row.
68+
- PASS - Generated profile does not persist before Save.
69+
- PASS - Save persists only the selected controller profile.
70+
- PASS - Repeating the same selected-controller flow creates a second profile only after a second explicit create/save sequence.
71+
- PASS - Unselected controllers do not create profiles and remain detected rows.
72+
- PASS - Existing User Controls profile defaults, editing, persistence, and ownership coverage still passes.
73+
74+
## Coverage
75+
76+
- PASS - `docs_build/dev/reports/playwright_v8_coverage_report.txt` was produced after the targeted Account/User Controls Playwright run.
77+
- PASS - Changed runtime JavaScript coverage includes `(93%) account/user-controls-page.js - changed runtime JS file with browser V8 coverage`.
78+
79+
## Manual Validation Steps
80+
81+
1. Open `/account/user-controls.html`.
82+
2. Connect or expose at least two game controllers.
83+
3. Confirm detected controllers render as selectable rows and no saved user profiles appear from detection alone.
84+
4. Select one detected controller row.
85+
5. Click `Create User Control Profile`.
86+
6. Confirm one generated profile opens in edit mode and no DB-backed profile appears until Save.
87+
7. Click Save and confirm exactly one profile persists for the selected controller.
88+
8. Confirm the unselected controller did not create a profile.
89+
9. Select the same detected controller again, create a profile again, and save.
90+
10. Confirm a second profile appears only after that second explicit flow.
91+
92+
## Samples Validation Decision
93+
94+
- SKIP - Full samples smoke was not run because the request explicitly excluded it and the PR does not affect sample contracts or sample runtime behavior.
95+
96+
## Completion
97+
98+
- PASS - Every requested item was implemented, validated, and explicitly marked PASS or documented as skipped where applicable.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
account/user-controls-page.js
22
tests/playwright/tools/InputMappingV2Tool.spec.mjs
33
docs_build/dev/reports/playwright_v8_coverage_report.txt
4-
docs_build/dev/reports/PR_26163_058-user-control-profile-selected-device-only.md
4+
docs_build/dev/reports/PR_26163_059-user-control-profile-generation-flow.md
55
docs_build/dev/reports/codex_review.diff
66
docs_build/dev/reports/codex_changed_files.txt

0 commit comments

Comments
 (0)