diff --git a/MatrixRoomUtils.Web/Pages/DataExportPage.razor b/MatrixRoomUtils.Web/Pages/DataExportPage.razor
deleted file mode 100644
index 732cd74..0000000
--- a/MatrixRoomUtils.Web/Pages/DataExportPage.razor
+++ /dev/null
@@ -1,67 +0,0 @@
-@page "/Export"
-@using System.Text.Json
-@inject NavigationManager NavigationManager
-@inject ILocalStorageService LocalStorage
-
-<PageTitle>Export</PageTitle>
-
-<h3>Data export</h3>
-
-<br/><br/>
-<h5>Signed in accounts - <a href="/Login">Add new account</a> or <a href="/ImportUsers">Import from TSV</a></h5>
-<hr/>
-@if (_isLoaded) {
- @foreach (var (token, user) in RuntimeCache.LoginSessions) {
- @* <IndexUserItem User="@user"/> *@
- <pre>
-@user.LoginResponse.UserId[1..].Split(":")[0]\auth\access_token=@token
-@user.LoginResponse.UserId[1..].Split(":")[0]\auth\device_id=@user.LoginResponse.DeviceId
-@user.LoginResponse.UserId[1..].Split(":")[0]\auth\home_server=@(RuntimeCache.HomeserverResolutionCache.ContainsKey(user.LoginResponse.HomeServer) ? RuntimeCache.HomeserverResolutionCache[user.LoginResponse.HomeServer].Result : "loading...")
-@user.LoginResponse.UserId[1..].Split(":")[0]\auth\user_id=@@@user.LoginResponse.UserId
-@user.LoginResponse.UserId[1..].Split(":")[0]\user\automatically_share_keys_with_trusted_users=true
-@user.LoginResponse.UserId[1..].Split(":")[0]\user\muted_tags=global
-@user.LoginResponse.UserId[1..].Split(":")[0]\user\online_key_backup=true
-@user.LoginResponse.UserId[1..].Split(":")[0]\user\only_share_keys_with_verified_users=false
- </pre>
- }
-}
-else {
- <p>Loading...</p>
- <p>@resolvedHomeservers/@totalHomeservers homeservers resolved...</p>
-}
-
-@code {
- private bool _isLoaded;
- private int resolvedHomeservers;
- private int totalHomeservers;
-
- protected override async Task OnInitializedAsync() {
- await base.OnInitializedAsync();
- if (!RuntimeCache.WasLoaded) {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
- }
- var homeservers = RuntimeCache.LoginSessions.Values.Select(x => x.LoginResponse.HomeServer).Distinct();
- totalHomeservers = homeservers.Count();
- StateHasChanged();
- foreach (var hs in homeservers) {
- if (RuntimeCache.HomeserverResolutionCache.ContainsKey(hs)) {
- resolvedHomeservers++;
- continue;
- }
- var resolvedHomeserver = (await new RemoteHomeServer(hs).Configure()).FullHomeServerDomain;
-
- RuntimeCache.HomeserverResolutionCache.Add(hs, new HomeServerResolutionResult { Result = resolvedHomeserver, ResolutionTime = DateTime.Now });
- await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
-
- Console.WriteLine("Saved to local storage:");
- Console.WriteLine(JsonSerializer.Serialize(RuntimeCache.HomeserverResolutionCache, new JsonSerializerOptions {
- WriteIndented = true
- }));
- resolvedHomeservers++;
- StateHasChanged();
- }
- StateHasChanged();
- _isLoaded = true;
- }
-
-}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/DebugTools.razor b/MatrixRoomUtils.Web/Pages/DebugTools.razor
index 4e4cec8..5116754 100644
--- a/MatrixRoomUtils.Web/Pages/DebugTools.razor
+++ b/MatrixRoomUtils.Web/Pages/DebugTools.razor
@@ -37,13 +37,10 @@ else {
public List<string> Rooms { get; set; } = new();
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
await base.OnInitializedAsync();
- if (RuntimeCache.CurrentHomeServer == null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
- Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x => x.RoomId).ToList();
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs == null) return;
+ Rooms = (await hs.GetJoinedRooms()).Select(x => x.RoomId).ToList();
Console.WriteLine("Fetched joined rooms!");
}
@@ -53,7 +50,9 @@ else {
private async Task SendGetRequest() {
var field = typeof(IHomeServer).GetRuntimeFields().First(x => x.ToString().Contains("<_httpClient>k__BackingField"));
- var httpClient = field.GetValue(RuntimeCache.CurrentHomeServer) as HttpClient;
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs == null) return;
+ var httpClient = field.GetValue(hs) as MatrixHttpClient;
try {
var res = await httpClient.GetAsync(get_request_url);
if (res.IsSuccessStatusCode) {
diff --git a/MatrixRoomUtils.Web/Pages/DevOptions.razor b/MatrixRoomUtils.Web/Pages/DevOptions.razor
index cdb5693..70dac31 100644
--- a/MatrixRoomUtils.Web/Pages/DevOptions.razor
+++ b/MatrixRoomUtils.Web/Pages/DevOptions.razor
@@ -7,69 +7,23 @@
<h3>Rory&::MatrixUtils - Developer options</h3>
<hr/>
-<InputCheckbox @bind-Value="@LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers" @oninput="@LogStuff"></InputCheckbox><label> Enable log views</label><br/>
-<InputCheckbox @bind-Value="@LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging" @oninput="@LogStuff"></InputCheckbox><label> Enable console logging</label><br/>
-<InputCheckbox @bind-Value="@LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools" @oninput="@LogStuff"></InputCheckbox><label> Enable portable devtools</label><br/>
-<button @onclick="@DropCaches">Drop caches</button>
-<button @onclick="@RandomiseCacheTimers">Randomise cache timers</button>
+<InputCheckbox @bind-Value="@settings.DeveloperSettings.EnableLogViewers" @oninput="@LogStuff"></InputCheckbox><label> Enable log views</label><br/>
+<InputCheckbox @bind-Value="@settings.DeveloperSettings.EnableConsoleLogging" @oninput="@LogStuff"></InputCheckbox><label> Enable console logging</label><br/>
+<InputCheckbox @bind-Value="@settings.DeveloperSettings.EnablePortableDevtools" @oninput="@LogStuff"></InputCheckbox><label> Enable portable devtools</label><br/>
<br/>
-<details open>
- <summary>View caches</summary>
- <p>Generic cache:</p>
- <ul>
- @foreach (var item in RuntimeCache.GenericResponseCache) {
- <li>
- @item.Key: @item.Value.Cache.Count entries<br/>
- @if (item.Value.Cache.Count > 0) {
- <p>Earliest expiry: @(item.Value.Cache.Min(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Min(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p>
- @* <p>Average expiry: @(item.Value.Cache.Average(x => x.Value.ExpiryTime.Value))(@item.Value.Cache.Average(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now) from now)</p> *@
- <p>Last expiry: @(item.Value.Cache.Max(x => x.Value.ExpiryTime)) (@string.Format("{0:g}", item.Value.Cache.Max(x => x.Value.ExpiryTime).Value.Subtract(DateTime.Now)) from now)</p>
- }
- </li>
- }
- </ul>
-</details>
-
@code {
+ MRUStorageWrapper.Settings settings { get; set; } = new();
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
+ settings = await TieredStorage.DataStorageProvider.LoadObjectAsync<MRUStorageWrapper.Settings>("mru.settings");
await base.OnInitializedAsync();
- Task.Run(async () => {
- while (true) {
- await Task.Delay(1000);
- StateHasChanged();
- }
- });
}
- protected async Task LogStuff() {
+ private async Task LogStuff() {
await Task.Delay(100);
- Console.WriteLine($"Settings: {LocalStorageWrapper.Settings.ToJson()}");
-
- await LocalStorageWrapper.SaveToLocalStorage(LocalStorage);
- }
-
- protected async Task DropCaches() {
- foreach (var (key, value) in RuntimeCache.GenericResponseCache) {
- value.Cache.Clear();
- }
-
- //RuntimeCache.GenericResponseCache.Clear();
- RuntimeCache.HomeserverResolutionCache.Clear();
- await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
- }
-
- protected async Task RandomiseCacheTimers() {
- foreach (var keyValuePair in RuntimeCache.GenericResponseCache) {
- Console.WriteLine($"Randomising cache timer for {keyValuePair.Key}");
- foreach (var cacheItem in keyValuePair.Value.Cache) {
- cacheItem.Value.ExpiryTime = DateTime.Now.AddSeconds(Random.Shared.Next(15, 120));
- }
-
- await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
- }
+ Console.WriteLine($"Settings: {settings.ToJson()}");
+ await TieredStorage.DataStorageProvider.SaveObjectAsync("mru.settings", settings);
}
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
index 858fad9..e3ebc72 100644
--- a/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
+++ b/MatrixRoomUtils.Web/Pages/HSAdmin/RoomQuery.razor
@@ -165,7 +165,9 @@
private async Task Search() {
Results.Clear();
- var searchRooms = RuntimeCache.CurrentHomeServer.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, localFilter: Filter).GetAsyncEnumerator();
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
+ var searchRooms = hs.Admin.SearchRoomsAsync(orderBy: OrderBy!, dir: Ascending ? "f" : "b", searchTerm: SearchTerm, localFilter: Filter).GetAsyncEnumerator();
while (await searchRooms.MoveNextAsync()) {
var room = searchRooms.Current;
Console.WriteLine("Hit: " + room.ToJson(false));
diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor
index 33cca61..16a6cee 100644
--- a/MatrixRoomUtils.Web/Pages/Index.razor
+++ b/MatrixRoomUtils.Web/Pages/Index.razor
@@ -1,7 +1,7 @@
@page "/"
-@using MatrixRoomUtils.Web.Shared.IndexComponents
-@inject NavigationManager NavigationManager
-@inject ILocalStorageService LocalStorage
+@using MatrixRoomUtils.Core.Helpers
+@using MatrixRoomUtils.Core.Responses
+@using MatrixRoomUtils.Web.Shared.SimpleComponents
<PageTitle>Index</PageTitle>
@@ -12,18 +12,67 @@ Small collection of tools to do not-so-everyday things.
<h5>Signed in accounts - <a href="/Login">Add new account</a></h5>
<hr/>
<form>
- @foreach (var (token, user) in RuntimeCache.LoginSessions) {
- <IndexUserItem User="@user"/>
+ @foreach (var (auth, user) in _users.OrderByDescending(x=>x.Value.RoomCount)) {
+ var _auth = auth;
+ var _user = user;
+ <div style="margin-bottom: 1em;">
+ <img style="border-radius: 50%; height: 3em; width: 3em;" src="@_user.AvatarUrl"/>
+ <p style="margin-left: 1em; margin-top: -0.5em; display: inline-block;">
+ <input type="radio" name="csa" checked="@(_currentSession.AccessToken == _auth.AccessToken)" @onclick="@(()=>SwitchSession(_auth))" style="text-decoration-line: unset;"/>
+ <b>@_user.DisplayName</b> on <b>@_auth.Homeserver</b>
+ <a role="button" @onclick="@(() => RemoveUser(_auth))">Remove</a>
+
+ </p>
+ <p style="margin-top: -1.5em; margin-left: 4em;">Member of @_user.RoomCount rooms</p>
+
+ </div>
}
</form>
@code
{
+ private Dictionary<LoginResponse, UserInfo> _users = new();
+
protected override async Task OnInitializedAsync() {
- if (!RuntimeCache.WasLoaded) {
- Console.WriteLine("[INDEX] !!! LOCALSTORAGE WAS NOT LOADED !!!");
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
- }
+ _currentSession = await MRUStorage.GetCurrentToken();
+ _users.Clear();
+ var tokens = await MRUStorage.GetAllTokens();
+ var profileTasks = tokens.Select(async token => {
+ UserInfo userInfo = new();
+ var hs = await HomeserverProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken);
+ var roomCountTask = hs.GetJoinedRooms();
+ var profile = await hs.GetProfile(hs.WhoAmI.UserId);
+ userInfo.DisplayName = profile.DisplayName ?? hs.WhoAmI.UserId;
+ userInfo.AvatarUrl = MediaResolver.ResolveMediaUri(hs.FullHomeServerDomain,
+ profile.AvatarUrl
+ ?? "https://api.dicebear.com/6.x/identicon/svg?seed=" + hs.WhoAmI.UserId
+ );
+ userInfo.RoomCount = (await roomCountTask).Count;
+ _users.Add(token, userInfo);
+ // StateHasChanged();
+ });
+ await Task.WhenAll(profileTasks);
await base.OnInitializedAsync();
}
+
+ private class UserInfo {
+ internal string AvatarUrl { get; set; }
+ internal string DisplayName { get; set; }
+ internal int RoomCount { get; set; } = 0;
+ }
+
+ private async Task RemoveUser(LoginResponse auth) {
+ await MRUStorage.RemoveToken(auth);
+ if ((await MRUStorage.GetCurrentToken()).AccessToken == auth.AccessToken)
+ MRUStorage.SetCurrentToken((await MRUStorage.GetAllTokens()).FirstOrDefault());
+ await OnInitializedAsync();
+ }
+
+ private LoginResponse _currentSession;
+
+ private async Task SwitchSession(LoginResponse auth) {
+ Console.WriteLine($"Switching to {auth.Homeserver} {auth.AccessToken} {auth.UserId}");
+ await MRUStorage.SetCurrentToken(auth);
+ await OnInitializedAsync();
+ }
}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
index 80dbfd1..5ccecab 100644
--- a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
+++ b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor
@@ -2,6 +2,7 @@
@using System.Text.Json
@using System.Diagnostics
@using MatrixRoomUtils.Core.Responses
+@using MatrixRoomUtils.Core.StateEventTypes
<h3>Known Homeserver List</h3>
<hr/>
@@ -33,10 +34,10 @@ else {
List<HomeServerInfo> HomeServers = new();
bool IsFinished { get; set; }
HomeServerInfoQueryProgress QueryProgress { get; set; } = new();
-
+ AuthenticatedHomeServer hs { get; set; }
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-
+ hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
var sw = Stopwatch.StartNew();
HomeServers = await GetHomeservers(progressCallback: async progress => {
if (sw.ElapsedMilliseconds > 1000) {
@@ -61,7 +62,8 @@ else {
private async Task<List<HomeServerInfo>> GetHomeservers(int memberLimit = 1000, Func<HomeServerInfoQueryProgress, Task<bool>>? progressCallback = null) {
HomeServerInfoQueryProgress progress = new();
List<HomeServerInfo> homeServers = new();
- var rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
+
+ var rooms = await hs.GetJoinedRooms();
progress.TotalRooms = rooms.Count;
var semaphore = new SemaphoreSlim(4);
@@ -70,53 +72,69 @@ else {
await semaphore.WaitAsync();
progress.ProcessedUsers.Add(room, new HomeServerInfoQueryProgress.State());
Console.WriteLine($"Fetching states for room ({rooms.IndexOf(room)}/{rooms.Count}) ({room.RoomId})");
- var states = (await room.GetStateAsync("")).Value.Deserialize<List<StateEventResponse>>();
- states.RemoveAll(x => x.Type != "m.room.member" || x.Content.GetProperty("membership").GetString() != "join");
- Console.WriteLine($"Room {room.RoomId} has {states.Count} members");
- if (states.Count > memberLimit) {
- Console.WriteLine("Skipping!");
- semaphore.Release();
- progress.ProcessedUsers.Remove(room);
- progress.TotalRooms--;
- return;
- }
- progress.ProcessedUsers[room].Total = states.Count;
- var updateInterval = progress.ProcessedUsers[room].Total >= 1000 ? 1000 : 100;
- while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000) {
- progress.ProcessedUsers[room].Blocked = true;
- await Task.Delay(1000);
- // if(progressCallback != null)
- // await progressCallback.Invoke(progress);
- }
- progress.ProcessedUsers[room].Blocked = false;
- var processedStates = 0;
- foreach (var state in states) {
- await semLock.WaitAsync();
- semLock.Release();
- if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200) {
- progress.ProcessedUsers[room].Slowmode = true;
- await Task.Delay(progress.ProcessedUsers[room].Total >= 500 ? 1000 : 100);
- }
- else {
- progress.ProcessedUsers[room].Slowmode = false;
- }
+ var states = room.GetFullStateAsync();
+ await foreach (var state in states) {
+ if (state.Type is not "m.room.member") continue;
+ progress.ProcessedUsers[room].Total++;
if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) {
homeServers.Add(new HomeServerInfo { Server = state.StateKey.Split(':')[1] });
- }
- var hs = homeServers.First(x => x.Server == state.StateKey.Split(':')[1]);
- if (!hs.KnownUsers.Contains(state.StateKey.Split(':')[0]))
- hs.KnownUsers.Add(state.StateKey.Split(':')[0]);
- if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback != null) {
- await semLock.WaitAsync();
- var _ = await progressCallback.Invoke(progress);
- semLock.Release();
+ Console.WriteLine($"Added new homeserver {state.StateKey.Split(':')[1]}");
}
}
- Console.WriteLine("Collected states!");
- progress.ProcessedRooms++;
- progress.ProcessedUsers[room].IsFinished = true;
- progressCallback?.Invoke(progress);
semaphore.Release();
+ progress.ProcessedUsers[room].IsFinished = true;
+ progress.ProcessedRooms++;
+ if (progressCallback is not null)
+ await progressCallback.Invoke(progress);
+
+
+
+ // states.RemoveAll(x => x.Type != "m.room.member" || (x.TypedContent as RoomMemberEventData).Membership != "join");
+ // Console.WriteLine($"Room {room.RoomId} has {states.Count} members");
+ // if (states.Count > memberLimit) {
+ // Console.WriteLine("Skipping!");
+ // semaphore.Release();
+ // progress.ProcessedUsers.Remove(room);
+ // progress.TotalRooms--;
+ // return;
+ // }
+ // progress.ProcessedUsers[room].Total = states.Count;
+ // var updateInterval = progress.ProcessedUsers[room].Total >= 1000 ? 1000 : 100;
+ // while (progress.ProcessedUsers.Any(x => x.Value.Total == 0) && progress.ProcessedUsers[room].Total >= 1000) {
+ // progress.ProcessedUsers[room].Blocked = true;
+ // await Task.Delay(1000);
+ // // if(progressCallback is not null)
+ // // await progressCallback.Invoke(progress);
+ // }
+ // progress.ProcessedUsers[room].Blocked = false;
+ // var processedStates = 0;
+ // foreach (var state in states) {
+ // await semLock.WaitAsync();
+ // semLock.Release();
+ // if (progress.ProcessedUsers.Count(x => x.Value.Total == 0) > 5 && progress.ProcessedUsers[room].Total >= 200) {
+ // progress.ProcessedUsers[room].Slowmode = true;
+ // await Task.Delay(progress.ProcessedUsers[room].Total >= 500 ? 1000 : 100);
+ // }
+ // else {
+ // progress.ProcessedUsers[room].Slowmode = false;
+ // }
+ // if (!homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) {
+ // homeServers.Add(new HomeServerInfo { Server = state.StateKey.Split(':')[1] });
+ // }
+ // var hs = homeServers.First(x => x.Server == state.StateKey.Split(':')[1]);
+ // if (!hs.KnownUsers.Contains(state.StateKey.Split(':')[0]))
+ // hs.KnownUsers.Add(state.StateKey.Split(':')[0]);
+ // if (++progress.ProcessedUsers[room].Processed % updateInterval == 0 && progressCallback is not null) {
+ // await semLock.WaitAsync();
+ // var _ = await progressCallback.Invoke(progress);
+ // semLock.Release();
+ // }
+ // }
+ // Console.WriteLine("Collected states!");
+ // progress.ProcessedRooms++;
+ // progress.ProcessedUsers[room].IsFinished = true;
+ // progressCallback?.Invoke(progress);
+ // semaphore.Release();
});
await Task.WhenAll(tasks);
@@ -136,7 +154,7 @@ else {
class HomeServerInfoQueryProgress {
public int ProcessedRooms { get; set; }
public int TotalRooms { get; set; }
- public Dictionary<Room, State> ProcessedUsers { get; } = new();
+ public Dictionary<GenericRoom, State> ProcessedUsers { get; } = new();
public List<HomeServerInfo> CurrentState { get; set; } = new();
public class State {
diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor
index 9df7fa6..e19dd04 100644
--- a/MatrixRoomUtils.Web/Pages/LoginPage.razor
+++ b/MatrixRoomUtils.Web/Pages/LoginPage.razor
@@ -1,6 +1,6 @@
@page "/Login"
-@using MatrixRoomUtils.Core.Authentication
@using System.Text.Json
+@using MatrixRoomUtils.Core.Responses
@using MatrixRoomUtils.Web.Shared.SimpleComponents
@inject ILocalStorageService LocalStorage
@inject IJSRuntime JsRuntime
@@ -22,20 +22,25 @@
<InputFile OnChange="@FileChanged" accept=".tsv"></InputFile>
<br/>
-<button @onclick="Login">Login</button>
<br/><br/>
<h4>Parsed records</h4>
<hr/>
<table border="1">
+ <thead>
+ <td>Username</td>
+ <td>Homeserver</td>
+ </thead>
@foreach (var (homeserver, username, password) in records) {
- <tr style="background-color: @(RuntimeCache.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}") ? "green" : "unset")">
+ var record = (homeserver, username, password);
+ <tr style="background-color: @(LoggedInSessions.Any(x => x.UserId == $"@{username}:{homeserver}") ? "green" : "unset")">
<td style="border-width: 1px;">@username</td>
<td style="border-width: 1px;">@homeserver</td>
- <td style="border-width: 1px;">@password.Length chars</td>
+ <td><a role="button" @onclick="() => records.Remove(record)">Remove</a></td>
</tr>
}
</table>
<br/>
+<button @onclick="Login">Login</button>
<br/>
<LogView></LogView>
@@ -43,26 +48,34 @@
readonly List<(string homeserver, string username, string password)> records = new();
(string homeserver, string username, string password) newRecordInput = ("", "", "");
+ List<LoginResponse> LoggedInSessions { get; set; } = new();
+
async Task Login() {
- foreach (var (homeserver, username, password) in records) {
- if (RuntimeCache.LoginSessions.Any(x => x.Value.LoginResponse.UserId == $"@{username}:{homeserver}")) continue;
- var result = await MatrixAuth.Login(homeserver, username, password);
- Console.WriteLine($"Obtained access token for {result.UserId}!");
-
- var userinfo = new UserInfo {
- LoginResponse = result
- };
- userinfo.Profile = await RuntimeCache.CurrentHomeServer.GetProfile(result.UserId);
- RuntimeCache.LastUsedToken = result.AccessToken;
+ var loginTasks = records.Select(async record => {
+ var (homeserver, username, password) = record;
+ if (LoggedInSessions.Any(x => x.UserId == $"@{username}:{homeserver}")) return;
+ try {
+ var result = await HomeserverProvider.Login(homeserver, username, password);
+ if (result == null) {
+ Console.WriteLine($"Failed to login to {homeserver} as {username}!");
+ return;
+ }
+ Console.WriteLine($"Obtained access token for {result.UserId}!");
- RuntimeCache.LoginSessions.Add(result.AccessToken, userinfo);
+ await MRUStorage.AddToken(result);
+ LoggedInSessions = await MRUStorage.GetAllTokens();
+ }
+ catch (Exception e) {
+ Console.WriteLine($"Failed to login to {homeserver} as {username}!");
+ Console.WriteLine(e);
+ }
StateHasChanged();
- }
-
- await LocalStorageWrapper.SaveToLocalStorage(LocalStorage);
+ });
+ await Task.WhenAll(loginTasks);
}
private async Task FileChanged(InputFileChangeEventArgs obj) {
+ LoggedInSessions = await MRUStorage.GetAllTokens();
Console.WriteLine(JsonSerializer.Serialize(obj, new JsonSerializerOptions {
WriteIndented = true
}));
@@ -78,7 +91,8 @@
}
}
- private void AddRecord() {
+ private async Task AddRecord() {
+ LoggedInSessions = await MRUStorage.GetAllTokens();
records.Add(newRecordInput);
newRecordInput = ("", "", "");
}
diff --git a/MatrixRoomUtils.Web/Pages/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/MediaLocator.razor
index 38d1514..6221041 100644
--- a/MatrixRoomUtils.Web/Pages/MediaLocator.razor
+++ b/MatrixRoomUtils.Web/Pages/MediaLocator.razor
@@ -82,7 +82,6 @@
}
async Task addMoreHomeservers() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
var res = await Http.GetAsync("/homeservers.txt");
var content = await res.Content.ReadAsStringAsync();
homeservers.Clear();
@@ -93,10 +92,8 @@
lines.ToList().ForEach(async line => {
await sem.WaitAsync();
try {
- homeservers.Add(await rhs.ResolveHomeserverFromWellKnown(line));
+ homeservers.Add(await HomeserverResolver.ResolveHomeserverFromWellKnown(line));
StateHasChanged();
- if (Random.Shared.Next(0, 101) == 50)
- await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage);
}
catch (Exception e) {
Console.WriteLine(e);
diff --git a/MatrixRoomUtils.Web/Pages/ModalTest.razor b/MatrixRoomUtils.Web/Pages/ModalTest.razor
index d031dc2..f32c672 100644
--- a/MatrixRoomUtils.Web/Pages/ModalTest.razor
+++ b/MatrixRoomUtils.Web/Pages/ModalTest.razor
@@ -31,20 +31,6 @@
double _y = 0;
double multiplier = 1;
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
- //var rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
-
- //rooms.ForEach(async room => {
- // var name = await room.GetNameAsync();
- // _windowInfos.Add(_windowInfos.Count, new WindowInfo() { X = _x, Y = _y, Title = name});
- // _x += 20;
- // _y += 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;
- // StateHasChanged();
- //});
-
for (int i = 0; i < 200; i++) {
var i1 = i;
_windowInfos.Add(_windowInfos.Count, new WindowInfo() {
diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
index 0840ebf..8e2609f 100644
--- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
+++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor
@@ -1,9 +1,8 @@
@page "/PolicyListEditor/{RoomId}"
@using MatrixRoomUtils.Core.StateEventTypes
@using System.Text.Json
+@using MatrixRoomUtils.Core.Helpers
@using MatrixRoomUtils.Core.Responses
-@inject ILocalStorageService LocalStorage
-@inject NavigationManager NavigationManager
<h3>Policy list editor - Editing @RoomId</h3>
<hr/>
@@ -31,12 +30,13 @@ else {
</tr>
</thead>
<tbody>
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity != null)) {
+ @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && (x.TypedContent as PolicyRuleStateEventData).Entity is not null)) {
+ var policyData = policyEvent.TypedContent as PolicyRuleStateEventData;
<tr>
- <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td>
- <td>@policyEvent.Content.Reason</td>
+ <td>Entity: @policyData.Entity<br/>State: @policyEvent.StateKey</td>
+ <td>@policyData.Reason</td>
<td>
- @policyEvent.Content.ExpiryDateTime
+ @policyData.ExpiryDateTime
</td>
<td>
<button class="btn" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Edit</button>
@@ -47,7 +47,7 @@ else {
</tbody>
</table>
<details>
- <summary>Invalid events</summary>
+ <summary>Redacted events</summary>
<table class="table table-striped table-hover" style="width: fit-Content;">
<thead>
<tr>
@@ -56,10 +56,11 @@ else {
</tr>
</thead>
<tbody>
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && x.Content.Entity == null)) {
+ @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.server" && (x.TypedContent as PolicyRuleStateEventData).Entity == null)) {
+ var policyData = policyEvent.TypedContent as PolicyRuleStateEventData;
<tr>
<td>@policyEvent.StateKey</td>
- <td>@policyEvent.Content.ToJson(false, true)</td>
+ <td>@policyEvent.RawContent.ToJson(false, true)</td>
</tr>
}
</tbody>
@@ -82,12 +83,13 @@ else {
</tr>
</thead>
<tbody>
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity != null)) {
+ @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && (x.TypedContent as PolicyRuleStateEventData).Entity is not null)) {
+ var policyData = policyEvent.TypedContent as PolicyRuleStateEventData;
<tr>
- <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td>
- <td>@policyEvent.Content.Reason</td>
+ <td>Entity: @policyData.Entity<br/>State: @policyEvent.StateKey</td>
+ <td>@policyData.Reason</td>
<td>
- @policyEvent.Content.ExpiryDateTime
+ @policyData.ExpiryDateTime
</td>
<td>
<button class="btn btn-danger" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Remove</button>
@@ -97,7 +99,7 @@ else {
</tbody>
</table>
<details>
- <summary>Invalid events</summary>
+ <summary>Redacted events</summary>
<table class="table table-striped table-hover" style="width: fit-Content;">
<thead>
<tr>
@@ -106,10 +108,10 @@ else {
</tr>
</thead>
<tbody>
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && x.Content.Entity == null)) {
+ @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.room" && (x.TypedContent as PolicyRuleStateEventData).Entity == null)) {
<tr>
<td>@policyEvent.StateKey</td>
- <td>@policyEvent.Content.ToJson(false, true)</td>
+ <td>@policyEvent.RawContent.ToJson(false, true)</td>
</tr>
}
</tbody>
@@ -135,17 +137,18 @@ else {
</tr>
</thead>
<tbody>
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) {
+ @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && (x.TypedContent as PolicyRuleStateEventData).Entity is not null)) {
+ var policyData = policyEvent.TypedContent as PolicyRuleStateEventData;
<tr>
@if (_enableAvatars) {
<td scope="col">
- <img style="width: 48px; height: 48px; aspect-ratio: unset; border-radius: 50%;" src="@(avatars.ContainsKey(policyEvent.Content.Entity) ? avatars[policyEvent.Content.Entity] : "")"/>
+ <img style="width: 48px; height: 48px; aspect-ratio: unset; border-radius: 50%;" src="@(avatars.ContainsKey(policyData.Entity) ? avatars[policyData.Entity] : "")"/>
</td>
}
- <td style="word-wrap: anywhere;">Entity: @string.Join("", policyEvent.Content.Entity.Take(64))<br/>State: @string.Join("", policyEvent.StateKey.Take(64))</td>
- <td>@policyEvent.Content.Reason</td>
+ <td style="word-wrap: anywhere;">Entity: @string.Join("", policyData.Entity.Take(64))<br/>State: @string.Join("", policyEvent.StateKey.Take(64))</td>
+ <td>@policyData.Reason</td>
<td>
- @policyEvent.Content.ExpiryDateTime
+ @policyData.ExpiryDateTime
</td>
<td>
<button class="btn btn-danger" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Remove</button>
@@ -155,7 +158,7 @@ else {
</tbody>
</table>
<details>
- <summary>Invalid events</summary>
+ <summary>Redacted events</summary>
<table class="table table-striped table-hover" style="width: fit-Content;">
<thead>
<tr>
@@ -164,10 +167,10 @@ else {
</tr>
</thead>
<tbody>
- @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity == null)) {
+ @foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && (x.TypedContent as PolicyRuleStateEventData).Entity == null)) {
<tr>
<td>@policyEvent.StateKey</td>
- <td>@policyEvent.Content.ToJson(false, true)</td>
+ <td>@policyEvent.RawContent.ToJson(false, true)</td>
</tr>
}
</tbody>
@@ -191,36 +194,32 @@ else {
static readonly Dictionary<string, string?> avatars = new();
static readonly Dictionary<string, RemoteHomeServer> servers = new();
- public static List<StateEventResponse<PolicyRuleStateEventData>> PolicyEvents { get; set; } = new();
+ public static List<StateEventResponse> PolicyEvents { get; set; } = new();
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
await base.OnInitializedAsync();
- // if(RuntimeCache.AccessToken == null || RuntimeCache.CurrentHomeserver == null)
- if (RuntimeCache.CurrentHomeServer == null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
RoomId = RoomId.Replace('~', '.');
await LoadStatesAsync();
Console.WriteLine("Policy list editor initialized!");
}
private async Task LoadStatesAsync() {
- // using var client = new HttpClient();
- // client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", LocalStorageWrapper.AccessToken);
- // var response = await client.GetAsync($"{LocalStorageWrapper.CurrentHomeserver}/_matrix/client/v3/rooms/{RoomId}/state");
- // var Content = await response.Content.ReadAsStringAsync();
- // Console.WriteLine(JsonSerializer.Deserialize<object>(Content).ToJson());
- // var stateEvents = JsonSerializer.Deserialize<List<StateEventResponse>>(Content);
- var room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId);
- var stateEventsQuery = await room.GetStateAsync("");
- if (stateEventsQuery == null) {
- Console.WriteLine("state events query is null!!!");
+ var hs = await MRUStorage.GetCurrentSession();
+ var room = await hs.GetRoom(RoomId);
+
+ var states = room.GetFullStateAsync();
+ await foreach (var state in states) {
+ if (!state.Type.StartsWith("m.policy.rule")) continue;
+ PolicyEvents.Add(state);
}
- var stateEvents = stateEventsQuery.Value.Deserialize<List<StateEventResponse>>();
- PolicyEvents = stateEvents.Where(x => x.Type.StartsWith("m.policy.rule"))
- .Select(x => JsonSerializer.Deserialize<StateEventResponse<PolicyRuleStateEventData>>(JsonSerializer.Serialize(x))).ToList();
+
+
+ // var stateEventsQuery = await room.GetStateAsync("");
+ // var stateEvents = stateEventsQuery.Value.Deserialize<List<StateEventResponse>>();
+ // PolicyEvents = stateEvents.Where(x => x.Type.StartsWith("m.policy.rule"))
+ // .Select(x => JsonSerializer.Deserialize<StateEventResponse>(JsonSerializer.Serialize(x))).ToList();
StateHasChanged();
}
@@ -228,10 +227,10 @@ else {
try {
if (avatars.ContainsKey(userId)) return;
var hs = userId.Split(':')[1];
- var server = servers.ContainsKey(hs) ? servers[hs] : await new RemoteHomeServer(userId.Split(':')[1]).Configure();
+ var server = servers.ContainsKey(hs) ? servers[hs] : new RemoteHomeServer(userId.Split(':')[1]);
if (!servers.ContainsKey(hs)) servers.Add(hs, server);
var profile = await server.GetProfile(userId);
- avatars.Add(userId, server.ResolveMediaUri(profile.AvatarUrl));
+ avatars.Add(userId, MediaResolver.ResolveMediaUri(server.FullHomeServerDomain, profile.AvatarUrl));
servers.Add(userId, server);
StateHasChanged();
}
@@ -241,8 +240,8 @@ else {
}
private async Task GetAllAvatars() {
- foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && x.Content.Entity != null)) {
- await GetAvatar(policyEvent.Content.Entity);
+ foreach (var policyEvent in PolicyEvents.Where(x => x.Type == "m.policy.rule.user" && (x.TypedContent as PolicyRuleStateEventData).Entity is not null)) {
+ await GetAvatar((policyEvent.TypedContent as PolicyRuleStateEventData).Entity);
}
StateHasChanged();
}
diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
index 8f711b5..4db2b5a 100644
--- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
+++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor
@@ -1,4 +1,7 @@
@page "/PolicyListEditor"
+@using System.Text.Json.Serialization
+@using MatrixRoomUtils.Core.Interfaces
+@using MatrixRoomUtils.Core.StateEventTypes
@inject ILocalStorageService LocalStorage
@inject NavigationManager NavigationManager
<h3>Policy list editor - Room list</h3>
@@ -39,28 +42,26 @@ else {
private int totalRoomCount { get; set; }
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
await base.OnInitializedAsync();
- if (RuntimeCache.CurrentHomeServer == null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
await EnumeratePolicyRooms();
Console.WriteLine("Policy list editor initialized!");
}
private async Task EnumeratePolicyRooms() {
- var xxxrooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
- totalRoomCount = xxxrooms.Count;
+ var hs = await MRUStorage.GetCurrentSession();
+ var rooms = await hs.GetJoinedRooms();
+ totalRoomCount = rooms.Count;
StateHasChanged();
- var xxxsemaphore = new SemaphoreSlim(1000);
- var xxxtasks = new List<Task<PolicyRoomInfo?>>();
- foreach (var room in xxxrooms) {
- xxxtasks.Add(GetPolicyRoomInfo(room.RoomId, xxxsemaphore));
+ var semaphore = new SemaphoreSlim(8);
+ var tasks = new List<Task<PolicyRoomInfo?>>();
+ foreach (var room in rooms) {
+ tasks.Add(GetPolicyRoomInfo(room.RoomId, semaphore));
}
- var xxxresults = await Task.WhenAll(xxxtasks);
- PolicyRoomList.AddRange(xxxresults.Where(x => x != null).Select(x => x.Value));
+ var results = await Task.WhenAll(tasks);
+ PolicyRoomList.AddRange(results.Where(x => x is not null).Select(x => x.Value));
Console.WriteLine($"Detected policy lists: {PolicyRoomList.ToJson()}");
}
@@ -68,15 +69,15 @@ else {
private async Task<PolicyRoomInfo?> GetPolicyRoomInfo(string room, SemaphoreSlim semaphore) {
try {
await semaphore.WaitAsync();
+ var hs = await MRUStorage.GetCurrentSession();
PolicyRoomInfo roomInfo = new() {
RoomId = room
};
- var r = await RuntimeCache.CurrentHomeServer.GetRoom(room);
- var shortcodeState = await r.GetStateAsync("org.matrix.mjolnir.shortcode");
- if (!shortcodeState.HasValue) return null;
- roomInfo.Shortcode = shortcodeState.Value.TryGetProperty("shortcode", out var shortcode) ? shortcode.GetString() : null;
+ var r = await hs.GetRoom(room);
+ var shortcodeState = await r.GetStateAsync<MjolnirShortcodeEventData>("org.matrix.mjolnir.shortcode");
+ roomInfo.Shortcode = shortcodeState.Shortcode;
- if (roomInfo.Shortcode != null) {
+ if (roomInfo.Shortcode is not null) {
roomInfo.Name = await r.GetNameAsync();
return roomInfo;
}
@@ -90,6 +91,8 @@ else {
}
}
+
+
public struct PolicyRoomInfo {
public
string RoomId { get; set; }
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor
index 9b0bb88..087adf8 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor
@@ -34,25 +34,22 @@ else {
<LogView></LogView>
@code {
- public List<Room> Rooms { get; set; } = new();
- public List<Room> Spaces { get; set; } = new();
+ public List<GenericRoom> Rooms { get; set; } = new();
+ public List<GenericRoom> Spaces { get; set; } = new();
protected override async Task OnInitializedAsync() {
Console.WriteLine("Initializing room manager");
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
Console.WriteLine("Loaded from local storage");
await base.OnInitializedAsync();
Console.WriteLine("Initialized base");
- if (RuntimeCache.CurrentHomeServer == null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
Console.WriteLine("Fetching joined rooms");
- var _rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
+ var _rooms = await hs.GetJoinedRooms();
StateHasChanged();
Console.WriteLine($"Got {_rooms.Count} rooms");
var semaphore = new SemaphoreSlim(10);
- var tasks = new List<Task<Room?>>();
+ var tasks = new List<Task<GenericRoom?>>();
foreach (var room in _rooms) {
tasks.Add(CheckIfSpace(room, semaphore));
}
@@ -61,14 +58,14 @@ else {
Console.WriteLine("Fetched joined rooms!");
}
- private async Task<Room?> CheckIfSpace(Room room, SemaphoreSlim semaphore) {
+ private async Task<GenericRoom?> CheckIfSpace(GenericRoom room, SemaphoreSlim semaphore) {
await semaphore.WaitAsync();
// Console.WriteLine($"Checking if {room.RoomId} is a space");
try {
var state = await room.GetStateAsync<CreateEvent>("m.room.create");
- if (state != null) {
+ if (state is not null) {
//Console.WriteLine(state.Value.ToJson());
- if (state.Type != null) {
+ if (state.Type is not null) {
if (state.Type == "m.space") {
Console.WriteLine($"Room {room.RoomId} is a space!");
Spaces.Add(room);
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
index 80d852a..8368aa5 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor
@@ -1,339 +1,339 @@
-@page "/RoomManagerCreateRoom"
-@using MatrixRoomUtils.Core.Responses
-@using System.Text.Json
-@using System.Reflection
-@using MatrixRoomUtils.Core.StateEventTypes
-@using MatrixRoomUtils.Web.Classes.RoomCreationTemplates
-@* ReSharper disable once RedundantUsingDirective - Must not remove this, Rider marks this as "unused" when it's not *@
-@using MatrixRoomUtils.Web.Shared.SimpleComponents
-
-<h3>Room Manager - Create Room</h3>
-
-@* <pre Contenteditable="true" @onkeypress="@JsonChanged" ="JsonString">@JsonString</pre> *@
-<style>
- table.table-top-first-tr tr td:first-child {
- vertical-align: top;
- }
-</style>
-<table class="table-top-first-tr">
- <tr>
- <td style="padding-bottom: 16px;">Preset:</td>
- <td style="padding-bottom: 16px;">
- <InputSelect @bind-Value="@RoomPreset">
- @foreach (var createRoomRequest in Presets) {
- <option value="@createRoomRequest.Key">@createRoomRequest.Key</option>
- }
- </InputSelect>
- </td>
- </tr>
- @if (creationEvent != null) {
- <tr>
- <td>Room name:</td>
- <td>
- <FancyTextBox @bind-Value="@creationEvent.Name"></FancyTextBox>
- </td>
- </tr>
- <tr>
- <td>Room alias (localpart):</td>
- <td>
- <FancyTextBox @bind-Value="@creationEvent.RoomAliasName"></FancyTextBox>
- </td>
- </tr>
- <tr>
- <td>Room type:</td>
- <td>
- <InputSelect @bind-Value="@creationEvent._creationContentBaseType.Type">
- <option value="">Room</option>
- <option value="m.space">Space</option>
- </InputSelect>
- <FancyTextBox @bind-Value="@creationEvent._creationContentBaseType.Type"></FancyTextBox>
- </td>
- </tr>
- <tr>
- <td style="padding-top: 16px;">History visibility:</td>
- <td style="padding-top: 16px;">
- @* <InputSelect @bind-Value="@creationEvent.HistoryVisibility"> *@
- @* <option value="invited">Invited</option> *@
- @* <option value="joined">Joined</option> *@
- @* <option value="shared">Shared</option> *@
- @* <option value="world_readable">World readable</option> *@
- @* </InputSelect> *@
- </td>
- </tr>
- <tr>
- <td>Guest access:</td>
- <td>
- <ToggleSlider Value="guestAccessEvent.IsGuestAccessEnabled" ValueChanged="@(v => { guestAccessEvent.IsGuestAccessEnabled = v; creationEvent["m.room.guest_access"].Content = guestAccessEvent; })">@(guestAccessEvent.IsGuestAccessEnabled ? "Guests can join" : "Guests cannot join") (@guestAccessEvent.GuestAccess)</ToggleSlider>
- @* <InputSelect @bind-Value="@creationEvent.GuestAccess"> *@
- @* <option value="can_join">Can join</option> *@
- @* <option value="forbidden">Forbidden</option> *@
- @* </InputSelect> *@
- </td>
- </tr>
-
- <tr>
- <td>Room icon:</td>
- <td>
- <img src="@RuntimeCache.CurrentHomeServer?.ResolveMediaUri(creationEvent.RoomIcon ?? "")" style="width: 128px; height: 128px; border-radius: 50%;"/>
- <div style=" display: inline-block;
- vertical-align: middle;">
- <FancyTextBox @bind-Value="@creationEvent.RoomIcon"></FancyTextBox><br/>
- <InputFile OnChange="RoomIconFilePicked"></InputFile>
- </div>
-
- </td>
- </tr>
- <tr>
- <td>Permissions:</td>
- <details>
- <summary>@creationEvent.PowerLevelContentOverride.Users.Count members</summary>
- @foreach (var user in creationEvent.PowerLevelContentOverride.Events.Keys) {
- var _event = user;
- <tr>
- <td><FancyTextBox Formatter="@GetPermissionFriendlyName" Value="@_event" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Events.ChangeKey(_event, val); }"></FancyTextBox>:</td>
- <td>
- <input type="number" value="@creationEvent.PowerLevelContentOverride.Events[_event]" @oninput="val => { creationEvent.PowerLevelContentOverride.Events[_event] = int.Parse(val.Value.ToString()); }" @onfocusout="() => { creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); }"/>
- </td>
- </tr>
- }
- @foreach (var user in creationEvent.PowerLevelContentOverride.Users.Keys) {
- var _user = user;
- <tr>
- <td><FancyTextBox Value="@_user" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Users.ChangeKey(_user, val); creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); }"></FancyTextBox>:</td>
- <td>
- <input type="number" value="@creationEvent.PowerLevelContentOverride.Users[_user]" @oninput="val => { creationEvent.PowerLevelContentOverride.Users[_user] = int.Parse(val.Value.ToString()); }"/>
- </td>
- </tr>
- }
- </details>
- </tr>
- <tr>
- <td>Server ACLs:</td>
- <td>
- <details>
- <summary>@(creationEvent.ServerACLs.Allow.Count) allow rules</summary>
- <StringListEditor ItemsChanged="OverwriteWrappedProperties" Items="@ServerACLAllowRules"></StringListEditor>
- </details>
- <details>
- <summary>@creationEvent.ServerACLs.Deny.Count deny rules</summary>
- <StringListEditor ItemsChanged="OverwriteWrappedProperties" Items="@ServerACLDenyRules"></StringListEditor>
- </details>
- </td>
- </tr>
-
- <tr>
- <td>Invited members:</td>
- <td>
- <details>
- <summary>@creationEvent.InitialState.Count(x => x.Type == "m.room.member") members</summary>
- <button @onclick="() => { RuntimeCache.LoginSessions.Select(x => x.Value.LoginResponse.UserId).ToList().ForEach(InviteMember); }">Invite all logged in accounts</button>
- @foreach (var member in creationEvent.InitialState.Where(x => x.Type == "m.room.member" && x.StateKey != RuntimeCache.CurrentHomeServer.UserId)) {
- <UserListItem UserId="@member.StateKey"></UserListItem>
- }
- </details>
- </td>
- </tr>
-
- @* Initial states, should remain at bottom? *@
-
- <tr>
- <td style="vertical-align: top;">Initial states:</td>
- <td>
- <details>
-
- @code{
-
- private static readonly string[] ImplementedStates = { "m.room.avatar", "m.room.history_visibility", "m.room.guest_access", "m.room.server_acl" };
-
- }
-
- <summary>@creationEvent.InitialState.Count(x => !ImplementedStates.Contains(x.Type)) custom states</summary>
- <table>
- @foreach (var initialState in creationEvent.InitialState.Where(x => !ImplementedStates.Contains(x.Type))) {
- <tr>
- <td style="vertical-align: top;">
- @(initialState.Type):
- @if (!string.IsNullOrEmpty(initialState.StateKey)) {
- <br/>
- <span>(@initialState.StateKey)</span>
- }
- </td>
-
- <td>
- <pre>@JsonSerializer.Serialize(initialState.Content, new JsonSerializerOptions { WriteIndented = true })</pre>
- </td>
- </tr>
- }
- </table>
- </details>
- <details>
- <summary>@creationEvent.InitialState.Count initial states</summary>
- <table>
- @foreach (var initialState in creationEvent.InitialState) {
- var _state = initialState;
- <tr>
- <td style="vertical-align: top;">
- <span>@(_state.Type):</span><br/>
- <button @onclick="() => { creationEvent.InitialState.Remove(_state); StateHasChanged(); }">Remove</button>
- </td>
-
- <td>
- <pre>@JsonSerializer.Serialize(_state.Content, new JsonSerializerOptions { WriteIndented = true })</pre>
- </td>
- </tr>
- }
- </table>
- </details>
- </td>
- </tr>
- }
-</table>
-<button @onclick="CreateRoom">Create room</button>
-<br/>
-<details>
- <summary>Creation JSON</summary>
- <pre>
- @creationEvent.ToJson(ignoreNull: true)
- </pre>
-</details>
-<details open>
- <summary>Creation JSON (with null values)</summary>
- <pre>
- @creationEvent.ToJson()
- </pre>
-</details>
-
-
-@code {
-
- private string RoomPreset {
- get {
- if (Presets.ContainsValue(creationEvent)) {
- return Presets.First(x => x.Value == creationEvent).Key;
- }
- return "Not a preset";
- }
- set {
- creationEvent = Presets[value];
- JsonChanged();
- OverwriteWrappedPropertiesFromEvent();
- creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
- creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
- guestAccessEvent = creationEvent["m.room.guest_access"].As<GuestAccessData>().Content;
-
- Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}");
- Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}");
- creationEvent["m.room.guest_access"].As<GuestAccessData>().Content.IsGuestAccessEnabled = true;
- Console.WriteLine("-- Created new guest access content --");
- Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}");
- Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}");
- Console.WriteLine($"Creation event casted back: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}");
- StateHasChanged();
- }
- }
-
- private Dictionary<string, string> creationEventValidationErrors { get; set; } = new();
-
- private CreateRoomRequest creationEvent { get; set; }
- GuestAccessData guestAccessEvent { get; set; }
-
- private Dictionary<string, CreateRoomRequest> Presets { get; set; } = new();
-
- protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-
- //creationEvent = Presets["Default room"] =
- foreach (var x in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(IRoomCreationTemplate))).ToList()) {
- Console.WriteLine($"Found room creation template in class: {x.FullName}");
- var instance = (IRoomCreationTemplate)Activator.CreateInstance(x);
- Presets[instance.Name] = instance.CreateRoomRequest;
- }
- Presets = Presets.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value);
-
- if (!Presets.ContainsKey("Default")) {
- Console.WriteLine($"No default room found in {Presets.Count} presets: {string.Join(", ", Presets.Keys)}");
- }
- else RoomPreset = "Default";
-
- await base.OnInitializedAsync();
- }
-
- private void JsonChanged() => Console.WriteLine(creationEvent.ToJson());
-
- //wrappers
- private List<string> ServerACLAllowRules { get; set; } = new();
- private List<string> ServerACLDenyRules { get; set; } = new();
-
- private void OverwriteWrappedPropertiesFromEvent() {
- Console.WriteLine("Overwriting wrapped properties from event");
- ServerACLAllowRules = creationEvent.ServerACLs.Allow;
- ServerACLDenyRules = creationEvent.ServerACLs.Deny;
- }
-
- private async Task OverwriteWrappedProperties() {
- Console.WriteLine("Overwriting wrapped properties");
- Console.WriteLine($"Allow: {ServerACLAllowRules.Count}: {string.Join(", ", ServerACLAllowRules)}");
- Console.WriteLine($"Deny: {ServerACLDenyRules.Count}: {string.Join(", ", ServerACLDenyRules)}");
- creationEvent.ServerACLs = new ServerACLData {
- Allow = ServerACLAllowRules,
- Deny = ServerACLDenyRules,
- AllowIpLiterals = creationEvent.ServerACLs.AllowIpLiterals
- };
-
- StateHasChanged();
- }
-
- private async Task RoomIconFilePicked(InputFileChangeEventArgs obj) {
- var res = await RuntimeCache.CurrentHomeServer.UploadFile(obj.File.Name, obj.File.OpenReadStream(), obj.File.ContentType);
- Console.WriteLine(res);
- creationEvent.RoomIcon = res;
- StateHasChanged();
- }
-
- private async Task CreateRoom() {
- Console.WriteLine("Create room");
- Console.WriteLine(creationEvent.ToJson());
- creationEvent.CreationContent.Add("rory.gay.created_using", "Rory&::MatrixRoomUtils (https://mru.rory.gay)");
- //creationEvent.CreationContent.Add();
- var id = await RuntimeCache.CurrentHomeServer.CreateRoom(creationEvent);
- // NavigationManager.NavigateTo($"/RoomManager/{id.RoomId.Replace('.','~')}");
- }
-
- private void InviteMember(string mxid) {
- if (!creationEvent.InitialState.Any(x => x.Type == "m.room.member" && x.StateKey == mxid) && RuntimeCache.CurrentHomeServer.UserId != mxid)
- creationEvent.InitialState.Add(new StateEvent {
- Type = "m.room.member",
- StateKey = mxid,
- Content = new {
- membership = "invite",
- reason = "Automatically invited at room creation time."
- }
- });
- }
-
- private string GetStateFriendlyName(string key) => key switch {
- "m.room.history_visibility" => "History visibility",
- "m.room.guest_access" => "Guest access",
- "m.room.join_rules" => "Join rules",
- "m.room.server_acl" => "Server ACL",
- "m.room.avatar" => "Avatar",
- _ => key
- };
-
- private string GetPermissionFriendlyName(string key) => key switch {
- "m.reaction" => "Send reaction",
- "m.room.avatar" => "Change room icon",
- "m.room.canonical_alias" => "Change room alias",
- "m.room.encryption" => "Enable encryption",
- "m.room.history_visibility" => "Change history visibility",
- "m.room.name" => "Change room name",
- "m.room.power_levels" => "Change power levels",
- "m.room.tombstone" => "Upgrade room",
- "m.room.topic" => "Change room topic",
- "m.room.pinned_events" => "Pin events",
- "m.room.server_acl" => "Change server ACLs",
- _ => key
- };
-
- }
-
+@* @page "/RoomManagerCreateRoom" *@
+@* @using MatrixRoomUtils.Core.Responses *@
+@* @using System.Text.Json *@
+@* @using System.Reflection *@
+@* @using MatrixRoomUtils.Core.Helpers *@
+@* @using MatrixRoomUtils.Core.StateEventTypes *@
+@* @using MatrixRoomUtils.Web.Classes.RoomCreationTemplates *@
+@* $1$ ReSharper disable once RedundantUsingDirective - Must not remove this, Rider marks this as "unused" when it's not #1# *@
+@* @using MatrixRoomUtils.Web.Shared.SimpleComponents *@
+@* *@
+@* <h3>Room Manager - Create Room</h3> *@
+@* *@
+@* $1$ <pre Contenteditable="true" @onkeypress="@JsonChanged" ="JsonString">@JsonString</pre> #1# *@
+@* <style> *@
+@* table.table-top-first-tr tr td:first-child { *@
+@* vertical-align: top; *@
+@* } *@
+@* </style> *@
+@* <table class="table-top-first-tr"> *@
+@* <tr> *@
+@* <td style="padding-bottom: 16px;">Preset:</td> *@
+@* <td style="padding-bottom: 16px;"> *@
+@* <InputSelect @bind-Value="@RoomPreset"> *@
+@* @foreach (var createRoomRequest in Presets) { *@
+@* <option value="@createRoomRequest.Key">@createRoomRequest.Key</option> *@
+@* } *@
+@* </InputSelect> *@
+@* </td> *@
+@* </tr> *@
+@* @if (creationEvent is not null) { *@
+@* <tr> *@
+@* <td>Room name:</td> *@
+@* <td> *@
+@* <FancyTextBox @bind-Value="@creationEvent.Name"></FancyTextBox> *@
+@* </td> *@
+@* </tr> *@
+@* <tr> *@
+@* <td>Room alias (localpart):</td> *@
+@* <td> *@
+@* <FancyTextBox @bind-Value="@creationEvent.RoomAliasName"></FancyTextBox> *@
+@* </td> *@
+@* </tr> *@
+@* <tr> *@
+@* <td>Room type:</td> *@
+@* <td> *@
+@* <InputSelect @bind-Value="@creationEvent._creationContentBaseType.Type"> *@
+@* <option value="">Room</option> *@
+@* <option value="m.space">Space</option> *@
+@* </InputSelect> *@
+@* <FancyTextBox @bind-Value="@creationEvent._creationContentBaseType.Type"></FancyTextBox> *@
+@* </td> *@
+@* </tr> *@
+@* <tr> *@
+@* <td style="padding-top: 16px;">History visibility:</td> *@
+@* <td style="padding-top: 16px;"> *@
+@* $1$ <InputSelect @bind-Value="@creationEvent.HistoryVisibility"> #1# *@
+@* $1$ <option value="invited">Invited</option> #1# *@
+@* $1$ <option value="joined">Joined</option> #1# *@
+@* $1$ <option value="shared">Shared</option> #1# *@
+@* $1$ <option value="world_readable">World readable</option> #1# *@
+@* $1$ </InputSelect> #1# *@
+@* </td> *@
+@* </tr> *@
+@* <tr> *@
+@* <td>Guest access:</td> *@
+@* <td> *@
+@* <ToggleSlider Value="guestAccessEvent.IsGuestAccessEnabled" ValueChanged="@(v => { guestAccessEvent.IsGuestAccessEnabled = v; creationEvent["m.room.guest_access"].Content = guestAccessEvent; })">@(guestAccessEvent.IsGuestAccessEnabled ? "Guests can join" : "Guests cannot join") (@guestAccessEvent.GuestAccess)</ToggleSlider> *@
+@* $1$ <InputSelect @bind-Value="@creationEvent.GuestAccess"> #1# *@
+@* $1$ <option value="can_join">Can join</option> #1# *@
+@* $1$ <option value="forbidden">Forbidden</option> #1# *@
+@* $1$ </InputSelect> #1# *@
+@* </td> *@
+@* </tr> *@
+@* *@
+@* <tr> *@
+@* <td>Room icon:</td> *@
+@* <td> *@
+@* <img src="@MediaResolver.ResolveMediaUri(creationEvent.RoomIcon ?? "")" style="width: 128px; height: 128px; border-radius: 50%;"/> *@
+@* <div style=" display: inline-block; *@
+@* vertical-align: middle;"> *@
+@* <FancyTextBox @bind-Value="@creationEvent.RoomIcon"></FancyTextBox><br/> *@
+@* <InputFile OnChange="RoomIconFilePicked"></InputFile> *@
+@* </div> *@
+@* *@
+@* </td> *@
+@* </tr> *@
+@* <tr> *@
+@* <td>Permissions:</td> *@
+@* <details> *@
+@* <summary>@creationEvent.PowerLevelContentOverride.Users.Count members</summary> *@
+@* @foreach (var user in creationEvent.PowerLevelContentOverride.Events.Keys) { *@
+@* var _event = user; *@
+@* <tr> *@
+@* <td><FancyTextBox Formatter="@GetPermissionFriendlyName" Value="@_event" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Events.ChangeKey(_event, val); }"></FancyTextBox>:</td> *@
+@* <td> *@
+@* <input type="number" value="@creationEvent.PowerLevelContentOverride.Events[_event]" @oninput="val => { creationEvent.PowerLevelContentOverride.Events[_event] = int.Parse(val.Value.ToString()); }" @onfocusout="() => { creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); }"/> *@
+@* </td> *@
+@* </tr> *@
+@* } *@
+@* @foreach (var user in creationEvent.PowerLevelContentOverride.Users.Keys) { *@
+@* var _user = user; *@
+@* <tr> *@
+@* <td><FancyTextBox Value="@_user" ValueChanged="val => { creationEvent.PowerLevelContentOverride.Users.ChangeKey(_user, val); creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); }"></FancyTextBox>:</td> *@
+@* <td> *@
+@* <input type="number" value="@creationEvent.PowerLevelContentOverride.Users[_user]" @oninput="val => { creationEvent.PowerLevelContentOverride.Users[_user] = int.Parse(val.Value.ToString()); }"/> *@
+@* </td> *@
+@* </tr> *@
+@* } *@
+@* </details> *@
+@* </tr> *@
+@* <tr> *@
+@* <td>Server ACLs:</td> *@
+@* <td> *@
+@* <details> *@
+@* <summary>@(creationEvent["server"].ServerACLs.Allow.Count) allow rules</summary> *@
+@* <StringListEditor ItemsChanged="OverwriteWrappedProperties" Items="@ServerACLAllowRules"></StringListEditor> *@
+@* </details> *@
+@* <details> *@
+@* <summary>@creationEvent.ServerACLs.Deny.Count deny rules</summary> *@
+@* <StringListEditor ItemsChanged="OverwriteWrappedProperties" Items="@ServerACLDenyRules"></StringListEditor> *@
+@* </details> *@
+@* </td> *@
+@* </tr> *@
+@* *@
+@* <tr> *@
+@* <td>Invited members:</td> *@
+@* <td> *@
+@* <details> *@
+@* <summary>@creationEvent.InitialState.Count(x => x.Type == "m.room.member") members</summary> *@
+@* <button @onclick="() => { RuntimeCache.LoginSessions.Select(x => x.Value.LoginResponse.UserId).ToList().ForEach(InviteMember); }">Invite all logged in accounts</button> *@
+@* @foreach (var member in creationEvent.InitialState.Where(x => x.Type == "m.room.member" && x.StateKey != RuntimeCache.CurrentHomeServer.UserId)) { *@
+@* <UserListItem UserId="@member.StateKey"></UserListItem> *@
+@* } *@
+@* </details> *@
+@* </td> *@
+@* </tr> *@
+@* *@
+@* $1$ Initial states, should remain at bottom? #1# *@
+@* *@
+@* <tr> *@
+@* <td style="vertical-align: top;">Initial states:</td> *@
+@* <td> *@
+@* <details> *@
+@* *@
+@* @code{ *@
+@* *@
+@* private static readonly string[] ImplementedStates = { "m.room.avatar", "m.room.history_visibility", "m.room.guest_access", "m.room.server_acl" }; *@
+@* *@
+@* } *@
+@* *@
+@* <summary>@creationEvent.InitialState.Count(x => !ImplementedStates.Contains(x.Type)) custom states</summary> *@
+@* <table> *@
+@* @foreach (var initialState in creationEvent.InitialState.Where(x => !ImplementedStates.Contains(x.Type))) { *@
+@* <tr> *@
+@* <td style="vertical-align: top;"> *@
+@* @(initialState.Type): *@
+@* @if (!string.IsNullOrEmpty(initialState.StateKey)) { *@
+@* <br/> *@
+@* <span>(@initialState.StateKey)</span> *@
+@* } *@
+@* </td> *@
+@* *@
+@* <td> *@
+@* <pre>@JsonSerializer.Serialize(initialState.Content, new JsonSerializerOptions { WriteIndented = true })</pre> *@
+@* </td> *@
+@* </tr> *@
+@* } *@
+@* </table> *@
+@* </details> *@
+@* <details> *@
+@* <summary>@creationEvent.InitialState.Count initial states</summary> *@
+@* <table> *@
+@* @foreach (var initialState in creationEvent.InitialState) { *@
+@* var _state = initialState; *@
+@* <tr> *@
+@* <td style="vertical-align: top;"> *@
+@* <span>@(_state.Type):</span><br/> *@
+@* <button @onclick="() => { creationEvent.InitialState.Remove(_state); StateHasChanged(); }">Remove</button> *@
+@* </td> *@
+@* *@
+@* <td> *@
+@* <pre>@JsonSerializer.Serialize(_state.Content, new JsonSerializerOptions { WriteIndented = true })</pre> *@
+@* </td> *@
+@* </tr> *@
+@* } *@
+@* </table> *@
+@* </details> *@
+@* </td> *@
+@* </tr> *@
+@* } *@
+@* </table> *@
+@* <button @onclick="CreateRoom">Create room</button> *@
+@* <br/> *@
+@* <details> *@
+@* <summary>Creation JSON</summary> *@
+@* <pre> *@
+@* @creationEvent.ToJson(ignoreNull: true) *@
+@* </pre> *@
+@* </details> *@
+@* <details open> *@
+@* <summary>Creation JSON (with null values)</summary> *@
+@* <pre> *@
+@* @creationEvent.ToJson() *@
+@* </pre> *@
+@* </details> *@
+@* *@
+@* *@
+@* @code { *@
+@* *@
+@* private string RoomPreset { *@
+@* get { *@
+@* if (Presets.ContainsValue(creationEvent)) { *@
+@* return Presets.First(x => x.Value == creationEvent).Key; *@
+@* } *@
+@* return "Not a preset"; *@
+@* } *@
+@* set { *@
+@* creationEvent = Presets[value]; *@
+@* JsonChanged(); *@
+@* OverwriteWrappedPropertiesFromEvent(); *@
+@* creationEvent.PowerLevelContentOverride.Events = creationEvent.PowerLevelContentOverride.Events.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); *@
+@* creationEvent.PowerLevelContentOverride.Users = creationEvent.PowerLevelContentOverride.Users.OrderByDescending(x => x.Value).ThenBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); *@
+@* guestAccessEvent = creationEvent["m.room.guest_access"].As<GuestAccessData>().Content; *@
+@* *@
+@* Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}"); *@
+@* Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}"); *@
+@* creationEvent["m.room.guest_access"].As<GuestAccessData>().Content.IsGuestAccessEnabled = true; *@
+@* Console.WriteLine("-- Created new guest access content --"); *@
+@* Console.WriteLine($"Creation event uncasted: {creationEvent["m.room.guest_access"].ToJson()}"); *@
+@* Console.WriteLine($"Creation event casted: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}"); *@
+@* Console.WriteLine($"Creation event casted back: {creationEvent["m.room.guest_access"].As<GuestAccessData>().ToJson()}"); *@
+@* StateHasChanged(); *@
+@* } *@
+@* } *@
+@* *@
+@* private Dictionary<string, string> creationEventValidationErrors { get; set; } = new(); *@
+@* *@
+@* private CreateRoomRequest creationEvent { get; set; } *@
+@* GuestAccessData guestAccessEvent { get; set; } *@
+@* *@
+@* private Dictionary<string, CreateRoomRequest> Presets { get; set; } = new(); *@
+@* *@
+@* protected override async Task OnInitializedAsync() { *@
+@* *@
+@* //creationEvent = Presets["Default room"] = *@
+@* foreach (var x in Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsClass && !x.IsAbstract && x.GetInterfaces().Contains(typeof(IRoomCreationTemplate))).ToList()) { *@
+@* Console.WriteLine($"Found room creation template in class: {x.FullName}"); *@
+@* var instance = (IRoomCreationTemplate)Activator.CreateInstance(x); *@
+@* Presets[instance.Name] = instance.CreateRoomRequest; *@
+@* } *@
+@* Presets = Presets.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); *@
+@* *@
+@* if (!Presets.ContainsKey("Default")) { *@
+@* Console.WriteLine($"No default room found in {Presets.Count} presets: {string.Join(", ", Presets.Keys)}"); *@
+@* } *@
+@* else RoomPreset = "Default"; *@
+@* *@
+@* await base.OnInitializedAsync(); *@
+@* } *@
+@* *@
+@* private void JsonChanged() => Console.WriteLine(creationEvent.ToJson()); *@
+@* *@
+@* //wrappers *@
+@* private List<string> ServerACLAllowRules { get; set; } = new(); *@
+@* private List<string> ServerACLDenyRules { get; set; } = new(); *@
+@* *@
+@* private void OverwriteWrappedPropertiesFromEvent() { *@
+@* Console.WriteLine("Overwriting wrapped properties from event"); *@
+@* ServerACLAllowRules = creationEvent.ServerACLs.Allow; *@
+@* ServerACLDenyRules = creationEvent.ServerACLs.Deny; *@
+@* } *@
+@* *@
+@* private async Task OverwriteWrappedProperties() { *@
+@* Console.WriteLine("Overwriting wrapped properties"); *@
+@* Console.WriteLine($"Allow: {ServerACLAllowRules.Count}: {string.Join(", ", ServerACLAllowRules)}"); *@
+@* Console.WriteLine($"Deny: {ServerACLDenyRules.Count}: {string.Join(", ", ServerACLDenyRules)}"); *@
+@* creationEvent.ServerACLs = new ServerACLData { *@
+@* Allow = ServerACLAllowRules, *@
+@* Deny = ServerACLDenyRules, *@
+@* AllowIpLiterals = creationEvent.ServerACLs.AllowIpLiterals *@
+@* }; *@
+@* *@
+@* StateHasChanged(); *@
+@* } *@
+@* *@
+@* private async Task RoomIconFilePicked(InputFileChangeEventArgs obj) { *@
+@* var res = await RuntimeCache.CurrentHomeServer.UploadFile(obj.File.Name, obj.File.OpenReadStream(), obj.File.ContentType); *@
+@* Console.WriteLine(res); *@
+@* creationEvent.RoomIcon = res; *@
+@* StateHasChanged(); *@
+@* } *@
+@* *@
+@* private async Task CreateRoom() { *@
+@* Console.WriteLine("Create room"); *@
+@* Console.WriteLine(creationEvent.ToJson()); *@
+@* creationEvent.CreationContent.Add("rory.gay.created_using", "Rory&::MatrixRoomUtils (https://mru.rory.gay)"); *@
+@* //creationEvent.CreationContent.Add(); *@
+@* var id = await RuntimeCache.CurrentHomeServer.CreateRoom(creationEvent); *@
+@* // NavigationManager.NavigateTo($"/RoomManager/{id.RoomId.Replace('.','~')}"); *@
+@* } *@
+@* *@
+@* private void InviteMember(string mxid) { *@
+@* if (!creationEvent.InitialState.Any(x => x.Type == "m.room.member" && x.StateKey == mxid) && RuntimeCache.CurrentHomeServer.UserId != mxid) *@
+@* creationEvent.InitialState.Add(new StateEvent { *@
+@* Type = "m.room.member", *@
+@* StateKey = mxid, *@
+@* Content = new { *@
+@* membership = "invite", *@
+@* reason = "Automatically invited at room creation time." *@
+@* } *@
+@* }); *@
+@* } *@
+@* *@
+@* private string GetStateFriendlyName(string key) => key switch { *@
+@* "m.room.history_visibility" => "History visibility", *@
+@* "m.room.guest_access" => "Guest access", *@
+@* "m.room.join_rules" => "Join rules", *@
+@* "m.room.server_acl" => "Server ACL", *@
+@* "m.room.avatar" => "Avatar", *@
+@* _ => key *@
+@* }; *@
+@* *@
+@* private string GetPermissionFriendlyName(string key) => key switch { *@
+@* "m.reaction" => "Send reaction", *@
+@* "m.room.avatar" => "Change room icon", *@
+@* "m.room.canonical_alias" => "Change room alias", *@
+@* "m.room.encryption" => "Enable encryption", *@
+@* "m.room.history_visibility" => "Change history visibility", *@
+@* "m.room.name" => "Change room name", *@
+@* "m.room.power_levels" => "Change power levels", *@
+@* "m.room.tombstone" => "Upgrade room", *@
+@* "m.room.topic" => "Change room topic", *@
+@* "m.room.pinned_events" => "Pin events", *@
+@* "m.room.server_acl" => "Change server ACLs", *@
+@* _ => key *@
+@* }; *@
+@* *@
+@* } *@
+@* *@
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
index a9c71c4..afa39b9 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor
@@ -14,7 +14,7 @@
<summary style="background: #fff1;">State list</summary>
@foreach (var stateEvent in States.OrderBy(x => x.StateKey).ThenBy(x => x.Type)) {
<p>@stateEvent.StateKey/@stateEvent.Type:</p>
- <pre>@stateEvent.Content.ToJson()</pre>
+ <pre>@stateEvent.RawContent.ToJson()</pre>
}
</details>
@@ -23,36 +23,57 @@
[Parameter]
public string RoomId { get; set; } = "invalid!!!!!!";
- private Room? Room { get; set; }
+ private GenericRoom? Room { get; set; }
- private StateEventResponse<object>[] States { get; set; } = Array.Empty<StateEventResponse<object>>();
- private List<Room> Rooms { get; } = new();
+ private StateEventResponse[] States { get; set; } = Array.Empty<StateEventResponse>();
+ private List<GenericRoom> Rooms { get; } = new();
private List<string> ServersInSpace { get; } = new();
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
- Room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId.Replace('~', '.'));
- var state = await Room.GetStateAsync("");
- if (state != null) {
- // Console.WriteLine(state.Value.ToJson());
- States = state.Value.Deserialize<StateEventResponse<object>[]>()!;
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
- foreach (var stateEvent in States) {
- if (stateEvent.Type == "m.space.child") {
- // if (stateEvent.Content.ToJson().Length < 5) return;
- var roomId = stateEvent.StateKey;
- var room = await RuntimeCache.CurrentHomeServer.GetRoom(roomId);
- if (room != null) {
- Rooms.Add(room);
- }
+ Room = await hs.GetRoom(RoomId.Replace('~', '.'));
+
+ var state = Room.GetFullStateAsync();
+ await foreach (var stateEvent in state) {
+ if (stateEvent.Type == "m.space.child") {
+ var roomId = stateEvent.StateKey;
+ var room = await hs.GetRoom(roomId);
+ if (room is not null) {
+ Rooms.Add(room);
}
- else if (stateEvent.Type == "m.room.member") {
- var serverName = stateEvent.StateKey.Split(':').Last();
- if (!ServersInSpace.Contains(serverName)) {
- ServersInSpace.Add(serverName);
- }
+ }
+ else if (stateEvent.Type == "m.room.member") {
+ var serverName = stateEvent.StateKey.Split(':').Last();
+ if (!ServersInSpace.Contains(serverName)) {
+ ServersInSpace.Add(serverName);
}
}
+ }
+ await base.OnInitializedAsync();
+
+ // var state = await Room.GetStateAsync("");
+ // if (state is not null) {
+ // // Console.WriteLine(state.Value.ToJson());
+ // States = state.Value.Deserialize<StateEventResponse[]>()!;
+ //
+ // foreach (var stateEvent in States) {
+ // if (stateEvent.Type == "m.space.child") {
+ // // if (stateEvent.Content.ToJson().Length < 5) return;
+ // var roomId = stateEvent.StateKey;
+ // var room = await hs.GetRoom(roomId);
+ // if (room is not null) {
+ // Rooms.Add(room);
+ // }
+ // }
+ // else if (stateEvent.Type == "m.room.member") {
+ // var serverName = stateEvent.StateKey.Split(':').Last();
+ // if (!ServersInSpace.Contains(serverName)) {
+ // ServersInSpace.Add(serverName);
+ // }
+ // }
+ // }
// if(state.Value.TryGetProperty("Type", out var Type))
// {
@@ -62,8 +83,8 @@
// //this is fine, apprently...
// //Console.WriteLine($"Room {room.RoomId} has no Content.Type in m.room.create!");
// }
- }
- await base.OnInitializedAsync();
+
+ // await base.OnInitializedAsync();
}
private async Task JoinAllRooms() {
diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor
index 9513a8a..e32b5cb 100644
--- a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerTimeline.razor
@@ -20,10 +20,11 @@
private List<StateEventResponse> Events { get; } = new();
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
RoomId = RoomId.Replace('~', '.');
Console.WriteLine("RoomId: " + RoomId);
- var room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId);
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
+ var room = await hs.GetRoom(RoomId);
MessagesResponse? msgs = null;
do {
msgs = await room.GetMessagesAsync(limit: 250, from: msgs?.End, dir: "b");
@@ -32,7 +33,7 @@
msgs.Chunk.Reverse();
Events.InsertRange(0, msgs.Chunk);
StateHasChanged();
- } while (msgs.End != null);
+ } while (msgs.End is not null);
await base.OnInitializedAsync();
}
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
index 296514c..b2d28f6 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateEditorPage.razor
@@ -45,12 +45,9 @@
public string status = "";
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
await base.OnInitializedAsync();
- if (RuntimeCache.CurrentHomeServer != null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
RoomId = RoomId.Replace('~', '.');
await LoadStatesAsync();
Console.WriteLine("Policy list editor initialized!");
@@ -59,25 +56,20 @@
private DateTime _lastUpdate = DateTime.Now;
private async Task LoadStatesAsync() {
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+
var StateLoaded = 0;
- using var client = new HttpClient();
- //TODO: can this be improved?
- client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken);
- var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/v3/rooms/{RoomId}/state");
- // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
- //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>();
- var _data = await response.Content.ReadAsStreamAsync();
- var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEventResponse>(_data);
- await foreach (var _ev in __events) {
- var e = new StateEventResponse {
- Type = _ev.Type,
- StateKey = _ev.StateKey,
- OriginServerTs = _ev.OriginServerTs,
- Content = _ev.Content
- };
- Events.Add(e);
- if (string.IsNullOrEmpty(e.StateKey)) {
- FilteredEvents.Add(e);
+ var response = (await hs.GetRoom(RoomId)).GetFullStateAsync();
+ await foreach (var _ev in response) {
+ // var e = new StateEventResponse {
+ // Type = _ev.Type,
+ // StateKey = _ev.StateKey,
+ // OriginServerTs = _ev.OriginServerTs,
+ // Content = _ev.Content
+ // };
+ Events.Add(_ev);
+ if (string.IsNullOrEmpty(_ev.StateKey)) {
+ FilteredEvents.Add(_ev);
}
StateLoaded++;
if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) {
@@ -104,8 +96,8 @@
await Task.Delay(1);
FilteredEvents = _FilteredEvents;
- if (_shownType != null)
- shownEventJson = _FilteredEvents.Where(x => x.Type == _shownType).First().Content.ToJson(indent: true, ignoreNull: true);
+ if (_shownType is not null)
+ shownEventJson = _FilteredEvents.Where(x => x.Type == _shownType).First().RawContent.ToJson(indent: true, ignoreNull: true);
StateHasChanged();
}
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor
index 82b5d75..55c44d9 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateRoomList.razor
@@ -22,13 +22,10 @@ else {
public List<string> Rooms { get; set; } = new();
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
await base.OnInitializedAsync();
- if (RuntimeCache.CurrentHomeServer == null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
- Rooms = (await RuntimeCache.CurrentHomeServer.GetJoinedRooms()).Select(x => x.RoomId).ToList();
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
+ Rooms = (await hs.GetJoinedRooms()).Select(x => x.RoomId).ToList();
Console.WriteLine("Fetched joined rooms!");
}
diff --git a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
index ff1d9ac..a0072ab 100644
--- a/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
+++ b/MatrixRoomUtils.Web/Pages/RoomState/RoomStateViewerPage.razor
@@ -1,6 +1,7 @@
@page "/RoomStateViewer/{RoomId}"
@using System.Net.Http.Headers
@using System.Text.Json
+@using MatrixRoomUtils.Core.Responses
@inject ILocalStorageService LocalStorage
@inject NavigationManager NavigationManager
<h3>Room state viewer - Viewing @RoomId</h3>
@@ -18,18 +19,18 @@
</tr>
</thead>
<tbody>
- @foreach (var stateEvent in FilteredEvents.Where(x => x.state_key == "").OrderBy(x => x.origin_server_ts)) {
+ @foreach (var stateEvent in FilteredEvents.Where(x => x.StateKey == "").OrderBy(x => x.OriginServerTs)) {
<tr>
- <td>@stateEvent.type</td>
+ <td>@stateEvent.Type</td>
<td style="max-width: fit-Content;">
- <pre>@stateEvent.content</pre>
+ <pre>@stateEvent.RawContent.ToJson()</pre>
</td>
</tr>
}
</tbody>
</table>
-@foreach (var group in FilteredEvents.GroupBy(x => x.state_key).OrderBy(x => x.Key).Where(x => x.Key != "")) {
+@foreach (var group in FilteredEvents.GroupBy(x => x.StateKey).OrderBy(x => x.Key).Where(x => x.Key != "")) {
<details>
<summary>@group.Key</summary>
<table class="table table-striped table-hover" style="width: fit-Content;">
@@ -40,11 +41,11 @@
</tr>
</thead>
<tbody>
- @foreach (var stateEvent in group.OrderBy(x => x.origin_server_ts)) {
+ @foreach (var stateEvent in group.OrderBy(x => x.OriginServerTs)) {
<tr>
- <td>@stateEvent.type</td>
+ <td>@stateEvent.Type</td>
<td style="max-width: fit-Content;">
- <pre>@stateEvent.content</pre>
+ <pre>@stateEvent.RawContent.ToJson()</pre>
</td>
</tr>
}
@@ -64,17 +65,14 @@
[Parameter]
public string? RoomId { get; set; }
- public List<PreRenderedStateEvent> FilteredEvents { get; set; } = new();
- public List<PreRenderedStateEvent> Events { get; set; } = new();
+ public List<StateEventResponse> FilteredEvents { get; set; } = new();
+ public List<StateEventResponse> Events { get; set; } = new();
public string status = "";
protected override async Task OnInitializedAsync() {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
await base.OnInitializedAsync();
- if (RuntimeCache.CurrentHomeServer == null) {
- NavigationManager.NavigateTo("/Login");
- return;
- }
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
RoomId = RoomId.Replace('~', '.');
await LoadStatesAsync();
Console.WriteLine("Policy list editor initialized!");
@@ -84,24 +82,13 @@
private async Task LoadStatesAsync() {
var StateLoaded = 0;
- //TODO: can we improve this?
- using var client = new HttpClient();
- client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", RuntimeCache.CurrentHomeServer.AccessToken);
- var response = await client.GetAsync($"{RuntimeCache.CurrentHomeServer.FullHomeServerDomain}/_matrix/client/v3/rooms/{RoomId}/state");
- // var response = await client.GetAsync($"http://localhost:5117/matrix-hq-state.json");
- //var _events = await response.Content.ReadFromJsonAsync<Queue<StateEventStruct>>();
- var _data = await response.Content.ReadAsStreamAsync();
- var __events = JsonSerializer.DeserializeAsyncEnumerable<StateEventStruct>(_data);
- await foreach (var _ev in __events) {
- var e = new PreRenderedStateEvent {
- type = _ev.type,
- state_key = _ev.state_key,
- origin_server_ts = _ev.origin_server_ts,
- content = _ev.content.ToJson(true, true)
- };
- Events.Add(e);
- if (string.IsNullOrEmpty(e.state_key)) {
- FilteredEvents.Add(e);
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
+ var response = (await hs.GetRoom(RoomId)).GetFullStateAsync();
+ await foreach (var _ev in response) {
+ Events.Add(_ev);
+ if (string.IsNullOrEmpty(_ev.StateKey)) {
+ FilteredEvents.Add(_ev);
}
StateLoaded++;
if ((DateTime.Now - _lastUpdate).TotalMilliseconds > 100) {
@@ -121,7 +108,7 @@
await Task.Delay(1);
var _FilteredEvents = Events;
if (!ShowMembershipEvents)
- _FilteredEvents = _FilteredEvents.Where(x => x.type != "m.room.member").ToList();
+ _FilteredEvents = _FilteredEvents.Where(x => x.Type != "m.room.member").ToList();
status = "Done, rerendering!";
StateHasChanged();
@@ -130,17 +117,6 @@
StateHasChanged();
}
- public struct PreRenderedStateEvent {
- public string content { get; set; }
- public long origin_server_ts { get; set; }
- public string state_key { get; set; }
- public string type { get; set; }
- // public string Sender { get; set; }
- // public string EventId { get; set; }
- // public string UserId { get; set; }
- // public string ReplacesState { get; set; }
- }
-
public bool ShowMembershipEvents {
get => _showMembershipEvents;
set {
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Index.razor b/MatrixRoomUtils.Web/Pages/Rooms/Index.razor
index 17551c9..20ddd0d 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/Index.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/Index.razor
@@ -1,20 +1,19 @@
@page "/Rooms"
<h3>Room list</h3>
-@if (Rooms != null) {
+@if (Rooms is not null) {
<RoomList Rooms="Rooms"></RoomList>
}
@code {
- private List<Room> Rooms { get; set; }
+ private List<GenericRoom> Rooms { get; set; }
- protected override async Task OnInitializedAsync()
- {
- await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage);
-
- Rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms();
+ protected override async Task OnInitializedAsync() {
+ var hs = await MRUStorage.GetCurrentSessionOrNavigate();
+ if (hs is null) return;
+ Rooms = await hs.GetJoinedRooms();
await base.OnInitializedAsync();
}
|