diff --git a/README.md b/README.md index e39a4bd..d2d5406 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ Gameplay capabilities now include: - Role-aware authorization with admin role support (including admin user/role management) - Campaign deletion by campaign owner or admin (unlinks characters from the campaign and clears campaign log entries) - User deletion by admin also deletes campaigns owned by that user and unlinks all characters from those deleted campaigns +- Play screen visibility is owner-scoped: only owned characters are listed, and private log entries are visible only to the roller - Campaign management owner labels use account display names (no GUID fallback rendering) - Character edit flow supports unlinking from campaigns (owner/GM/admin) and assigning to any existing campaign via expanded campaign options - Campaign management supports character deletion by character owner or admin diff --git a/RpgRoller/Components/Pages/Workspace.razor b/RpgRoller/Components/Pages/Workspace.razor index baa2a99..bf178e5 100644 --- a/RpgRoller/Components/Pages/Workspace.razor +++ b/RpgRoller/Components/Pages/Workspace.razor @@ -33,12 +33,12 @@
SelectedCampaign?.Characters.FirstOrDefault(c => c.Id == SelectedCharacterId); + private CampaignDetails? PlaySelectedCampaign + { + get + { + if (SelectedCampaign is null) + return null; + + if (User is null) + return new CampaignDetails(SelectedCampaign.Id, SelectedCampaign.Name, SelectedCampaign.RulesetId, SelectedCampaign.Gm, [], [], []); + + var ownedCharacters = SelectedCampaign.Characters + .Where(character => character.OwnerUserId == User.Id) + .ToList(); + var ownedCharacterIds = ownedCharacters.Select(character => character.Id).ToHashSet(); + var ownedSkillGroups = SelectedCampaign.SkillGroups + .Where(group => ownedCharacterIds.Contains(group.CharacterId)) + .ToList(); + var ownedSkills = SelectedCampaign.Skills + .Where(skill => ownedCharacterIds.Contains(skill.CharacterId)) + .ToList(); + + return new CampaignDetails( + SelectedCampaign.Id, + SelectedCampaign.Name, + SelectedCampaign.RulesetId, + SelectedCampaign.Gm, + ownedCharacters, + ownedSkillGroups, + ownedSkills); + } + } + + private CharacterSummary? PlaySelectedCharacter + { + get + { + if (PlaySelectedCampaign is null || PlaySelectedCampaign.Characters.Count == 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]; + } + } + + private Guid? PlaySelectedCharacterId => PlaySelectedCharacter?.Id; + + private List PlaySelectedCharacterSkills => + PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue + ? [] + : PlaySelectedCampaign.Skills + .Where(skill => skill.CharacterId == PlaySelectedCharacterId.Value) + .OrderBy(skill => skill.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); + + private List PlaySelectedCharacterSkillGroups => + PlaySelectedCampaign is null || !PlaySelectedCharacterId.HasValue + ? [] + : PlaySelectedCampaign.SkillGroups + .Where(group => group.CharacterId == PlaySelectedCharacterId.Value) + .OrderBy(group => group.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); + + private List PlayVisibleCampaignLog => + User is null + ? CampaignLog.Where(entry => !string.Equals(entry.Visibility, "private", StringComparison.OrdinalIgnoreCase)).ToList() + : CampaignLog + .Where(entry => + !string.Equals(entry.Visibility, "private", StringComparison.OrdinalIgnoreCase) || + entry.RollerUserId == User.Id) + .ToList(); + private bool IsCurrentUserGm => SelectedCampaign is not null && User is not null && SelectedCampaign.Gm.Id == User.Id;