about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTheArcaneBrony <myrainbowdash949@gmail.com>2023-10-17 17:11:49 +0200
committerTheArcaneBrony <myrainbowdash949@gmail.com>2023-10-17 17:11:49 +0200
commitc5c3c3506ec10e373d5c0ebb15146e4ed4e36df5 (patch)
treee74107e266ced599100d43c4e5c0823d4292dfdd
parentRefactors (diff)
downloadMatrixUtils-c5c3c3506ec10e373d5c0ebb15146e4ed4e36df5.tar.xz
Add profile management page
m---------ArcaneLibs0
m---------LibMatrix0
-rw-r--r--MatrixRoomUtils.Desktop/Components/RoomListEntry.axaml.cs2
-rw-r--r--MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs8
-rw-r--r--MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj1
-rw-r--r--MatrixRoomUtils.Web/Pages/Index.razor12
-rw-r--r--MatrixRoomUtils.Web/Pages/Rooms/Create.razor12
-rw-r--r--MatrixRoomUtils.Web/Pages/Rooms/Index.razor16
-rw-r--r--MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor2
-rw-r--r--MatrixRoomUtils.Web/Pages/Rooms/Space.razor8
-rw-r--r--MatrixRoomUtils.Web/Pages/Rooms/StateEditor.razor1
-rw-r--r--MatrixRoomUtils.Web/Pages/Rooms/StateViewer.razor1
-rw-r--r--MatrixRoomUtils.Web/Pages/SpaceDebug.razor25
-rw-r--r--MatrixRoomUtils.Web/Pages/User/Manage.razor55
-rw-r--r--MatrixRoomUtils.Web/Shared/InlineUserItem.razor2
-rw-r--r--MatrixRoomUtils.Web/Shared/NavMenu.razor6
-rw-r--r--MatrixRoomUtils.Web/Shared/RoomListItem.razor6
-rw-r--r--MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor2
-rw-r--r--MatrixRoomUtils.Web/Shared/UserListItem.razor2
-rw-r--r--MatrixRoomUtils.sln.DotSettings.user6
m---------MxApiExtensions0
21 files changed, 122 insertions, 45 deletions
diff --git a/ArcaneLibs b/ArcaneLibs
-Subproject fadd59b2d7303546585f1543ddbbc268068a70a
+Subproject e4e36357535e1f44119a2861027a71d3f92f989
diff --git a/LibMatrix b/LibMatrix
-Subproject f5447484512d726f4403f0d7725777d0a95601f
+Subproject 0ad13628bb8ef899927b7b42b5357fe616ce057
diff --git a/MatrixRoomUtils.Desktop/Components/RoomListEntry.axaml.cs b/MatrixRoomUtils.Desktop/Components/RoomListEntry.axaml.cs
index d687679..c7567ce 100644
--- a/MatrixRoomUtils.Desktop/Components/RoomListEntry.axaml.cs
+++ b/MatrixRoomUtils.Desktop/Components/RoomListEntry.axaml.cs
@@ -47,7 +47,7 @@ public partial class RoomListEntry : UserControl {
                 var hs = await svc.ServiceProvider.GetService<MRUStorageWrapper>()?.GetCurrentSessionOrPrompt()!;
                 var hsResolver = svc.ServiceProvider.GetService<HomeserverResolverService>();
                 var storage = svc.ServiceProvider.GetService<TieredStorageService>()?.CacheStorageProvider;
-                var resolvedUrl = await hsResolver.ResolveMediaUri(hs.FullHomeServerDomain, mxcUrl);
+                var resolvedUrl = await hsResolver.ResolveMediaUri(hs.ServerName, mxcUrl);
                 var storageKey = $"media/{mxcUrl.Replace("mxc://", "").Replace("/", ".")}";
                 try {
                     if (!await storage.ObjectExistsAsync(storageKey))
diff --git a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
index 1fa56be..bea1ced 100644
--- a/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
+++ b/MatrixRoomUtils.Web/Classes/RoomCreationTemplates/DefaultRoomCreationTemplate.cs
@@ -15,25 +15,25 @@ public class DefaultRoomCreationTemplate : IRoomCreationTemplate {
             InitialState = new List<StateEvent> {
                 new() {
                     Type = "m.room.history_visibility",
-                    TypedContent = new HistoryVisibilityEventContent() {
+                    TypedContent = new RoomHistoryVisibilityEventContent() {
                         HistoryVisibility = "world_readable"
                     }
                 },
                 new() {
                     Type = "m.room.guest_access",
-                    TypedContent = new GuestAccessEventContent {
+                    TypedContent = new RoomGuestAccessEventContent {
                         GuestAccess = "can_join"
                     }
                 },
                 new() {
                     Type = "m.room.join_rules",
-                    TypedContent = new JoinRulesEventContent {
+                    TypedContent = new RoomJoinRulesEventContent {
                         JoinRule = "public"
                     }
                 },
                 new() {
                     Type = "m.room.server_acl",
-                    TypedContent = new ServerACLEventContent() {
+                    TypedContent = new RoomServerACLEventContent() {
                         Allow = new List<string>() { "*" },
                         Deny = new List<string>(),
                         AllowIpLiterals = false
diff --git a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj
index 3c8d362..03cc9ae 100644
--- a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj
+++ b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj
@@ -24,4 +24,5 @@
     </ItemGroup>
 
 
+
 </Project>
diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor
index 845bbb9..834c373 100644
--- a/MatrixRoomUtils.Web/Pages/Index.razor
+++ b/MatrixRoomUtils.Web/Pages/Index.razor
@@ -36,7 +36,7 @@ Small collection of tools to do not-so-everyday things.
                 </td>
                 <td>
                     <p>
-                        <LinkButton href="">Manage</LinkButton>
+                        <LinkButton OnClick="@(()=>ManageUser(_auth))">Manage</LinkButton>
                         <LinkButton OnClick="@(() => RemoveUser(_auth))">Remove</LinkButton>
                         <LinkButton OnClick="@(() => RemoveUser(_auth, true))">Log out</LinkButton>
                     </p>
@@ -72,10 +72,7 @@ Small collection of tools to do not-so-everyday things.
             var profile = await hs.GetProfileAsync(hs.WhoAmI.UserId);
             userInfo.DisplayName = profile.DisplayName ?? hs.WhoAmI.UserId;
             Console.WriteLine(profile.ToJson());
-            userInfo.AvatarUrl = await hsResolver.ResolveMediaUri(hs.FullHomeServerDomain,
-                profile.AvatarUrl
-                ?? "https://api.dicebear.com/6.x/identicon/svg?seed=" + hs.WhoAmI.UserId
-                );
+            userInfo.AvatarUrl = string.IsNullOrWhiteSpace(profile.AvatarUrl) ? "https://api.dicebear.com/6.x/identicon/svg?seed=" + hs.WhoAmI.UserId : hs.ResolveMediaUri(profile.AvatarUrl);
             userInfo.RoomCount = (await roomCountTask).Count;
             _users.Add(token, userInfo);
     // StateHasChanged();
@@ -116,4 +113,9 @@ Small collection of tools to do not-so-everyday things.
         await MRUStorage.SetCurrentToken(auth);
         await OnInitializedAsync();
     }
+
+    private async Task ManageUser(UserAuth auth) {
+        await SwitchSession(auth);
+        NavigationManager.NavigateTo("/User/Manage");
+    }
 }
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Create.razor b/MatrixRoomUtils.Web/Pages/Rooms/Create.razor
index 5202c40..3225862 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/Create.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/Create.razor
@@ -90,7 +90,7 @@
         <tr>
             <td>Room icon:</td>
             <td>
-                <img src="@hsResolver.ResolveMediaUri(HomeServer.HomeServerDomain, roomAvatarEvent.Url)" style="width: 128px; height: 128px; border-radius: 50%;"/>
+                <img src="@hsResolver.ResolveMediaUri(HomeServer.ServerName, roomAvatarEvent.Url)" style="width: 128px; height: 128px; border-radius: 50%;"/>
                 <div style="display: inline-block; vertical-align: middle;">
                     <FancyTextBox @bind-Value="@roomAvatarEvent.Url"></FancyTextBox><br/>
                     <InputFile OnChange="RoomIconFilePicked"></InputFile>
@@ -135,7 +135,7 @@
                 }
                 else {
                     <details>
-                        <summary>@((creationEvent["m.room.server_acls"].TypedContent as ServerACLEventContent).Allow.Count) allow rules</summary>
+                        <summary>@((creationEvent["m.room.server_acls"].TypedContent as RoomServerACLEventContent).Allow.Count) allow rules</summary>
                         @* <StringListEditor @bind-Items="@serverAcl.Allow"></StringListEditor> *@
                     </details>
                 }
@@ -145,7 +145,7 @@
                 }
                 else {
                     <details>
-                        <summary>@((creationEvent["m.room.server_acls"].TypedContent as ServerACLEventContent).Deny.Count) deny rules</summary>
+                        <summary>@((creationEvent["m.room.server_acls"].TypedContent as RoomServerACLEventContent).Deny.Count) deny rules</summary>
                         @* <StringListEditor @bind-Items="@serverAcl.Allow"></StringListEditor> *@
                     </details>
                 }
@@ -255,9 +255,9 @@
 
     private MatrixException? _matrixException { get; set; }
 
-    private HistoryVisibilityEventContent? historyVisibility => creationEvent?["m.room.history_visibility"].TypedContent as HistoryVisibilityEventContent;
-    private GuestAccessEventContent? guestAccessEvent => creationEvent?["m.room.guest_access"].TypedContent as GuestAccessEventContent;
-    private ServerACLEventContent? serverAcl => creationEvent?["m.room.server_acls"].TypedContent as ServerACLEventContent;
+    private RoomHistoryVisibilityEventContent? historyVisibility => creationEvent?["m.room.history_visibility"].TypedContent as RoomHistoryVisibilityEventContent;
+    private RoomGuestAccessEventContent? guestAccessEvent => creationEvent?["m.room.guest_access"].TypedContent as RoomGuestAccessEventContent;
+    private RoomServerACLEventContent? serverAcl => creationEvent?["m.room.server_acls"].TypedContent as RoomServerACLEventContent;
     private RoomAvatarEventContent? roomAvatarEvent => creationEvent?["m.room.avatar"].TypedContent as RoomAvatarEventContent;
 
     protected override async Task OnInitializedAsync() {
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Index.razor b/MatrixRoomUtils.Web/Pages/Rooms/Index.razor
index 99e8cbb..69a0ede 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/Index.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/Index.razor
@@ -3,6 +3,7 @@
 @using LibMatrix.Helpers
 @using LibMatrix.Responses
 @using LibMatrix.EventTypes.Spec.State
+@using LibMatrix
 <h3>Room list</h3>
 
 <p>@Status</p>
@@ -58,10 +59,14 @@
         GlobalProfile = await hs.GetProfileAsync(hs.WhoAmI.UserId);
 
         Status = "Syncing...";
-        SyncResult? sync = null;
+        var syncHelper = new SyncHelper(hs) {
+            Timeout = 0,
+            Filter = filter
+        };
+        // SyncResponse? sync = null;
         string? nextBatch = null;
-        while (sync is null or { Rooms.Join.Count: >= 1}) {
-            sync = await hs.SyncHelper.Sync(since: nextBatch, filter: filter, timeout: 0);
+        var syncs = syncHelper.EnumerateSyncAsync();
+        await foreach (var sync in syncs) {
             nextBatch = sync?.NextBatch ?? nextBatch;
             if (sync is null) continue;
             Console.WriteLine($"Got sync, next batch: {nextBatch}!");
@@ -86,7 +91,12 @@
             Status = $"Got {Rooms.Count} rooms so far! Next batch: {nextBatch}";
             StateHasChanged();
             await Task.Delay(100);
+            if (!syncHelper.IsInitialSync) break;
         }
+        // while (sync is null or { Rooms.Join.Count: >= 1}) {
+            // sync = await syncHelper.SyncAsync(since: nextBatch, filter: filter, timeout: 0);
+            
+        // }
         Console.WriteLine("Sync done!");
         Status = "Sync complete!";
         foreach (var roomInfo in Rooms) {
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor b/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor
index e6f436e..15220da 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/PolicyList.razor
@@ -235,7 +235,7 @@ else {
             var server = servers.ContainsKey(hs) ? servers[hs] : new RemoteHomeServer(userId.Split(':')[1]);
             if (!servers.ContainsKey(hs)) servers.Add(hs, server);
             var profile = await server.GetProfileAsync(userId);
-            avatars.Add(userId, await hsResolver.ResolveMediaUri(server.FullHomeServerDomain, profile.AvatarUrl));
+            avatars.Add(userId, await hsResolver.ResolveMediaUri(server.BaseUrl, profile.AvatarUrl));
             servers.Add(userId, server);
             StateHasChanged();
         }
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Space.razor b/MatrixRoomUtils.Web/Pages/Rooms/Space.razor
index 9474b21..d0236e2 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/Space.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/Space.razor
@@ -3,6 +3,7 @@
 @using LibMatrix.Responses
 @using LibMatrix.RoomTypes
 @using ArcaneLibs.Extensions
+@using LibMatrix
 <h3>Room manager - Viewing Space</h3>
 
 <button onclick="@JoinAllRooms">Join all rooms</button>
@@ -93,10 +94,9 @@
     // await base.OnInitializedAsync();
     }
 
-    private Task JoinAllRooms() {
-        List<Task> tasks = Rooms.Select(room => room.JoinAsync(ServersInSpace.ToArray())).ToList();
-        Task.WaitAll(tasks.ToArray());
-        return Task.CompletedTask;
+    private async Task JoinAllRooms() {
+        List<Task<RoomIdResponse>> tasks = Rooms.Select(room => room.JoinAsync(ServersInSpace.ToArray())).ToList();
+        await Task.WhenAll(tasks);
     }
 
 }
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/StateEditor.razor b/MatrixRoomUtils.Web/Pages/Rooms/StateEditor.razor
index f7a6106..e47ba11 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/StateEditor.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/StateEditor.razor
@@ -2,6 +2,7 @@
 @using LibMatrix.Extensions
 @using LibMatrix.Responses
 @using ArcaneLibs.Extensions
+@using LibMatrix
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 <h3>Room state editor - Editing @RoomId</h3>
diff --git a/MatrixRoomUtils.Web/Pages/Rooms/StateViewer.razor b/MatrixRoomUtils.Web/Pages/Rooms/StateViewer.razor
index 6e8fe2f..e9c5da1 100644
--- a/MatrixRoomUtils.Web/Pages/Rooms/StateViewer.razor
+++ b/MatrixRoomUtils.Web/Pages/Rooms/StateViewer.razor
@@ -2,6 +2,7 @@
 @using LibMatrix.Extensions
 @using LibMatrix.Responses
 @using ArcaneLibs.Extensions
+@using LibMatrix
 @inject ILocalStorageService LocalStorage
 @inject NavigationManager NavigationManager
 <h3>Room state viewer - Viewing @RoomId</h3>
diff --git a/MatrixRoomUtils.Web/Pages/SpaceDebug.razor b/MatrixRoomUtils.Web/Pages/SpaceDebug.razor
index 1ad6276..b07ba84 100644
--- a/MatrixRoomUtils.Web/Pages/SpaceDebug.razor
+++ b/MatrixRoomUtils.Web/Pages/SpaceDebug.razor
@@ -1,6 +1,7 @@
 @page "/SpaceDebug"
 @using LibMatrix.RoomTypes
 @using LibMatrix.Filters
+@using LibMatrix.Helpers
 <h3>SpaceDebug</h3>
 <hr/>
 
@@ -48,10 +49,8 @@
         var hs = await MRUStorage.GetCurrentSessionOrNavigate();
         if (hs is null) return;
 
-        Status = "Syncing...";
-        string nextBatch = null;
-        while (nextBatch != "end") {
-            var sync = await hs.SyncHelper.Sync(since: nextBatch, filter: new SyncFilter() {
+        var syncHelper = new SyncHelper(hs) {
+            Filter = new SyncFilter() {
                 Presence = new(0),
                 Room = new() {
                     AccountData = new(limit: 0),
@@ -60,8 +59,13 @@
                     Timeline = new(limit: 0)
                 },
                 AccountData = new(limit: 0)
-            });
+            }
+        };
+        
+        Status = "Syncing...";
 
+        var syncs = syncHelper.EnumerateSyncAsync();
+        await foreach (var sync in syncs) {
             if (sync is null) {
                 Status = "Sync failed";
                 continue;
@@ -69,23 +73,20 @@
 
             if (sync.Rooms is null) {
                 Status = "No rooms in sync...";
-                nextBatch = "end";
-                continue;
+                break;
             }
 
             if (sync.Rooms.Join is null) {
                 Status = "No joined rooms in sync...";
-                nextBatch = "end";
-                continue;
+                break;
             }
 
             if (sync.Rooms.Join.Count == 0) {
                 Status = "Joined rooms list was empty...";
-                nextBatch = "end";
-                continue;
+                break;
             }
 
-            nextBatch = sync.NextBatch;
+            // nextBatch = sync.NextBatch;
             foreach (var (roomId, data) in sync.Rooms!.Join!) {
                 data.State?.Events?.ForEach(e => {
                     if (e.Type == "m.space.child") {
diff --git a/MatrixRoomUtils.Web/Pages/User/Manage.razor b/MatrixRoomUtils.Web/Pages/User/Manage.razor
new file mode 100644
index 0000000..281cbfc
--- /dev/null
+++ b/MatrixRoomUtils.Web/Pages/User/Manage.razor
@@ -0,0 +1,55 @@
+@page "/User/Manage"
+@using LibMatrix.Homeservers
+@using LibMatrix.EventTypes.Spec.State
+@using ArcaneLibs.Extensions
+<h3>Manage user - @HomeServer?.WhoAmI?.UserId</h3>
+<hr/>
+
+@if (Profile is not null) {
+    <h4>Profile</h4>
+    <hr/>
+
+    <img src="@HomeServer.ResolveMediaUri(Profile.AvatarUrl)" style="width: 128px; height: 128px; border-radius: 50%;"/>
+    <div style="display: inline-block; vertical-align: middle;">
+        <span>Display name: </span><FancyTextBox @bind-Value="@Profile.DisplayName"></FancyTextBox><br/>
+        <span>Avatar URL: </span><FancyTextBox @bind-Value="@Profile.AvatarUrl"></FancyTextBox>
+        <InputFile OnChange="@AvatarChanged"></InputFile><br/>
+        <LinkButton OnClick="@(() => UpdateProfile())">Update profile</LinkButton>
+        <LinkButton OnClick="@(() => UpdateProfile(true))">Update profile (restore room overrides)</LinkButton>
+    </div>
+    @if (Busy) {
+        <div>Busy processing profile update, please do not leave this page...</div>
+    }
+}
+
+@code {
+
+    private AuthenticatedHomeserverGeneric? HomeServer { get; set; }
+    private ProfileResponseEventContent? Profile { get; set; }
+    private bool Busy { get; set; } = false;
+
+    protected override async Task OnInitializedAsync() {
+        HomeServer = await MRUStorage.GetCurrentSessionOrNavigate();
+        if (HomeServer is null) return;
+        if (HomeServer.WhoAmI?.UserId is not null)
+            Profile = (await HomeServer.GetProfileAsync(HomeServer.WhoAmI.UserId)).DeepClone();
+
+        await base.OnInitializedAsync();
+    }
+
+    private async Task AvatarChanged(InputFileChangeEventArgs arg) {
+        var res = await HomeServer.UploadFile(arg.File.Name, arg.File.OpenReadStream(), arg.File.ContentType);
+        Console.WriteLine(res);
+        Profile.AvatarUrl = res;
+        StateHasChanged();
+    }
+
+    private async Task UpdateProfile(bool restoreRoomProfiles = false) {
+        Busy = true;
+        StateHasChanged();
+        await HomeServer.UpdateProfileAsync(Profile, restoreRoomProfiles);
+        Busy = false;
+        StateHasChanged();
+    }
+
+}
\ No newline at end of file
diff --git a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
index e82b505..3aea0e0 100644
--- a/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
+++ b/MatrixRoomUtils.Web/Shared/InlineUserItem.razor
@@ -61,7 +61,7 @@
         }
 
 
-        ProfileAvatar ??= await hsResolver.ResolveMediaUri(HomeServer.FullHomeServerDomain, User.AvatarUrl);
+        ProfileAvatar ??= await hsResolver.ResolveMediaUri(HomeServer.ServerName, User.AvatarUrl);
         ProfileName ??= User.DisplayName;
 
         _semaphoreSlim.Release();
diff --git a/MatrixRoomUtils.Web/Shared/NavMenu.razor b/MatrixRoomUtils.Web/Shared/NavMenu.razor
index 48d3196..ad671c5 100644
--- a/MatrixRoomUtils.Web/Shared/NavMenu.razor
+++ b/MatrixRoomUtils.Web/Shared/NavMenu.razor
@@ -53,6 +53,12 @@
                 <span class="oi oi-plus" aria-hidden="true"></span> HS Admin
             </NavLink>
         </div>
+        
+        <div class="nav-item px-3">
+            <NavLink class="nav-link" href="SpaceDebug">
+                <span class="oi oi-plus" aria-hidden="true"></span> Space relationships
+            </NavLink>
+        </div>
 
         <div class="nav-item px-3">
             <h5 style="margin-left: 1em;">MRU</h5>
diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor
index d83568e..0e1d70d 100644
--- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor
+++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor
@@ -9,9 +9,9 @@
     @if (OwnMemberState != null) {
         <img class="imageUnloaded @(string.IsNullOrWhiteSpace(OwnMemberState?.AvatarUrl ?? GlobalProfile?.AvatarUrl) ? "" : "imageLoaded")"
              style="@(ChildContent is not null ? "vertical-align: baseline;" : "") width: 32px; height: 32px; border-radius: 50%; @(OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? "border-color: red; border-width: 3px; border-style: dashed;" : "")"
-             src="@hsResolver.ResolveMediaUri(hs.FullHomeServerDomain, OwnMemberState.AvatarUrl ?? GlobalProfile.AvatarUrl ?? "/icon-192.png").Result"/>
+             src="@hsResolver.ResolveMediaUri(hs.ServerName, OwnMemberState.AvatarUrl ?? GlobalProfile.AvatarUrl ?? "/icon-192.png").Result"/>
         <span style="vertical-align: middle; margin-right: 8px; border-radius: 75px; @(OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? "background-color: red;" : "")">
-            @(OwnMemberState?.Displayname ?? GlobalProfile?.DisplayName ?? "Loading...")
+            @(OwnMemberState?.DisplayName ?? GlobalProfile?.DisplayName ?? "Loading...")
         </span>
         <span style="vertical-align: middle; padding-right: 8px; padding-left: 0px;">-></span>
     }
@@ -137,7 +137,7 @@
 
             var state = (await RoomInfo.GetStateEvent("m.room.avatar")).TypedContent as RoomAvatarEventContent;
             if (state?.Url is { } url) {
-                roomIcon = await hsResolver.ResolveMediaUri(hs.FullHomeServerDomain, url);
+                roomIcon = await hsResolver.ResolveMediaUri(hs.ServerName, url);
                 // Console.WriteLine($"Got avatar for room {RoomId}: {roomIcon} ({url})");
             }
         }
diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
index 27c636f..b58afba 100644
--- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
+++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
@@ -12,7 +12,7 @@
             <i>@Event.StateKey was invited</i>
             break;
         case "join" when Event.ReplacesState is not null:
-            <i>@Event.StateKey changed their display name to @(roomMemberData.Displayname ?? Event.Sender)</i>
+            <i>@Event.StateKey changed their display name to @(roomMemberData.DisplayName ?? Event.Sender)</i>
             break;
         case "join":
             <i><InlineUserItem User="@(new ProfileResponseEventContent())" HomeServer="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> joined</i>
diff --git a/MatrixRoomUtils.Web/Shared/UserListItem.razor b/MatrixRoomUtils.Web/Shared/UserListItem.razor
index 7c439cd..9010820 100644
--- a/MatrixRoomUtils.Web/Shared/UserListItem.razor
+++ b/MatrixRoomUtils.Web/Shared/UserListItem.razor
@@ -44,7 +44,7 @@
         }
 
     // UserId = User.;
-        profileAvatar = await hsResolver.ResolveMediaUri(hs.FullHomeServerDomain, User.AvatarUrl);
+        profileAvatar = await hsResolver.ResolveMediaUri(hs.ServerName, User.AvatarUrl);
         profileName = User.DisplayName;
 
         _semaphoreSlim.Release();
diff --git a/MatrixRoomUtils.sln.DotSettings.user b/MatrixRoomUtils.sln.DotSettings.user
index f9024a8..b2b542c 100644
--- a/MatrixRoomUtils.sln.DotSettings.user
+++ b/MatrixRoomUtils.sln.DotSettings.user
@@ -15,8 +15,8 @@
 	<s:Int64 x:Key="/Default/Environment/Hierarchy/Build/SolutionBuilderNext/ParallelProcessesCount2/@EntryValue">12</s:Int64>
 	
 	<s:Boolean x:Key="/Default/Environment/Hierarchy/Build/SolutionBuilderNext/ShouldRestoreNugetPackages/@EntryValue">True</s:Boolean>
-	<s:String x:Key="/Default/Environment/Highlighting/HighlightingSourceSnapshotLocation/@EntryValue">/home/root@Rory/.cache/JetBrains/Rider2023.2/resharper-host/temp/Rider/vAny/CoverageData/_MatrixRoomUtils.2147452914/Snapshot/snapshot.utdcvr</s:String>
-	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=10c2dea2_002D6490_002D4ee9_002D8f89_002D2bf8c99bcf8e/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &amp;lt;LibMatrix&amp;gt; #5" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
+	
+	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=10c2dea2_002D6490_002D4ee9_002D8f89_002D2bf8c99bcf8e/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from &amp;lt;LibMatrix&amp;gt; #5" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
   &lt;Project Location="/home/root@Rory/git/Matrix/MatrixRoomUtils" Presentation="&amp;lt;LibMatrix&amp;gt;" /&gt;
 &lt;/SessionState&gt;</s:String>
 	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=24cf7b5e_002D6eb8_002D4f8e_002D80e5_002Dba9e1170805a/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from &amp;lt;LibMatrix&amp;gt; #4" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
@@ -41,7 +41,7 @@
 	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=b41031ac_002Dfe6a_002D4ad7_002Db7d5_002D46c2a6404301/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from &amp;lt;LibMatrix&amp;gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
   &lt;Project Location="/home/root@Rory/git/Matrix/MatrixRoomUtils" Presentation="&amp;lt;LibMatrix&amp;gt;" /&gt;
 &lt;/SessionState&gt;</s:String>
-	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=c33adfe1_002D4af3_002D4c1e_002D9689_002De5e34a9f9113/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from &amp;lt;LibMatrix&amp;gt; #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
+	<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=c33adfe1_002D4af3_002D4c1e_002D9689_002De5e34a9f9113/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &amp;lt;LibMatrix&amp;gt; #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
   &lt;Project Location="/home/root@Rory/git/Matrix/MatrixRoomUtils" Presentation="&amp;lt;LibMatrix&amp;gt;" /&gt;
 &lt;/SessionState&gt;</s:String>
 	
diff --git a/MxApiExtensions b/MxApiExtensions
-Subproject 143b7fb859d97e815ed5340a1889db93e17a762
+Subproject 72b8f014866be5d0631a5b432b9d55569554e52