diff options
author | Rory& <root@rory.gay> | 2024-01-24 02:31:56 +0100 |
---|---|---|
committer | Rory& <root@rory.gay> | 2024-01-24 17:05:25 +0100 |
commit | 03313562d21d5db9bf6a14ebbeab80e06c883d3a (patch) | |
tree | e000546a2ee8e6a886a7ed9fd01ad674178fb7cb /MatrixUtils.Web/Pages/Rooms/Index.razor | |
parent | Make RMU installable (diff) | |
download | MatrixUtils-03313562d21d5db9bf6a14ebbeab80e06c883d3a.tar.xz |
MRU->RMU, fixes, cleanup
Diffstat (limited to 'MatrixUtils.Web/Pages/Rooms/Index.razor')
-rw-r--r-- | MatrixUtils.Web/Pages/Rooms/Index.razor | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/MatrixUtils.Web/Pages/Rooms/Index.razor b/MatrixUtils.Web/Pages/Rooms/Index.razor new file mode 100644 index 0000000..0ec9487 --- /dev/null +++ b/MatrixUtils.Web/Pages/Rooms/Index.razor @@ -0,0 +1,250 @@ +@page "/Rooms" +@using LibMatrix.Filters +@using LibMatrix.Helpers +@using LibMatrix.Extensions +@using LibMatrix.Responses +@using System.Collections.ObjectModel +@using System.Diagnostics +@using ArcaneLibs.Extensions +@using MatrixUtils.Abstractions +@inject ILogger<Index> logger +<h3>Room list</h3> + +<p>@Status</p> +<p>@Status2</p> + +<LinkButton href="/Rooms/Create">Create new room</LinkButton> + +<RoomList Rooms="Rooms" GlobalProfile="@GlobalProfile" @bind-StillFetching="RenderContents"></RoomList> + +@code { + private ObservableCollection<RoomInfo> Rooms { get; } = new(); + private UserProfileResponse GlobalProfile { get; set; } + + private AuthenticatedHomeserverGeneric? Homeserver { get; set; } + + private static SyncFilter filter = new() { + AccountData = new SyncFilter.EventFilter { + NotTypes = new List<string> { "*" }, + Limit = 1 + }, + Presence = new SyncFilter.EventFilter { + NotTypes = new List<string> { "*" }, + Limit = 1 + }, + Room = new SyncFilter.RoomFilter { + AccountData = new SyncFilter.RoomFilter.StateFilter { + NotTypes = new List<string> { "*" }, + Limit = 1 + }, + Ephemeral = new SyncFilter.RoomFilter.StateFilter { + NotTypes = new List<string> { "*" }, + Limit = 1 + }, + State = new SyncFilter.RoomFilter.StateFilter { + Types = new List<string> { + "m.room.create", + "m.room.name", + "m.room.avatar", + "org.matrix.mjolnir.shortcode", + "m.room.power_levels", + } + }, + Timeline = new SyncFilter.RoomFilter.StateFilter { + NotTypes = new List<string> { "*" }, + Limit = 1 + } + } + }; + + // private static SyncFilter profileUpdateFilter = new() { + // AccountData = new SyncFilter.EventFilter { + // NotTypes = new List<string> { "*" }, + // Limit = 1 + // }, + // Presence = new SyncFilter.EventFilter { + // NotTypes = new List<string> { "*" }, + // Limit = 1 + // }, + // Room = new SyncFilter.RoomFilter { + // AccountData = new SyncFilter.RoomFilter.StateFilter { + // NotTypes = new List<string> { "*" }, + // Limit = 1 + // }, + // Ephemeral = new SyncFilter.RoomFilter.StateFilter { + // NotTypes = new List<string> { "*" }, + // Limit = 1 + // }, + // State = new SyncFilter.RoomFilter.StateFilter { + // Types = new List<string> { + // "m.room.member" + // }, + // Senders = new() + // }, + // Timeline = new SyncFilter.RoomFilter.StateFilter { + // NotTypes = new List<string> { "*" }, + // Limit = 1 + // } + // } + // }; + + private SyncHelper syncHelper; + + // SyncHelper profileSyncHelper; + + protected override async Task OnInitializedAsync() { + Homeserver = await RMUStorage.GetCurrentSessionOrNavigate(); + if (Homeserver is null) return; + var rooms = await Homeserver.GetJoinedRooms(); + // SemaphoreSlim _semaphore = new(160, 160); + + var roomTasks = rooms.Select(async room => { + RoomInfo ri; + // await _semaphore.WaitAsync(); + ri = new() { Room = room }; + await Task.WhenAll((filter.Room?.State?.Types ?? []).Select(x => ri.GetStateEvent(x))); + return ri; + }).ToAsyncEnumerable(); + + await foreach (var room in roomTasks) { + Rooms.Add(room); + StateHasChanged(); + // await Task.Delay(50); + // _semaphore.Release(); + } + + if (rooms.Count >= 150) RenderContents = true; + + GlobalProfile = await Homeserver.GetProfileAsync(Homeserver.WhoAmI.UserId); + syncHelper = new SyncHelper(Homeserver, logger) { + Timeout = 30000, + Filter = filter, + MinimumDelay = TimeSpan.FromMilliseconds(5000) + }; + // profileSyncHelper = new SyncHelper(Homeserver, logger) { + // Timeout = 10000, + // Filter = profileUpdateFilter, + // MinimumDelay = TimeSpan.FromMilliseconds(5000) + // }; + // profileUpdateFilter.Room.State.Senders.Add(Homeserver.WhoAmI.UserId); + + RunSyncLoop(syncHelper); + // RunSyncLoop(profileSyncHelper); + RunQueueProcessor(); + + await base.OnInitializedAsync(); + } + + private async Task RunQueueProcessor() { + var renderTimeSw = Stopwatch.StartNew(); + var isInitialSync = true; + while (true) { + try { + while (queue.Count == 0) { + Console.WriteLine("Queue is empty, waiting..."); + await Task.Delay(isInitialSync ? 100 : 2500); + } + + Console.WriteLine($"Queue no longer empty after {renderTimeSw.Elapsed}!"); + + int maxUpdates = 10; + isInitialSync = false; + while (maxUpdates-- > 0 && queue.TryDequeue(out var queueEntry)) { + var (roomId, roomData) = queueEntry; + Console.WriteLine($"Dequeued room {roomId}"); + RoomInfo room; + + if (Rooms.Any(x => x.Room.RoomId == roomId)) { + room = Rooms.First(x => x.Room.RoomId == roomId); + Console.WriteLine($"QueueWorker: {roomId} already known with {room.StateEvents?.Count ?? 0} state events"); + } + else { + Console.WriteLine($"QueueWorker: encountered new room {roomId}!"); + room = new RoomInfo() { + Room = Homeserver.GetRoom(roomId) + }; + Rooms.Add(room); + } + + if (room.StateEvents is null) { + Console.WriteLine($"QueueWorker: {roomId} does not have state events on record?"); + throw new InvalidDataException("Somehow this is null???"); + } + + if (roomData.State?.Events is { Count: > 0 }) + room.StateEvents.MergeStateEventLists(roomData.State.Events); + else { + Console.WriteLine($"QueueWorker: could not merge state for {room.Room.RoomId} as new data contains no state events!"); + } + } + Console.WriteLine($"QueueWorker: {queue.Count} entries left in queue, {maxUpdates} maxUpdates left, RenderContents: {RenderContents}"); + Status = $"Got {Rooms.Count} rooms so far! {queue.Count} entries in processing queue..."; + + RenderContents |= queue.Count == 0; + await Task.Delay(Rooms.Count); + } + catch (Exception e) { + Console.WriteLine("QueueWorker exception: " + e); + } + } + } + + private bool RenderContents { get; set; } = false; + + private string _status; + + public string Status { + get => _status; + set { + _status = value; + StateHasChanged(); + } + } + + private string _status2; + + public string Status2 { + get => _status2; + set { + _status2 = value; + StateHasChanged(); + } + } + + private Queue<KeyValuePair<string, SyncResponse.RoomsDataStructure.JoinedRoomDataStructure>> queue = new(); + + private async Task RunSyncLoop(SyncHelper syncHelper) { + Status = "Initial syncing..."; + Console.WriteLine("starting sync"); + + var syncs = syncHelper.EnumerateSyncAsync(); + await foreach (var sync in syncs) { + Console.WriteLine("trying sync"); + if (sync is null) continue; + + Status = $"Got sync with {sync.Rooms?.Join?.Count ?? 0} room updates, next batch: {sync.NextBatch}!"; + if (sync?.Rooms?.Join != null) + foreach (var joinedRoom in sync.Rooms.Join) + if ( /*joinedRoom.Value.AccountData?.Events?.Count > 0 ||*/ joinedRoom.Value.State?.Events?.Count > 0) { + joinedRoom.Value.State.Events.RemoveAll(x => x.Type == "m.room.member" && x.StateKey != Homeserver.WhoAmI?.UserId); + // We can't trust servers to give us what we ask for, and this ruins performance + // Thanks, Conduit. + joinedRoom.Value.State.Events.RemoveAll(x => filter.Room?.State?.Types?.Contains(x.Type) == false); + if (filter.Room?.State?.NotSenders?.Any() ?? false) + joinedRoom.Value.State.Events.RemoveAll(x => filter.Room?.State?.NotSenders?.Contains(x.Sender) ?? false); + + queue.Enqueue(joinedRoom); + } + if (sync.Rooms.Leave is {Count: > 0}) + foreach (var leftRoom in sync.Rooms.Leave) + if (Rooms.Any(x => x.Room.RoomId == leftRoom.Key)) + Rooms.Remove(Rooms.First(x => x.Room.RoomId == leftRoom.Key)); + + Status = $"Got {Rooms.Count} rooms so far! {queue.Count} entries in processing queue... " + + $"{sync?.Rooms?.Join?.Count ?? 0} new updates!"; + + Status2 = $"Next batch: {sync.NextBatch}"; + } + } + +} \ No newline at end of file |