fix: unify custom roll visibility

This commit is contained in:
2026-05-05 00:44:54 +02:00
parent f01d100740
commit f8b09be399
6 changed files with 19 additions and 8 deletions

View File

@@ -198,8 +198,8 @@ public partial class CampaignLogPanel
private string CustomRollStatusText => private string CustomRollStatusText =>
SelectedCharacterId.HasValue && !string.IsNullOrWhiteSpace(SelectedCharacterName) SelectedCharacterId.HasValue && !string.IsNullOrWhiteSpace(SelectedCharacterName)
? $"For {SelectedCharacterName} • {RollVisibilityLabel}" ? $"For {SelectedCharacterName} • Uses {RollVisibilityLabel.ToLowerInvariant()} visibility"
: "Select a character to enable"; : $"Select a character to enable • {RollVisibilityLabel} visibility selected";
private string CustomRollHelpText => SelectedCampaignRulesetId.ToLowerInvariant() switch private string CustomRollHelpText => SelectedCampaignRulesetId.ToLowerInvariant() switch
{ {

View File

@@ -59,7 +59,10 @@
</div> </div>
<div class="chip-toolbar"> <div class="chip-toolbar">
<label class="visibility-control" for="roll-visibility">Visibility</label> <label class="visibility-control" for="roll-visibility">Visibility</label>
<select id="roll-visibility" value="@(RollVisibility == "private" ? "private" : "public")" @onchange="OnRollVisibilityChangedAsync"> <select id="roll-visibility"
@bind:get="NormalizedRollVisibility"
@bind:set="OnRollVisibilityChangedAsync"
@bind:event="oninput">
<option value="public">Public</option> <option value="public">Public</option>
<option value="private">Private</option> <option value="private">Private</option>
</select> </select>

View File

@@ -70,10 +70,9 @@ public partial class CharacterPanel
await SkillUpdated.InvokeAsync(skillId); await SkillUpdated.InvokeAsync(skillId);
} }
private async Task OnRollVisibilityChangedAsync(ChangeEventArgs args) private async Task OnRollVisibilityChangedAsync(string? selectedVisibility)
{ {
var selectedVisibility = args.Value?.ToString() ?? "public"; await RollVisibilityChanged.InvokeAsync(selectedVisibility ?? "public");
await RollVisibilityChanged.InvokeAsync(selectedVisibility);
} }
private async Task RollSkillAsync(CharacterSheetSkill skill) private async Task RollSkillAsync(CharacterSheetSkill skill)
@@ -372,6 +371,9 @@ public partial class CharacterPanel
[Parameter] public EventCallback<string> RollVisibilityChanged { get; set; } [Parameter] public EventCallback<string> RollVisibilityChanged { get; set; }
private string NormalizedRollVisibility =>
string.Equals(RollVisibility, "private", StringComparison.OrdinalIgnoreCase) ? "private" : "public";
[Parameter] public Func<Guid, string> OwnerLabel { get; set; } = _ => string.Empty; [Parameter] public Func<Guid, string> OwnerLabel { get; set; } = _ => string.Empty;
[Parameter] public Func<CharacterSheetSkill, string> SkillDefinitionLabel { get; set; } = _ => string.Empty; [Parameter] public Func<CharacterSheetSkill, string> SkillDefinitionLabel { get; set; } = _ => string.Empty;

View File

@@ -171,7 +171,7 @@ public partial class Workspace : IAsyncDisposable
private WorkspaceSessionCoordinator Session => m_Session ??= new(State, Feedback, JS, ApiClient, WorkspaceQuery, private WorkspaceSessionCoordinator Session => m_Session ??= new(State, Feedback, JS, ApiClient, WorkspaceQuery,
() => IsAdminRoute, RedirectToPlayAsync, () => IsAdminRoute, RedirectToPlayAsync,
Scope.ReloadCampaignsAsync, Scope.ReloadCharacterCampaignOptionsAsync, Scope.RefreshCampaignScopeAsync, Scope.ReloadCampaignsAsync, Scope.ReloadCharacterCampaignOptionsAsync, Scope.RefreshCampaignScopeAsync,
Live.SyncStateEventsAsync, Live.StopStateEventsAsync, EnsureAdminUsersLoadedAsync, RequestRefreshAsync, Live.SyncStateEventsAsync, Live.StopStateEventsAsync, EnsureAdminUsersLoadedAsync,
Play.ResetCampaignLogDetailState, message => LoggedOut.InvokeAsync(message)); Play.ResetCampaignLogDetailState, message => LoggedOut.InvokeAsync(message));
private IReadOnlyList<AppHeaderMenuItem> HeaderMenuItems private IReadOnlyList<AppHeaderMenuItem> HeaderMenuItems

View File

@@ -14,6 +14,7 @@ public sealed class WorkspaceSessionCoordinator(
Func<Guid?, Task> reloadCampaignsAsync, Func<Guid?, Task> reloadCampaignsAsync,
Func<Task> reloadCharacterCampaignOptionsAsync, Func<Task> reloadCharacterCampaignOptionsAsync,
Func<Task> refreshCampaignScopeAsync, Func<Task> refreshCampaignScopeAsync,
Func<Task> requestRefreshAsync,
Func<Task> syncStateEventsAsync, Func<Task> syncStateEventsAsync,
Func<Task> stopStateEventsAsync, Func<Task> stopStateEventsAsync,
Func<Task> ensureAdminUsersLoadedAsync, Func<Task> ensureAdminUsersLoadedAsync,
@@ -97,6 +98,7 @@ public sealed class WorkspaceSessionCoordinator(
{ {
state.RollVisibility = NormalizeRollVisibility(visibility); state.RollVisibility = NormalizeRollVisibility(visibility);
await js.InvokeVoidAsync("rpgRollerApi.setSessionValue", RollVisibilitySessionKey, state.RollVisibility); await js.InvokeVoidAsync("rpgRollerApi.setSessionValue", RollVisibilitySessionKey, state.RollVisibility);
await requestRefreshAsync();
} }
public void ClearAuthenticatedState() public void ClearAuthenticatedState()

View File

@@ -503,6 +503,8 @@ const tests = [
}), }),
"Expected custom roll composer to be interactive." "Expected custom roll composer to be interactive."
); );
assert.match(await elementText(driver, ".custom-roll-composer-head .muted"), /uses public visibility/i);
await fillInput(driver, "#custom-roll-expression", "bad"); await fillInput(driver, "#custom-roll-expression", "bad");
await clickText(driver, ".custom-roll-composer button", "Roll"); await clickText(driver, ".custom-roll-composer button", "Roll");
@@ -525,7 +527,9 @@ const tests = [
() => driver.executeScript(() => { () => driver.executeScript(() => {
const className = document.querySelector("#custom-roll-expression")?.className || ""; const className = document.querySelector("#custom-roll-expression")?.className || "";
const firstLogEntry = document.querySelector(".log-panel .log-entry"); const firstLogEntry = document.querySelector(".log-panel .log-entry");
return !/error/.test(className) && Boolean(firstLogEntry?.textContent.includes("Custom roll")); return !/error/.test(className) &&
Boolean(firstLogEntry?.textContent.includes("Custom roll")) &&
Boolean(firstLogEntry?.textContent.includes("Public"));
}), }),
"Expected successful custom roll entry." "Expected successful custom roll entry."
); );