diff --git a/LibMatrix b/LibMatrix
-Subproject 896ee7f099f817e8cc9aba96a9db00fcce67163
+Subproject b5860ce2011b96a2919d5306445b0e8bd8408b3
diff --git a/MatrixRoomUtils.sln b/MatrixRoomUtils.sln
index 08f236d..f52a446 100644
--- a/MatrixRoomUtils.sln
+++ b/MatrixRoomUtils.sln
@@ -60,8 +60,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArcaneLibs.UsageTest", "Lib
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MatrixUtils.DmSpaced", "MatrixUtils.DmSpaced\MatrixUtils.DmSpaced.csproj", "{B3FEA1EF-6CFE-49C5-A0B2-11DB58D4CD1C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorApp1", "tmp\BlazorApp1\BlazorApp1.csproj", "{2057E543-84D9-483A-9A14-6399E7062419}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -164,10 +162,6 @@ Global
{B3FEA1EF-6CFE-49C5-A0B2-11DB58D4CD1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3FEA1EF-6CFE-49C5-A0B2-11DB58D4CD1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3FEA1EF-6CFE-49C5-A0B2-11DB58D4CD1C}.Release|Any CPU.Build.0 = Release|Any CPU
- {2057E543-84D9-483A-9A14-6399E7062419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2057E543-84D9-483A-9A14-6399E7062419}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2057E543-84D9-483A-9A14-6399E7062419}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2057E543-84D9-483A-9A14-6399E7062419}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{F4E241C3-0300-4B87-8707-BCBDEF1F0185} = {8F4F6BEC-0C66-486B-A21A-1C35B2EDAD33}
diff --git a/MatrixUtils.Web/MatrixUtils.Web.csproj b/MatrixUtils.Web/MatrixUtils.Web.csproj
index c2732de..f27ae40 100644
--- a/MatrixUtils.Web/MatrixUtils.Web.csproj
+++ b/MatrixUtils.Web/MatrixUtils.Web.csproj
@@ -48,7 +48,26 @@
</ItemGroup>
<ItemGroup>
- <Folder Include="Pages\Tools\Moderation\Draupnir\" />
+ <_ContentIncludedByDefault Remove="Pages\Client\ClientComponents\ClientRoomList.razor" />
+ <_ContentIncludedByDefault Remove="Pages\Client\ClientComponents\ClientStatusList.razor" />
+ <_ContentIncludedByDefault Remove="Pages\Client\ClientComponents\MatrixClient.razor" />
+ <_ContentIncludedByDefault Remove="Pages\Client\Index.razor" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <AdditionalFiles Include="Pages\Labs\Client\ClientComponents\ClientRoomList.razor" />
+ <AdditionalFiles Include="Pages\Labs\Client\ClientComponents\ClientStatusList.razor" />
+ <AdditionalFiles Include="Pages\Labs\Client\ClientComponents\MatrixClient.razor" />
+ <AdditionalFiles Include="Pages\Labs\Client\Index.razor" />
+ <AdditionalFiles Include="Pages\Labs\DMSpace\DMSpaceStages\DMSpaceStage0.razor" />
+ <AdditionalFiles Include="Pages\Labs\DMSpace\DMSpaceStages\DMSpaceStage1.razor" />
+ <AdditionalFiles Include="Pages\Labs\DMSpace\DMSpaceStages\DMSpaceStage2.razor" />
+ <AdditionalFiles Include="Pages\Labs\DMSpace\DMSpaceStages\DMSpaceStage3.razor" />
+ <AdditionalFiles Include="Pages\Labs\Rooms2\Index2Components\MainTabComponents\MainTabSpaceItem.razor" />
+ <AdditionalFiles Include="Pages\Labs\Rooms2\Index2Components\RoomsIndex2ByRoomTypeTab.razor" />
+ <AdditionalFiles Include="Pages\Labs\Rooms2\Index2Components\RoomsIndex2DMsTab.razor" />
+ <AdditionalFiles Include="Pages\Labs\Rooms2\Index2Components\RoomsIndex2MainTab.razor" />
+ <AdditionalFiles Include="Pages\Labs\Rooms2\Index2Components\RoomsIndex2SyncContainer.razor" />
</ItemGroup>
</Project>
diff --git a/MatrixUtils.Web/Pages/Dev/ModalTest.razor b/MatrixUtils.Web/Pages/Dev/ModalTest.razor
deleted file mode 100644
index 4a0487f..0000000
--- a/MatrixUtils.Web/Pages/Dev/ModalTest.razor
+++ /dev/null
@@ -1,88 +0,0 @@
-@page "/Dev/ModalTest"
-@inject IJSRuntime JsRuntime
-<h3>ModalTest</h3>
-
-@foreach (var (key, value) in _windowInfos) {
- @* <ModalWindow X="@value.X" Y="@value.Y" Title="@value.Title">@value.Content</ModalWindow> *@
-}
-@for (var i = 0; i < 5; i++) {
- var i1 = i;
- <ModalWindow X="@Random.Shared.Next(1400)" Y="@Random.Shared.Next(1000)" Title="@("Window " + i1)" OnCloseClicked="() => OnCloseClicked(i1)">
- @for (var j = 0; j < i1; j++) {
- <h1>@j</h1>
- }
- </ModalWindow>
-}
-
-@code {
-
- private Dictionary<int, WindowInfo> _windowInfos = new();
-
- private class WindowInfo {
- public double X;
- public double Y;
- public string Title;
- public RenderFragment Content;
- }
-
- protected override async Task OnInitializedAsync() {
- double _x = 2;
- double _xv = 20;
- double _y = 0;
- double multiplier = 1;
-
- for (var i = 0; i < 200; i++) {
- var i1 = i;
- _windowInfos.Add(_windowInfos.Count, new WindowInfo {
- X = _x,
- Y = _y,
- Title = "Win" + i1,
- Content = builder => {
- builder.OpenComponent<ModalWindow>(0);
- builder.AddAttribute(1, "X", _x);
- builder.AddAttribute(2, "Y", _y);
- builder.AddAttribute(3, "Title", "Win" + i1);
- builder.AddAttribute(4, "ChildContent", (RenderFragment)(builder2 => {
- builder2.OpenElement(0, "h1");
- builder2.AddContent(1, "Hello " + i1);
- builder2.CloseElement();
- }));
- builder.CloseComponent();
- }
- });
- //_x += _xv /= 1000/System.Math.Sqrt((double)_windowInfos.Count)*_windowInfos.Count.ToString().Length*multiplier;
- _y += 20;
- _x += 20;
- var dimension = await JsRuntime.InvokeAsync<WindowDimension>("getWindowDimensions");
- if (_x > dimension.Width - 100) _x %= dimension.Width - 100;
- if (_y > dimension.Height - 50) {
- _y %= dimension.Height - 50;
- _xv = 20;
- }
- if (
- (_windowInfos.Count < 10 && _windowInfos.Count % 2 == 0) ||
- (_windowInfos.Count < 100 && _windowInfos.Count % 10 == 0) ||
- (_windowInfos.Count < 1000 && _windowInfos.Count % 50 == 0) ||
- (_windowInfos.Count < 10000 && _windowInfos.Count % 100 == 0)
- ) {
- StateHasChanged();
- await Task.Delay(25);
- }
- if(_windowInfos.Count > 750) multiplier = 2;
- if(_windowInfos.Count > 1500) multiplier = 3;
-
- }
-
- await base.OnInitializedAsync();
- }
-
- private void OnCloseClicked(int i1) {
- Console.WriteLine("Close clicked on " + i1);
- }
-
- public class WindowDimension {
- public int Width { get; set; }
- public int Height { get; set; }
- }
-
-}
diff --git a/MatrixUtils.Web/Pages/Index.razor b/MatrixUtils.Web/Pages/Index.razor
index b3dc7d4..8dfd1be 100644
--- a/MatrixUtils.Web/Pages/Index.razor
+++ b/MatrixUtils.Web/Pages/Index.razor
@@ -186,7 +186,7 @@ Small collection of tools to do not-so-everyday things.
ServerVersion = await (serverVersionTask ?? Task.FromResult<ServerVersionResponse?>(null)!),
Homeserver = hs
});
- if (updateSw.ElapsedMilliseconds > 250) {
+ if (updateSw.ElapsedMilliseconds > 25) {
updateSw.Restart();
StateHasChanged();
}
diff --git a/MatrixUtils.Web/Pages/Client/ClientComponents/ClientRoomList.razor b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/ClientRoomList.razor
index 845f30d..b370080 100644
--- a/MatrixUtils.Web/Pages/Client/ClientComponents/ClientRoomList.razor
+++ b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/ClientRoomList.razor
@@ -1,4 +1,4 @@
-@using ClientContext = MatrixUtils.Web.Pages.Client.Index.ClientContext
+@using ClientContext = MatrixUtils.Web.Pages.Labs.Client.Index.ClientContext
@* user header and room list *@
@foreach (var room in Data.SyncWrapper.Rooms) {
<LinkButton OnClick="@(async () => Data.SelectedRoom = room)" Color="@(Data.SelectedRoom == room ? "#FF00FF" : "")">
diff --git a/MatrixUtils.Web/Pages/Client/ClientComponents/ClientStatusList.razor b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/ClientStatusList.razor
index 1100c98..c680c13 100644
--- a/MatrixUtils.Web/Pages/Client/ClientComponents/ClientStatusList.razor
+++ b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/ClientStatusList.razor
@@ -1,4 +1,4 @@
-@using ClientContext = MatrixUtils.Web.Pages.Client.Index.ClientContext;
+@using ClientContext = MatrixUtils.Web.Pages.Labs.Client.Index.ClientContext;
@using System.Collections.ObjectModel
@foreach (var ctx in Data) {
diff --git a/MatrixUtils.Web/Pages/Client/ClientComponents/ClientSyncWrapper.cs b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/ClientSyncWrapper.cs
index 16051b8..16051b8 100644
--- a/MatrixUtils.Web/Pages/Client/ClientComponents/ClientSyncWrapper.cs
+++ b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/ClientSyncWrapper.cs
diff --git a/MatrixUtils.Web/Pages/Client/ClientComponents/MatrixClient.razor b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/MatrixClient.razor
index b4a81f7..7d3e52a 100644
--- a/MatrixUtils.Web/Pages/Client/ClientComponents/MatrixClient.razor
+++ b/MatrixUtils.Web/Pages/Labs/Client/ClientComponents/MatrixClient.razor
@@ -1,4 +1,4 @@
-@using Index = MatrixUtils.Web.Pages.Client.Index
+@using Index = MatrixUtils.Web.Pages.Labs.Client.Index
@using MatrixUtils.Web.Pages.Client.ClientComponents
<div class="container-fluid">
diff --git a/MatrixUtils.Web/Pages/Client/Index.razor b/MatrixUtils.Web/Pages/Labs/Client/Index.razor
index 2a9a327..5b489b0 100644
--- a/MatrixUtils.Web/Pages/Client/Index.razor
+++ b/MatrixUtils.Web/Pages/Labs/Client/Index.razor
@@ -1,4 +1,4 @@
-@page "/Client"
+@page "/Labs/Client"
@using LibMatrix
@using MatrixUtils.Abstractions
@using MatrixUtils.Web.Pages.Client.ClientComponents
diff --git a/MatrixUtils.Web/Pages/User/DMSpace.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpace.razor
index e3dba30..c0dc8a6 100644
--- a/MatrixUtils.Web/Pages/User/DMSpace.razor
+++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpace.razor
@@ -1,10 +1,10 @@
-@page "/User/DMSpace/Setup"
+@page "/Labs/DMSpace/Setup"
@using LibMatrix
@using LibMatrix.Responses
@using MatrixUtils.Abstractions
@using MatrixUtils.LibDMSpace
@using MatrixUtils.LibDMSpace.StateEvents
-@using MatrixUtils.Web.Pages.User.DMSpaceStages
+@using MatrixUtils.Web.Pages.Labs.DMSpace.DMSpaceStages
@using System.Text.Json.Serialization
<h3>DM Space Management</h3>
<hr/>
@@ -49,7 +49,7 @@
protected override async Task OnInitializedAsync() {
if (NavigationManager.Uri.Contains("?stage=")) {
- NavigationManager.NavigateTo("/User/DMSpace/Setup", true);
+ NavigationManager.NavigateTo(NavigationManager.Uri.Replace("stage=", ""), true); //"/User/DMSpace/Setup"
}
DMSpaceRootPage = this;
SetupData.Homeserver ??= await RMUStorage.GetCurrentSessionOrNavigate();
diff --git a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage0.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage0.razor
index 5f6508c..5f6508c 100644
--- a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage0.razor
+++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage0.razor
diff --git a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage1.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor
index 2176467..2176467 100644
--- a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage1.razor
+++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage1.razor
diff --git a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage2.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor
index a70e9c5..a70e9c5 100644
--- a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage2.razor
+++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage2.razor
diff --git a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage3.razor b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor
index 865e956..865e956 100644
--- a/MatrixUtils.Web/Pages/User/DMSpaceStages/DMSpaceStage3.razor
+++ b/MatrixUtils.Web/Pages/Labs/DMSpace/DMSpaceStages/DMSpaceStage3.razor
diff --git a/MatrixUtils.Web/Pages/Labs/Index.razor b/MatrixUtils.Web/Pages/Labs/Index.razor
new file mode 100644
index 0000000..fbe4b62
--- /dev/null
+++ b/MatrixUtils.Web/Pages/Labs/Index.razor
@@ -0,0 +1,11 @@
+@page "/Labs"
+<h3>Index of /Labs</h3>
+<p>Welcome to RMU Laboratories! We wish you a safe and informative time!</p>
+<p>These pages are a work in progress, and may not work <b>or cause permanent account changes!</b></p>
+<p>We do not claim responsibility in case something goes wrong here!</p>
+<p><b style="color: red;">Here be dragons!!</b></p>
+<br/>
+
+<a href="/Labs/Rooms2">Room List v3</a><br/>
+<a href="/Labs/Client">Client implementation attempt</a><br/>
+<a href="/Labs/DMSpace/Setup">DM Space setup</a><br/>
\ No newline at end of file
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2MainTab.razor.css b/MatrixUtils.Web/Pages/Labs/Index.razor.css
index e69de29..e69de29 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2MainTab.razor.css
+++ b/MatrixUtils.Web/Pages/Labs/Index.razor.css
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2.razor
index 98b8a1d..3392960 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2.razor
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2.razor
@@ -1,9 +1,9 @@
-@page "/Rooms2"
+@page "/Labs/Rooms2"
@using LibMatrix.Responses
@using System.Collections.ObjectModel
@using System.ComponentModel
@using MatrixUtils.Abstractions
-@using MatrixUtils.Web.Pages.Rooms.Index2Components
+@using MatrixUtils.Web.Pages.Labs.Rooms2.Index2Components
@inject ILogger<Index> logger
<h3>Room list</h3>
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/MainTabComponents/MainTabSpaceItem.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/MainTabComponents/MainTabSpaceItem.razor
index 6483f01..6483f01 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/MainTabComponents/MainTabSpaceItem.razor
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/MainTabComponents/MainTabSpaceItem.razor
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/MainTabComponents/MainTabSpaceItem.razor.css b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/MainTabComponents/MainTabSpaceItem.razor.css
index d6e413f..d6e413f 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/MainTabComponents/MainTabSpaceItem.razor.css
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/MainTabComponents/MainTabSpaceItem.razor.css
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2ByRoomTypeTab.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2ByRoomTypeTab.razor
index f4cf849..f4cf849 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2ByRoomTypeTab.razor
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2ByRoomTypeTab.razor
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2DMsTab.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2DMsTab.razor
index f4cf849..f4cf849 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2DMsTab.razor
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2DMsTab.razor
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2MainTab.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor
index b163a52..7ccfae2 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2MainTab.razor
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor
@@ -1,11 +1,7 @@
@using MatrixUtils.Abstractions
-@using System.Security.Cryptography
-@using ArcaneLibs.Extensions
@using System.ComponentModel
-@using System.Diagnostics
@using LibMatrix.EventTypes.Spec.State
-@using MatrixUtils.Web.Pages.Rooms.Index2Components.MainTabComponents
-@using Microsoft.AspNetCore.Components.Rendering
+@using MatrixUtils.Web.Pages.Labs.Rooms2.Index2Components.MainTabComponents
<h3>RoomsIndex2MainTab</h3>
@* <div> *@
diff --git a/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor.css b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor.css
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2MainTab.razor.css
diff --git a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2SyncContainer.razor b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor
index 418ee02..91f228d 100644
--- a/MatrixUtils.Web/Pages/Rooms/Index2Components/RoomsIndex2SyncContainer.razor
+++ b/MatrixUtils.Web/Pages/Labs/Rooms2/Index2Components/RoomsIndex2SyncContainer.razor
@@ -2,7 +2,6 @@
@using LibMatrix.Responses
@using MatrixUtils.Abstractions
@using System.Diagnostics
-@using System.Diagnostics.CodeAnalysis
@using LibMatrix.EventTypes.Spec.State
@using LibMatrix.Extensions
@using LibMatrix.Utilities
diff --git a/MatrixUtils.Web/Pages/Tools/LeaveRoom.razor b/MatrixUtils.Web/Pages/Tools/Debug/LeaveRoom.razor
index 841552e..841552e 100644
--- a/MatrixUtils.Web/Pages/Tools/LeaveRoom.razor
+++ b/MatrixUtils.Web/Pages/Tools/Debug/LeaveRoom.razor
diff --git a/MatrixUtils.Web/Pages/Tools/MediaLocator.razor b/MatrixUtils.Web/Pages/Tools/Debug/MediaLocator.razor
index 6e87926..6e87926 100644
--- a/MatrixUtils.Web/Pages/Tools/MediaLocator.razor
+++ b/MatrixUtils.Web/Pages/Tools/Debug/MediaLocator.razor
diff --git a/MatrixUtils.Web/Pages/Tools/MigrateRoom.razor b/MatrixUtils.Web/Pages/Tools/Debug/MigrateRoom.razor
index 11d35f1..11d35f1 100644
--- a/MatrixUtils.Web/Pages/Tools/MigrateRoom.razor
+++ b/MatrixUtils.Web/Pages/Tools/Debug/MigrateRoom.razor
diff --git a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor b/MatrixUtils.Web/Pages/Tools/Debug/SpaceDebug.razor
index 263879b..263879b 100644
--- a/MatrixUtils.Web/Pages/Tools/SpaceDebug.razor
+++ b/MatrixUtils.Web/Pages/Tools/Debug/SpaceDebug.razor
diff --git a/MatrixUtils.Web/Pages/Tools/Index.razor b/MatrixUtils.Web/Pages/Tools/Index.razor
index f1e04a3..3aec2e3 100644
--- a/MatrixUtils.Web/Pages/Tools/Index.razor
+++ b/MatrixUtils.Web/Pages/Tools/Index.razor
@@ -1,10 +1,31 @@
@page "/Tools"
-<h3>Other tools</h3>
-
-<a href="/Tools/CopyPowerlevel">Copy highest powerlevel across all session</a><br/>
-<a href="/Tools/KnownHomeserverList">Find all homeservers you share a room with</a><br/>
-<a href="/Tools/MassRoomJoin">Join room across all session</a><br/>
-<a href="/Tools/MediaLocator">Locate lost media</a><br/>
-<a href="/Tools/SpaceDebug">Debug space relationships</a><br/>
-<a href="/Tools/MigrateRoom">Migrate users from a split room to a new room</a><br/>
-<a href="/Tools/LeaveRoom">Leave room by ID</a><br/>
+<h3>Index of /Tools</h3>
+
+<h4 class="tool-category">Information tools</h4>
+<hr/>
+<a href="/Tools/Info/PolicyListActivity">View policy list activity</a><br/>
+<a href="/Tools/Info/KnownHomeserverList">Find all homeservers you share a room with</a><br/>
+<a href="/Tools/Info/SessionCount">Show session counts for users in a given room</a><br/>
+
+<h4 class="tool-category">User tools</h4>
+<hr/>
+<a href="/Tools/User/MassRoomJoin">Join room across all session</a><br/>
+<a href="/Tools/User/CopyPowerlevel">Copy highest powerlevel across all session</a><br/>
+<a href="/Tools/User/ViewAccountData">View account data</a><br/>
+
+<h4 class="tool-category">Moderation tools</h4>
+<hr/>
+<a href="/Tools/Moderation/InviteCounter">Count invites by inviter</a><br/>
+<a href="/Tools/Moderation/MembershipHistory">View membership history</a><br/>
+<a href="/Tools/Moderation/UserTrace">Trace user across rooms</a><br/>
+<a href="/tools/Moderation/MassCMEBan">Mass write policies to Community Moderation Effort</a><br/>
+<a href="/tools/Moderation/RoomIntersections">Find rooms with common users</a><br/>
+<a href="/tools/Moderation/DraupnirProtectedRoomsEditor">Edit Draupnir protected rooms set</a><br/>
+
+
+<h4 class="tool-category">Debugging tools</h4>
+<hr/>
+<a href="/Tools/Debug/SpaceDebug">Debug space relationships</a><br/>
+<a href="/Tools/Debug/LeaveRoom">Leave room by ID</a><br/>
+<a href="/Tools/Debug/MediaLocator">Locate lost media</a><br/>
+<a href="/Tools/Debug/MigrateRoom">Migrate users from a split room to a new room</a><br/>
diff --git a/MatrixUtils.Web/Pages/Tools/Index.razor.css b/MatrixUtils.Web/Pages/Tools/Index.razor.css
new file mode 100644
index 0000000..c9bd995
--- /dev/null
+++ b/MatrixUtils.Web/Pages/Tools/Index.razor.css
@@ -0,0 +1,6 @@
+.tool-category {
+ margin-top: 20px;
+}
+hr{
+ margin: unset;
+}
\ No newline at end of file
diff --git a/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor b/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor
index ddd7b15..ddd7b15 100644
--- a/MatrixUtils.Web/Pages/Tools/KnownHomeserverList.razor
+++ b/MatrixUtils.Web/Pages/Tools/Info/KnownHomeserverList.razor
diff --git a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor
index c94d0b0..c94d0b0 100644
--- a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor
+++ b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor
diff --git a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor.css b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor.css
index 443fdb5..443fdb5 100644
--- a/MatrixUtils.Web/Pages/Tools/PolicyListActivity.razor.css
+++ b/MatrixUtils.Web/Pages/Tools/Info/PolicyListActivity.razor.css
diff --git a/MatrixUtils.Web/Pages/Tools/SessionCount.razor b/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor
index 3b68bfa..3b68bfa 100644
--- a/MatrixUtils.Web/Pages/Tools/SessionCount.razor
+++ b/MatrixUtils.Web/Pages/Tools/Info/SessionCount.razor
diff --git a/MatrixUtils.Web/Pages/Moderation/DraupnirProtectedRoomsEditor.razor b/MatrixUtils.Web/Pages/Tools/Moderation/DraupnirProtectedRoomsEditor.razor
index f9cbfa2..805bd40 100644
--- a/MatrixUtils.Web/Pages/Moderation/DraupnirProtectedRoomsEditor.razor
+++ b/MatrixUtils.Web/Pages/Tools/Moderation/DraupnirProtectedRoomsEditor.razor
@@ -1,9 +1,12 @@
@page "/Moderation/DraupnirProtectedRoomsEditor"
+@page "/Tools/Moderation/DraupnirProtectedRoomsEditor"
@using System.Text.Json.Serialization
@using LibMatrix.EventTypes.Spec.State
@using LibMatrix.RoomTypes
<h3>Edit Draupnir protected rooms</h3>
<hr/>
+<p><b>Note:</b> You will need to restart Draupnir after applying changes!</p>
+<p>Minor note: This <i>should</i> also work with Mjolnir, but this hasn't been tested, and as such functionality cannot be guaranteed.</p>
@if (data is not null) {
<div class="row">
diff --git a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor b/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor
index 8f4b4dd..2123d4d 100644
--- a/MatrixUtils.Web/Pages/Tools/InviteCounter.razor
+++ b/MatrixUtils.Web/Pages/Tools/Moderation/InviteCounter.razor
@@ -1,12 +1,7 @@
-@page "/Tools/InviteCounter"
-@using ArcaneLibs.Extensions
-@using LibMatrix.RoomTypes
+@page "/Tools/Moderation/InviteCounter"
@using System.Collections.ObjectModel
-@using LibMatrix
-@using System.Collections.Frozen
@using LibMatrix.EventTypes.Spec.State
-@using MatrixUtils.Abstractions
-<h3>User Trace</h3>
+<h3>Invite counter</h3>
<hr/>
<br/>
diff --git a/MatrixUtils.Web/Pages/Tools/MassCMEBan.razor b/MatrixUtils.Web/Pages/Tools/Moderation/MassCMEBan.razor
index cbbca9e..ea1e5f6 100644
--- a/MatrixUtils.Web/Pages/Tools/MassCMEBan.razor
+++ b/MatrixUtils.Web/Pages/Tools/Moderation/MassCMEBan.razor
@@ -1,12 +1,6 @@
-@page "/Tools/MassCMEBan"
-@using ArcaneLibs.Extensions
-@using LibMatrix.RoomTypes
+@page "/Tools/Moderation/MassCMEBan"
@using System.Collections.ObjectModel
-@using LibMatrix
-@using System.Collections.Frozen
-@using LibMatrix.EventTypes.Spec.State
@using LibMatrix.EventTypes.Spec.State.Policy
-@using MatrixUtils.Abstractions
<h3>User Trace</h3>
<hr/>
diff --git a/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor b/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor
new file mode 100644
index 0000000..e5ba004
--- /dev/null
+++ b/MatrixUtils.Web/Pages/Tools/Moderation/MembershipHistory.razor
@@ -0,0 +1,276 @@
+@page "/Tools/Moderation/MembershipHistory"
+@using System.Collections.ObjectModel
+@using LibMatrix
+@using LibMatrix.EventTypes.Spec.State
+<h3>Membership history viewer</h3>
+<hr/>
+
+<br/>
+<span>Room ID: </span>
+<InputText @bind-Value="@roomId"></InputText>
+<LinkButton OnClick="@Execute">Execute</LinkButton>
+<p><InputCheckbox @bind-Value="ChronologicalOrder"/> Chronological order</p>
+<p>
+ <span>Show </span>
+ <InputCheckbox @bind-Value="ShowJoins"/> joins
+ <InputCheckbox @bind-Value="ShowLeaves"/> leaves
+ <InputCheckbox @bind-Value="ShowUpdates"/> profile updates
+ <InputCheckbox @bind-Value="ShowKnocks"/> knocks
+ <InputCheckbox @bind-Value="ShowInvites"/> invites
+ <InputCheckbox @bind-Value="ShowKicks"/> kicks
+ <InputCheckbox @bind-Value="ShowBans"/> bans
+</p>
+<p>
+ <LinkButton OnClick="@(async () => { ShowJoins = ShowLeaves = ShowUpdates = ShowKnocks = ShowInvites = ShowKicks = ShowBans = false; })">Hide all</LinkButton>
+ <LinkButton OnClick="@(async () => { ShowJoins = ShowLeaves = ShowUpdates = ShowKnocks = ShowInvites = ShowKicks = ShowBans = true; })">Show all</LinkButton>
+ <LinkButton OnClick="@(async () => { ShowJoins ^= true; ShowLeaves ^= true; ShowUpdates ^= true; ShowKnocks ^= true; ShowInvites ^= true; ShowKicks ^= true; ShowBans ^= true; })">Toggle all</LinkButton>
+</p>
+<p>
+ <span>Sender: </span>
+ <InputSelect @bind-Value="Sender">
+ <option value="">All</option>
+ @foreach (var sender in Memberships.Select(x => x.Sender).Distinct()) {
+ <option value="@sender">@sender</option>
+ }
+ </InputSelect>
+</p>
+<p>
+ <span>User: </span>
+ <InputSelect @bind-Value="User">
+ <option value="">All</option>
+ @foreach (var user in Memberships.Select(x => x.StateKey).Distinct()) {
+ <option value="@user">@user</option>
+ }
+ </InputSelect>
+</p>
+
+
+<br/>
+
+<details>
+ <summary>Results</summary>
+ @{
+ Dictionary<string, StateEventResponse> previousMemberships = [];
+ var filteredMemberships = Memberships.AsEnumerable();
+ if (ChronologicalOrder) {
+ filteredMemberships = filteredMemberships.Reverse();
+ }
+ if(!string.IsNullOrWhiteSpace(Sender)) {
+ filteredMemberships = filteredMemberships.Where(x => x.Sender == Sender);
+ }
+ if(!string.IsNullOrWhiteSpace(User)) {
+ filteredMemberships = filteredMemberships.Where(x => x.StateKey == User);
+ }
+
+ @foreach (var membership in filteredMemberships) {
+ RoomMemberEventContent content = membership.TypedContent as RoomMemberEventContent;
+ @switch (content.Membership) {
+ case RoomMemberEventContent.MembershipTypes.Invite: {
+ if (_showInvites) {
+ <p style="color: green;">@membership.Sender invited @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p>
+ }
+
+ break;
+ }
+ case RoomMemberEventContent.MembershipTypes.Ban: {
+ if (_showBans) {
+ <p style="color: red;">@membership.Sender banned @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p>
+ }
+
+ break;
+ }
+ case RoomMemberEventContent.MembershipTypes.Leave: {
+ if (membership.Sender == membership.StateKey) {
+ if (_showLeaves) {
+ <p style="color: #C66;">@membership.Sender left the room</p>
+ }
+ }
+ else {
+ if (_showKicks) {
+ <p style="color: darkorange;">@membership.Sender kicked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p>
+ }
+ }
+
+ break;
+ }
+ case RoomMemberEventContent.MembershipTypes.Knock: {
+ if (_showKnocks) {
+ <p>@membership.Sender knocked @membership.StateKey @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p>
+ }
+
+ break;
+ }
+ case RoomMemberEventContent.MembershipTypes.Join: {
+ if (previousMemberships.TryGetValue(membership.StateKey, out var previous)
+ && (previous.TypedContent as RoomMemberEventContent).Membership == RoomMemberEventContent.MembershipTypes.Join) {
+ if (_showUpdates) {
+ <p style="color: #777;">@membership.Sender changed their profile</p>
+ }
+ }
+ else {
+ if (_showJoins) {
+ <p style="color: #6C6;">@membership.Sender joined the room @(string.IsNullOrWhiteSpace(content.Reason) ? "" : $"(reason: {content.Reason})")</p>
+ }
+ }
+
+ break;
+ }
+ default: {
+ <b>Unknown membership @content.Membership!</b>
+ break;
+ }
+ }
+
+ previousMemberships[membership.StateKey] = membership;
+ }
+ }
+</details>
+
+<br/>
+<details open>
+ <summary>Log</summary>
+ @foreach (var line in log.Reverse()) {
+ <pre>@line</pre>
+ }
+</details>
+
+@code {
+
+#region Filter bindings
+
+ private bool _chronologicalOrder = false;
+
+ private bool ChronologicalOrder {
+ get => _chronologicalOrder;
+ set {
+ _chronologicalOrder = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showJoins = true;
+
+ private bool ShowJoins {
+ get => _showJoins;
+ set {
+ _showJoins = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showLeaves = true;
+
+ private bool ShowLeaves {
+ get => _showLeaves;
+ set {
+ _showLeaves = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showUpdates = true;
+
+ private bool ShowUpdates {
+ get => _showUpdates;
+ set {
+ _showUpdates = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showKnocks = true;
+
+ private bool ShowKnocks {
+ get => _showKnocks;
+ set {
+ _showKnocks = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showInvites = true;
+
+ private bool ShowInvites {
+ get => _showInvites;
+ set {
+ _showInvites = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showKicks = true;
+
+ private bool ShowKicks {
+ get => _showKicks;
+ set {
+ _showKicks = value;
+ StateHasChanged();
+ }
+ }
+
+ private bool _showBans = true;
+
+ private bool ShowBans {
+ get => _showBans;
+ set {
+ _showBans = value;
+ StateHasChanged();
+ }
+ }
+
+ private string sender = "";
+
+ private string Sender {
+ get => sender;
+ set {
+ sender = value;
+ StateHasChanged();
+ }
+ }
+
+ private string user = "";
+
+ private string User {
+ get => user;
+ set {
+ user = value;
+ StateHasChanged();
+ }
+ }
+
+#endregion
+
+ private ObservableCollection<string> log { get; set; } = new();
+ private List<StateEventResponse> Memberships { get; set; } = [];
+ private AuthenticatedHomeserverGeneric hs { get; set; }
+
+ [Parameter, SupplyParameterFromQuery(Name = "room")]
+ public string roomId { get; set; }
+
+ protected override async Task OnInitializedAsync() {
+ log.CollectionChanged += (sender, args) => StateHasChanged();
+ hs = await RMUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
+
+ StateHasChanged();
+ Console.WriteLine("Rerendered!");
+ await base.OnInitializedAsync();
+ if (!string.IsNullOrWhiteSpace(roomId))
+ await Execute();
+ }
+
+ private async Task Execute() {
+ Memberships.Clear();
+ var room = hs.GetRoom(roomId);
+ var events = room.GetManyMessagesAsync(limit: int.MaxValue, chunkSize: 5000);
+ await foreach (var resp in events) {
+ var all = resp.State.Concat(resp.Chunk);
+ Memberships.AddRange(all.Where(x => x.Type == RoomMemberEventContent.EventId));
+
+ log.Add($"{resp.State.Count} state, {resp.Chunk.Count} timeline");
+ }
+
+ StateHasChanged();
+ }
+
+}
\ No newline at end of file
diff --git a/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor b/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor
index 173ff01..b8baeb8 100644
--- a/MatrixUtils.Web/Pages/Tools/RoomIntersections.razor
+++ b/MatrixUtils.Web/Pages/Tools/Moderation/RoomIntersections.razor
@@ -1,4 +1,4 @@
-@page "/Tools/RoomIntersections"
+@page "/Tools/Moderation/RoomIntersections"
@using LibMatrix.RoomTypes
@using System.Collections.ObjectModel
@using LibMatrix
diff --git a/MatrixUtils.Web/Pages/Tools/UserTrace.razor b/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor
index 95fe02b..915f8dc 100644
--- a/MatrixUtils.Web/Pages/Tools/UserTrace.razor
+++ b/MatrixUtils.Web/Pages/Tools/Moderation/UserTrace.razor
@@ -1,12 +1,8 @@
-@page "/Tools/UserTrace"
+@page "/Tools/Moderation/UserTrace"
@using ArcaneLibs.Extensions
@using LibMatrix.RoomTypes
@using System.Collections.ObjectModel
@using LibMatrix
-@using System.Collections.Frozen
-@using LibMatrix.EventTypes.Spec.State
-@using LibMatrix.Filters
-@using MatrixUtils.Abstractions
<h3>User Trace</h3>
<hr/>
diff --git a/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor b/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor
index 667b518..667b518 100644
--- a/MatrixUtils.Web/Pages/Tools/CopyPowerlevel.razor
+++ b/MatrixUtils.Web/Pages/Tools/User/CopyPowerlevel.razor
diff --git a/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor b/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor
index a2ad388..a2ad388 100644
--- a/MatrixUtils.Web/Pages/Tools/MassJoinRoom.razor
+++ b/MatrixUtils.Web/Pages/Tools/User/MassJoinRoom.razor
diff --git a/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor b/MatrixUtils.Web/Pages/Tools/User/ViewAccountData.razor
index d8b02bb..d8b02bb 100644
--- a/MatrixUtils.Web/Pages/Tools/ViewAccountData.razor
+++ b/MatrixUtils.Web/Pages/Tools/User/ViewAccountData.razor
diff --git a/MatrixUtils.Web/Shared/NavMenu.razor b/MatrixUtils.Web/Shared/NavMenu.razor
index 43e2237..770a246 100644
--- a/MatrixUtils.Web/Shared/NavMenu.razor
+++ b/MatrixUtils.Web/Shared/NavMenu.razor
@@ -7,6 +7,8 @@
</div>
</div>
+@* icons: https://www.appstudio.dev/app/OpenIconic.html *@
+
<div class="@NavMenuCssClass nav-scrollable" @onclick="ToggleNavMenu">
<nav class="flex-column">
<div class="nav-item px-3">
@@ -30,19 +32,19 @@
<div class="nav-item px-3">
<NavLink class="nav-link" href="Rooms">
- <span class="oi oi-plus" aria-hidden="true"></span> Room list
+ <span class="oi oi-list-rich" aria-hidden="true"></span> Room list
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="User/Profile">
- <span class="oi oi-plus" aria-hidden="true"></span> Manage profile
+ <span class="oi oi-person" aria-hidden="true"></span> Manage profile
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="User/DirectMessages">
- <span class="oi oi-plus" aria-hidden="true"></span> Manage DMs
+ <span class="oi oi-people" aria-hidden="true"></span> Manage DMs
</NavLink>
</div>
@@ -55,7 +57,7 @@
<div class="nav-item px-3">
<NavLink class="nav-link" href="HSAdmin">
- <span class="oi oi-plus" aria-hidden="true"></span> Homeserver admin
+ <span class="oi oi-hard-drive" aria-hidden="true"></span> Homeserver admin
</NavLink>
</div>
@@ -65,6 +67,12 @@
</NavLink>
</div>
+ <div class="nav-item px-3">
+ <NavLink class="nav-link" href="Labs">
+ <span class="oi oi-beaker" aria-hidden="true"></span> Labs
+ </NavLink>
+ </div>
+
<!-- RMU -->
<div class="nav-item px-3">
@@ -74,13 +82,13 @@
<div class="nav-item px-3">
<NavLink class="nav-link" href="Dev/Options">
- <span class="oi oi-plus" aria-hidden="true"></span> Developer options
+ <span class="oi oi-wrench" aria-hidden="true"></span> Developer options
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="Dev/Utilities">
- <span class="oi oi-plus" aria-hidden="true"></span> Developer utilities
+ <span class="oi oi-code" aria-hidden="true"></span> Developer utilities
</NavLink>
</div>
</nav>
diff --git a/MatrixUtils.Web/Shared/NavMenu.razor.css b/MatrixUtils.Web/Shared/NavMenu.razor.css
index 447f2df..afaa292 100644
--- a/MatrixUtils.Web/Shared/NavMenu.razor.css
+++ b/MatrixUtils.Web/Shared/NavMenu.razor.css
@@ -66,3 +66,8 @@
overflow-y: auto;
}
}
+
+
+hr {
+ margin: 0;
+}
\ No newline at end of file
|