Commit Graph

9 Commits

Author SHA1 Message Date
funman300 abda354562 feat(engine): emit SyncCompleteEvent on pull resolve
ARCHITECTURE.md §5 lists SyncCompleteEvent(Result<SyncResponse, String>) as
a cross-system event, but it was never declared or fired. Add the message
to events.rs, register it in SyncPlugin, and emit it from poll_pull_result
on both the success path (carrying the merged payload + conflicts as
SyncResponse) and the failure path (carrying the user-facing error
message). UI/persistence systems can now react to sync completion without
polling SyncStatusResource.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 21:14:21 +00:00
funman300 7cda2a9f1a fix(engine): resolve all clippy warnings introduced by PNG asset pipeline
CI / Test & Lint (push) Failing after 1m34s
CI / Release Build (push) Has been skipped
- Collapse nested-if patterns into let-chains across 13 plugins (42 instances)
- Add #[allow(clippy::too_many_arguments)] to 5 Bevy systems in card_plugin
  and input_plugin where ECS parameter count exceeds the lint threshold
- Gate Theme import in table_plugin under #[cfg(test)] — only used by
  test-only colour helpers; removing the unconditional import silences the
  unused-import lint without breaking the test suite
- Wrap ButtonInput<MouseButton> in Option<> in update_input_platform so that
  tests using MinimalPlugins (no InputPlugin) no longer panic on startup

All 789 tests pass; cargo clippy --workspace -- -D warnings is clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 03:35:41 +00:00
funman300 41d75b50de feat/fix/perf(engine,data,assetgen): ambient audio, sync bug fixes, hot-path cleanup
**ambient_loop.wav (task 5)**
- solitaire_assetgen: add ambient_loop() synthesizer — 5 s seamless loop,
  55 Hz drone with 2nd/3rd harmonics, 0.2 Hz LFO breath, 16-bit mono 44100 Hz
- audio_plugin: load ambient_loop.wav via include_bytes!() replacing the
  card_flip.wav placeholder; decouple start_ambient_loop() from SoundLibrary

**sync bug fixes (task 11)**
- sync_plugin: LocalOnlyProvider returning UnsupportedPlatform now sets
  SyncStatus::Idle instead of displaying a misleading "Sync not configured" error
- sync_client: extract_pull_body / extract_push_body now return SyncError::Auth
  only for HTTP 401/403; all other non-2xx statuses return SyncError::Network
- sync_plugin: push_on_exit now logs a warn! on failure instead of silently
  discarding the result

**hot-path performance (task 12)**
- card_plugin: card_positions() now returns &Card references (lifetime-bound to
  GameState) instead of owned Card clones — eliminates 52 Card clones per
  sync_cards() call (runs every animation frame)
- input_plugin: card_position() takes &PileType instead of PileType, eliminating
  PileType copies at every drag hit-test call site
- animation_plugin: eliminate intermediate AnimSpeed clone in handle_win_cascade()

**docs (tasks 11, 13)**
- docs/sync_test_runbook.md: manual test runbook for cross-machine sync
- docs/android_investigation.md: cargo-mobile2 port investigation and effort estimate

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 23:51:58 +00:00
funman300 648cd44387 chore(deps): migrate to Bevy 0.17
- Event/EventReader/EventWriter renamed to Message/MessageReader/MessageWriter
- add_event → add_message for all 67 call sites
- ScrollPosition changed to tuple struct ScrollPosition(Vec2)
- CursorIcon import moved from bevy::winit::cursor to bevy::window
- WindowResolution::from((f32,f32)) removed — use (u32,u32) tuple
- World::send_event → World::write_message in test code

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:04:44 -07:00
funman300 59a023ed5e chore(workspace): fix all clippy warnings in test code
Resolves 15 violations found by `cargo clippy --workspace --tests -D warnings`:
- Remove unused imports (Card, Rank) in cursor_plugin tests
- Replace absurd i32::MAX comparison with a meaningful >= 0 check
- Use range .contains() instead of manual >= && <= (manual_range_contains)
- Move impl FromRequestParts before test module in middleware.rs (items_after_test_module)
- Move _VEC3_REFERENCED const before test module in input_plugin.rs
- Convert runtime assert on constant to const { assert!(...) }
- Use .contains() instead of .iter().any() for slice membership
- Replace .get(...).is_none() with !.contains_key(...) in HashMap checks
- Collapse Default::default() + field assignment into struct literal initializers
  across solitaire_sync, solitaire_data, and solitaire_engine test helpers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 18:02:27 +00:00
