diff --git a/MatrixRoomUtils.Web/Shared/RoomList.razor b/MatrixRoomUtils.Web/Shared/RoomList.razor
new file mode 100644
index 0000000..ca93fa6
--- /dev/null
+++ b/MatrixRoomUtils.Web/Shared/RoomList.razor
@@ -0,0 +1,56 @@
+@using MatrixRoomUtils.Web.Shared.RoomListComponents;
+<p>@Rooms.Count rooms total, @RoomsWithTypes.Sum(x=>x.Value.Count) fetched so far...</p>
+@foreach (var category in RoomsWithTypes.OrderBy(x => x.Value.Count)) {
+ <RoomListCategory Category="@category"></RoomListCategory>
+}
+
+@code {
+
+ [Parameter]
+ public List<Room> Rooms { get; set; }
+
+ Dictionary<string, List<Room>> RoomsWithTypes = new();
+
+ protected override async Task OnInitializedAsync() {
+ if (RoomsWithTypes.Any()) return;
+
+ await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
+
+ var tasks = Rooms.Select(AddRoom);
+ await Task.WhenAll(tasks);
+
+ await base.OnInitializedAsync();
+ }
+
+ private string GetRoomTypeName(string? roomType) => roomType switch {
+ "m.space" => "Space",
+ "msc3588.stories.stories-room" => "Story room",
+ null => "Room",
+ _ => roomType
+ };
+
+
+ private static SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(8, 8);
+ private async Task AddRoom(Room room) {
+ await _semaphoreSlim.WaitAsync();
+ var roomType = GetRoomTypeName(await room.GetRoomType());
+
+ if (roomType == "Room") {
+ var shortcodeState = await room.GetStateAsync("org.matrix.mjolnir.shortcode");
+ if (shortcodeState.HasValue) roomType = "Legacy policy room";
+ }
+
+ if (!RoomsWithTypes.ContainsKey(roomType)) {
+ RoomsWithTypes.Add(roomType, new List<Room>());
+ }
+ RoomsWithTypes[roomType].Add(room);
+
+ // if (RoomsWithTypes.Count % 10 == 0)
+ StateHasChanged();
+ await Task.Delay(100);
+ _semaphoreSlim.Release();
+ }
+
+ private bool _isSpaceChildrenOpen = false;
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/RoomList.razor.css b/MatrixRoomUtils.Web/Shared/RoomList.razor.css
new file mode 100644
index 0000000..a159305
--- /dev/null
+++ b/MatrixRoomUtils.Web/Shared/RoomList.razor.css
@@ -0,0 +1,8 @@
+.room-list-item {
+ background-color: #ffffff11;
+ border-radius: 0.5em;
+ display: block;
+ margin-top: 4px;
+ padding: 4px;
+ width: fit-content;
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/RoomListComponents/RoomListCategory.razor b/MatrixRoomUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
new file mode 100644
index 0000000..ecdcc68
--- /dev/null
+++ b/MatrixRoomUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
@@ -0,0 +1,24 @@
+<details>
+ <summary>@roomType (@rooms.Count)</summary>
+ @foreach (var room in rooms) {
+ <div class="room-list-item">
+ <RoomListItem Room="@room" ShowOwnProfile="@(roomType == "Room")"></RoomListItem>
+ <MatrixRoomUtils.Web.Shared.SimpleComponents.LinkButton href="@($"/Rooms/{room.RoomId}/Timeline")">View timeline</MatrixRoomUtils.Web.Shared.SimpleComponents.LinkButton>
+
+ @if (roomType == "Space") {
+ <RoomListSpace Space="@room"></RoomListSpace>
+ }
+ </div>
+ }
+</details>
+<br/>
+
+@code {
+
+ [Parameter]
+ public KeyValuePair<string, List<Room>> Category { get; set; }
+
+ private string roomType => Category.Key;
+ private List<Room> rooms => Category.Value;
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/RoomListComponents/RoomListSpace.razor b/MatrixRoomUtils.Web/Shared/RoomListComponents/RoomListSpace.razor
new file mode 100644
index 0000000..c90ae8f
--- /dev/null
+++ b/MatrixRoomUtils.Web/Shared/RoomListComponents/RoomListSpace.razor
@@ -0,0 +1,42 @@
+<LinkButton href="@($"/Rooms/{Space.RoomId}/Space")">Manage space</LinkButton>
+
+<br/>
+<details @ontoggle="SpaceChildrenOpened">
+ <summary>@Children.Count children</summary>
+ @if (_shouldRenderChildren) {
+ <p>Breadcrumb: @Breadcrumbs</p>
+ <div style="margin-left: 8px;">
+ <RoomList Rooms="Children"></RoomList>
+ </div>
+ }
+</details>
+
+@code {
+
+ [Parameter]
+ public Room Space { get; set; }
+
+ [Parameter, CascadingParameter]
+ public string? Breadcrumbs {
+ get => _breadcrumbs + Space.RoomId;
+ set => _breadcrumbs = value;
+ }
+
+ private List<Room> Children { get; set; } = new();
+
+ protected override async Task OnInitializedAsync() {
+ if (Breadcrumbs == null) throw new ArgumentNullException(nameof(Breadcrumbs));
+ Children = (await Space.AsSpace.GetRoomsAsync()).Where(x => !Breadcrumbs.Contains(x.RoomId)).ToList();
+ await base.OnInitializedAsync();
+ }
+
+ private bool _shouldRenderChildren = false;
+ private string? _breadcrumbs;
+
+ private async Task SpaceChildrenOpened() {
+ if (_shouldRenderChildren) return;
+ _shouldRenderChildren = true;
+ Console.WriteLine($"[RoomList] Rendering children of {Space.RoomId}");
+ }
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor
index f58ab3a..6dc0683 100644
--- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor
+++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor
@@ -2,7 +2,7 @@
@using System.Text.Json
<div class="roomListItem" style="background-color: #ffffff11; border-radius: 25px; margin: 8px; width: fit-Content; @(hasDangerousRoomVersion ? "border: red 4px solid;" : hasOldRoomVersion ? "border: #FF0 1px solid;" : "")">
@if (ShowOwnProfile) {
- <img class="imageUnloaded @(string.IsNullOrWhiteSpace(profileAvatar) ? "" : "imageLoaded")" style="@(ChildContent != null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@(profileAvatar ?? "/icon-192.png")" @onload="Callback"/>
+ <img class="imageUnloaded @(string.IsNullOrWhiteSpace(profileAvatar) ? "" : "imageLoaded")" style="@(ChildContent != null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@(profileAvatar ?? "/icon-192.png")" />
<span style="vertical-align: middle; margin-right: 8px; border-radius: 75px; @(hasCustomProfileName ? "background-color: red;" : "")">@(profileName ?? "Loading...")</span>
<span style="vertical-align: middle; padding-right: 8px; padding-left: 0px;">-></span>
}
@@ -51,7 +51,7 @@
await _semaphoreSlim.WaitAsync();
- var hs = RuntimeCache.CurrentHomeServer; //await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure();
+ var hs = RuntimeCache.CurrentHomeServer;
if (Room == null) {
if (RoomId == null) {
@@ -119,6 +119,4 @@
await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
}
- private void Callback(ProgressEventArgs obj) => Console.WriteLine("prog: " + obj.ToJson(false));
-
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor
index d17d0de..966c44d 100644
--- a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor
@@ -3,7 +3,7 @@
<input autofocus type="@(IsPassword ? "password" : "text")" @bind="Value" @onfocusout="() => { isVisible = false; ValueChanged.InvokeAsync(Value); }" @ref="elementToFocus"/>
}
else {
- <span tabindex="0" style="border-bottom: #ccc solid 1px; height: 1.4em; display: inline-block; @(string.IsNullOrEmpty(Value) ? "min-width: 50px;" : "")" @onfocusin="() => isVisible = true">@(Formatter?.Invoke(Value) ?? (IsPassword ? string.Join("", Value.Select(x => '*')) : Value))</span>
+ <span class="fancy-textbox-inline" tabindex="0" style="@(string.IsNullOrEmpty(Value) ? "min-width: 50px;" : "")" @onfocusin="() => isVisible = true">@(Formatter?.Invoke(Value) ?? (IsPassword ? string.Join("", Value.Select(x => '*')) : Value))</span>
}
@code {
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor.css b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor.css
new file mode 100644
index 0000000..01b2c6f
--- /dev/null
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/FancyTextBox.razor.css
@@ -0,0 +1,5 @@
+.fancy-textbox-inline {
+ border-bottom: #ccc solid 1px;
+ height: 1.4em;
+ display: inline-block;
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/SimpleComponents/LinkButton.razor b/MatrixRoomUtils.Web/Shared/SimpleComponents/LinkButton.razor
new file mode 100644
index 0000000..8c9e73b
--- /dev/null
+++ b/MatrixRoomUtils.Web/Shared/SimpleComponents/LinkButton.razor
@@ -0,0 +1,13 @@
+<a href="@href" class="btn btn-primary">
+ @ChildContent
+</a>
+
+@code {
+
+ [Parameter]
+ public string href { get; set; }
+
+ [Parameter]
+ public RenderFragment ChildContent { get; set; }
+
+}
\ No newline at end of file
|