diff options
Diffstat (limited to 'MatrixUtils.Web/Shared')
-rw-r--r-- | MatrixUtils.Web/Shared/ActivityGraph.razor | 148 | ||||
-rw-r--r-- | MatrixUtils.Web/Shared/ActivityGraph.razor.css | 16 | ||||
-rw-r--r-- | MatrixUtils.Web/Shared/MainLayout.razor | 4 | ||||
-rw-r--r-- | MatrixUtils.Web/Shared/MxcImage.razor | 3 | ||||
-rw-r--r-- | MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor | 4 | ||||
-rw-r--r-- | MatrixUtils.Web/Shared/UserListItem.razor | 6 |
6 files changed, 174 insertions, 7 deletions
diff --git a/MatrixUtils.Web/Shared/ActivityGraph.razor b/MatrixUtils.Web/Shared/ActivityGraph.razor new file mode 100644 index 0000000..51fb539 --- /dev/null +++ b/MatrixUtils.Web/Shared/ActivityGraph.razor @@ -0,0 +1,148 @@ +@using System.Drawing +@using System.Runtime.InteropServices +@using System.Diagnostics + +@if (Data is { Count: > 0 }) +{ + @* 12*5=60 *@ + <div style="display: grid; grid-template-columns: 35px repeat(60, 1.5em); grid-template-rows: 1.5em repeat(7, 1.5em); gap: 0;"> + @* row 0: month labels with colspan *@ + @* @foreach (var month in Enumerable.Range(1, 12)) *@ + @* { *@ + @* <div style="grid-row: 1; grid-column: @((int)(month * 4.3) + 1);"> *@ + @* <span aria-hidden="true">@(new DateTime(2021, month, 1).ToString("MMM")[..3])</span> *@ + @* </div> *@ + @* } *@ + + @* column 0: day labels *@ + @* @for (var i = 0; i < 7; i++) *@ + @* { *@ + @* <div style="text-align: left; grid-column: 1; grid-row: @(i + 2)"> *@ + @* @(((DayOfWeek)i).ToString()[..3]) *@ + @* </div> *@ + @* } *@ + + + <div style="grid-row: 1; grid-column: 5;">Jan</div> + <div style="grid-row: 1; grid-column: 9;">Feb</div> + <div style="grid-row: 1; grid-column: 13;">Mar</div> + <div style="grid-row: 1; grid-column: 18;">Apr</div> + <div style="grid-row: 1; grid-column: 22;">May</div> + <div style="grid-row: 1; grid-column: 26;">Jun</div> + <div style="grid-row: 1; grid-column: 31;">Jul</div> + <div style="grid-row: 1; grid-column: 35;">Aug</div> + <div style="grid-row: 1; grid-column: 39;">Sep</div> + <div style="grid-row: 1; grid-column: 44;">Oct</div> + <div style="grid-row: 1; grid-column: 48;">Nov</div> + <div style="grid-row: 1; grid-column: 52;">Dec</div> + <div style="text-align: left; grid-column: 1; grid-row: 2">Sun</div> + <div style="text-align: left; grid-column: 1; grid-row: 3">Mon</div> + <div style="text-align: left; grid-column: 1; grid-row: 4">Tue</div> + <div style="text-align: left; grid-column: 1; grid-row: 5">Wed</div> + <div style="text-align: left; grid-column: 1; grid-row: 6">Thu</div> + <div style="text-align: left; grid-column: 1; grid-row: 7">Fri</div> + <div style="text-align: left; grid-column: 1; grid-row: 8">Sat</div> + + + @* pad activity cell dates... *@ + <div style="grid-column: 2; grid-row: 2 / span @((int)(new DateOnly(Data.Keys.First().Year, 1, 1).DayOfWeek));"></div> + + @* the actual activity cells *@ + + @code{ + bool needsBorder = false; + } + + @for (DateOnly date = new DateOnly(Data.Keys.First().Year, 1, 1); date <= new DateOnly(Data.Keys.First().Year, 1, 1).AddYears(1).AddDays(-1); date = date.AddDays(1)) + { + var hasData = Data.TryGetValue(date, out var color); + var needsTopBorder = date.Day == 1 && date.Month != 1 && date.DayOfWeek != DayOfWeek.Sunday; + if (date.DayOfWeek == DayOfWeek.Sunday) + needsBorder = date.AddDays(7).Day <= 7 && date.Month != 12; + var needsLeftBorder = date.Day <= 7; + + <div class="activity-cell-container" + style="grid-row: @((int)date.DayOfWeek + 2); border-@(needsLeftBorder ? "left" : "right"): @(needsBorder ? "2px solid white" : "none"); border-top: @(needsTopBorder ? "2px solid white" : "none");"> + @if (hasData) + { + <div class="activity-cell" + style="background-color: rgb(@(color.R / GlobalMax.R * 255), @(color.G / GlobalMax.G * 255), @(color.B / GlobalMax.B * 255));" + title="@($"{color.R} {RLabel}, {color.G} {GLabel}, and {color.B} {BLabel} on {date.ToString("D")}")"> + </div> + } + else + { + <div class="activity-cell" + title="@($"No data on {date.ToString("D")}")"> + </div> + } + </div> + } + </div> +} + + +@code { + private Dictionary<DateOnly, RGB> _data = new(); + private RGB? _globalMax = null; + + [Parameter] + public Dictionary<DateOnly, RGB> Data + { + get => _data; + set + { + // var sw = Stopwatch.StartNew(); + if (value is not { Count: > 0 }) return; + // Console.WriteLine($"Recalculating activity graph ({value.Count} datapoints)..."); + + + // var year = (int)value.Keys.Average(x => x.Year); + // value = value + // .Where(x => x.Key.Year == year) + // .OrderBy(x => x.Key) + // .ToDictionary(x => x.Key, x => x.Value); + + _data = value; + // Console.WriteLine($"Recalculated activity graph in {sw.Elapsed}"); + // StateHasChanged(); + } + } + + [Parameter] + public RGB GlobalMax + { + get + { + if (_globalMax is not null) return _globalMax.Value; + if (Data is not { Count: > 0 }) return new RGB() { R = 255, G = 255, B = 255 }; + return new RGB() + { + R = Data.Values.Max(x => x.R), + G = Data.Values.Max(x => x.G), + B = Data.Values.Max(x => x.B) + }; + } + set => _globalMax = value; + } + + [Parameter] public string RLabel { get; set; } = "R"; + [Parameter] public string GLabel { get; set; } = "G"; + [Parameter] public string BLabel { get; set; } = "B"; + + [StructLayout(LayoutKind.Sequential, Size = sizeof(float) * 3, Pack = 1)] + public struct RGB() + { + public float R = 0; + public float G = 0; + public float B = 0; + + public RGB(float r, float g, float b) : this() + { + R = r; + G = g; + B = b; + } + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Shared/ActivityGraph.razor.css b/MatrixUtils.Web/Shared/ActivityGraph.razor.css new file mode 100644 index 0000000..d8e543c --- /dev/null +++ b/MatrixUtils.Web/Shared/ActivityGraph.razor.css @@ -0,0 +1,16 @@ +.activity-cell-container { + width: 100%; + height: 100%; + align-content: center; + justify-content: center; +} + +.activity-cell { + width: 85%; + height: 85%; + border-radius: 5px; +} + +.day-label { + grid-column: 1; +} \ No newline at end of file diff --git a/MatrixUtils.Web/Shared/MainLayout.razor b/MatrixUtils.Web/Shared/MainLayout.razor index d8bf411..41c3d69 100644 --- a/MatrixUtils.Web/Shared/MainLayout.razor +++ b/MatrixUtils.Web/Shared/MainLayout.razor @@ -8,8 +8,8 @@ <main> <div class="top-row px-4"> <PortableDevTools></PortableDevTools> - <a href="https://cgit.rory.gay/matrix/MatrixRoomUtils.git/" target="_blank">Git</a> - <a href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a> + <a style="color: #ccc; text-decoration: underline" href="https://cgit.rory.gay/matrix/MatrixRoomUtils.git/" target="_blank">Git</a> + <a style="color: #ccc; text-decoration: underline" href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a> </div> <article class="Content px-4"> diff --git a/MatrixUtils.Web/Shared/MxcImage.razor b/MatrixUtils.Web/Shared/MxcImage.razor index f31c19f..e651c3f 100644 --- a/MatrixUtils.Web/Shared/MxcImage.razor +++ b/MatrixUtils.Web/Shared/MxcImage.razor @@ -30,6 +30,7 @@ StateHasChanged(); } } + [Parameter] public RemoteHomeserver? Homeserver { get; set; } @@ -41,7 +42,7 @@ } } - private string StyleString => $"{Style} {(Circular ? "border-radius: 50%;" : "")} {(Width.HasValue ? $"width: {Width}px;" : "")} {(Height.HasValue ? $"height: {Height}px;" : "")}"; + private string StyleString => $"{Style} {(Circular ? "border-radius: 50%;" : "")} {(Width.HasValue ? $"width: {Width}px;" : "")} {(Height.HasValue ? $"height: {Height}px;" : "")} object-fit: cover;"; private static readonly string Prefix = "mxc://"; private static readonly int PrefixLength = Prefix.Length; diff --git a/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor b/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor index 9c481e3..6954990 100644 --- a/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor +++ b/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor @@ -48,9 +48,7 @@ if (Breadcrumbs.Contains(room.RoomId)) continue; var roomInfo = KnownRooms.FirstOrDefault(x => x.Room.RoomId == room.RoomId); if (roomInfo is null) { - roomInfo = new RoomInfo() { - Room = room - }; + roomInfo = new RoomInfo(room); KnownRooms.Add(roomInfo); } if(joinedRooms.Any(x=>x.RoomId == room.RoomId)) diff --git a/MatrixUtils.Web/Shared/UserListItem.razor b/MatrixUtils.Web/Shared/UserListItem.razor index 525296e..daa9c9e 100644 --- a/MatrixUtils.Web/Shared/UserListItem.razor +++ b/MatrixUtils.Web/Shared/UserListItem.razor @@ -2,8 +2,9 @@ @using LibMatrix.EventTypes.Spec.State @using LibMatrix.Homeservers @using LibMatrix.Responses +@using ArcaneLibs <div style="background-color: #ffffff11; border-radius: 25px; margin: 8px; width: fit-Content;"> - <img style="@(ChildContent is not null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%;" src="@(string.IsNullOrWhiteSpace(User?.AvatarUrl) ? "https://api.dicebear.com/6.x/identicon/svg?seed=" + UserId : User.AvatarUrl)"/> + <img style="@(ChildContent is not null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%;" src="@(string.IsNullOrWhiteSpace(User?.AvatarUrl) ? _identiconGenerator.GenerateAsDataUri(UserId) : User.AvatarUrl)"/> <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px;">@User?.DisplayName</span> <div style="display: inline-block;"> @@ -27,6 +28,8 @@ private AuthenticatedHomeserverGeneric _homeserver = null!; + private SvgIdenticonGenerator _identiconGenerator = new(); + protected override async Task OnInitializedAsync() { _homeserver = await RMUStorage.GetCurrentSessionOrNavigate(); if (_homeserver is null) return; @@ -35,6 +38,7 @@ if (UserId == null) { throw new ArgumentNullException(nameof(UserId)); } + User = await _homeserver.GetProfileAsync(UserId); } |