From a39e04329e00d3a35d2b9b58a00ca8a6b66dd67f Mon Sep 17 00:00:00 2001 From: funman300 Date: Tue, 7 Jul 2026 16:01:25 -0700 Subject: [PATCH] fix(engine): force full board repaint when the decor-view poller fires (#130) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The #152 poller fixes resolution + layout on a missed fold/unfold, but a transient clip could survive if card sprites held stale visuals after geometry converged. Emit StateChangedEvent alongside the synthetic WindowResized so card_plugin re-renders every sprite from scratch — silent self-heal, no player-facing prompt. Co-Authored-By: Claude Fable 5 --- solitaire_engine/src/safe_area.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/solitaire_engine/src/safe_area.rs b/solitaire_engine/src/safe_area.rs index bab5ede..ebfcc79 100644 --- a/solitaire_engine/src/safe_area.rs +++ b/solitaire_engine/src/safe_area.rs @@ -82,7 +82,8 @@ impl Plugin for SafeAreaInsetsPlugin { ); #[cfg(target_os = "android")] - app.init_resource::() + app.add_message::() + .init_resource::() .add_systems(Update, android::refresh_insets) .add_systems(Update, android::rearm_on_resumed) .add_systems(Update, android::refresh_surface_size); @@ -330,11 +331,16 @@ mod android { /// `on_window_resized` in `table_plugin` recomputes the board layout, /// 3. re-arms the inset poller, because a screen change almost always /// moves the system bars too — covering the "re-poll never fires" - /// hole left open in #116. + /// hole left open in #116, + /// 4. emits `StateChangedEvent` so `card_plugin`'s sync pipeline + /// re-renders every card sprite from scratch — belt-and-braces for + /// the transient tableau clip of #130, where geometry converged but + /// stale card visuals survived the relayout. pub(super) fn refresh_surface_size( mut frame: Local, mut windows: Query<(Entity, &mut Window)>, mut resize_events: MessageWriter, + mut state_events: MessageWriter, mut poll: ResMut, ) { const POLL_INTERVAL_FRAMES: u32 = 30; // ~0.5 s @ 60 fps @@ -381,6 +387,7 @@ mod android { width: decor_w as f32 / scale, height: decor_h as f32 / scale, }); + state_events.write(crate::events::StateChangedEvent); poll.0 = 0; }