about summary refs log tree commit diff
path: root/MatrixUtils.Web/Shared
diff options
context:
space:
mode:
Diffstat (limited to 'MatrixUtils.Web/Shared')
-rw-r--r--MatrixUtils.Web/Shared/InlineUserItem.razor5
-rw-r--r--MatrixUtils.Web/Shared/MainLayout.razor12
-rw-r--r--MatrixUtils.Web/Shared/MainLayout.razor.css1
-rw-r--r--MatrixUtils.Web/Shared/MxcAvatar.razor49
-rw-r--r--MatrixUtils.Web/Shared/MxcImage.razor78
-rw-r--r--MatrixUtils.Web/Shared/NavMenu.razor6
-rw-r--r--MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor102
-rw-r--r--MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor60
-rw-r--r--MatrixUtils.Web/Shared/RoomList.razor5
-rw-r--r--MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor13
-rw-r--r--MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor11
-rw-r--r--MatrixUtils.Web/Shared/RoomListItem.razor53
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor2
-rw-r--r--MatrixUtils.Web/Shared/UserListItem.razor7
21 files changed, 311 insertions, 107 deletions
diff --git a/MatrixUtils.Web/Shared/InlineUserItem.razor b/MatrixUtils.Web/Shared/InlineUserItem.razor

index 9c6608a..eaf7a92 100644 --- a/MatrixUtils.Web/Shared/InlineUserItem.razor +++ b/MatrixUtils.Web/Shared/InlineUserItem.razor
@@ -1,4 +1,4 @@ -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses <div style="background-color: #ffffff11; border-radius: 0.5em; height: 1em; display: inline-block; vertical-align: middle;" alt="@UserId"> <img style="@(ChildContent is not null ? "vertical-align: baseline;" : "vertical-align: top;") width: 1em; height: 1em; border-radius: 50%;" src="@ProfileAvatar"/> @@ -39,7 +39,6 @@ protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - Homeserver ??= await RMUStorage.GetCurrentSessionOrNavigate(); if(Homeserver is null) return; await _semaphoreSlim.WaitAsync(); @@ -59,7 +58,7 @@ } - ProfileAvatar ??= Homeserver.ResolveMediaUri(User.AvatarUrl); + // ProfileAvatar ??= Homeserver.ResolveMediaUri(User.AvatarUrl); ProfileName ??= User.DisplayName; _semaphoreSlim.Release(); diff --git a/MatrixUtils.Web/Shared/MainLayout.razor b/MatrixUtils.Web/Shared/MainLayout.razor
index c67f73c..b32735f 100644 --- a/MatrixUtils.Web/Shared/MainLayout.razor +++ b/MatrixUtils.Web/Shared/MainLayout.razor
@@ -1,5 +1,4 @@ -@using ArcaneLibs -@inherits LayoutComponentBase +@inherits LayoutComponentBase <div class="page"> <div class="sidebar"> @@ -10,16 +9,15 @@ <div class="top-row px-4"> @* <PortableDevTools/> *@ @* <ResourceUsage/> *@ - <a style="color: #ccc; text-decoration: underline" href="https://cgit.rory.gay/matrix/MatrixRoomUtils.git/" target="_blank">Git</a> - <a style="color: #ccc; text-decoration: underline" href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" target="_blank">Matrix</a> + <a style="color: #ccc; text-decoration: underline" href="https://cgit.rory.gay/matrix/tools/MatrixUtils.git/" target="_blank">Git</a> + <a style="color: #ccc; text-decoration: underline" href="https://matrix.to/#/%23mru%3Arory.gay?via=rory.gay&via=matrix.org&via=feline.support" + target="_blank">Matrix</a> </div> <article class="Content px-4"> @Body </article> - - </main> </div> -<UpdateAvailableDetector/> \ No newline at end of file +<UpdateAvailableDetector/> diff --git a/MatrixUtils.Web/Shared/MainLayout.razor.css b/MatrixUtils.Web/Shared/MainLayout.razor.css
index 01a5066..924393b 100644 --- a/MatrixUtils.Web/Shared/MainLayout.razor.css +++ b/MatrixUtils.Web/Shared/MainLayout.razor.css
@@ -57,6 +57,7 @@ main { .sidebar { width: 250px; + min-width: 250px; height: 100vh; position: sticky; top: 0; diff --git a/MatrixUtils.Web/Shared/MxcAvatar.razor b/MatrixUtils.Web/Shared/MxcAvatar.razor new file mode 100644
index 0000000..822894a --- /dev/null +++ b/MatrixUtils.Web/Shared/MxcAvatar.razor
@@ -0,0 +1,49 @@ +<MxcImage Homeserver="@Homeserver" Uri="@MxcUri" style="@StyleString"/> + +@code { + private string _style; + + [Parameter] + public string? MxcUri { + get; + set { + if(field == value) return; + field = value; + // UriHasChanged(value); + StateHasChanged(); + } + } + + [Parameter] + public bool Circular { get; set; } + + [Parameter] + public int Size { get; set; } = 48; + + [Parameter] + public string SizeUnit { get; set; } = "px"; + + [Parameter] + public required AuthenticatedHomeserverGeneric Homeserver { get; set; } + + private string StyleString => $"{(Circular ? "border-radius: 50%;" : "")} width: {Size}{SizeUnit}; height: {Size}{SizeUnit}; object-fit: cover;"; + + private static readonly string Prefix = "mxc://"; + private static readonly int PrefixLength = Prefix.Length; + + // private async Task UriHasChanged(string? value) { + // if (string.IsNullOrWhiteSpace(value) || !value.StartsWith(Prefix)) { + // Console.WriteLine($"[MxcAvatar] UriHasChanged: {value} does not start with {Prefix}!"); + // return; + // } + // + // if (Homeserver is null) { + // Console.WriteLine($"[MxcAvatar] Homeserver is required for MxcAvatar! URI: {MxcUri}, Homeserver: {Homeserver?.ToString() ?? "null"}"); + // return; + // } + // + // Console.WriteLine($"[MxcAvatar] Homeserver: {Homeserver}"); + // StateHasChanged(); + // } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Shared/MxcImage.razor b/MatrixUtils.Web/Shared/MxcImage.razor
index e651c3f..26609ee 100644 --- a/MatrixUtils.Web/Shared/MxcImage.razor +++ b/MatrixUtils.Web/Shared/MxcImage.razor
@@ -1,69 +1,69 @@ -<img src="@ResolvedUri" style="@StyleString"/> -@code { - private string _mxcUri; - private string _style; - private string _resolvedUri; +<AuthorizedImage src="@ResolvedUrl" AccessToken="@Homeserver?.AccessToken" style="@StyleString"/> +@code { [Parameter] - public string MxcUri { - get => _mxcUri ?? ""; + public string? Uri { + get; set { - Console.WriteLine($"New MXC uri: {value}"); - _mxcUri = value; + // Console.WriteLine($"New MXC uri: {value}"); + if (field == value) return; + field = value; UriHasChanged(value); } } + [Parameter] public bool Circular { get; set; } - + [Parameter] public int? Width { get; set; } - + [Parameter] public int? Height { get; set; } - + [Parameter] - public string Style { - get => _style; + public string? Style { + get; set { - _style = value; + field = value; StateHasChanged(); } } - + [Parameter] - public RemoteHomeserver? Homeserver { get; set; } + public required AuthenticatedHomeserverGeneric Homeserver { get; set; } - private string ResolvedUri { - get => _resolvedUri; + private string? ResolvedUrl { + get; set { - _resolvedUri = value; + field = value; StateHasChanged(); } } private string StyleString => $"{Style} {(Circular ? "border-radius: 50%;" : "")} {(Width.HasValue ? $"width: {Width}px;" : "")} {(Height.HasValue ? $"height: {Height}px;" : "")} object-fit: cover;"; - - private static readonly string Prefix = "mxc://"; - private static readonly int PrefixLength = Prefix.Length; - private async Task UriHasChanged(string value) { - if (!value.StartsWith(Prefix)) { - Console.WriteLine($"UriHasChanged: {value} does not start with {Prefix}, passing as resolved URI!!!"); - ResolvedUri = value; - return; - } - var uri = value[PrefixLength..].Split('/'); - Console.WriteLine($"UriHasChanged: {value} {uri[0]}"); - if (Homeserver is null) { - Console.WriteLine($"Homeserver is null, creating new remotehomeserver for {uri[0]}"); - Homeserver = await hsProvider.GetRemoteHomeserver(uri[0]); + // private static readonly string Prefix = "mxc://"; + // private static readonly int PrefixLength = Prefix.Length; + + private async Task UriHasChanged(string? value) { + try { + if (string.IsNullOrWhiteSpace(value)) { + ResolvedUrl = null; + return; + } + + if (Homeserver is null) { + Console.WriteLine($"Homeserver is required for MxcImage! Uri: {value}, Homeserver: {Homeserver?.ToString() ?? "null"}"); + return; + } + + ResolvedUrl = await Homeserver.GetMediaUrlAsync(value); + // Console.WriteLine($"[MxcImage] Resolved URL: {ResolvedUrl}"); + StateHasChanged(); + } catch (Exception e) { + await Console.Error.WriteLineAsync($"Error resolving media URL: {e}"); } - ResolvedUri = Homeserver.ResolveMediaUri(value); - Console.WriteLine($"ResolvedUri: {ResolvedUri}"); } - // [Parameter] - // public string Class { get; set; } - } \ No newline at end of file diff --git a/MatrixUtils.Web/Shared/NavMenu.razor b/MatrixUtils.Web/Shared/NavMenu.razor
index 770a246..7371e66 100644 --- a/MatrixUtils.Web/Shared/NavMenu.razor +++ b/MatrixUtils.Web/Shared/NavMenu.razor
@@ -37,6 +37,12 @@ </div> <div class="nav-item px-3"> + <NavLink class="nav-link" href="PolicyLists"> + <span class="oi oi-ban" aria-hidden="true"></span> Manage policy lists + </NavLink> + </div> + + <div class="nav-item px-3"> <NavLink class="nav-link" href="User/Profile"> <span class="oi oi-person" aria-hidden="true"></span> Manage profile </NavLink> diff --git a/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor b/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor new file mode 100644
index 0000000..11ba18a --- /dev/null +++ b/MatrixUtils.Web/Shared/PolicyEditorComponents/MassPolicyEditorModal.razor
@@ -0,0 +1,102 @@ +@using LibMatrix.EventTypes.Spec.State.Policy +@using System.Reflection +@using ArcaneLibs.Attributes +@using LibMatrix +@using System.Collections.Frozen +@using LibMatrix.EventTypes +@using LibMatrix.RoomTypes +<ModalWindow Title="@("Creating many new " + (PolicyTypes.ContainsKey(MappedType??"") ? PolicyTypes[MappedType!].GetFriendlyNamePluralOrNull()?.ToLower() ?? PolicyTypes[MappedType!].Name : "event"))" + OnCloseClicked="@OnClose" X="60" Y="60" MinWidth="600"> + <span>Policy type:</span> + <select @bind="@MappedType"> + <option>Select a value</option> + @foreach (var (type, mappedType) in PolicyTypes) { + <option value="@type">@mappedType.GetFriendlyName().ToLower()</option> + } + </select><br/> + + <span>Reason:</span> + <FancyTextBox @bind-Value="@Reason"></FancyTextBox><br/> + + <span>Recommendation:</span> + <FancyTextBox @bind-Value="@Recommendation"></FancyTextBox><br/> + + <span>Entities:</span><br/> + <InputTextArea @bind-Value="@Users" style="width: 500px;"></InputTextArea><br/> + + + @* <details> *@ + @* <summary>JSON data</summary> *@ + @* <pre> *@ + @* $1$ @PolicyEvent.ToJson(true, true) #1# *@ + @* </pre> *@ + @* </details> *@ + <LinkButton OnClick="@(() => { OnClose.Invoke(); return Task.CompletedTask; })"> Cancel </LinkButton> + <LinkButton OnClick="@(() => { _ = Save(); return Task.CompletedTask; })"> Save </LinkButton> + +</ModalWindow> + +@code { + + [Parameter] + public required Action OnClose { get; set; } + + [Parameter] + public required Action OnSaved { get; set; } + + [Parameter] + public required GenericRoom Room { get; set; } + + public string Recommendation { get; set; } = "m.ban"; + public string Reason { get; set; } = "spam"; + public string Users { get; set; } = ""; + + private static FrozenSet<Type> KnownPolicyTypes = StateEvent.KnownStateEventTypes.Where(x => x.IsAssignableTo(typeof(PolicyRuleEventContent))).ToFrozenSet(); + + private static Dictionary<string, Type> PolicyTypes = KnownPolicyTypes + .ToDictionary(x => x.GetCustomAttributes<MatrixEventAttribute>().First(y => !string.IsNullOrWhiteSpace(y.EventName)).EventName, x => x); + + private string? MappedType { get; set; } + + private async Task Save() { + try { + await DoActualSave(); + } + catch (Exception e) { + Console.WriteLine($"Failed to save: {e}"); + } + } + + private async Task DoActualSave() { + Console.WriteLine($"Saving ---"); + Console.WriteLine($"Users = {Users}"); + var users = Users.Split("\n").Select(x => x.Trim()).Where(x => x.StartsWith('@')).ToList(); + var tasks = users.Select(x => ExecuteBan(Room, x)).ToList(); + await Task.WhenAll(tasks); + + OnSaved.Invoke(); + } + + private async Task ExecuteBan(GenericRoom room, string entity) { + bool success = false; + while (!success) { + try { + var content = Activator.CreateInstance(PolicyTypes[MappedType!]) as PolicyRuleEventContent; + content.Recommendation = Recommendation; + content.Reason = Reason; + content.Entity = entity; + await room.SendStateEventAsync(MappedType!, content.GetDraupnir2StateKey(), content); + success = true; + } + catch (MatrixException e) { + if (e is not { ErrorCode: MatrixException.ErrorCodes.M_FORBIDDEN }) throw; + Console.WriteLine(e); + } + catch (Exception e) { + //ignored + Console.WriteLine(e); + } + } + } + +} \ No newline at end of file diff --git a/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor b/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor
index 1bd00d1..5819bee 100644 --- a/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor +++ b/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor
@@ -35,39 +35,61 @@ </thead> <tbody> @foreach (var prop in props) { + var isNullable = Nullable.GetUnderlyingType(prop.PropertyType) is not null; <tr> <td style="padding-right: 8px;"> <span>@prop.GetFriendlyName()</span> - @if (Nullable.GetUnderlyingType(prop.PropertyType) is not null) { + @if (Nullable.GetUnderlyingType(prop.PropertyType) is null) { <span style="color: red;">*</span> } </td> @{ var getter = prop.GetGetMethod(); var setter = prop.GetSetMethod(); - } - @switch (Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType) { - case Type t when t == typeof(string): - <FancyTextBox Value="@(getter?.Invoke(PolicyData, null) as string)" ValueChanged="@(e => { Console.WriteLine($"{prop.Name} ({setter is not null}) -> {e}"); setter?.Invoke(PolicyData, [e]); PolicyEvent.TypedContent = PolicyData; StateHasChanged(); })"></FancyTextBox> - break; - default: - <p style="color: red;">Unsupported type: @prop.PropertyType</p> - break; + if (getter is null) { + <p style="color: red;">Missing property getter: @prop.Name</p> + } + else { + switch (Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType) { + case Type t when t == typeof(string): + <FancyTextBox Value="@(getter?.Invoke(PolicyData, null) as string)" ValueChanged="@((string e) => { Console.WriteLine($"{prop.Name} ({setter is not null}) -> {e}"); setter?.Invoke(PolicyData, [e]); PolicyEvent.TypedContent = PolicyData; StateHasChanged(); })"></FancyTextBox> + break; + case Type t when t == typeof(DateTime): + if (!isNullable) { + @* <InputDate TValue="DateTime" Value="@(getter?.Invoke(PolicyData, null) as DateTime? ?? new DateTime())" ValueChanged="@(e => { Console.WriteLine($"{prop.Name} ({setter is not null}) -> {e}"); setter?.Invoke(PolicyData, [e]); PolicyEvent.TypedContent = PolicyData; StateHasChanged(); })"></InputDate> *@ + } + else { + var value = getter?.Invoke(PolicyData, null) as DateTime?; + if (value is null) { + <button @onclick="() => { setter?.Invoke(PolicyData, [DateTime.Now]); PolicyEvent.TypedContent = PolicyData; StateHasChanged(); }">Add value</button> + } + else { + var notNullValue = Nullable.GetValueRefOrDefaultRef(ref value); + Console.WriteLine($"Value: {value?.ToString() ?? "null"}"); + <InputDate TValue="DateTime" ValueExpression="@(() => notNullValue)" ValueChanged="@(e => { Console.WriteLine($"{prop.Name} ({setter is not null}) -> {e}"); setter?.Invoke(PolicyData, [e]); PolicyEvent.TypedContent = PolicyData; StateHasChanged(); })"></InputDate> + <button @onclick="() => { setter?.Invoke(PolicyData, [null]); PolicyEvent.TypedContent = PolicyData; StateHasChanged(); }">Remove value</button> + } + } + + break; + default: + <p style="color: red;">Unsupported type: @prop.PropertyType</p> + break; + } + } } </tr> } </tbody> </table> - <br/> - <pre> - @PolicyEvent.ToJson(true, false) - </pre> + <details> + <summary>JSON data</summary> + <pre> + @PolicyEvent.ToJson(true, true) + </pre> + </details> <LinkButton OnClick="@(() => { OnClose.Invoke(); return Task.CompletedTask; })"> Cancel </LinkButton> <LinkButton OnClick="@(() => { OnSave.Invoke(PolicyEvent); return Task.CompletedTask; })"> Save </LinkButton> - @* <span>Target entity: </span> *@ - @* <FancyTextBox @bind-Value="@policyData.Entity"></FancyTextBox><br/> *@ - @* <span>Reason: </span> *@ - @* <FancyTextBox @bind-Value="@policyData.Reason"></FancyTextBox> *@ } else { <p>Policy data is null</p> @@ -102,7 +124,7 @@ .ToDictionary(x => x.GetCustomAttributes<MatrixEventAttribute>().First(y => !string.IsNullOrWhiteSpace(y.EventName)).EventName, x => x); private StateEventResponse? _policyEvent; - + private string? MappedType { get => _policyEvent?.Type; set { @@ -110,9 +132,9 @@ PolicyEvent.Type = value; PolicyEvent.TypedContent ??= Activator.CreateInstance(PolicyTypes[value]) as PolicyRuleEventContent; PolicyData = PolicyEvent.TypedContent as PolicyRuleEventContent; + PolicyData.Recommendation ??= "m.ban"; } } } - } \ No newline at end of file diff --git a/MatrixUtils.Web/Shared/RoomList.razor b/MatrixUtils.Web/Shared/RoomList.razor
index 42c5a9f..ba9cd69 100644 --- a/MatrixUtils.Web/Shared/RoomList.razor +++ b/MatrixUtils.Web/Shared/RoomList.razor
@@ -10,7 +10,7 @@ } else { @foreach (var category in RoomsWithTypes.OrderBy(x => x.Value.Count)) { - <RoomListCategory Category="@category" GlobalProfile="@GlobalProfile"></RoomListCategory> + <RoomListCategory Category="@category" GlobalProfile="@GlobalProfile" Homeserver="@Homeserver"></RoomListCategory> } } @@ -35,6 +35,9 @@ else { } [Parameter] + public AuthenticatedHomeserverGeneric? Homeserver { get; set; } + + [Parameter] public UserProfileResponse? GlobalProfile { get; set; } [Parameter] diff --git a/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor b/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
index 1f5ce89..1ab0a1a 100644 --- a/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor +++ b/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
@@ -1,12 +1,12 @@ +@using LibMatrix.EventTypes.Spec.State.RoomInfo @using MatrixUtils.Web.Classes.Constants -@using LibMatrix.EventTypes.Spec.State @using LibMatrix.Responses @using MatrixUtils.Abstractions <details open> <summary>@RoomType (@Rooms.Count)</summary> @foreach (var room in Rooms) { <div class="room-list-item"> - <RoomListItem RoomInfo="@room" ShowOwnProfile="@(RoomType == "Room")"></RoomListItem> + <RoomListItem RoomInfo="@room" ShowOwnProfile="@(RoomType == "Room")" Homeserver="@Homeserver"/> @* @if (RoomVersionDangerLevel(room) != 0 && *@ @* (room.StateEvents.FirstOrDefault(x=>x.Type == "m.room.power_levels")?.TypedContent is RoomPowerLevelEventContent powerLevels && powerLevels.UserHasPermission(Homeserver.UserId, "m.room.tombstone"))) { *@ @* <MatrixUtils.Web.Shared.SimpleComponents.LinkButton Color="@(RoomVersionDangerLevel(room) == 2 ? "#ff0000" : "#ff8800")" href="@($"/Rooms/Create?Import={room.Room.RoomId}")">Upgrade room</MatrixUtils.Web.Shared.SimpleComponents.LinkButton> *@ @@ -14,10 +14,11 @@ <LinkButton href="@($"/Rooms/{room.Room.RoomId}/Timeline")">View timeline</LinkButton> <LinkButton href="@($"/Rooms/{room.Room.RoomId}/State/View")">View state</LinkButton> <LinkButton href="@($"/Rooms/{room.Room.RoomId}/State/Edit")">Edit state</LinkButton> + <LinkButton href="@($"/Rooms/{room.Room.RoomId}/Upgrade")" Color="#888800">Upgrade/replace room</LinkButton> <LinkButton href="@($"/Tools/LeaveRoom?roomId={room.Room.RoomId}")" Color="#FF0000">Leave room</LinkButton> @if (room.CreationEventContent?.Type == "m.space") { - <RoomListSpace Space="@room"></RoomListSpace> + <RoomListSpace Space="@room" Homeserver="@Homeserver"/> } else if (room.CreationEventContent?.Type == "support.feline.policy.lists.msc.v1" || RoomType == "org.matrix.mjolnir.policy") { <LinkButton href="@($"/Rooms/{room.Room.RoomId}/Policies")">Manage policies</LinkButton> @@ -35,9 +36,9 @@ [Parameter] public UserProfileResponse? GlobalProfile { get; set; } - [CascadingParameter] - public AuthenticatedHomeserverGeneric Homeserver { get; set; } = null!; - + [Parameter] + public AuthenticatedHomeserverGeneric? Homeserver { get; set; } + private string RoomType => Category.Key; private List<RoomInfo> Rooms => Category.Value; diff --git a/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor b/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor
index 6954990..27f0499 100644 --- a/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor +++ b/MatrixUtils.Web/Shared/RoomListComponents/RoomListSpace.razor
@@ -35,15 +35,18 @@ set => _breadcrumbs = value; } + [Parameter] + public required AuthenticatedHomeserverGeneric Homeserver { get; set; } + private ObservableCollection<RoomInfo> Children { get; set; } = new(); private Collection<RoomInfo> Unjoined { get; set; } = new(); protected override async Task OnInitializedAsync() { if (Breadcrumbs == null) throw new ArgumentNullException(nameof(Breadcrumbs)); + if (Homeserver is null) throw new ArgumentNullException(nameof(Homeserver)); await Task.Delay(Random.Shared.Next(1000, 10000)); var rooms = Space.Room.AsSpace.GetChildrenAsync(); - var hs = await RMUStorage.GetCurrentSessionOrNavigate(); - var joinedRooms = await hs.GetJoinedRooms(); + var joinedRooms = await Homeserver.GetJoinedRooms(); await foreach (var room in rooms) { if (Breadcrumbs.Contains(room.RoomId)) continue; var roomInfo = KnownRooms.FirstOrDefault(x => x.Room.RoomId == room.RoomId); @@ -51,10 +54,12 @@ roomInfo = new RoomInfo(room); KnownRooms.Add(roomInfo); } - if(joinedRooms.Any(x=>x.RoomId == room.RoomId)) + + if (joinedRooms.Any(x => x.RoomId == room.RoomId)) Children.Add(roomInfo); else Unjoined.Add(roomInfo); } + await base.OnInitializedAsync(); } diff --git a/MatrixUtils.Web/Shared/RoomListItem.razor b/MatrixUtils.Web/Shared/RoomListItem.razor
index bfaa900..2d85f64 100644 --- a/MatrixUtils.Web/Shared/RoomListItem.razor +++ b/MatrixUtils.Web/Shared/RoomListItem.razor
@@ -1,19 +1,26 @@ +@using ArcaneLibs @using LibMatrix -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses @using MatrixUtils.Abstractions @using MatrixUtils.Web.Classes.Constants @if (RoomInfo is not null) { <div class="roomListItem @(HasDangerousRoomVersion ? "dangerousRoomVersion" : HasOldRoomVersion ? "oldRoomVersion" : "")" id="@RoomInfo.Room.RoomId"> @if (OwnMemberState != null) { - @* Class="@("avatar32" + (OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? " highlightChange" : "") + (ChildContent is not null ? " vcenter" : ""))" *@ - <MxcImage Homeserver="hs" Circular="true" Height="32" Width="32" MxcUri="@(OwnMemberState.AvatarUrl ?? GlobalProfile.AvatarUrl)"/> + <MxcAvatar Homeserver="@Homeserver" Circular="true" Size="32" MxcUri="@(OwnMemberState.AvatarUrl ?? GlobalProfile.AvatarUrl)"/> <span class="centerVertical border75 @(OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? "highlightChange" : "")"> @(OwnMemberState?.DisplayName ?? GlobalProfile?.DisplayName ?? "Loading...") </span> <span class="centerVertical noLeftPadding">-></span> } - <MxcImage Circular="true" Height="32" Width="32" MxcUri="@RoomInfo.RoomIcon" Style="@(ChildContent is not null ? "vertical-align: middle;" : "")"/> + @* <MxcImage Circular="true" Height="32" Width="32" MxcUri="@RoomInfo.RoomIcon" Style="@(ChildContent is not null ? "vertical-align: middle;" : "")"/> *@ + + @if (!string.IsNullOrWhiteSpace(RoomInfo.RoomIcon)) { + <MxcAvatar Homeserver="@Homeserver" Circular="true" Size="32" MxcUri="@RoomInfo.RoomIcon"/> + } + else { + <img src="@Identicon" width="32" height="32" style="border-radius: 50%;"/> + } <div class="inlineBlock"> <span class="centerVertical">@RoomInfo.RoomName</span> @if (ChildContent is not null) { @@ -42,8 +49,6 @@ else { } } - - [Parameter] public bool ShowOwnProfile { get; set; } = false; @@ -61,27 +66,36 @@ else { OnParametersSetAsync(); } } + + [Parameter] + public AuthenticatedHomeserverGeneric? Homeserver { get; set; } private bool HasOldRoomVersion { get; set; } = false; private bool HasDangerousRoomVersion { get; set; } = false; + private string Identicon { get; set; } + + private static SvgIdenticonGenerator _identiconGenerator = new SvgIdenticonGenerator(); + private static SemaphoreSlim _semaphoreSlim = new(8); private RoomInfo? _roomInfo; private bool _loadData = false; - private static AuthenticatedHomeserverGeneric? hs { get; set; } private bool _hooked; - + private async Task RoomInfoChanged() { + if (RoomInfo is null) return; + Identicon = _identiconGenerator.GenerateAsDataUri(RoomInfo.Room.RoomId); + RoomInfo.PropertyChanged += async (_, a) => { if (a.PropertyName == nameof(RoomInfo.CreationEventContent)) { await CheckRoomVersion(); } - + StateHasChanged(); }; } - + // protected override async Task OnParametersSetAsync() { // if (RoomInfo != null) { // if (!_hooked) { @@ -127,21 +141,24 @@ else { protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - hs ??= await RMUStorage.GetCurrentSessionOrNavigate(); - if (hs is null) return; + // hs ??= await sessionStore.GetCurrentHomeserver(navigateOnFailure: true); + // if (hs is null) return; + if (Homeserver is null) { + Console.WriteLine($"RoomListItem called without homeserver"); + } await CheckRoomVersion(); } private async Task LoadOwnProfile() { if (!ShowOwnProfile) return; try { - // OwnMemberState ??= (await RoomInfo.GetStateEvent("m.room.member", hs.UserId)).TypedContent as RoomMemberEventContent; - GlobalProfile ??= await hs.GetProfileAsync(hs.UserId); + // OwnMemberState ??= (await RoomInfo.GetStateEvent("m.room.member", hs.UserId)).TypedContent as RoomMemberEventContent; + GlobalProfile ??= await Homeserver.GetProfileAsync(Homeserver.UserId); } catch (MatrixException e) { if (e is { ErrorCode: "M_FORBIDDEN" }) { - Console.WriteLine($"Failed to get profile for {hs.UserId}: {e.Message}"); + Console.WriteLine($"Failed to get profile for {Homeserver.UserId}: {e.Message}"); ShowOwnProfile = false; } else { @@ -151,8 +168,8 @@ else { } private async Task CheckRoomVersion() { - if (RoomInfo?.CreationEventContent is null) return; - + if (RoomInfo?.CreationEventContent is null) return; + var ce = RoomInfo.CreationEventContent; if (int.TryParse(ce.RoomVersion, out var rv)) { if (rv < 10) @@ -163,7 +180,7 @@ else { if (RoomConstants.DangerousRoomVersions.Contains(ce.RoomVersion)) { HasDangerousRoomVersion = true; - // RoomName = "Dangerous room: " + RoomName; + // RoomName = "Dangerous room: " + RoomName; } } diff --git a/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor
index 08aeffe..f107eb3 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor
@@ -1,5 +1,5 @@ @using LibMatrix -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses <h3>BaseTimelineItem</h3> diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor
index 0488e36..d1984dd 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor
@@ -1,5 +1,5 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem @if (currentEventContent is not null) { diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor
index bdd6104..5d09603 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor
@@ -1,5 +1,5 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem @if (currentEventContent is not null) { diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
index 3b18b95..e5a5650 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor
@@ -1,5 +1,5 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @using LibMatrix.Responses @inherits BaseTimelineItem diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
index 81956b0..98b5a6d 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor
@@ -15,7 +15,7 @@ } case "m.image": { <i>@currentEventContent.Body</i><br/> - <img src="@Homeserver.ResolveMediaUri(currentEventContent.Url)"> + @* <img src="@Homeserver.ResolveMediaUri(currentEventContent.Url)"> *@ break; } default: { diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor
index f3e6c7e..aeb987a 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor
@@ -1,5 +1,5 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem <i> diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor
index 63594a9..c342c83 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor
@@ -1,5 +1,5 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem @if (currentEventContent is not null) { diff --git a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor
index f70d563..467c644 100644 --- a/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor +++ b/MatrixUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor
@@ -1,5 +1,5 @@ @using ArcaneLibs.Extensions -@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.EventTypes.Spec.State.RoomInfo @inherits BaseTimelineItem @if (currentEventContent is not null) { diff --git a/MatrixUtils.Web/Shared/UserListItem.razor b/MatrixUtils.Web/Shared/UserListItem.razor
index d4652b2..5084807 100644 --- a/MatrixUtils.Web/Shared/UserListItem.razor +++ b/MatrixUtils.Web/Shared/UserListItem.razor
@@ -23,13 +23,14 @@ [Parameter] public string UserId { get; set; } - private AuthenticatedHomeserverGeneric _homeserver = null!; + [Parameter] + public AuthenticatedHomeserverGeneric _homeserver { get; set; } private SvgIdenticonGenerator _identiconGenerator = new(); protected override async Task OnInitializedAsync() { - _homeserver = await RMUStorage.GetCurrentSessionOrNavigate(); - if (_homeserver is null) return; + // _homeserver = await sessionStore.GetCurrentHomeserver(navigateOnFailure: true); + // if (_homeserver is null) return; if (User == null) { if (UserId == null) {