Files
workutils/docs/superpowers/plans/2026-08-01-workutils-unified-ui-p3-limited-adaptation.md
T
2026-08-01 12:42:14 +08:00

16 KiB
Raw Blame History

WorkUtils Unified UI P3 Limited Adaptation and Finalization Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Apply the unified theme to Git review, mobile UI automation, settings, and plugin management without structural rewrites, then remove remaining application-level visual inconsistencies and complete full regression/visual acceptance.

Architecture: Treat the four limited modules as compatibility consumers of P0 components. Only replace visual construction, style classes, fonts, icons, and shell entry points; retain their existing controllers, panes, services, and state machines. Finish with repository-wide architecture guards that prevent regression to Emoji, duplicate settings navigation, arbitrary fonts, and ad-hoc loading code.

Tech Stack: Java 17, JavaFX 17.0.15, AtlantaFX 2.0.1, P0–P2 shared UI components, JUnit 5, Maven Wrapper.

Global Constraints

  • Do not refactor Git review window structure, review workflow, service boundaries, or DiffEngine.
  • Do not split mobile UI automation or rewrite its run/record state machine.
  • Do not change settings information architecture, persistence, validation, or plugin-management behavior.
  • Preserve Windows native title-bar controls and the light-only theme.
  • Settings remains top-right-only in the application shell; no sidebar duplicate may return.
  • Use Feather through AppIcon/IconFactory; no visible Emoji or mixed icon set in the application UI.
  • Visual checks are read-only: do not submit reviews, run mobile automation, change settings, reorder plugins, synchronize Git, or write exports.

File Structure

Create

  • src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java — repository-wide regression guard.

