Extract workspace state holder

This commit is contained in:
2026-04-04 23:55:19 +02:00
parent 17b049d2ca
commit 4f77d4a702
4 changed files with 218 additions and 139 deletions

View File

@@ -0,0 +1,150 @@
using RpgRoller.Contracts;
using RpgRoller.Domain;
namespace RpgRoller.Components.Pages;
public sealed class WorkspaceState
{
public UserSummary? User { get; set; }
public Guid? ActiveCharacterId { get; set; }
public Guid? SelectedCampaignId { get; set; }
public CampaignRoster? SelectedCampaign { get; set; }
public List<CampaignSummary> Campaigns { get; set; } = [];
public List<CampaignOption> CharacterCampaignOptions { get; set; } = [];
public List<CharacterSheetSkill> SelectedCharacterSkills { get; set; } = [];
public List<CharacterSheetSkillGroup> SelectedCharacterSkillGroups { get; set; } = [];
public List<CampaignLogListEntry> CampaignLog { get; set; } = [];
public List<RulesetDefinition> Rulesets { get; set; } = [];
public List<AdminUserSummary> AdminUsers { get; set; } = [];
public Guid? SelectedCharacterId { get; set; }
public RollResult? LastRoll { get; set; }
public List<string> KnownUsernames { get; set; } = [];
public string RollVisibility { get; set; } = "public";
public bool IsMutating { get; set; }
public bool IsCampaignDataLoading { get; set; }
public bool IsAdminDataLoading { get; set; }
public bool HasLoadedAdminUsers { get; set; }
public bool HasHealthIssue { get; set; }
public string HealthIssueMessage { get; set; } = "Retry to restore the API connection.";
public List<WorkspaceToast> Toasts { get; } = [];
public string CurrentScreen { get; set; } = "play";
public string MobilePanel { get; set; } = "character";
public string ConnectionState { get; set; } = "offline";
public string LiveAnnouncement { get; set; } = string.Empty;
public bool IsScreenMenuOpen { get; set; }
public bool ShowCreateCharacterModal { get; set; }
public bool ShowEditCharacterModal { get; set; }
public bool CanEditCharacterOwner { get; set; }
public Guid? EditingCharacterId { get; set; }
public CharacterFormModel CreateCharacterInitialModel { get; set; } = new();
public CharacterFormModel EditCharacterInitialModel { get; set; } = new();
public int CreateCharacterFormVersion { get; set; }
public int EditCharacterFormVersion { get; set; }
public bool StateRefreshInProgress { get; set; }
public bool HasInteractiveRenderStarted { get; set; }
public CampaignStateSnapshot? CurrentCampaignState { get; set; }
public Guid? CampaignLogCursor { get; set; }
public Guid? ExpandedCampaignLogRollId { get; set; }
public Guid? FreshCampaignLogRollId { get; set; }
public Dictionary<Guid, CampaignRollDetail> CampaignLogDetails { get; } = [];
public HashSet<Guid> CampaignLogDetailsLoading { get; } = [];
public Dictionary<Guid, string> CampaignLogDetailErrors { get; } = [];
public string? SelectedCampaignName => SelectedCampaign?.Name ?? Campaigns.FirstOrDefault(campaign => campaign.Id == SelectedCampaignId)?.Name;
public CharacterSummary? SelectedCharacter =>
SelectedCampaign?.Characters.FirstOrDefault(character => character.Id == SelectedCharacterId);
public CampaignRoster? PlaySelectedCampaign
{
get
{
if (SelectedCampaign is null)
return null;
if (User is null)
return new CampaignRoster(SelectedCampaign.Id, SelectedCampaign.Name, SelectedCampaign.RulesetId, SelectedCampaign.Gm, []);
var ownedCharacters = SelectedCampaign.Characters
.Where(character => character.OwnerUserId == User.Id)
.ToArray();
return new CampaignRoster(
SelectedCampaign.Id,
SelectedCampaign.Name,
SelectedCampaign.RulesetId,
SelectedCampaign.Gm,
ownedCharacters);
}
}
public CharacterSummary? PlaySelectedCharacter
{
get
{
var playSelectedCampaign = PlaySelectedCampaign;
if (playSelectedCampaign is null || playSelectedCampaign.Characters.Length == 0)
return null;
if (SelectedCharacterId.HasValue)
{
var selectedCharacter = playSelectedCampaign.Characters.FirstOrDefault(character => character.Id == SelectedCharacterId.Value);
if (selectedCharacter is not null)
return selectedCharacter;
}
if (ActiveCharacterId.HasValue)
{
var activeCharacter = playSelectedCampaign.Characters.FirstOrDefault(character => character.Id == ActiveCharacterId.Value);
if (activeCharacter is not null)
return activeCharacter;
}
return playSelectedCampaign.Characters[0];
}
}
public Guid? PlaySelectedCharacterId => PlaySelectedCharacter?.Id;
public List<CharacterSheetSkill> PlaySelectedCharacterSkills =>
PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue ? [] : SelectedCharacterSkills;
public List<CharacterSheetSkillGroup> PlaySelectedCharacterSkillGroups =>
PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue ? [] : SelectedCharacterSkillGroups;
public List<CampaignLogListEntry> PlayVisibleCampaignLog => CampaignLog;
public bool IsCurrentUserGm =>
SelectedCampaign is not null && User is not null && SelectedCampaign.Gm.Id == User.Id;
public bool IsCurrentUserAdmin =>
User is not null && User.Roles.Contains(UserRoles.Admin, StringComparer.OrdinalIgnoreCase);
public bool CanDeleteSelectedCampaign =>
SelectedCampaign is not null && User is not null && (SelectedCampaign.Gm.Id == User.Id || IsCurrentUserAdmin);
public bool IsSelectedCampaignD6 =>
string.Equals(SelectedCampaign?.RulesetId, "d6", StringComparison.OrdinalIgnoreCase);
public bool IsPlayScreen => string.Equals(CurrentScreen, "play", StringComparison.OrdinalIgnoreCase);
public bool IsManagementScreen => string.Equals(CurrentScreen, "management", StringComparison.OrdinalIgnoreCase);
public bool IsAdminScreen => string.Equals(CurrentScreen, "admin", StringComparison.OrdinalIgnoreCase);
public string ConnectionStateLabel => ConnectionState switch
{
"connected" => "Connected",
"reconnecting" => "Reconnecting",
_ => "Offline fallback"
};
public string ConnectionStateCssClass => ConnectionState switch
{
"connected" => "ok",
"reconnecting" => "warn",
_ => "offline"
};
public string AppCssClass => IsPlayScreen ? "rr-app app-play" : "rr-app";
}