diff --git a/PlotLine/Hubs/WordCompanionFollowHub.cs b/PlotLine/Hubs/WordCompanionFollowHub.cs index 817f9b7..a5e1753 100644 --- a/PlotLine/Hubs/WordCompanionFollowHub.cs +++ b/PlotLine/Hubs/WordCompanionFollowHub.cs @@ -14,6 +14,7 @@ public sealed class WordCompanionFollowHub( IOnboardingRepository onboarding, IManuscriptScanPreviewStore scanStore, IOnboardingService onboardingService, + IOnboardingBuildRepository onboardingBuilds, ILogger logger) : Hub { public override async Task OnConnectedAsync() @@ -223,13 +224,55 @@ public sealed class WordCompanionFollowHub( var companionConnectionId = await presence.GetCompanionConnectionIdAsync(userId); if (!string.IsNullOrWhiteSpace(companionConnectionId)) { + await onboardingBuilds.MarkMarkerSyncSentAsync(result.BuildID); await Clients.Client(companionConnectionId).SendAsync("UpdateOnboardingBuildMarkers", result); } + else + { + await onboardingBuilds.MarkMarkerSyncFailedAsync(result.BuildID, "The Word Companion disconnected before marker sync could be sent."); + await Clients.Group(PresenceGroup(userId)).SendAsync("OnboardingBuildProgress", new OnboardingBuildProgress + { + Status = "Failed", + Message = "The Word Companion disconnected before PlotDirector could update and save Word markers.", + PercentComplete = 90, + ChaptersCreated = result.ChaptersCreated, + ScenesCreated = result.ScenesCreated, + CharactersCreated = result.CharactersCreated + result.CharactersReused, + SceneAppearancesCreated = result.SceneAppearancesCreated, + PreviewID = previewId + }); + } - await Clients.Group(PresenceGroup(userId)).SendAsync("OnboardingBuildCompleted", result); return result; } + public async Task CompleteOnboardingBuildMarkerSync(int buildId) + { + var userId = RequireUserId(); + await onboardingBuilds.MarkMarkerSyncCompletedAsync(buildId); + await Clients.Group(PresenceGroup(userId)).SendAsync("OnboardingBuildProgress", new OnboardingBuildProgress + { + Status = "Complete", + Message = "Manuscript structure has been created and saved. Word and this browser page may now be closed.", + PercentComplete = 100 + }); + await Clients.Group(PresenceGroup(userId)).SendAsync("OnboardingBuildMarkerSyncCompleted", new { buildId }); + } + + public async Task FailOnboardingBuildMarkerSync(int buildId, string message) + { + var userId = RequireUserId(); + await onboardingBuilds.MarkMarkerSyncFailedAsync(buildId, message); + await Clients.Group(PresenceGroup(userId)).SendAsync("OnboardingBuildProgress", new OnboardingBuildProgress + { + Status = "Failed", + Message = string.IsNullOrWhiteSpace(message) + ? "Word marker sync failed. Keep Word open and try again." + : message, + PercentComplete = 90 + }); + } + public override async Task OnDisconnectedAsync(Exception? exception) { int? disconnectedUserId = null; diff --git a/PlotLine/Views/Onboarding/BuildComplete.cshtml b/PlotLine/Views/Onboarding/BuildComplete.cshtml index ef3b646..ac18b04 100644 --- a/PlotLine/Views/Onboarding/BuildComplete.cshtml +++ b/PlotLine/Views/Onboarding/BuildComplete.cshtml @@ -1,12 +1,12 @@ @model OnboardingManuscriptBuildResult @{ - ViewData["Title"] = "Chapters prepared"; + ViewData["Title"] = "Manuscript imported"; }
    - @foreach (var label in new[] { "Welcome", "Writing Preferences", "Project", "Book", "Connect Word", "Scan", "Review", "Prepare Chapters", "Complete" }) + @foreach (var label in new[] { "Welcome", "Writing Preferences", "Project", "Book", "Connect Word", "Scan", "Review", "Create Structure", "Complete" }) {
  1. @@ -15,12 +15,12 @@ }
-

Prepare Chapters

+

Core Import Complete

-

Your chapters are ready.

+

Your manuscript has been imported.

-

@(Model.AlreadyBuilt ? "These chapters have already been prepared in PlotDirector, so nothing was duplicated." : "PlotDirector prepared the approved chapters. Story Intelligence will create scenes after you review the analysis.")

+

@(Model.AlreadyBuilt ? "This manuscript structure has already been created in PlotDirector, so nothing was duplicated." : "PlotDirector created the approved chapters and scenes, updated the Word markers, and saved the manuscript. Word and this browser page may now be closed.")

@if (!string.IsNullOrWhiteSpace(Model.MarkerWarning)) {

@Model.MarkerWarning

@@ -33,7 +33,7 @@ @Model.ChaptersCreated
- Scenes created now + Scenes @Model.ScenesCreated
@@ -47,12 +47,13 @@
-

Next: analyse manuscript

-

Story Intelligence will detect scenes from the approved chapter text. You will review the results before PlotDirector creates scenes.

+

Optional: analyse manuscript

+

Story Intelligence can now enrich the existing scenes with summaries, context, relationships, knowledge, timeline details and metrics. You can analyse now or return later.

diff --git a/PlotLine/Views/Onboarding/Index.cshtml b/PlotLine/Views/Onboarding/Index.cshtml index e8e525e..6ddde7a 100644 --- a/PlotLine/Views/Onboarding/Index.cshtml +++ b/PlotLine/Views/Onboarding/Index.cshtml @@ -300,8 +300,8 @@ {
-

Review saved. PlotDirector can now analyse the approved chapters.

-

Next: analyse the manuscript and review suggested scenes.

+

Review saved. PlotDirector can now import the approved manuscript structure.

+

Next: detect scene boundaries, create PlotDirector scenes, then update and save Word markers.