diff --git a/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor b/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor
index 4fd151d..1bd00d1 100644
--- a/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor
+++ b/MatrixUtils.Web/Shared/PolicyEditorComponents/PolicyEditorModal.razor
@@ -7,12 +7,9 @@
@using LibMatrix.EventTypes
<ModalWindow Title="@((string.IsNullOrWhiteSpace(PolicyEvent.EventId) ? "Creating new " : "Editing ") + (PolicyEvent.MappedType.GetFriendlyNameOrNull()?.ToLower() ?? "event"))"
OnCloseClicked="@OnClose" X="60" Y="60" MinWidth="300">
- @{
- var policyData = (PolicyEvent.TypedContent as PolicyRuleEventContent)!;
- }
@if (string.IsNullOrWhiteSpace(PolicyEvent.EventId)) {
<span>Policy type:</span>
- <select @bind="@PolicyEvent.Type">
+ <select @bind="@MappedType">
<option>Select a value</option>
@foreach (var (type, mappedType) in PolicyTypes) {
<option value="@type">@mappedType.GetFriendlyName().ToLower()</option>
@@ -20,7 +17,6 @@
</select>
}
-
@{
// enumerate all properties with friendly name
var props = PolicyEvent.MappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
@@ -29,64 +25,94 @@
.ToFrozenSet();
var propNames = props.Select(x => x.GetFriendlyNameOrNull() ?? x.GetJsonPropertyName()!).ToFrozenSet();
}
- <table>
- <thead style="border-bottom: solid #ffffff44 1px;">
- <tr>
- <th>Property</th>
- <th>Value</th>
- </tr>
- </thead>
- <tbody>
- @foreach (var prop in props) {
+ @if (PolicyData is not null) {
+ <table>
+ <thead style="border-bottom: solid #ffffff44 1px;">
<tr>
- <td style="padding-right: 8px;">
- <span>@prop.GetFriendlyName()</span>
- @if (Nullable.GetUnderlyingType(prop.PropertyType) is not 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]); StateHasChanged(); })"></FancyTextBox>
- break;
- default:
- <p style="color: red;">Unsupported type: @prop.PropertyType</p>
- break;
- }
+ <th>Property</th>
+ <th>Value</th>
</tr>
- }
- </tbody>
- </table>
- <br/>
- <pre>
- @PolicyEvent.ToJson(true, false)
- </pre>
- <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> *@
+ </thead>
+ <tbody>
+ @foreach (var prop in props) {
+ <tr>
+ <td style="padding-right: 8px;">
+ <span>@prop.GetFriendlyName()</span>
+ @if (Nullable.GetUnderlyingType(prop.PropertyType) is not 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;
+ }
+ </tr>
+ }
+ </tbody>
+ </table>
+ <br/>
+ <pre>
+ @PolicyEvent.ToJson(true, false)
+ </pre>
+ <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>
+ }
</ModalWindow>
@code {
[Parameter]
- public StateEventResponse? PolicyEvent { get; set; }
+ public StateEventResponse? PolicyEvent {
+ get => _policyEvent;
+ set {
+ if (value is not null && value != _policyEvent)
+ PolicyData = (value.TypedContent as PolicyRuleEventContent)!;
+ _policyEvent = value;
+ if (string.IsNullOrWhiteSpace(value.StateKey))
+ value.StateKey = Guid.NewGuid().ToString();
+ }
+ }
[Parameter]
public required Action OnClose { get; set; }
-
+
[Parameter]
public required Action<StateEventResponse> OnSave { get; set; }
+ public PolicyRuleEventContent? PolicyData { 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 StateEventResponse? _policyEvent;
+
+ private string? MappedType {
+ get => _policyEvent?.Type;
+ set {
+ if (value is not null && PolicyTypes.ContainsKey(value)) {
+ PolicyEvent.Type = value;
+ PolicyEvent.TypedContent ??= Activator.CreateInstance(PolicyTypes[value]) as PolicyRuleEventContent;
+ PolicyData = PolicyEvent.TypedContent as PolicyRuleEventContent;
+ }
+ }
+ }
+
+
}
\ No newline at end of file
diff --git a/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor b/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
index 4b24c18..7670ec5 100644
--- a/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
+++ b/MatrixUtils.Web/Shared/RoomListComponents/RoomListCategory.razor
@@ -4,7 +4,7 @@
@using LibMatrix.Homeservers
@using LibMatrix.Responses
@using MatrixUtils.Abstractions
-<details>
+<details open>
<summary>@RoomType (@Rooms.Count)</summary>
@foreach (var room in Rooms) {
<div class="room-list-item">
diff --git a/MatrixUtils.Web/Shared/RoomListItem.razor b/MatrixUtils.Web/Shared/RoomListItem.razor
index 2e7a372..623a03a 100644
--- a/MatrixUtils.Web/Shared/RoomListItem.razor
+++ b/MatrixUtils.Web/Shared/RoomListItem.razor
@@ -10,14 +10,14 @@
@if (RoomInfo is not null) {
<div class="roomListItem @(HasDangerousRoomVersion ? "dangerousRoomVersion" : HasOldRoomVersion ? "oldRoomVersion" : "")" id="@RoomInfo.Room.RoomId">
@if (OwnMemberState != null) {
- <MxcImage Class="@("avatar32" + (OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? " highlightChange" : "") + (ChildContent is not null ? " vcenter" : ""))"
- MxcUri="@(OwnMemberState.AvatarUrl ?? GlobalProfile.AvatarUrl)"/>
+ @* Class="@("avatar32" + (OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? " highlightChange" : "") + (ChildContent is not null ? " vcenter" : ""))" *@
+ <MxcImage Circular="true" Height="32" Width="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 class="avatar32" 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;" : "")"/>
<div class="inlineBlock">
<span class="centerVertical">@RoomInfo.RoomName</span>
@if (ChildContent is not null) {
@@ -40,11 +40,14 @@ else {
public RoomInfo? RoomInfo {
get => _roomInfo;
set {
+ if (RoomInfo != value)
+ RoomInfoChanged();
_roomInfo = value;
- OnParametersSetAsync();
}
}
+
+
[Parameter]
public bool ShowOwnProfile { get; set; } = false;
@@ -72,72 +75,66 @@ else {
private static AuthenticatedHomeserverGeneric? hs { get; set; }
private bool _hooked;
- protected override async Task OnParametersSetAsync() {
- if (RoomInfo != null) {
- if (!_hooked) {
- _hooked = true;
- RoomInfo.PropertyChanged += (_, a) => {
- Console.WriteLine(a.PropertyName);
- StateHasChanged();
- };
- }
-
- if (LoadData) {
- try {
- await RoomInfo.GetStateEvent("m.room.create");
- if (ShowOwnProfile)
- OwnMemberState ??= (await RoomInfo.GetStateEvent("m.room.member", hs.WhoAmI.UserId)).TypedContent as RoomMemberEventContent;
-
- await RoomInfo.GetStateEvent("m.room.name");
- await RoomInfo.GetStateEvent("m.room.avatar");
- }
- catch (MatrixException e) {
- if (e.ErrorCode == "M_FORBIDDEN") {
- LoadData = false;
- RoomInfo.StateEvents.Add(new() {
- Type = "m.room.create",
- TypedContent = new RoomCreateEventContent() { RoomVersion = "0" },
- RoomId = null, Sender = null, EventId = null //TODO: implement
- });
- RoomInfo.StateEvents.Add(new() {
- Type = "m.room.name",
- TypedContent = new RoomNameEventContent() {
- Name = "M_FORBIDDEN: Are you a member of this room? " + RoomInfo.Room.RoomId
- },
- RoomId = null, Sender = null, EventId = null //TODO: implement
- });
- }
- }
+
+ private async Task RoomInfoChanged() {
+ RoomInfo.PropertyChanged += async (_, a) => {
+ if (a.PropertyName == nameof(RoomInfo.CreationEventContent)) {
+ await CheckRoomVersion();
}
- }
-
- await base.OnParametersSetAsync();
+
+ StateHasChanged();
+ };
}
+
+ // protected override async Task OnParametersSetAsync() {
+ // if (RoomInfo != null) {
+ // if (!_hooked) {
+ // _hooked = true;
+ // RoomInfo.PropertyChanged += (_, a) => {
+ // Console.WriteLine(a.PropertyName);
+ // StateHasChanged();
+ // };
+ // }
+ //
+ // if (LoadData) {
+ // try {
+ // await RoomInfo.GetStateEvent("m.room.create");
+ // if (ShowOwnProfile)
+ // OwnMemberState ??= (await RoomInfo.GetStateEvent("m.room.member", hs.WhoAmI.UserId)).TypedContent as RoomMemberEventContent;
+ //
+ // await RoomInfo.GetStateEvent("m.room.name");
+ // await RoomInfo.GetStateEvent("m.room.avatar");
+ // }
+ // catch (MatrixException e) {
+ // if (e.ErrorCode == "M_FORBIDDEN") {
+ // LoadData = false;
+ // RoomInfo.StateEvents.Add(new() {
+ // Type = "m.room.create",
+ // TypedContent = new RoomCreateEventContent() { RoomVersion = "0" },
+ // RoomId = null, Sender = null, EventId = null //TODO: implement
+ // });
+ // RoomInfo.StateEvents.Add(new() {
+ // Type = "m.room.name",
+ // TypedContent = new RoomNameEventContent() {
+ // Name = "M_FORBIDDEN: Are you a member of this room? " + RoomInfo.Room.RoomId
+ // },
+ // RoomId = null, Sender = null, EventId = null //TODO: implement
+ // });
+ // }
+ // }
+ // }
+ // }
+ //
+ // await base.OnParametersSetAsync();
+ // }
protected override async Task OnInitializedAsync() {
await base.OnInitializedAsync();
- await _semaphoreSlim.WaitAsync();
-
hs ??= await RMUStorage.GetCurrentSessionOrNavigate();
if (hs is null) return;
- try {
- await CheckRoomVersion();
- // await GetRoomInfo();
- // await LoadOwnProfile();
- }
- catch (MatrixException e) {
- if (e is not { ErrorCode: "M_FORBIDDEN" }) {
- throw;
- }
- // RoomName = "Error: " + e.Message;
- // RoomIcon = "/blobfox_outage.gif";
- }
- catch (Exception e) {
- Console.WriteLine($"Failed to load room info for {RoomInfo.Room.RoomId}: {e.Message}");
- }
- _semaphoreSlim.Release();
+ await CheckRoomVersion();
}
private async Task LoadOwnProfile() {
@@ -158,10 +155,8 @@ else {
}
private async Task CheckRoomVersion() {
- while (RoomInfo?.CreationEventContent is null) {
- Console.WriteLine($"Room creation event content for {RoomInfo.Room.RoomId} is null...");
- await Task.Delay(Random.Shared.Next(1000, 2500));
- }
+ if (RoomInfo?.CreationEventContent is null) return;
+
var ce = RoomInfo.CreationEventContent;
if (int.TryParse(ce.RoomVersion, out var rv)) {
if (rv < 10)
|