root 9a4071c74e refactor(engine): propagate SyncError through pull task instead of String
PullTask and PullTaskResult now carry Result<SyncPayload, SyncError>
instead of Result<SyncPayload, String>. poll_pull_result pattern-matches
on the error variant to show user-friendly messages:
  Network  → "Can't reach server — check your connection"
  Auth     → "Login expired — tap Sync Now after re-logging in"
  Other    → original error Display

Also removed the stale TODO comment from SyncError in lib.rs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 01:05:59 +00:00
root 20db4b312a feat(engine): ManualSyncRequestEvent + Sync Now button in settings
- Added ManualSyncRequestEvent to events.rs (exported from lib.rs).
- SyncPlugin now handles ManualSyncRequestEvent: if no pull is in
  flight, spawns a new AsyncComputeTaskPool task and sets status to
  Syncing. Ignores duplicate requests while a pull is active.
- Settings panel "Sync" section now shows the status text alongside a
  "Sync Now" button that fires ManualSyncRequestEvent.
- Cleaned up stale doc comment in input_plugin.rs (Esc pause note).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 00:03:24 +00:00
root 3c01cef5f3 feat(engine): implement Draw Mode, Theme, and Music Volume settings
Settings panel "coming soon" stubs replaced with live controls:

- Draw Mode toggle (Draw 1 / Draw 3): new games read draw_mode from
  SettingsResource instead of the previous game's mode. Falls back to
  the current game's mode in headless/test contexts where SettingsPlugin
  is absent.

- Theme selector (Green → Blue → Dark → Green): SettingsChangedEvent
  drives TablePlugin's background Sprite colour so the table re-colours
  immediately without a restart.

- Music Volume [−]/[+]: dedicated kira sub-tracks created for SFX and
  music on startup. SFX sounds are routed to the SFX track; the music
  track exists for future ambient audio. Both volumes are set on
  SettingsChangedEvent and at startup.

Also fixed: time_attack timer_expiry test double-fires when
MinimalPlugins time delta is nonzero — removed the intermediate
0.001-remaining update step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 23:53:48 +00:00
root 34ba4dc6ed feat(workspace): full server + sync implementation, all tests green
- solitaire_server: Axum auth, sync push/pull, leaderboard, daily
  challenge, account deletion, JWT middleware, rate limiting via
  tower_governor, SQLite migrations, health endpoint
- solitaire_server: expose build_test_router (no rate limiting) so
  integration tests work without a peer IP in oneshot requests
- solitaire_sync: SyncPayload, merge logic, shared API types
- solitaire_data: SyncProvider trait, LocalOnlyProvider,
  SolitaireServerClient, auth_tokens keyring integration, blanket
  Box<dyn SyncProvider> impl
- solitaire_data/settings: derive Default on SyncBackend (clippy fix)
- .sqlx/: offline query cache so server compiles without a live DB
- sqlx: removed non-existent "offline" feature flag
- keyring v2: fixed Entry::new() returning Result<Entry>
- sqlx 0.8: all SQLite TEXT columns wrapped in Option<T>
- Integration tests: max_connections(1) on in-memory pool so all
  connections share the same schema

All 191 tests pass; cargo clippy -D warnings clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 23:32:56 +00:00