Modify

  • src/main/java/com/example/workutils/biz/gitreview/GitReviewWindow.java
  • src/main/java/com/example/workutils/biz/mobileuiauto/MobileUiAutomationWindow.java
  • src/main/java/com/example/workutils/system/config/SettingsWindow.java
  • src/main/java/com/example/workutils/system/plugin/PluginManagementWindow.java
  • src/main/java/com/example/workutils/system/plugin/PluginDescriptor.java
  • Plugin descriptor/factory classes under src/main/java/com/example/workutils/biz/*/*Plugin.java
  • src/main/resources/css/light-theme.css
  • src/test/java/com/example/workutils/system/ui/SharedPaneAccessibilityTest.java
  • src/test/java/com/example/workutils/system/plugin/DefaultPluginConfigurationTest.java

Task 1: Add repository-wide visual architecture guards

Files:

  • Create: src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java

Interfaces:

  • Produces source(String): SourceFile and an explicit limitedUiSources() list. Start with Git review only; append mobile, settings/plugin management, then all plugin descriptors in their migration tasks so every task ends green.

  • Step 1: Write the failing architecture tests

private record SourceFile(Path path, String text) {}

private static SourceFile source(String relativePath) throws IOException {
    Path path = Path.of("src/main/java/com/example/workutils", relativePath);
    return new SourceFile(path, Files.readString(path));
}

private static List<SourceFile> limitedUiSources() throws IOException {
    return List.of(source("biz/gitreview/GitReviewWindow.java"));
}

private static long count(List<SourceFile> files, String needle) {
    return files.stream()
            .mapToLong(file -> (file.text().length()
                    - file.text().replace(needle, "").length()) / needle.length())
            .sum();
}

@Test
void applicationUiDoesNotUseEmojiIconsOrHardcodedMicrosoftYaHei() throws IOException {
    for (SourceFile file : limitedUiSources()) {
        assertFalse(file.text().contains("Microsoft YaHei"), file.path().toString());
        assertFalse(file.text().matches("(?s).*new Label\\(\"[⚙🛠✅❌❓▶].*"),
                file.path().toString());
    }
}

@Test
void settingsAndLoadingHaveSingleOwners() throws IOException {
    String app = Files.readString(Path.of(
            "src/main/java/com/example/workutils/WorkUtilsApplication.java"));
    assertFalse(app.contains("new MainWindow.NavItem(\n                AppIcon.SETTINGS, \"系统设置\""));
    assertEquals(0, count(limitedUiSources(), "setBtnLoading("));
}

Limit Emoji scanning to JavaFX application controls. Exclude ApiDocGenerator HTML output where symbols may be document content rather than application chrome.

  • Step 2: Run and record failures

Run: .\mvnw.cmd -q -Dtest=UnifiedUiArchitectureTest test

Expected: FAIL on Git review fonts/icons. Continue directly to Task 2 before committing.

Task 2: Theme-adapt Git review without structural refactoring

Files:

  • Modify: src/main/java/com/example/workutils/biz/gitreview/GitReviewWindow.java
  • Modify: src/main/resources/css/light-theme.css
  • Include: src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java

Interfaces:

  • Preserves every existing method signature, pane hierarchy, review action, service call, and loading behavior.

  • Consumes only P0 tokens/icons/style classes.

  • Step 1: Add a structural checksum assertion before edits

assertTrue(source.contains("class GitReviewWindow"));
assertTrue(source.contains("GitReviewService"));
assertFalse(source.contains("new AppShell("));

The window must remain a plugin content view and must not create its own shell.

  • Step 2: Replace visual literals only

Replace direct fonts, colors, button graphics, and local spinner construction with semantic style classes, IconFactory, and LoadingButtonBinder. Do not extract panes, rename business methods, or change action ordering.

  • Step 3: Run Git review compilation/architecture checks

Run: .\mvnw.cmd -q -Dtest=UnifiedUiArchitectureTest,WindowNotificationDependencyTest test

Expected: Git review visual assertions pass; notification boundary remains intact.

  • Step 4: Capture read-only Git review states

Capture initial/empty/configured views without starting a review. Verify shell typography and icons while confirming the internal layout is structurally unchanged.

  • Step 5: Commit
git add src/main/java/com/example/workutils/biz/gitreview/GitReviewWindow.java src/main/resources/css/light-theme.css src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java
git commit -m "适配 Git 评审统一主题"

Task 3: Theme-adapt mobile UI automation without state-machine changes

Files:

  • Modify: src/main/java/com/example/workutils/biz/mobileuiauto/MobileUiAutomationWindow.java
  • Modify: src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java

Interfaces:

  • Preserves MobileAutomationService, AutomationRunHandle, callback types, run/record controls, and current window composition.

  • Step 1: Add source boundary assertions

First append biz/mobileuiauto/MobileUiAutomationWindow.java to limitedUiSources(), then add:

assertTrue(source.contains("MobileAutomationService"));
assertTrue(source.contains("AutomationRunHandle"));
assertFalse(source.contains("class RecordingStateMachine"));
assertFalse(source.contains("class RunStateMachine"));
  • Step 2: Replace only theme consumers

Use token fonts, shared controls, Feather icons, and CSS classes. Preserve current button event handlers and every service/callback interaction. If a control has ad-hoc spinner code, bind its existing operation state through LoadingButtonBinder only when an AsyncOperationController already exists; otherwise style the existing state without creating a new state machine in P3.

  • Step 3: Run compile and architecture tests

Run: .\mvnw.cmd -q -Dtest=UnifiedUiArchitectureTest test

Run: .\mvnw.cmd -q -DskipTests compile

Expected: both pass; no new run/record state types appear.

  • Step 4: Capture read-only states

Capture the idle screen only. Do not connect devices, start recordings, run scripts, or alter execution history.

  • Step 5: Commit
git add src/main/java/com/example/workutils/biz/mobileuiauto/MobileUiAutomationWindow.java src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java src/main/resources/css/light-theme.css
git commit -m "适配手机 UI 自动化统一主题"

Task 4: Theme-adapt settings and plugin management

Files:

  • Modify: src/main/java/com/example/workutils/system/config/SettingsWindow.java
  • Modify: src/main/java/com/example/workutils/system/plugin/PluginManagementWindow.java
  • Modify: src/test/java/com/example/workutils/system/ui/SharedPaneAccessibilityTest.java
  • Modify: src/test/java/com/example/workutils/system/plugin/DefaultPluginConfigurationTest.java
  • Modify: src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java

Interfaces:

  • Preserves all settings tabs, save/reload behavior, config files, data-source management, plugin enable/order behavior, and drag/drop semantics.

  • Step 1: Add failing unique-entry and accessibility assertions

First append system/config/SettingsWindow.java and system/plugin/PluginManagementWindow.java to limitedUiSources(), then add:

String app = Files.readString(Path.of(
        "src/main/java/com/example/workutils/WorkUtilsApplication.java"));
String management = Files.readString(Path.of(
        "src/main/java/com/example/workutils/system/plugin/PluginManagementWindow.java"));
assertFalse(app.contains("AppIcon.SETTINGS, \"系统设置\","));
assertTrue(management.contains("setAccessibleText(\"拖动调整插件顺序\")"));
  • Step 2: Run focused tests and verify failure

Run: .\mvnw.cmd -q -Dtest=DefaultPluginConfigurationTest,SharedPaneAccessibilityTest,UnifiedUiArchitectureTest test

Expected: FAIL on remaining Unicode grip/icon or missing accessible labels.

  • Step 3: Apply theme classes without changing information architecture

Replace fonts/icons/inline styles; keep all current tabs and field grouping. Replace the ≡ drag label with Feather MENU, preserving drag handlers and user data. Do not move settings sections or change persistence.

  • Step 4: Run focused tests and capture

Run: .\mvnw.cmd -q -Dtest=DefaultPluginConfigurationTest,SharedPaneAccessibilityTest,UnifiedUiArchitectureTest test

Expected: PASS. Open settings from the top-right entry and inspect tabs without saving or reordering anything.

  • Step 5: Commit
git add src/main/java/com/example/workutils/system/config/SettingsWindow.java src/main/java/com/example/workutils/system/plugin/PluginManagementWindow.java src/test/java/com/example/workutils/system/ui/SharedPaneAccessibilityTest.java src/test/java/com/example/workutils/system/plugin/DefaultPluginConfigurationTest.java src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java src/main/resources/css/light-theme.css
git commit -m "适配设置与插件管理统一主题"

Task 5: Replace remaining descriptor Emoji with semantic icons

Files:

  • Modify: src/main/java/com/example/workutils/system/plugin/PluginDescriptor.java
  • Modify: plugin classes matching src/main/java/com/example/workutils/biz/*/*Plugin.java
  • Modify: src/main/java/com/example/workutils/WorkUtilsApplication.java
  • Modify: src/test/java/com/example/workutils/system/plugin/DefaultPluginConfigurationTest.java
  • Modify: src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java

