diff --git a/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor b/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor
index 2903ab8..6df56ba 100644
--- a/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor
+++ b/MatrixUtils.Web/Pages/Rooms/PolicyLists.razor
@@ -1,12 +1,24 @@
@page "/PolicyLists"
+@using ArcaneLibs
@using ArcaneLibs.Extensions
@using LibMatrix
@using LibMatrix.EventTypes
@using LibMatrix.EventTypes.Common
@using LibMatrix.EventTypes.Spec.State.Policy
+@using LibMatrix.Helpers
+@using LibMatrix.Responses
@using LibMatrix.RoomTypes
@inject ILogger<Index> logger
-<h3>Policy lists </h3> @* <LinkButton href="/Rooms/Create">Create new policy list</LinkButton> *@
+<h3>
+ <span>Policy lists </span>
+ <LinkButton OnClickAsync="@(() => {
+ ShowPolicyListCreationWindow = true;
+ return Task.CompletedTask;
+ })">
+ <span class="oi oi-plus" aria-hidden="true"> Create</span>
+ </LinkButton>
+</h3>
+
@if (!string.IsNullOrWhiteSpace(Status)) {
<p>@Status</p>
@@ -16,22 +28,17 @@
}
<hr/>
-<table>
+<table class="table table-striped table-hover table-bordered align-middle" aria-busy="@isLoading">
<thead>
<tr>
- <th/>
<th>Room name</th>
<th>Policies</th>
+ <th/>
</tr>
</thead>
<tbody>
@foreach (var room in Rooms.OrderByDescending(x => x.PolicyCounts.Sum(y => y.Value))) {
<tr>
- <td>
- <LinkButton href="@($"/Rooms/{room.Room.RoomId}/Policies")">
- <span class="oi oi-pencil" aria-hidden="true"></span>
- </LinkButton>
- </td>
<td style="padding-right: 24px;">
<span>@room.RoomName</span>
@if (room.IsLegacy) {
@@ -50,11 +57,44 @@
<span>@(room.PolicyCounts.GetValueOrDefault(RoomInfo.PolicyType.Server) ?? 0) server policies</span><br/>
<span>@(room.PolicyCounts.GetValueOrDefault(RoomInfo.PolicyType.Room) ?? 0) room policies</span><br/>
</td>
+ <td>
+ <LinkButton href="@($"/Rooms/{room.Room.RoomId}/Policies")">
+ <span class="oi oi-pencil" aria-hidden="true"> View/edit policies</span>
+ </LinkButton>
+ </td>
</tr>
}
</tbody>
</table>
+@if (ShowPolicyListCreationWindow && Homeserver != null) {
+ <ModalWindow Title="New policy list">
+ @if (!string.IsNullOrWhiteSpace(_roomBuilder.Avatar.Url)) {
+ <MxcAvatar Homeserver="@Homeserver" MxcUri="@_roomBuilder.Avatar.Url" Circular="true" Size="4" SizeUnit="em"/>
+ }
+ else {
+ <img class="avatar" style="height: 4em; width: 4em; border-radius: 50%;" src="@IdenticonGenerator.GenerateAsDataUri(Homeserver.WhoAmI.UserId)"/>
+ }
+ <div style="display: inline-block; vertical-align: middle; padding-left: 1em;">
+ <FancyTextBox @bind-Value="@_roomBuilder.Name.Name"></FancyTextBox>
+ <br/>
+ <span>#</span>
+ <FancyTextBox @bind-Value="@_roomBuilder.AliasLocalPart"></FancyTextBox>
+ <span>:@Homeserver!.ServerName</span>
+ <br/>
+ <FancyTextBox @bind-Value="@_roomBuilder.Avatar.Url"></FancyTextBox>
+ <InputFile OnChange="@RoomIconFilePicked"></InputFile>
+ </div>
+ <br/>
+
+ <span>Bot shortcode: </span>
+ <FancyTextBox @bind-Value="@_shortcodeEvent.Shortcode"></FancyTextBox>
+ <br/>
+ <LinkButton OnClickAsync="@CreatePolicyList">Create</LinkButton>
+
+ </ModalWindow>
+}
+
@code {
private List<RoomInfo> Rooms { get; } = [];
@@ -65,44 +105,39 @@
Homeserver = await sessionStore.GetCurrentHomeserver(navigateOnFailure: true);
if (Homeserver is null) return;
+ isLoading = true;
Status = "Fetching rooms...";
-
- var userEventTypes = EventContent.GetMatchingEventTypes<UserPolicyRuleEventContent>();
- var serverEventTypes = EventContent.GetMatchingEventTypes<ServerPolicyRuleEventContent>();
- var roomEventTypes = EventContent.GetMatchingEventTypes<RoomPolicyRuleEventContent>();
- var knownPolicyTypes = (List<string>) [..userEventTypes, ..serverEventTypes, ..roomEventTypes];
-
- List<GenericRoom> roomsByType = [];
+ List<Task> _tasks = [];
await foreach (var room in Homeserver.GetJoinedRoomsByType("support.feline.policy.lists.msc.v1")) {
- roomsByType.Add(room);
+ // roomsByType.Add(room);
Status2 = $"Found {room.RoomId} (MSC3784)...";
+ _tasks.Add(Task.Run(async () => {
+ Rooms.Add(await RoomInfo.FromRoom(room));
+ StateHasChanged();
+ }));
}
- List<Task<RoomInfo>> tasks = roomsByType.Select(async room => {
- Status2 = $"Fetching room {room.RoomId}...";
- return await RoomInfo.FromRoom(room);
- }).ToList();
+ await Task.WhenAll(_tasks);
- var results = tasks.ToAsyncEnumerable();
- await foreach (var result in results) {
- Rooms.Add(result);
- StateHasChanged();
- }
+ isLoading = false;
+ Status = "";
+ Status2 = "";
+ }
+ private async Task ScanLegacyLists() {
+ isLoading = true;
Status = "Searching for legacy lists...";
-
var rooms = (await Homeserver.GetJoinedRooms())
.Where(x => !Rooms.Any(y => y.Room.RoomId == x.RoomId))
.Select(async room => {
var state = await room.GetFullStateAsListAsync();
var policies = state
- .Where(x => knownPolicyTypes.Contains(x.Type))
+ .Where(x => PolicyRoom.SpecPolicyEventTypes.Contains(x.Type))
.ToList();
if (policies.Count == 0) return null;
Status2 = $"Found legacy list {room.RoomId}...";
return await RoomInfo.FromRoom(room, state, true);
- })
- .ToAsyncEnumerable();
+ }).ToAsyncEnumerable();
await foreach (var room in rooms) {
if (room is not null) {
@@ -110,32 +145,36 @@
StateHasChanged();
}
}
-
+
+ isLoading = false;
Status = "";
Status2 = "";
- await base.OnInitializedAsync();
}
- private string _status;
-
- public string Status {
- get => _status;
+ private string? Status {
+ get;
set {
- _status = value;
+ field = value;
StateHasChanged();
}
}
- private string _status2;
-
- public string Status2 {
- get => _status2;
+ private string? Status2 {
+ get;
set {
- _status2 = value;
+ field = value;
StateHasChanged();
}
}
+ private bool ShowPolicyListCreationWindow {
+ get;
+ set {
+ field = value;
+ StateHasChanged();
+ }
+ } = true;
+
private class RoomInfo {
public GenericRoom Room { get; set; }
public string RoomName { get; set; }
@@ -149,11 +188,6 @@
Server
}
- private static readonly List<string> userEventTypes = EventContent.GetMatchingEventTypes<UserPolicyRuleEventContent>();
- private static readonly List<string> serverEventTypes = EventContent.GetMatchingEventTypes<ServerPolicyRuleEventContent>();
- private static readonly List<string> roomEventTypes = EventContent.GetMatchingEventTypes<RoomPolicyRuleEventContent>();
- private static readonly List<string> allKnownPolicyTypes = [..userEventTypes, ..serverEventTypes, ..roomEventTypes];
-
public static async Task<RoomInfo> FromRoom(GenericRoom room, List<StateEventResponse>? state = null, bool legacy = false) {
state ??= await room.GetFullStateAsListAsync();
return new RoomInfo() {
@@ -165,12 +199,40 @@
?? room.RoomId,
Shortcode = (await room.GetStateOrNullAsync<MjolnirShortcodeEventContent>(MjolnirShortcodeEventContent.EventId))?.Shortcode,
PolicyCounts = new() {
- { PolicyType.User, state.Count(x => userEventTypes.Contains(x.Type)) },
- { PolicyType.Server, state.Count(x => serverEventTypes.Contains(x.Type)) },
- { PolicyType.Room, state.Count(x => roomEventTypes.Contains(x.Type)) }
+ { PolicyType.User, state.Count(x => PolicyRoom.UserPolicyEventTypes.Contains(x.Type)) },
+ { PolicyType.Server, state.Count(x => PolicyRoom.ServerPolicyEventTypes.Contains(x.Type)) },
+ { PolicyType.Room, state.Count(x => PolicyRoom.RoomPolicyEventTypes.Contains(x.Type)) }
}
};
}
}
+ private readonly RoomBuilder _roomBuilder = new() {
+ Type = "support.feline.policy.lists.msc.v1",
+ Name = new() { Name = "New policy list" },
+ AliasLocalPart = "policies"
+ };
+
+ private readonly MjolnirShortcodeEventContent _shortcodeEvent = new() {
+ Shortcode = "policy-list"
+ };
+
+ private bool isLoading = true;
+
+ private static readonly SvgIdenticonGenerator IdenticonGenerator = new();
+
+ private async Task RoomIconFilePicked(InputFileChangeEventArgs obj) {
+ var res = await Homeserver!.UploadFile(obj.File.Name, obj.File.OpenReadStream(), obj.File.ContentType);
+ Console.WriteLine(res);
+ _roomBuilder.Avatar.Url = res;
+ StateHasChanged();
+ }
+
+ private async Task CreatePolicyList() {
+ var room = await _roomBuilder.Create(Homeserver!);
+ Status = $"Created policy list {room.RoomId} ({room.GetNameAsync()})";
+ await room.SendStateEventAsync(MjolnirShortcodeEventContent.EventId, _shortcodeEvent);
+ NavigationManager.NavigateTo($"/Rooms/{room.RoomId}/Policies");
+ }
+
}
\ No newline at end of file
|