feat(sync): re-auth prompt on expired session + server deployment artifacts
On auth failure during pull (access + refresh both expired), sync_plugin now fires SyncConfigureRequestEvent so the Connect modal reopens automatically instead of leaving the player with a silent error status. The modal's existing double-open guard keeps repeated failures idempotent. Also removes the unused SyncAuthResultEvent (results handled inline in SyncSetupPlugin via PendingAuthTask polling) and adds server deployment artifacts: Dockerfile (multi-stage, SQLX_OFFLINE), docker-compose.yml (SQLite volume, health-check), and .env.example for local development setup. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -134,12 +134,6 @@ pub struct ManualSyncRequestEvent;
|
||||
#[derive(Message, Debug, Clone, Copy, Default)]
|
||||
pub struct SyncConfigureRequestEvent;
|
||||
|
||||
/// Result of an async login or register attempt. `Ok(username)` on success;
|
||||
/// `Err(human-readable message)` on failure. Consumed by `SyncSetupPlugin`
|
||||
/// to update the in-world provider and surface errors in the modal.
|
||||
#[derive(Message, Debug, Clone)]
|
||||
pub struct SyncAuthResultEvent(pub Result<String, String>);
|
||||
|
||||
/// Request to disconnect from the current sync backend, clear stored
|
||||
/// credentials, and reset to `SyncBackend::Local`. Fired by the "Disconnect"
|
||||
/// button in the Settings sync section.
|
||||
|
||||
@@ -25,7 +25,10 @@ use solitaire_data::{
|
||||
use solitaire_sync::{merge, SyncPayload, SyncResponse};
|
||||
|
||||
use crate::achievement_plugin::{AchievementsResource, AchievementsStoragePath};
|
||||
use crate::events::{GameWonEvent, ManualSyncRequestEvent, SyncCompleteEvent};
|
||||
use crate::events::{
|
||||
GameWonEvent, InfoToastEvent, ManualSyncRequestEvent, SyncCompleteEvent,
|
||||
SyncConfigureRequestEvent,
|
||||
};
|
||||
use crate::game_plugin::RecordingReplay;
|
||||
use crate::progress_plugin::{ProgressResource, ProgressStoragePath};
|
||||
use crate::resources::{GameStateResource, SyncStatus, SyncStatusResource};
|
||||
@@ -104,6 +107,8 @@ impl Plugin for SyncPlugin {
|
||||
.init_resource::<PendingReplayUpload>()
|
||||
.add_message::<ManualSyncRequestEvent>()
|
||||
.add_message::<SyncCompleteEvent>()
|
||||
.add_message::<SyncConfigureRequestEvent>()
|
||||
.add_message::<InfoToastEvent>()
|
||||
.add_systems(Startup, start_pull)
|
||||
.add_systems(
|
||||
Update,
|
||||
@@ -191,6 +196,8 @@ fn poll_pull_result(
|
||||
mut progress: ResMut<ProgressResource>,
|
||||
progress_path: Res<ProgressStoragePath>,
|
||||
mut complete_writer: MessageWriter<SyncCompleteEvent>,
|
||||
mut configure_sync: MessageWriter<SyncConfigureRequestEvent>,
|
||||
mut toast: MessageWriter<InfoToastEvent>,
|
||||
) {
|
||||
let Some(task) = task_res.0.as_mut() else {
|
||||
return;
|
||||
@@ -240,10 +247,19 @@ fn poll_pull_result(
|
||||
warn!("sync pull failed: {e}");
|
||||
let msg = match &e {
|
||||
SyncError::Network(_) => "Can't reach server — check your connection".to_string(),
|
||||
SyncError::Auth(_) => "Login expired — tap Sync Now after re-logging in".to_string(),
|
||||
SyncError::Auth(_) => "Session expired — please reconnect".to_string(),
|
||||
SyncError::Serialization(_) => format!("Unexpected server response: {e}"),
|
||||
SyncError::UnsupportedPlatform => unreachable!("handled above"),
|
||||
};
|
||||
// On auth failure, reopen the Connect modal so the player can
|
||||
// re-enter credentials without having to navigate through Settings.
|
||||
// `open_sync_setup_modal` is idempotent — it ignores the event when
|
||||
// the modal is already on screen, so repeated pull failures don't
|
||||
// stack multiple modals.
|
||||
if matches!(e, SyncError::Auth(_)) {
|
||||
toast.write(InfoToastEvent("Session expired — please reconnect".to_string()));
|
||||
configure_sync.write(SyncConfigureRequestEvent);
|
||||
}
|
||||
status.0 = SyncStatus::Error(msg.clone());
|
||||
complete_writer.write(SyncCompleteEvent(Err(msg)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user