Interfaces:

  • Changes PluginDescriptor.icon from String to AppIcon.

  • Changes getIcon(): String to getIcon(): AppIcon and all factory/embedding call sites accordingly.

  • Step 1: Add a failing descriptor type assertion

Expand limitedUiSources() to all JavaFX application UI and plugin descriptor/factory sources using Files.walk, while explicitly excluding biz/apidoc/generator/ApiDocGenerator.java because it renders document content rather than application chrome. Then add:

@Test
void descriptorCarriesSemanticIconType() {
    PluginDescriptor descriptor = PluginDescriptor.builder()
            .id("scan")
            .name("扫描功能")
            .icon(AppIcon.SCANNER)
            .build();
    AppIcon icon = descriptor.getIcon();
    assertEquals(AppIcon.SCANNER, icon);
}

Add a compile-time expectation in call sites by assigning AppIcon icon = descriptor.getIcon().

  • Step 2: Run and verify failure

Run: .\mvnw.cmd -q -Dtest=DefaultPluginConfigurationTest,UnifiedUiArchitectureTest test

Expected: FAIL/compile failure while descriptors still return strings.

  • Step 3: Migrate the descriptor type atomically

Update constructor, getter, all plugin declarations, MainWindow.NavItem, plugin management rows, and embed calls in one changeset. Use the semantic mappings defined in P0; do not expose Feather enum types outside system.ui.icon.

  • Step 4: Run full tests

Run: .\mvnw.cmd -q test

Expected: PASS with zero failures/errors.

  • Step 5: Commit
git add src/main/java/com/example/workutils/system/plugin src/main/java/com/example/workutils/biz src/main/java/com/example/workutils/WorkUtilsApplication.java src/test/java/com/example/workutils/system/plugin src/test/java/com/example/workutils/system/ui/UnifiedUiArchitectureTest.java
git commit -m "完成插件语义图标迁移"

Task 6: Full visual, accessibility, and regression acceptance

Files:

  • Modify only when acceptance finds a concrete defect in a previously touched P0–P3 file.
  • Update tests first for every discovered defect.

Interfaces:

  • Produces no new product API; this task validates the approved design and guards.

  • Step 1: Run all automated gates fresh

Run: .\mvnw.cmd -q test

Run: .\mvnw.cmd -q -DskipTests compile

Run: git diff --check

Expected: all exit 0, zero test failures/errors.

  • Step 2: Run repository scans

Run: rg -n 'Microsoft YaHei|setBtnLoading\(|new ProgressIndicator\(|⚙️|🛠|▶' src/main/java/com/example/workutils

Expected: no application-chrome matches. Document-content matches are allowed only where UnifiedUiArchitectureTest explicitly excludes them.

  • Step 3: Capture the full read-only screenshot matrix

Capture welcome plus every enabled plugin at 1440px expanded, 1440px collapsed, and 1024px expanded. For API export also capture a controlled loading state. Use non-sensitive fixture/sample data and do not trigger external/file-changing operations.

  • Step 4: Compare against the approved visual baseline

Place the approved reference and each implementation screenshot side by side at matching viewport/state. Check header 48px, rail 214/56px, unique settings location, type scale, icon baseline, 8px spacing rhythm, control height, row height, border/radius, focus visibility, loading stability, and clipping.

  • Step 5: Keyboard/accessibility smoke test

Tab through header settings, navigation, primary form controls, action buttons, cancel controls where real, tabs, history actions, and collapsed-rail tooltips. Confirm accessible text changes with operation state and focus never disappears.

  • Step 6: Fix defects through red-green cycles

For each defect: add one failing focused test, run it to confirm failure, make the smallest P0–P3 file change, rerun the focused test, then rerun the full gate. Do not bundle unrelated visual polish.

  • Step 7: Commit final verified fixes
git add src/main src/test
git commit -m "完成统一 UI 视觉验收"

If acceptance requires no code changes, do not create an empty commit.

P3 Completion Gate

Completion requires fresh evidence from full tests, compile, git diff --check, repository scans, the complete screenshot matrix, side-by-side reference comparisons, and keyboard/accessibility smoke checks. Do not claim the unified UI complete from automated tests alone.