using PlotLine.ViewModels; namespace PlotLine.Models; public sealed record StoryPosition(int ProjectId, int? BookId = null, int? ChapterId = null, int? SceneId = null) { public bool IsValid => ProjectId > 0 && (BookId is null or > 0) && (ChapterId is null or > 0) && (SceneId is null or > 0); public bool IsScenePosition => SceneId.HasValue; public static StoryPosition? FromScene(SceneEditViewModel? scene) { if (scene?.Project is null) { return null; } return new StoryPosition(scene.Project.ProjectID, scene.Book?.BookID, scene.ChapterID, scene.SceneID > 0 ? scene.SceneID : null); } public static StoryPosition? FromScene(Scene? scene, int projectId) { if (scene is null || projectId <= 0) { return null; } return new StoryPosition(projectId, scene.BookID > 0 ? scene.BookID : null, scene.ChapterID, scene.SceneID); } public static StoryPosition? FromRuntimeCurrentScene(WordCompanionRuntimeCurrentSceneRequest request) { var position = new StoryPosition(request.ProjectId, request.BookId, request.ChapterId, request.SceneId); return position.IsValid ? position : null; } public static StoryPosition? FromRuntimeCurrentScene(WordCompanionRuntimeCurrentSceneResponse? response) { if (response is null) { return null; } var position = new StoryPosition(response.ProjectId, response.BookId, response.ChapterId, response.SceneId); return position.IsValid ? position : null; } public static StoryPosition? FromTimelineSelection(int projectId, int? bookId, int? chapterId, int? sceneId) { if (projectId <= 0) { return null; } var position = new StoryPosition(projectId, bookId, chapterId, sceneId); return position.IsValid ? position : null; } public string? SceneEditUrl => SceneId.HasValue ? $"/Scenes/Edit/{SceneId.Value}" : null; }