using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using RpgRoller.Contracts; namespace RpgRoller.Components.Pages.HomeControls; [ExcludeFromCodeCoverage] public partial class CampaignLogPanel { protected override async Task OnAfterRenderAsync(bool firstRender) { var currentLastRollId = CampaignLog.LastOrDefault()?.RollId; if (IsCampaignDataLoading || CampaignLog.Count == 0) { LastRenderedLogCount = CampaignLog.Count; LastRenderedLogRollId = currentLastRollId; return; } if (firstRender || CampaignLog.Count > LastRenderedLogCount || currentLastRollId != LastRenderedLogRollId) { try { await JS.InvokeVoidAsync("rpgRollerApi.scrollElementToBottom", LogPanelRef); } catch (JSDisconnectedException) { } catch (InvalidOperationException ex) when (ex.Message.Contains("statically rendered", StringComparison.OrdinalIgnoreCase)) { } } LastRenderedLogCount = CampaignLog.Count; LastRenderedLogRollId = currentLastRollId; } [Inject] private IJSRuntime JS { get; set; } = null!; private ElementReference LogPanelRef { get; set; } private int LastRenderedLogCount { get; set; } private Guid? LastRenderedLogRollId { get; set; } [Parameter] public bool IsCampaignDataLoading { get; set; } [Parameter] public IReadOnlyList CampaignLog { get; set; } = []; [Parameter] public Guid? ExpandedRollId { get; set; } [Parameter] public Guid? FreshRollId { get; set; } [Parameter] public EventCallback ToggleRollDetailRequested { get; set; } [Parameter] public Func ResolveRollDetail { get; set; } = _ => null; [Parameter] public Func IsRollDetailLoading { get; set; } = _ => false; [Parameter] public Func GetRollDetailError { get; set; } = _ => null; private static IReadOnlyList GetEventBadges(CampaignLogListEntry entry) { return (entry.EventBadges ?? []) .Select(ToEventBadgeView) .Where(badge => badge is not null) .Cast() .ToArray(); } private static bool HasSummary(CampaignLogListEntry entry) { return (entry.EventBadges?.Length ?? 0) > 0 || !string.IsNullOrWhiteSpace(entry.SummaryText); } private static EventBadgeView? ToEventBadgeView(string code) { return code switch { "w6" => new EventBadgeView("Wild 6", "positive"), "w1" => new EventBadgeView("Wild 1", "danger"), "n20" => new EventBadgeView("Nat 20", "positive"), "n1" => new EventBadgeView("Nat 1", "danger"), "rf" => new EventBadgeView("Fumble", "danger"), "r100" => new EventBadgeView("100", "rare"), "r66" => new EventBadgeView("66", "rare"), _ => null }; } private static string LogEntryCssClass(CampaignLogListEntry entry, bool isExpanded, bool isFresh) { var classes = new List { entry.VisibilityStyle }; if (isExpanded) classes.Add("expanded"); if (isFresh) classes.Add("fresh"); return string.Join(" ", classes); } private sealed record EventBadgeView(string Label, string Tone); }