MatrixRoomUtils

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | LICENSE

commit ac7ed016b00941380099d9a0b2601f4bc353f39f
parent a67276252c8bfcd6b6c5344e70debc6d67d917a9
Author: TheArcaneBrony <myrainbowdash949@gmail.com>
Date:   Sat, 27 May 2023 02:23:30 +0200

Remove a bunch of caching, make room listings more reliable

Diffstat:
MMatrixRoomUtils.Core/Responses/StateEventResponse.cs | 24+++++++++++++-----------
MMatrixRoomUtils.Core/Room.cs | 123++++++++++++++++++++++---------------------------------------------------------
MMatrixRoomUtils.Core/RuntimeCache.cs | 4++--
MMatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs | 88+++++++++++++++++++++++++++++++++++++++----------------------------------------
MMatrixRoomUtils.Web/Pages/DataExportPage.razor | 2+-
MMatrixRoomUtils.Web/Pages/DevOptions.razor | 5++---
MMatrixRoomUtils.Web/Pages/Index.razor | 1-
MMatrixRoomUtils.Web/Pages/MediaLocator.razor | 2+-
MMatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor | 42+++++++++++++++++++++---------------------
MMatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor | 14+++++++++-----
MMatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor | 2+-
MMatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor | 2+-
MMatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor | 6++----
MMatrixRoomUtils.Web/Shared/NavMenu.razor | 10+++++-----
MMatrixRoomUtils.Web/Shared/RoomListItem.razor | 30+++++++++++++++++-------------
15 files changed, 152 insertions(+), 203 deletions(-)

diff --git a/MatrixRoomUtils.Core/Responses/StateEventResponse.cs b/MatrixRoomUtils.Core/Responses/StateEventResponse.cs @@ -4,31 +4,33 @@ namespace MatrixRoomUtils.Core; public class StateEventResponse { - [JsonPropertyName("Content")] + [JsonPropertyName("content")] public dynamic Content { get; set; } [JsonPropertyName("origin_server_ts")] public long OriginServerTs { get; set; } - [JsonPropertyName("RoomId")] + [JsonPropertyName("room_id")] public string RoomId { get; set; } - [JsonPropertyName("Sender")] + [JsonPropertyName("sender")] public string Sender { get; set; } - [JsonPropertyName("StateKey")] + [JsonPropertyName("state_key")] public string StateKey { get; set; } - [JsonPropertyName("Type")] + [JsonPropertyName("type")] public string Type { get; set; } - [JsonPropertyName("Unsigned")] + [JsonPropertyName("unsigned")] public dynamic Unsigned { get; set; } - [JsonPropertyName("EventId")] + [JsonPropertyName("event_id")] public string EventId { get; set; } - [JsonPropertyName("UserId")] + [JsonPropertyName("user_id")] public string UserId { get; set; } - [JsonPropertyName("ReplacesState")] + [JsonPropertyName("replaces_state")] public string ReplacesState { get; set; } - [JsonPropertyName("PrevContent")] + [JsonPropertyName("prev_content")] public dynamic PrevContent { get; set; } } public class StateEventResponse<T> : StateEventResponse where T : class { - public T content { get; set; } + + [JsonPropertyName("content")] + public T Content { get; set; } } \ No newline at end of file diff --git a/MatrixRoomUtils.Core/Room.cs b/MatrixRoomUtils.Core/Room.cs @@ -10,8 +10,6 @@ namespace MatrixRoomUtils.Core; public class Room { - private static SemaphoreSlim _semaphore = new SemaphoreSlim(16, 16); - private readonly HttpClient _httpClient; public string RoomId { get; set; } @@ -21,72 +19,26 @@ public class Room RoomId = roomId; } - public async Task<JsonElement?> GetStateAsync(string type, string state_key = "", bool logOnFailure = false) + public async Task<JsonElement?> GetStateAsync(string type, string stateKey = "", bool logOnFailure = true) { - await _semaphore.WaitAsync(); var url = $"/_matrix/client/v3/rooms/{RoomId}/state"; - var stateCombo = ""; - if (!string.IsNullOrEmpty(state_key)) stateCombo += $"{type}/{state_key}"; - else if (!string.IsNullOrEmpty(type)) stateCombo += $"{type}"; - if (!string.IsNullOrEmpty(stateCombo)) url += $"/{stateCombo}"; - var cache_key = "room_states#" + RoomId; - if (!RuntimeCache.GenericResponseCache.ContainsKey(cache_key)) - { - Console.WriteLine($"[!!] No cache for {cache_key}, creating..."); - RuntimeCache.GenericResponseCache.Add(cache_key, new ObjectCache<object?>() - { - Name = cache_key - }); - } - var cache = RuntimeCache.GenericResponseCache[cache_key]; - - if (cache.ContainsKey(stateCombo)) - { - if (cache[stateCombo].ExpiryTime > DateTime.Now) - { - // Console.WriteLine($"[:3] Found cached state: {RuntimeCache.GenericResponseCache[cache_key][url].Result}"); - _semaphore.Release(); - return (JsonElement?) cache[stateCombo].Result; - } - else - { - Console.WriteLine($"[!!] Cached state expired at {cache[stateCombo].ExpiryTime}: {cache[stateCombo].Result}"); - if(cache[stateCombo].ExpiryTime == null)Console.WriteLine("Exiryt time was null"); - } - } - // else - // { - // Console.WriteLine($"[!!] No cached state for {url}"); - // } + if (!string.IsNullOrEmpty(type)) url += $"/{type}"; + if (!string.IsNullOrEmpty(stateKey)) url += $"/{stateKey}"; var res = await _httpClient.GetAsync(url); if (!res.IsSuccessStatusCode) { - if (logOnFailure) Console.WriteLine($"{RoomId}/{state_key}/{type} - got status: {res.StatusCode}"); - _semaphore.Release(); + if (logOnFailure) Console.WriteLine($"{RoomId}/{stateKey}/{type} - got status: {res.StatusCode}"); return null; } var result = await res.Content.ReadFromJsonAsync<JsonElement>(); - var expiryTime = type switch - { - "m.room.name" => TimeSpan.FromMinutes(30), - "org.matrix.mjolnir.shortcode" => TimeSpan.FromHours(4), - "" => TimeSpan.FromSeconds(0), - _ => TimeSpan.FromMinutes(15) - }; - if(!string.IsNullOrWhiteSpace(type) && !string.IsNullOrWhiteSpace(state_key)) - cache[stateCombo] = new GenericResult<object>() - { - Result = result, - ExpiryTime = DateTime.Now.Add(expiryTime) - }; - _semaphore.Release(); return result; } - public async Task<T?> GetStateAsync<T>(string type, string state_key = "", bool logOnFailure = false) + + public async Task<T?> GetStateAsync<T>(string type, string stateKey = "", bool logOnFailure = false) { - var res = await GetStateAsync(type, state_key, logOnFailure); + var res = await GetStateAsync(type, stateKey, logOnFailure); if (res == null) return default; return res.Value.Deserialize<T>(); } @@ -108,27 +60,28 @@ public class Room public async Task JoinAsync(string[]? homeservers = null) { string join_url = $"/_matrix/client/r0/join/{HttpUtility.UrlEncode(RoomId)}"; - Console.WriteLine($"Calling {join_url} with {(homeservers == null ? 0 : homeservers.Length)} via's..."); - if(homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] }; - var full_join_url = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers); - var res = await _httpClient.PostAsync(full_join_url, null); + Console.WriteLine($"Calling {join_url} with {homeservers?.Length ?? 0} via's..."); + if (homeservers == null || homeservers.Length == 0) homeservers = new[] { RoomId.Split(':')[1] }; + var fullJoinUrl = $"{join_url}?server_name=" + string.Join("&server_name=", homeservers); + var res = await _httpClient.PostAsync(fullJoinUrl, null); } - - public async Task<List<string>> GetMembersAsync() + + public async Task<List<string>> GetMembersAsync(bool joinedOnly = true) { var res = await GetStateAsync(""); if (!res.HasValue) return new List<string>(); var members = new List<string>(); foreach (var member in res.Value.EnumerateArray()) { - if(member.GetProperty("Type").GetString() != "m.room.member") continue; - var member_id = member.GetProperty("StateKey").GetString(); - members.Add(member_id); + if (member.GetProperty("type").GetString() != "m.room.member") continue; + if (joinedOnly && member.GetProperty("content").GetProperty("membership").GetString() != "join") continue; + var memberId = member.GetProperty("state_key").GetString(); + members.Add(memberId ?? throw new InvalidOperationException("Event type was member but state key was null!")); } return members; } - + public async Task<List<string>> GetAliasesAsync() { var res = await GetStateAsync("m.room.aliases"); @@ -141,54 +94,54 @@ public class Room return aliases; } - + public async Task<string> GetCanonicalAliasAsync() { var res = await GetStateAsync("m.room.canonical_alias"); if (!res.HasValue) return ""; return res.Value.GetProperty("alias").GetString() ?? ""; } - + public async Task<string> GetTopicAsync() { var res = await GetStateAsync("m.room.topic"); if (!res.HasValue) return ""; return res.Value.GetProperty("topic").GetString() ?? ""; } - + public async Task<string> GetAvatarUrlAsync() { var res = await GetStateAsync("m.room.avatar"); if (!res.HasValue) return ""; return res.Value.GetProperty("url").GetString() ?? ""; } - + public async Task<JoinRules> GetJoinRuleAsync() { var res = await GetStateAsync("m.room.join_rules"); if (!res.HasValue) return new JoinRules(); return res.Value.Deserialize<JoinRules>() ?? new JoinRules(); } - + public async Task<string> GetHistoryVisibilityAsync() { var res = await GetStateAsync("m.room.history_visibility"); if (!res.HasValue) return ""; return res.Value.GetProperty("history_visibility").GetString() ?? ""; } - + public async Task<string> GetGuestAccessAsync() { var res = await GetStateAsync("m.room.guest_access"); if (!res.HasValue) return ""; return res.Value.GetProperty("guest_access").GetString() ?? ""; } - + public async Task<CreateEvent> GetCreateEventAsync() { var res = await GetStateAsync("m.room.create"); if (!res.HasValue) return new CreateEvent(); - + res.FindExtraJsonFields(typeof(CreateEvent)); return res.Value.Deserialize<CreateEvent>() ?? new CreateEvent(); @@ -197,17 +150,11 @@ public class Room public class CreateEvent { - [JsonPropertyName("creator")] - public string Creator { get; set; } - [JsonPropertyName("room_version")] - public string RoomVersion { get; set; } - [JsonPropertyName("type")] - public string? Type { get; set; } - [JsonPropertyName("predecessor")] - public object? Predecessor { get; set; } - - [JsonPropertyName("m.federate")] - public bool Federate { get; set; } + [JsonPropertyName("creator")] public string Creator { get; set; } + [JsonPropertyName("room_version")] public string RoomVersion { get; set; } + [JsonPropertyName("type")] public string? Type { get; set; } + [JsonPropertyName("predecessor")] public object? Predecessor { get; set; } + [JsonPropertyName("m.federate")] public bool Federate { get; set; } } public class JoinRules @@ -215,9 +162,7 @@ public class JoinRules private const string Public = "public"; private const string Invite = "invite"; private const string Knock = "knock"; - - [JsonPropertyName("join_rule")] - public string JoinRule { get; set; } - [JsonPropertyName("allow")] - public List<string> Allow { get; set; } + + [JsonPropertyName("join_rule")] public string JoinRule { get; set; } + [JsonPropertyName("allow")] public List<string> Allow { get; set; } } \ No newline at end of file diff --git a/MatrixRoomUtils.Core/RuntimeCache.cs b/MatrixRoomUtils.Core/RuntimeCache.cs @@ -76,8 +76,8 @@ public class ObjectCache<T> where T : class set { Cache[key] = value; - Console.WriteLine($"set({key}) = {Cache[key].Result.ToJson(indent:false)}"); - Console.WriteLine($"new_state: {this.ToJson(indent:false)}"); + // Console.WriteLine($"set({key}) = {Cache[key].Result.ToJson(indent:false)}"); + // Console.WriteLine($"new_state: {this.ToJson(indent:false)}"); // Console.WriteLine($"New item in cache: {key} - {Cache[key].Result.ToJson(indent: false)}"); // Console.Error.WriteLine("Full cache: " + Cache.ToJson()); } diff --git a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs @@ -7,85 +7,83 @@ public partial class LocalStorageWrapper { private static SemaphoreSlim _semaphoreSlim = new(1); public static Settings Settings { get; set; } = new(); - + //some basic logic - public static async Task ReloadLocalStorage(ILocalStorageService localStorage) - { - await SaveToLocalStorage(localStorage); - await LoadFromLocalStorage(localStorage); - } - public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) + public static async Task InitialiseRuntimeVariables(ILocalStorageService localStorage) { - await _semaphoreSlim.WaitAsync(); - if (RuntimeCache.WasLoaded) return; - RuntimeCache.WasLoaded = true; - Settings = await localStorage.GetItemAsync<Settings>("rory.matrixroomutils.settings") ?? new(); - //RuntimeCache stuff async void Save() => await SaveToLocalStorage(localStorage); RuntimeCache.Save = Save; - RuntimeCache.SaveObject = async (key, obj) => await localStorage.SetItemAsync(key, obj); - // RuntimeCache.AccessToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.token"); - RuntimeCache.LastUsedToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.last_used_token"); - // RuntimeCache.CurrentHomeserver = await localStorage.GetItemAsync<string>("rory.matrixroomutils.current_homeserver"); - RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.user_cache") ?? new(); - RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new(); - Console.WriteLine($"[LocalStorageWrapper] Loaded {RuntimeCache.LoginSessions.Count} login sessions, {RuntimeCache.HomeserverResolutionCache.Count} homeserver resolution cache entries"); + RuntimeCache.SaveObject = async (key, obj) => await localStorage.SetItemAsync(key, obj); if (RuntimeCache.LastUsedToken != null) { Console.WriteLine($"Access token is not null, creating authenticated home server"); Console.WriteLine($"Homeserver cache: {RuntimeCache.HomeserverResolutionCache.Count} entries"); // Console.WriteLine(RuntimeCache.HomeserverResolutionCache.ToJson()); - RuntimeCache.CurrentHomeServer = await new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.UserId, RuntimeCache.LastUsedToken, RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.HomeServer).Configure(); + RuntimeCache.CurrentHomeServer = await new AuthenticatedHomeServer(RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.UserId, RuntimeCache.LastUsedToken, + RuntimeCache.LoginSessions[RuntimeCache.LastUsedToken].LoginResponse.HomeServer).Configure(); Console.WriteLine("Created authenticated home server"); } - RuntimeCache.GenericResponseCache = await localStorage.GetItemAsync<Dictionary<string, ObjectCache<object>>>("rory.matrixroomutils.generic_cache") ?? new(); - - foreach (var s in (await localStorage.KeysAsync()).Where(x=>x.StartsWith("rory.matrixroomutils.generic_cache:")).ToList()) + } + + public static async Task LoadFromLocalStorage(ILocalStorageService localStorage) + { + await _semaphoreSlim.WaitAsync(); + if (RuntimeCache.WasLoaded) + { + _semaphoreSlim.Release(); + return; + } + Console.WriteLine("Loading from local storage..."); + Settings = await localStorage.GetItemAsync<Settings>("rory.matrixroomutils.settings") ?? new(); + + RuntimeCache.LastUsedToken = await localStorage.GetItemAsync<string>("rory.matrixroomutils.last_used_token"); + RuntimeCache.LoginSessions = await localStorage.GetItemAsync<Dictionary<string, UserInfo>>("rory.matrixroomutils.login_sessions") ?? new(); + RuntimeCache.HomeserverResolutionCache = await localStorage.GetItemAsync<Dictionary<string, HomeServerResolutionResult>>("rory.matrixroomutils.homeserver_resolution_cache") ?? new(); + Console.WriteLine($"[LocalStorageWrapper] Loaded {RuntimeCache.LoginSessions.Count} login sessions, {RuntimeCache.HomeserverResolutionCache.Count} homeserver resolution cache entries"); + + //RuntimeCache.GenericResponseCache = await localStorage.GetItemAsync<Dictionary<string, ObjectCache<object>>>("rory.matrixroomutils.generic_cache") ?? new(); + + foreach (var s in (await localStorage.KeysAsync()).Where(x => x.StartsWith("rory.matrixroomutils.generic_cache:")).ToList()) { Console.WriteLine($"Loading generic cache entry {s}"); RuntimeCache.GenericResponseCache[s.Replace("rory.matrixroomutils.generic_cache:", "")] = await localStorage.GetItemAsync<ObjectCache<object>>(s); } + await InitialiseRuntimeVariables(localStorage); + RuntimeCache.WasLoaded = true; _semaphoreSlim.Release(); } public static async Task SaveToLocalStorage(ILocalStorageService localStorage) { + Console.WriteLine("Saving to local storage..."); await localStorage.SetItemAsync("rory.matrixroomutils.settings", Settings); - // if(RuntimeCache.AccessToken != null) await localStorage.SetItemAsStringAsync("rory.matrixroomutils.token", RuntimeCache.AccessToken); - // if(RuntimeCache.CurrentHomeserver != null) await localStorage.SetItemAsync("rory.matrixroomutils.current_homeserver", RuntimeCache.CurrentHomeserver); - if(RuntimeCache.LoginSessions != null) await localStorage.SetItemAsync("rory.matrixroomutils.user_cache", RuntimeCache.LoginSessions); - if(RuntimeCache.LastUsedToken != null) await localStorage.SetItemAsync("rory.matrixroomutils.last_used_token", RuntimeCache.LastUsedToken); - await localStorage.SetItemAsync("rory.matrixroomutils.homeserver_resolution_cache", - RuntimeCache.HomeserverResolutionCache.DistinctBy(x => x.Key) - .ToDictionary(x => x.Key, x => x.Value)); - await localStorage.SetItemAsync("rory.matrixroomutils.generic_cache", RuntimeCache.GenericResponseCache); - // foreach (var s in RuntimeCache.GenericResponseCache.Keys) - // { - // await localStorage.SetItemAsync($"rory.matrixroomutils.generic_cache:{s}", RuntimeCache.GenericResponseCache[s]); - // } + if (RuntimeCache.LoginSessions != null) await localStorage.SetItemAsync("rory.matrixroomutils.login_sessions", RuntimeCache.LoginSessions); + if (RuntimeCache.LastUsedToken != null) await localStorage.SetItemAsync("rory.matrixroomutils.last_used_token", RuntimeCache.LastUsedToken); } - public static async Task SaveFieldToLocalStorage(ILocalStorageService localStorage, string key) + + public static async Task SaveCacheToLocalStorage(ILocalStorageService localStorage, bool awaitSave = true, bool saveGenericCache = true) { - if (key == "rory.matrixroomutils.settings") await localStorage.SetItemAsync(key, Settings); - // if (key == "rory.matrixroomutils.token") await localStorage.SetItemAsStringAsync(key, RuntimeCache.AccessToken); - // if (key == "rory.matrixroomutils.current_homeserver") await localStorage.SetItemAsync(key, RuntimeCache.CurrentHomeserver); - if (key == "rory.matrixroomutils.user_cache") await localStorage.SetItemAsync(key, RuntimeCache.LoginSessions); - if (key == "rory.matrixroomutils.last_used_token") await localStorage.SetItemAsync(key, RuntimeCache.LastUsedToken); - if (key == "rory.matrixroomutils.homeserver_resolution_cache") await localStorage.SetItemAsync(key, RuntimeCache.HomeserverResolutionCache); - //if (key == "rory.matrixroomutils.generic_cache") await localStorage.SetItemAsync(key, RuntimeCache.GenericResponseCache); + await localStorage.SetItemAsync("rory.matrixroomutils.homeserver_resolution_cache", + RuntimeCache.HomeserverResolutionCache.DistinctBy(x => x.Key) + .ToDictionary(x => x.Key, x => x.Value)); + //await localStorage.SetItemAsync("rory.matrixroomutils.generic_cache", RuntimeCache.GenericResponseCache); + if(saveGenericCache) + foreach (var s in RuntimeCache.GenericResponseCache.Keys) + { + var t = localStorage.SetItemAsync($"rory.matrixroomutils.generic_cache:{s}", RuntimeCache.GenericResponseCache[s]); + if (awaitSave) await t; + } } } - public class Settings { public DeveloperSettings DeveloperSettings { get; set; } = new(); } - public class DeveloperSettings { public bool EnableLogViewers { get; set; } = false; diff --git a/MatrixRoomUtils.Web/Pages/DataExportPage.razor b/MatrixRoomUtils.Web/Pages/DataExportPage.razor @@ -59,7 +59,7 @@ else var resolvedHomeserver = (await new RemoteHomeServer(hs).Configure()).FullHomeServerDomain; RuntimeCache.HomeserverResolutionCache.Add(hs, new() { Result = resolvedHomeserver, ResolutionTime = DateTime.Now }); - await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); Console.WriteLine("Saved to local storage:"); Console.WriteLine(JsonSerializer.Serialize(RuntimeCache.HomeserverResolutionCache, new JsonSerializerOptions() diff --git a/MatrixRoomUtils.Web/Pages/DevOptions.razor b/MatrixRoomUtils.Web/Pages/DevOptions.razor @@ -39,7 +39,6 @@ { await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); - await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); Task.Run(async () => { while (true) @@ -62,7 +61,7 @@ { RuntimeCache.GenericResponseCache.Clear(); RuntimeCache.HomeserverResolutionCache.Clear(); - await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } protected async Task RandomiseCacheTimers() @@ -75,7 +74,7 @@ cacheItem.Value.ExpiryTime = DateTime.Now.AddSeconds(Random.Shared.Next(15, 120)); } - await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } } diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor @@ -28,6 +28,5 @@ Small collection of tools to do not-so-everyday things. await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); } await base.OnInitializedAsync(); - await LocalStorageWrapper.ReloadLocalStorage(LocalStorage); } } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/MediaLocator.razor @@ -113,7 +113,7 @@ homeservers.Add(await rhs.ResolveHomeserverFromWellKnown(line)); StateHasChanged(); if(Random.Shared.Next(0,101) == 50) - await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } catch (Exception e) { diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor @@ -33,13 +33,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.Content.Entity != null)) { <tr> - <td>Entity: @policyEvent.content.Entity<br/>State: @policyEvent.StateKey</td> - <td>@policyEvent.content.Reason</td> + <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td> + <td>@policyEvent.Content.Reason</td> <td> - @policyEvent.content.ExpiryDateTime + @policyEvent.Content.ExpiryDateTime </td> <td> <button class="btn" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Edit</button> @@ -59,11 +59,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.Content.Entity == null)) { <tr> <td>@policyEvent.StateKey</td> - <td>@policyEvent.content.ToJson(indent: false, ignoreNull: true)</td> + <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td> </tr> } </tbody> @@ -88,13 +88,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.Content.Entity != null)) { <tr> - <td>Entity: @policyEvent.content.Entity<br/>State: @policyEvent.StateKey</td> - <td>@policyEvent.content.Reason</td> + <td>Entity: @policyEvent.Content.Entity<br/>State: @policyEvent.StateKey</td> + <td>@policyEvent.Content.Reason</td> <td> - @policyEvent.content.ExpiryDateTime + @policyEvent.Content.ExpiryDateTime </td> <td> <button class="btn btn-danger" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Remove</button> @@ -113,11 +113,11 @@ 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.Content.Entity == null)) { <tr> <td>@policyEvent.StateKey</td> - <td>@policyEvent.content.ToJson(indent: false, ignoreNull: true)</td> + <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td> </tr> } </tbody> @@ -146,17 +146,17 @@ 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.Content.Entity != null)) { <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] : "")"/></td> + <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] : "")"/></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("", policyEvent.Content.Entity.Take(64))<br/>State: @string.Join("", policyEvent.StateKey.Take(64))</td> + <td>@policyEvent.Content.Reason</td> <td> - @policyEvent.content.ExpiryDateTime + @policyEvent.Content.ExpiryDateTime </td> <td> <button class="btn btn-danger" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Remove</button> @@ -175,11 +175,11 @@ 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.Content.Entity == null)) { <tr> <td>@policyEvent.StateKey</td> - <td>@policyEvent.content.ToJson(indent: false, ignoreNull: true)</td> + <td>@policyEvent.Content.ToJson(indent: false, ignoreNull: true)</td> </tr> } </tbody> @@ -261,9 +261,9 @@ else private async Task GetAllAvatars() { - 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.Content.Entity != null)) { - await GetAvatar(policyEvent.content.Entity); + await GetAvatar(policyEvent.Content.Entity); } StateHasChanged(); } diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor @@ -20,7 +20,7 @@ else @foreach (var room in Spaces) { <a style="color: unset; text-decoration: unset;" href="/RoomManager/Space/@room.RoomId.Replace('.', '~')"> - <RoomListItem Room="@room" ShowOwnProfile="true"></RoomListItem> + <RoomListItem Room="@room" ShowOwnProfile="false"></RoomListItem> </a> } </details> @@ -44,19 +44,23 @@ else 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; } - Rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms(); + Console.WriteLine("Fetching joined rooms"); + var _rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms(); StateHasChanged(); - Console.WriteLine($"Got {Rooms.Count} rooms"); + Console.WriteLine($"Got {_rooms.Count} rooms"); var semaphore = new SemaphoreSlim(10); var tasks = new List<Task<Room?>>(); - foreach (var room in Rooms) + foreach (var room in _rooms) { tasks.Add(CheckIfSpace(room, semaphore)); } @@ -81,7 +85,6 @@ else { Console.WriteLine($"Room {room.RoomId} is a space!"); Spaces.Add(room); - Rooms.Remove(room); StateHasChanged(); return room; } @@ -92,6 +95,7 @@ else } else { + Rooms.Add(room); //this is fine, apprently... // Console.WriteLine($"Room {room.RoomId} has no Content.type in m.room.create!"); } diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerCreateRoom.razor @@ -79,7 +79,7 @@ <details> @code{ - private static string[] ImplementedStates = new[] { "m.room.avatar", "m.room.history_visibility", "m.room.guest_access", }; + private static readonly string[] ImplementedStates = { "m.room.avatar", "m.room.history_visibility", "m.room.guest_access", }; } <summary>@creationEvent.InitialState.Count(x => !ImplementedStates.Contains(x.Type)) custom states</summary> diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor @@ -16,7 +16,7 @@ @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.Content.ToJson()</pre> } </details> diff --git a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor @@ -41,7 +41,6 @@ { Console.WriteLine(User.ToJson()); RuntimeCache.LoginSessions.Remove(User.AccessToken); - await LocalStorageWrapper.ReloadLocalStorage(LocalStorage); StateHasChanged(); } @@ -50,9 +49,8 @@ { RuntimeCache.LastUsedToken = User.AccessToken; //RuntimeCache.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(LocalStorageWrapper.LoginSessions[Token].LoginResponse.HomeServer); - await LocalStorageWrapper.ReloadLocalStorage(LocalStorage); - + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.InitialiseRuntimeVariables(LocalStorage); StateHasChanged(); } - } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor b/MatrixRoomUtils.Web/Shared/NavMenu.razor @@ -51,11 +51,11 @@ <h5 style="margin-left: 1em;">Extra tools</h5> <hr style="margin-bottom: 0em;"/> </div> - <div class="nav-item px-3"> - <NavLink class="nav-link" href="KnownHomeserverList"> - <span class="oi oi-plus" aria-hidden="true"></span> Known homeserver list - </NavLink> - </div> + @* <div class="nav-item px-3"> *@ + @* <NavLink class="nav-link" href="KnownHomeserverList"> *@ + @* <span class="oi oi-plus" aria-hidden="true"></span> Known homeserver list *@ + @* </NavLink> *@ + @* </div> *@ @* <div class="nav-item px-3"> *@ @* <NavLink class="nav-link" href="MediaLocator"> *@ @* <span class="oi oi-plus" aria-hidden="true"></span> Media locator *@ diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor @@ -43,24 +43,26 @@ private bool hasOldRoomVersion { get; set; } = false; private bool hasDangerousRoomVersion { get; set; } = false; + + + private static SemaphoreSlim _semaphoreSlim = new(128); protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - - if (!RuntimeCache.WasLoaded) - { - Console.WriteLine("Loading from local storage"); - await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); - } - + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + + await _semaphoreSlim.WaitAsync(); + + var hs = await new AuthenticatedHomeServer(RuntimeCache.CurrentHomeServer.UserId, RuntimeCache.CurrentHomeServer.AccessToken, RuntimeCache.CurrentHomeServer.HomeServerDomain).Configure(); + if (Room == null) { if (RoomId == null) { throw new ArgumentNullException(nameof(RoomId)); } - Room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId); + Room = await hs.GetRoom(RoomId); } else { @@ -96,7 +98,8 @@ var url = state.Value.GetProperty("url").GetString(); if (url != null) { - roomIcon = RuntimeCache.CurrentHomeServer.ResolveMediaUri(url); + roomIcon = hs.ResolveMediaUri(url); + Console.WriteLine($"Got avatar for room {RoomId}: {roomIcon} ({url})"); } } catch (InvalidOperationException e) @@ -107,16 +110,16 @@ if (ShowOwnProfile) { - var profile = await RuntimeCache.CurrentHomeServer.GetProfile(RuntimeCache.CurrentHomeServer.UserId, debounce: true); + var profile = await hs.GetProfile(hs.UserId, debounce: true); - var memberState = await Room.GetStateAsync("m.room.member", RuntimeCache.CurrentHomeServer.UserId); + var memberState = await Room.GetStateAsync("m.room.member", hs.UserId); if (memberState.HasValue) { memberState.Value.TryGetProperty("avatar_url", out var _avatar); if (_avatar.ValueKind == JsonValueKind.String) { hasCustomProfileAvatar = _avatar.GetString() != profile.AvatarUrl; - profileAvatar = RuntimeCache.CurrentHomeServer.ResolveMediaUri(_avatar.GetString()); + profileAvatar = hs.ResolveMediaUri(_avatar.GetString()); } else { @@ -135,8 +138,9 @@ } } } + _semaphoreSlim.Release(); if (Random.Shared.Next(100) == 1) - await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + await LocalStorageWrapper.SaveCacheToLocalStorage(LocalStorage); } } \ No newline at end of file