diff options
Diffstat (limited to 'MatrixRoomUtils.Web')
19 files changed, 560 insertions, 93 deletions
diff --git a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs index a439ea1..c224160 100644 --- a/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs +++ b/MatrixRoomUtils.Web/Classes/LocalStorageWrapper.cs @@ -1,6 +1,5 @@ using Blazored.LocalStorage; using MatrixRoomUtils.Core; -using MatrixRoomUtils.Core.Extensions; namespace MatrixRoomUtils.Web.Classes; @@ -27,7 +26,7 @@ public partial class LocalStorageWrapper { Console.WriteLine($"Access token is not null, creating authenticated home server"); Console.WriteLine($"Homeserver cache: {RuntimeCache.HomeserverResolutionCache.Count} entries"); - Console.WriteLine(RuntimeCache.HomeserverResolutionCache.ToJson()); + // 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(); Console.WriteLine("Created authenticated home server"); } @@ -47,6 +46,17 @@ public partial class LocalStorageWrapper .ToDictionary(x => x.Key, x => x.Value)); await localStorage.SetItemAsync("rory.matrixroomutils.generic_cache", RuntimeCache.GenericResponseCache); } + public static async Task SaveFieldToLocalStorage(ILocalStorageService localStorage, string key) + { + 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); + + } } @@ -59,4 +69,6 @@ public class Settings public class DeveloperSettings { public bool EnableLogViewers { get; set; } = false; + public bool EnableConsoleLogging { get; set; } = true; + public bool EnablePortableDevtools { get; set; } = false; } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj index f167eaa..77a039c 100644 --- a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj +++ b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj @@ -20,4 +20,8 @@ <_ContentIncludedByDefault Remove="wwwroot\sample-data\weather.json" /> </ItemGroup> + <ItemGroup> + <None Include="wwwroot\homeservers.txt" /> + </ItemGroup> + </Project> diff --git a/MatrixRoomUtils.Web/Pages/About.razor b/MatrixRoomUtils.Web/Pages/About.razor index fc9128e..d47e60b 100644 --- a/MatrixRoomUtils.Web/Pages/About.razor +++ b/MatrixRoomUtils.Web/Pages/About.razor @@ -1,5 +1,4 @@ @page "/About" -@using MatrixRoomUtils.Web.Shared.IndexComponents @using System.Net @inject NavigationManager NavigationManager @inject ILocalStorageService LocalStorage diff --git a/MatrixRoomUtils.Web/Pages/DevOptions.razor b/MatrixRoomUtils.Web/Pages/DevOptions.razor index 0cc38d8..e1b6ac0 100644 --- a/MatrixRoomUtils.Web/Pages/DevOptions.razor +++ b/MatrixRoomUtils.Web/Pages/DevOptions.razor @@ -1,6 +1,4 @@ @page "/DevOptions" -@using MatrixRoomUtils.Web.Shared.IndexComponents -@using System.Net @using MatrixRoomUtils.Core.Extensions @inject NavigationManager NavigationManager @inject ILocalStorageService LocalStorage @@ -10,8 +8,32 @@ <h3>Rory&::MatrixUtils - Developer options</h3> <hr/> -<InputCheckbox @bind-Value="@LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers" @oninput="@LogStuff"></InputCheckbox><label> Enable log views</label> +<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> +<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/> + Default expiry: @item.Value.DefaultExpiry<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 { protected override async Task OnInitializedAsync() @@ -19,6 +41,14 @@ await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); await base.OnInitializedAsync(); await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + Task.Run(async () => + { + while (true) + { + await Task.Delay(100); + StateHasChanged(); + } + }); } protected async Task LogStuff() @@ -29,4 +59,25 @@ await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); } + protected async Task DropCaches() + { + RuntimeCache.GenericResponseCache.Clear(); + RuntimeCache.HomeserverResolutionCache.Clear(); + await LocalStorageWrapper.SaveToLocalStorage(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.SaveToLocalStorage(LocalStorage); + } + } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor new file mode 100644 index 0000000..b77012b --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor @@ -0,0 +1,7 @@ +@page "/HSAdmin" +<h3>Homeserver Admininistration</h3> +<hr/> + +@code { + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor new file mode 100644 index 0000000..f396025 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/KnownHomeserverList.razor @@ -0,0 +1,79 @@ +@page "/KnownHomeserverList" +@using System.Text.Json +@using MatrixRoomUtils.Core.Extensions +<h3>Known Homeserver List</h3> +<hr/> + +@if (!IsFinished) +{ + <p>Loading... Please wait...</p> +} +else +{ + @foreach (var server in HomeServers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList()) + { + <p>@server.Server - @server.KnownUserCount</p> + } +} +<hr/> + +@code { + List<HomeServerInfo> HomeServers = new(); + bool IsFinished { get; set; } + + protected override async Task OnInitializedAsync() + { + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + + HomeServers = await GetHomeservers(); + + IsFinished = true; + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + } + + + private async Task<List<HomeServerInfo>> GetHomeservers() + { + List<HomeServerInfo> homeServers = new(); + var rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms(); + // Dictionary<string, StateEvent> roomMembers = new(); + //start a task for each room + var tasks = rooms.Select(async room => + { + Console.WriteLine($"Fetching states for room ({rooms.IndexOf(room)}/{rooms.Count}) ({room.RoomId})"); + StateHasChanged(); + + var states = (await room.GetStateAsync("")).Value.Deserialize<List<StateEvent>>(); + states.RemoveAll(x => x.type != "m.room.member"); + Console.WriteLine($"Room {room.RoomId} has {states.Count} members"); + foreach (var state in states) + { + if (!homeServers.Any(x => x.Server == state.state_key.Split(':')[1])) + { + homeServers.Add(new HomeServerInfo() { Server = state.state_key.Split(':')[1] }); + } + var hs = homeServers.First(x => x.Server == state.state_key.Split(':')[1]); + if(!hs.KnownUsers.Contains(state.state_key.Split(':')[0])) + hs.KnownUsers.Add(state.state_key.Split(':')[0]); + } + Console.WriteLine("Collected states!"); + }); + await Task.WhenAll(tasks); + + Console.WriteLine("Calculating member counts..."); + homeServers.ForEach(x => x.KnownUserCount = x.KnownUsers.Count); + Console.WriteLine(homeServers.First(x=>x.Server=="rory.gay").ToJson()); + Console.WriteLine("Recalculated!"); + return homeServers; + } + + class HomeServerInfo + { + public string Server { get; set; } + public int? KnownUserCount { get; set; } + public List<string> KnownUsers { get; set; } = new(); + } + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/MediaLocator.razor index cd244ef..06256f0 100644 --- a/MatrixRoomUtils.Web/Pages/MediaLocator.razor +++ b/MatrixRoomUtils.Web/Pages/MediaLocator.razor @@ -1,11 +1,46 @@ @page "/MediaLocator" -<h3>MediaLocator</h3> +@inject HttpClient Http +<h3>Media locator</h3> <hr/> +<b>This is going to expose your IP address to all these homeservers!</b> +<details> + <summary>Checked homeserver list (@homeservers.Count entries)</summary> + <ul> + @foreach (var hs in homeservers) + { + <li>@hs</li> + } + </ul> +</details> +<button @onclick="addMoreHomeservers">Add more homeservers</button> +<br/> <span>MXC URL: </span> <input type="text" @bind="mxcUrl" /> <button @onclick="executeSearch">Search</button> +@if (successResults.Count > 0) +{ + <h4>Successes</h4> + <ul> + @foreach (var result in successResults) + { + <li>@result</li> + } + </ul> +} + +@if (errorResults.Count > 0) +{ + <h4>Errors</h4> + <ul> + @foreach (var result in errorResults) + { + <li>@result</li> + } + </ul> +} + @code { string mxcUrl { get; set; } @@ -15,22 +50,82 @@ protected override async Task OnInitializedAsync() { - base.OnInitializedAsync(); - + await base.OnInitializedAsync(); + homeservers.AddRange(new [] + { + "matrix.org", + "feline.support", + "rory.gay", + "the-apothecary.club", + "envs.net", + "projectsegfau.lt" + }); } async Task executeSearch() { - var client = new HttpClient(); - var response = await client.GetAsync($"https://matrix.org/_matrix/media/r0/identicon/{mxcUrl}"); - if (response.IsSuccessStatusCode) + var sem = new SemaphoreSlim(128, 128); + homeservers.ForEach(async hs => { - successResults.Add(mxcUrl); - } - else - { - errorResults.Add(mxcUrl); - } + await sem.WaitAsync(); + var httpClient = new HttpClient { BaseAddress = new Uri(hs) }; + httpClient.Timeout = TimeSpan.FromSeconds(5); + var rmu = mxcUrl.Replace("mxc://", $"{hs}/_matrix/media/r0/download/"); + try + { + var res = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, rmu)); + if (res.IsSuccessStatusCode) + { + successResults.Add($"{hs}: found - {res.Content.Headers.ContentLength} bytes"); + StateHasChanged(); + return; + } + errorResults.Add($"Error: {hs} - {res.StatusCode}\n" + await res.Content.ReadAsStringAsync()); + } + catch (Exception e) + { + errorResults.Add($"Error: {e}"); + } + finally + { + sem.Release(); + } + StateHasChanged(); + }); } + + async Task addMoreHomeservers() + { + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + var res = await Http.GetAsync("/homeservers.txt"); + var content = await res.Content.ReadAsStringAsync(); + homeservers.Clear(); + var lines = content.Split("\n"); + + var rhs = new RemoteHomeServer("rory.gay"); + var sem = new SemaphoreSlim(128, 128); + lines.ToList().ForEach(async line => + { + await sem.WaitAsync(); + try + { + homeservers.Add(await rhs.ResolveHomeserverFromWellKnown(line)); + StateHasChanged(); + if(Random.Shared.Next(0,101) == 50) + await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + sem.Release(); + } + }); + + + StateHasChanged(); + } } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor index 5dfb2d6..d0f9b87 100644 --- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor +++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListEditorPage.razor @@ -41,7 +41,8 @@ else @policyEvent.content.ExpiryDateTime </td> <td> - <button class="btn btn-danger" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Remove</button> + <button class="btn" @* @onclick="async () => await RemovePolicyAsync(policyEvent)" *@>Edit</button> + @* <button class="btn btn-danger" $1$ @onclick="async () => await RemovePolicyAsync(policyEvent)" #1#>Remove</button> *@ </td> </tr> } diff --git a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor index e9d1be4..f25fbae 100644 --- a/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor +++ b/MatrixRoomUtils.Web/Pages/PolicyList/PolicyListRoomList.razor @@ -19,8 +19,13 @@ else } foreach (var s in PolicyRoomList) { - <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">[@s.Shortcode] @s.Name (@s.RoomId)</a> - <br/> + + <a style="color: unset; text-decoration: unset;" href="/PolicyListEditor/@s.RoomId.Replace('.','~')"><RoomListItem RoomId="@s.RoomId"> + <br/> + <span>Shortcode: @s.Shortcode</span> + </RoomListItem></a> + @* <a href="@(NavigationManager.Uri + "/" + s.RoomId.Replace('.', '~'))">[@s.Shortcode] @s.Name (@s.RoomId)</a> *@ + @* <br/> *@ } } @@ -74,15 +79,11 @@ else { try { - //TODO: refactor!!!!! await semaphore.WaitAsync(); 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; diff --git a/MatrixRoomUtils.Web/Pages/RoomManager.razor b/MatrixRoomUtils.Web/Pages/RoomManager.razor deleted file mode 100644 index deb6fd5..0000000 --- a/MatrixRoomUtils.Web/Pages/RoomManager.razor +++ /dev/null @@ -1,40 +0,0 @@ -@page "/RoomManager" -@inject ILocalStorageService LocalStorage -@inject NavigationManager NavigationManager -<h3>Room manager</h3> -<hr/> -@if (Rooms.Count == 0) -{ - <p>You are not in any rooms!</p> - @* <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> *@ -} -else -{ - <details open> - <summary>Room List</summary> - @foreach (var room in Rooms) - { - <a style="color: unset; text-decoration: unset;" href="/RoomStateViewer/@room.Replace('.', '~')"><RoomListItem RoomId="@room" ShowOwnProfile="true"></RoomListItem></a> - } - </details> - -} - -<div style="margin-bottom: 4em;"></div> -<LogView></LogView> - -@code { - public List<string> Rooms { get; set; } = new(); - protected override async Task OnInitializedAsync() - { - if (!RuntimeCache.WasLoaded) 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(); - Console.WriteLine("Fetched joined rooms!"); - } -} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor new file mode 100644 index 0000000..6d27679 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManager.razor @@ -0,0 +1,96 @@ +@page "/RoomManager" +@inject ILocalStorageService LocalStorage +@inject NavigationManager NavigationManager +<h3>Room manager</h3> +<hr/> +@if (Rooms.Count == 0) +{ + <p>You are not in any rooms!</p> + @* <p>Loading progress: @checkedRoomCount/@totalRoomCount</p> *@ +} +else +{ + <p>You are in @Rooms.Count rooms and @Spaces.Count spaces</p> + <details open> + <summary>Space List</summary> + @foreach (var room in Spaces) + { + <a style="color: unset; text-decoration: unset;" href="/RoomManager/Space/@room.RoomId.Replace('.', '~')"><RoomListItem Room="@room" ShowOwnProfile="true"></RoomListItem></a> + } + </details> + <details open> + <summary>Room List</summary> + @foreach (var room in Rooms) + { + <a style="color: unset; text-decoration: unset;" href="/RoomManager/Room/@room.RoomId.Replace('.', '~')"><RoomListItem Room="@room" ShowOwnProfile="true"></RoomListItem></a> + } + </details> + +} + +<div style="margin-bottom: 4em;"></div> +<LogView></LogView> + +@code { + public List<Room> Rooms { get; set; } = new(); + public List<Room> Spaces { get; set; } = new(); + protected override async Task OnInitializedAsync() + { + if (!RuntimeCache.WasLoaded) await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + await base.OnInitializedAsync(); + if (RuntimeCache.CurrentHomeServer == null) + { + NavigationManager.NavigateTo("/Login"); + return; + } + Rooms = await RuntimeCache.CurrentHomeServer.GetJoinedRooms(); + StateHasChanged(); + var semaphore = new SemaphoreSlim(1000); + var tasks = new List<Task<Room?>>(); + foreach (var room in Rooms) + { + tasks.Add(CheckIfSpace(room, semaphore)); + } + await Task.WhenAll(tasks); + + Console.WriteLine("Fetched joined rooms!"); + } + + private async Task<Room?> CheckIfSpace(Room room, SemaphoreSlim semaphore) + { + await semaphore.WaitAsync(); + try + { + var state = await room.GetStateAsync("m.room.create"); + if (state != null) + { + //Console.WriteLine(state.Value.ToJson()); + if(state.Value.TryGetProperty("type", out var type)) + { + if(type.ToString() == "m.space") + { + Spaces.Add(room); + Rooms.Remove(room); + StateHasChanged(); + return room; + } + } + else + { + //this is fine, apprently... + //Console.WriteLine($"Room {room.RoomId} has no content.type in m.room.create!"); + } + } + } + catch (Exception e) + { + Console.WriteLine(e); + return null; + } + finally + { + semaphore.Release(); + } + return null; + } +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor new file mode 100644 index 0000000..4a5bddf --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/RoomManager/RoomManagerSpace.razor @@ -0,0 +1,77 @@ +@page "/RoomManager/Space/{RoomId}" +@using MatrixRoomUtils.Core.Extensions +@using System.Text.Json +<h3>Room manager - Viewing Space</h3> + +<button onclick="@JoinAllRooms">Join all rooms</button> +@foreach (var room in Rooms) +{ + <RoomListItem Room="room" ShowOwnProfile="true"></RoomListItem> +} + + +<br/> +<details style="background: #0002;"> + <summary style="background: #fff1;">State list</summary> + @foreach (var stateEvent in States.OrderBy(x => x.state_key).ThenBy(x => x.type)) + { + <p>@stateEvent.state_key/@stateEvent.type:</p> + <pre>@stateEvent.content.ToJson()</pre> + } +</details> + +@code { + + [Parameter] + public string RoomId { get; set; } = "invalid!!!!!!"; + + private Room? Room { get; set; } + + private StateEvent<object>[] States { get; set; } = Array.Empty<StateEvent<object>>(); + private List<Room> Rooms { get; set; } = 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<StateEvent<object>[]>()!; + + foreach (var stateEvent in States) + { + if (stateEvent.type == "m.space.child") + { + // if (stateEvent.content.ToJson().Length < 5) return; + var roomId = stateEvent.state_key; + var room = await RuntimeCache.CurrentHomeServer.GetRoom(roomId); + if (room != null) + { + Rooms.Add(room); + } + } + } + + // if(state.Value.TryGetProperty("type", out var type)) + // { + // } + // else + // { + // //this is fine, apprently... + // //Console.WriteLine($"Room {room.RoomId} has no content.type in m.room.create!"); + // } + } + await base.OnInitializedAsync(); + } + + private async Task JoinAllRooms() + { + foreach (var room in Rooms) + { + room.JoinAsync(); + } + } + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Properties/launchSettings.json b/MatrixRoomUtils.Web/Properties/launchSettings.json index d5a26f5..aa41dc8 100644 --- a/MatrixRoomUtils.Web/Properties/launchSettings.json +++ b/MatrixRoomUtils.Web/Properties/launchSettings.json @@ -11,7 +11,7 @@ "http": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, + "launchBrowser": false, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "applicationUrl": "http://localhost:5117", "environmentVariables": { @@ -21,7 +21,7 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, + "launchBrowser": false, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "applicationUrl": "https://localhost:7014;http://localhost:5117", "environmentVariables": { diff --git a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor index 08161b2..87ef831 100644 --- a/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor +++ b/MatrixRoomUtils.Web/Shared/IndexComponents/IndexUserItem.razor @@ -10,22 +10,30 @@ <div style="margin-bottom: 1em;"> <img style="border-radius: 50%; height: 3em; width: 3em;" src="@_avatarUrl"/> - <span style="margin-left: 1em;"><input type="radio" name="csa" checked="@(RuntimeCache.LastUsedToken == User.AccessToken)" onclick="@SetCurrent" style="text-decoration-line: unset;"/> <b>@User.Profile.DisplayName</b> on <b>@User.LoginResponse.HomeServer</b></span> - <a href="#" onclick="@RemoveUser">Remove</a> + <p style="margin-left: 1em; margin-top: -0.5em; display: inline-block;"> + <input type="radio" name="csa" checked="@(RuntimeCache.LastUsedToken == User.AccessToken)" onclick="@SetCurrent" style="text-decoration-line: unset;"/> + <b>@User.Profile.DisplayName</b> on <b>@User.LoginResponse.HomeServer</b> + <a href="#" onclick="@RemoveUser">Remove</a> + </p> + <p style="margin-top: -1.5em; margin-left: 4em;">Member of @_roomCount rooms</p> + </div> @code { [Parameter] public UserInfo User { get; set; } = null!; - + private string _avatarUrl { get; set; } + private int _roomCount { get; set; } = 0; protected override async Task OnInitializedAsync() { + var hs = await new AuthenticatedHomeServer(User.LoginResponse.UserId, User.AccessToken, User.LoginResponse.HomeServer).Configure(); if (User.Profile.AvatarUrl != null && User.Profile.AvatarUrl != "") - _avatarUrl = await (await new AuthenticatedHomeServer(User.LoginResponse.UserId, User.AccessToken, User.LoginResponse.HomeServer).Configure()).ResolveMediaUri(User.Profile.AvatarUrl); + _avatarUrl = await hs.ResolveMediaUri(User.Profile.AvatarUrl); else _avatarUrl = "https://api.dicebear.com/6.x/identicon/svg?seed=" + User.LoginResponse.UserId; + _roomCount = (await hs.GetJoinedRooms()).Count; await base.OnInitializedAsync(); } @@ -34,15 +42,17 @@ Console.WriteLine(User.ToJson()); RuntimeCache.LoginSessions.Remove(User.AccessToken); await LocalStorageWrapper.ReloadLocalStorage(LocalStorage); - + StateHasChanged(); } + private async Task SetCurrent() { RuntimeCache.LastUsedToken = User.AccessToken; - //RuntimeCache.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(LocalStorageWrapper.LoginSessions[Token].LoginResponse.HomeServer); + //RuntimeCache.CurrentHomeserver = await MatrixAuth.ResolveHomeserverFromWellKnown(LocalStorageWrapper.LoginSessions[Token].LoginResponse.HomeServer); await LocalStorageWrapper.ReloadLocalStorage(LocalStorage); - + StateHasChanged(); } + } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/LogView.razor b/MatrixRoomUtils.Web/Shared/LogView.razor index f60f271..80fd355 100644 --- a/MatrixRoomUtils.Web/Shared/LogView.razor +++ b/MatrixRoomUtils.Web/Shared/LogView.razor @@ -1,13 +1,27 @@ @using System.Text -<u>Logs</u><br/> -<pre> - @_stringBuilder -</pre> +@if (LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) +{ + <u>Logs</u> + <br/> + <pre> + @_stringBuilder + </pre> +} @code { StringBuilder _stringBuilder = new(); - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) + { + Console.WriteLine("Console logging disabled!"); + var _sw = new StringWriter(); + Console.SetOut(_sw); + Console.SetError(_sw); + return; + } + if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableLogViewers) return; //intecept stdout with textwriter to get logs var sw = new StringWriter(_stringBuilder); Console.SetOut(sw); @@ -27,6 +41,6 @@ } // ReSharper disable once FunctionNeverReturns - This is intentional behavior }); - base.OnInitialized(); + await base.OnInitializedAsync(); } } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/MainLayout.razor b/MatrixRoomUtils.Web/Shared/MainLayout.razor index da27978..b1b0b53 100644 --- a/MatrixRoomUtils.Web/Shared/MainLayout.razor +++ b/MatrixRoomUtils.Web/Shared/MainLayout.razor @@ -1,5 +1,4 @@ -@using MatrixRoomUtils.Core.Extensions -@using System.Net +@using System.Net @inherits LayoutComponentBase <div class="page"> @@ -9,6 +8,7 @@ <main> <div class="top-row px-4"> + <PortableDevTools></PortableDevTools> <a href="https://git.rory.gay/MatrixRoomUtils.git/" target="_blank">Git</a> <a href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a> @if (showDownload) @@ -31,6 +31,16 @@ using var hc = new HttpClient(); var hr = await hc.SendAsync(new(HttpMethod.Head, NavigationManager.ToAbsoluteUri("/MRU-BIN.tar.xz").AbsoluteUri)); showDownload = hr.StatusCode == HttpStatusCode.OK; + + await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + if (!LocalStorageWrapper.Settings.DeveloperSettings.EnableConsoleLogging) + { + Console.WriteLine("Console logging disabled!"); + var sw = new StringWriter(); + Console.SetOut(sw); + Console.SetError(sw); + } + await base.OnInitializedAsync(); } diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor b/MatrixRoomUtils.Web/Shared/NavMenu.razor index b77935d..8136715 100644 --- a/MatrixRoomUtils.Web/Shared/NavMenu.razor +++ b/MatrixRoomUtils.Web/Shared/NavMenu.razor @@ -52,10 +52,15 @@ <hr style="margin-bottom: 0em;"/> </div> <div class="nav-item px-3"> - <NavLink class="nav-link" href="MediaLocator"> - <span class="oi oi-plus" aria-hidden="true"></span> Media locator + <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 *@ + @* </NavLink> *@ + @* </div> *@ <div class="nav-item px-3"> <h5 style="margin-left: 1em;">MRU</h5> <hr style="margin-bottom: 0em;"/> diff --git a/MatrixRoomUtils.Web/Shared/PortableDevTools.razor b/MatrixRoomUtils.Web/Shared/PortableDevTools.razor new file mode 100644 index 0000000..84e7791 --- /dev/null +++ b/MatrixRoomUtils.Web/Shared/PortableDevTools.razor @@ -0,0 +1,31 @@ + +@if (Enabled) +{ + <a href="/DevOptions">Portable devtools (enabled)</a> + <div id="PortableDevTools" style="position: fixed; bottom: 0; right: 0; min-width: 200px; min-height: 100px; background: #0002;" draggable> + <p>Cache size: @RuntimeCache.GenericResponseCache.Sum(x=>x.Value.Cache.Count)</p> + </div> +} +else { + <a href="/DevOptions">Portable devtools (disabled)</a> +} + +@code { + private bool Enabled { get; set; } = LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools; + + protected override async Task OnInitializedAsync() + { + // if(!RuntimeCache.WasLoaded) + // await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); + // StateHasChanged(); + Task.Run(async () => + { + while (true) + { + await Task.Delay(100); + Enabled = LocalStorageWrapper.Settings.DeveloperSettings.EnablePortableDevtools; + StateHasChanged(); + } + }); + } +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor index 15ca5c0..16ced75 100644 --- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor +++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor @@ -3,17 +3,27 @@ <div style="background-color: #ffffff11; border-radius: 25px; margin: 8px; width: fit-content;"> @if (ShowOwnProfile) { - <img style="width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@profileAvatar"/> + <img style="@(ChildContent != null ? "vertical-align: baseline;":"") width: 32px; height: 32px; border-radius: 50%; @(hasCustomProfileAvatar ? "border-color: red; border-width: 3px; border-style: dashed;" : "")" src="@profileAvatar"/> <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px; @(hasCustomProfileName ? "background-color: red;" : "")">@profileName</span> <span style="vertical-align: middle; padding-right: 8px; padding-left: 0px;">-></span> } - <img style="width: 32px; height: 32px; border-radius: 50%;" src="@roomIcon"/> - <span style="vertical-align: middle; padding-right: 8px;">@roomName</span> + <img style="@(ChildContent != null ? "vertical-align: baseline;":"") width: 32px; height: 32px; border-radius: 50%;" src="@roomIcon"/> + <div style="display: inline-block;"> + <span style="vertical-align: middle; padding-right: 8px;">@roomName</span> + @if (ChildContent != null) + { + @ChildContent + } + </div> + </div> @code { [Parameter] + public RenderFragment? ChildContent { get; set; } + + [Parameter] public Room Room { get; set; } [Parameter] @@ -33,8 +43,9 @@ protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - - if(!RuntimeCache.WasLoaded) { + + if (!RuntimeCache.WasLoaded) + { Console.WriteLine("Loading from local storage"); await LocalStorageWrapper.LoadFromLocalStorage(LocalStorage); } @@ -47,6 +58,10 @@ } Room = await RuntimeCache.CurrentHomeServer.GetRoom(RoomId); } + else + { + RoomId = Room.RoomId; + } roomName = await Room.GetNameAsync(); if (roomName == null) @@ -66,8 +81,8 @@ if (ShowOwnProfile) { - var profile = await RuntimeCache.CurrentHomeServer.GetProfile(RuntimeCache.CurrentHomeServer.UserId, debounce: true); - + var profile = await RuntimeCache.CurrentHomeServer.GetProfile(RuntimeCache.CurrentHomeServer.UserId, debounce: true); + var memberState = await Room.GetStateAsync("m.room.member", RuntimeCache.CurrentHomeServer.UserId); if (memberState.HasValue) { @@ -86,7 +101,7 @@ { hasCustomProfileName = _name.GetString() != profile.DisplayName; profileName = _name.GetString(); - // Console.WriteLine($"{profile.DisplayName} - {_name.GetString()}: {hasCustomProfileName}"); + // Console.WriteLine($"{profile.DisplayName} - {_name.GetString()}: {hasCustomProfileName}"); } else { @@ -94,7 +109,7 @@ } } } - if(Random.Shared.Next(100) == 1) + if (Random.Shared.Next(100) == 1) await LocalStorageWrapper.SaveToLocalStorage(LocalStorage); } |