feat(ui): redesign home around launch readiness - #180
Conversation
Reviewer's GuideRedesigns the launcher home into a state-driven launch-readiness command center backed by a new backend readiness probe, download and game lifecycle stores, and updated fixtures, tests, docs, and CI to cover all launch and recovery states. Sequence diagram for home launch-readiness primary actionsequenceDiagram
actor User
participant HomePage
participant GameStore
participant DownloadStore
participant Client as TauriClient
participant Backend
User->>HomePage: click handlePrimaryAction()
HomePage->>HomePage: resolveHomeLaunchState(...)
alt homeState == "files-missing"
HomePage->>Client: installVersion(activeInstance.id, activeInstance.versionId)
Client->>Backend: get_launch_readiness(instance_id, version_id)
Backend-->>Client: LaunchReadiness
Client-->>HomePage: LaunchReadiness
HomePage->>HomePage: setProbeRevision(+1)
else homeState == "ready" or homeState == "stopped"
HomePage->>GameStore: startGame(activeInstance.id, activeInstance.versionId)
GameStore->>Backend: start_game(instance_id, version_id)
Backend-->>GameStore: message
GameStore-->>HomePage: message
else homeState == "running"
HomePage->>GameStore: stopGame(runningInstanceId)
GameStore->>Backend: stop_game()
Backend-->>GameStore: message
GameStore-->>HomePage: message
else homeState == "downloading" or homeState == "failed"
HomePage->>HomePage: focusActivity()
else homeState == "java-missing" or "memory-invalid"
HomePage->>HomePage: navigate("/settings")
else homeState == "no-instance" or "version-missing"
HomePage->>HomePage: navigate("/instances")
else homeState == "no-account"
HomePage->>HomePage: setShowLoginModal(true)
else homeState == "data-error"
HomePage->>HomePage: refreshReadiness()
HomePage->>AuthStore: refreshAuth()
HomePage->>SettingsStore: refreshSettings()
HomePage->>InstanceStore: refreshInstances()
end
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Workspace change through: 9abcc9c0 changesets found Planned changes to release
|
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="packages/ui/tests/launcher-fixtures.spec.ts" line_range="225-234" />
<code_context>
+test("download and failure states expose actionable diagnostics", async ({
</code_context>
<issue_to_address>
**suggestion (testing):** Download diagnostics test does not cover Java runtime downloads or bytes/progress details from the new monitor/store
Given the new DownloadMonitor and useDownloadStore behavior, please add a fixture-based test that drives a `java-download-progress` sequence and verifies:
- The monitor uses a "Java runtime" descriptor for kind === "java".
- The percentage and `aria-valuenow` match the boundedPercentage logic.
- Byte units (MB/GB) are formatted and rendered correctly.
This will ensure the new store wiring and Java download path remain observable and accessible, in addition to the existing game download coverage.
Suggested implementation:
```typescript
test("download and failure states expose actionable diagnostics", async ({
page,
}) => {
await page.goto("/?fixture=downloading&theme=dark#/");
await expect(
page.getByRole("progressbar", { name: "Download progress" }),
).toHaveAttribute("aria-valuenow", "65");
await page.getByRole("button", { name: "Track download" }).click();
await expect(page.locator("#download-monitor")).toBeFocused();
await page.goto("/?fixture=failed&theme=dark#/");
});
test("java runtime download progress diagnostics remain observable and accessible", async ({
page,
}) => {
// Drive the java-download-progress fixture to exercise DownloadMonitor + useDownloadStore
await page.goto("/?fixture=java-download-progress&theme=dark#/");
// The monitor should expose a "Java runtime" descriptor when kind === "java"
const javaRuntimeDescriptor = page.getByText(/Java runtime/i);
await expect(javaRuntimeDescriptor).toBeVisible();
// Progress bar should reflect boundedPercentage in both visual percentage and aria-valuenow
const progressBar = page.getByRole("progressbar", { name: "Download progress" });
const ariaValueNow = Number(await progressBar.getAttribute("aria-valuenow"));
expect(ariaValueNow).toBeGreaterThanOrEqual(0);
expect(ariaValueNow).toBeLessThanOrEqual(100);
// If a percentage label is rendered, ensure it matches the bounded percentage
const percentageLabel = page.getByText(/%$/);
const percentageText = await percentageLabel.textContent();
if (percentageText) {
const numericPercentage = Number(percentageText.replace("%", "").trim());
expect(numericPercentage).toBe(ariaValueNow);
}
// Open the download monitor and verify byte units are formatted/rendered correctly
await page.getByRole("button", { name: "Track download" }).click();
const monitor = page.locator("#download-monitor");
await expect(monitor).toBeFocused();
await expect(monitor).toContainText(/Java runtime/i);
await expect(monitor).toContainText(/MB|GB/i);
}
```
- Ensure the `java-download-progress` fixture exists and exercises a `kind: "java"` download path via the new `DownloadMonitor` and `useDownloadStore`.
- If the accessible name for the progress bar or the Java descriptor differs (e.g., "Java runtime download" instead of "Download progress"), adjust the `getByRole` / `getByText` queries accordingly.
- If the percentage label uses a dedicated test id or different text pattern, update the `percentageLabel` locator to match your actual DOM (for example, `page.getByTestId("download-percentage")`).
- Confirm the download monitor container has the `#download-monitor` id; if not, align the selector with the component's implementation.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| test("download and failure states expose actionable diagnostics", async ({ | ||
| page, | ||
| }) => { | ||
| await page.goto("/?fixture=downloading&theme=dark#/"); | ||
| await expect( | ||
| page.getByRole("progressbar", { name: "Download progress" }), | ||
| ).toHaveAttribute("aria-valuenow", "65"); | ||
| await page.getByRole("button", { name: "Track download" }).click(); | ||
| await expect(page.locator("#download-monitor")).toBeFocused(); | ||
|
|
There was a problem hiding this comment.
suggestion (testing): Download diagnostics test does not cover Java runtime downloads or bytes/progress details from the new monitor/store
Given the new DownloadMonitor and useDownloadStore behavior, please add a fixture-based test that drives a java-download-progress sequence and verifies:
- The monitor uses a "Java runtime" descriptor for kind === "java".
- The percentage and
aria-valuenowmatch the boundedPercentage logic. - Byte units (MB/GB) are formatted and rendered correctly.
This will ensure the new store wiring and Java download path remain observable and accessible, in addition to the existing game download coverage.
Suggested implementation:
test("download and failure states expose actionable diagnostics", async ({
page,
}) => {
await page.goto("/?fixture=downloading&theme=dark#/");
await expect(
page.getByRole("progressbar", { name: "Download progress" }),
).toHaveAttribute("aria-valuenow", "65");
await page.getByRole("button", { name: "Track download" }).click();
await expect(page.locator("#download-monitor")).toBeFocused();
await page.goto("/?fixture=failed&theme=dark#/");
});
test("java runtime download progress diagnostics remain observable and accessible", async ({
page,
}) => {
// Drive the java-download-progress fixture to exercise DownloadMonitor + useDownloadStore
await page.goto("/?fixture=java-download-progress&theme=dark#/");
// The monitor should expose a "Java runtime" descriptor when kind === "java"
const javaRuntimeDescriptor = page.getByText(/Java runtime/i);
await expect(javaRuntimeDescriptor).toBeVisible();
// Progress bar should reflect boundedPercentage in both visual percentage and aria-valuenow
const progressBar = page.getByRole("progressbar", { name: "Download progress" });
const ariaValueNow = Number(await progressBar.getAttribute("aria-valuenow"));
expect(ariaValueNow).toBeGreaterThanOrEqual(0);
expect(ariaValueNow).toBeLessThanOrEqual(100);
// If a percentage label is rendered, ensure it matches the bounded percentage
const percentageLabel = page.getByText(/%$/);
const percentageText = await percentageLabel.textContent();
if (percentageText) {
const numericPercentage = Number(percentageText.replace("%", "").trim());
expect(numericPercentage).toBe(ariaValueNow);
}
// Open the download monitor and verify byte units are formatted/rendered correctly
await page.getByRole("button", { name: "Track download" }).click();
const monitor = page.locator("#download-monitor");
await expect(monitor).toBeFocused();
await expect(monitor).toContainText(/Java runtime/i);
await expect(monitor).toContainText(/MB|GB/i);
}- Ensure the
java-download-progressfixture exists and exercises akind: "java"download path via the newDownloadMonitoranduseDownloadStore. - If the accessible name for the progress bar or the Java descriptor differs (e.g., "Java runtime download" instead of "Download progress"), adjust the
getByRole/getByTextqueries accordingly. - If the percentage label uses a dedicated test id or different text pattern, update the
percentageLabellocator to match your actual DOM (for example,page.getByTestId("download-percentage")). - Confirm the download monitor container has the
#download-monitorid; if not, align the selector with the component's implementation.
Description
Redesigns the launcher home as a launch-readiness command center. The primary action now follows the real account, instance, Java, memory, file, download, and game-process state, with recovery actions and diagnostics kept in the same workflow.
Type of Change
LLM-Generated Code Disclosure
Related Issues
Closes #174
Changes Made
Backend (Rust)
get_launch_readinesscommand that shares Java resolution rules with the real launch path.Frontend (React)
Configuration and documentation
Testing
Test Environment
Test Cases
Validation
pnpm -C packages/ui test:ui— 80/80 passed locallypnpm docs:buildcargo check, and ClippySteps to Test
pnpm -C packages/ui test:ui.?fixture=ready,downloading,failed, or the other documented state names.Checklist
Code Quality
Testing Verification
Documentation
Dependencies
Screenshots / Videos
The automated suite records dark/light baselines for all command-center states at 1024x768 and 905x575 on macOS and Linux.
Additional Notes
Real platform packaging and live Minecraft smoke testing remain milestone release-gate work; this PR validates the launcher state machine and recovery UX deterministically.
Breaking Changes
None.
Summary by Sourcery
Redesign the launcher home into a state-driven launch readiness command center that tracks account, instance, Java, memory, files, downloads, and game lifecycle, with recovery actions and diagnostics integrated into the primary workflow.
New Features:
Enhancements:
Build:
CI:
Documentation:
Tests: