From c37bcb0e4a878d4f4c0e47988adb8624131c82cd Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Thu, 9 Nov 2023 07:38:33 +0100 Subject: event types --- ArcaneLibs | 2 +- LibMatrix | 2 +- .../MatrixRoomUtils.LibDMSpace.csproj | 4 +- .../StateEvents/DMRoomInfo.cs | 2 +- .../StateEvents/DMSpaceInfo.cs | 2 +- MatrixRoomUtils.Web/Classes/MRUStorageWrapper.cs | 4 +- MatrixRoomUtils.Web/Classes/RoomInfo.cs | 15 +- MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj | 4 +- MatrixRoomUtils.Web/Pages/Dev/DevUtilities.razor | 7 +- MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor | 22 +- MatrixRoomUtils.Web/Pages/Index.razor | 22 +- MatrixRoomUtils.Web/Pages/LoginPage.razor | 46 ++-- .../ModerationUtilities/UserRoomHistory.razor | 113 ++++++++++ MatrixRoomUtils.Web/Pages/Rooms/Create.razor | 2 +- MatrixRoomUtils.Web/Pages/Rooms/Index.razor | 1 + MatrixRoomUtils.Web/Pages/Rooms/Timeline.razor | 8 +- MatrixRoomUtils.Web/Pages/ServerInfo.razor | 235 +++++++++++++++++++++ .../Pages/Tools/KnownHomeserverList.razor | 124 +++-------- MatrixRoomUtils.Web/Pages/Tools/MediaLocator.razor | 2 +- MatrixRoomUtils.Web/Pages/User/DMManager.razor | 11 +- MatrixRoomUtils.Web/Shared/MxcImage.razor | 43 ++++ MatrixRoomUtils.Web/Shared/RoomListItem.razor | 83 +++++--- .../TimelineComponents/BaseTimelineItem.razor | 19 +- .../TimelineCanonicalAliasItem.razor | 27 +++ .../TimelineHistoryVisibilityItem.razor | 27 +++ .../TimelineComponents/TimelineMemberItem.razor | 8 +- .../TimelineComponents/TimelineMessageItem.razor | 32 ++- .../TimelineRoomCreateItem.razor | 6 +- .../TimelineComponents/TimelineRoomNameItem.razor | 27 +++ .../TimelineComponents/TimelineRoomTopicItem.razor | 37 ++++ .../TimelineComponents/TimelineUnknownItem.razor | 2 +- MatrixRoomUtils.Web/_Imports.razor | 2 +- MatrixRoomUtils.sln.DotSettings.user | 6 + MxApiExtensions | 2 +- 34 files changed, 759 insertions(+), 190 deletions(-) create mode 100644 MatrixRoomUtils.Web/Pages/ModerationUtilities/UserRoomHistory.razor create mode 100644 MatrixRoomUtils.Web/Pages/ServerInfo.razor create mode 100644 MatrixRoomUtils.Web/Shared/MxcImage.razor create mode 100644 MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor create mode 100644 MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor create mode 100644 MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor create mode 100644 MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor diff --git a/ArcaneLibs b/ArcaneLibs index 8f3dce2..f99ce19 160000 --- a/ArcaneLibs +++ b/ArcaneLibs @@ -1 +1 @@ -Subproject commit 8f3dce2beefb1117816c89d8f2a638e76306a9a0 +Subproject commit f99ce19767f85d6d2f05919b91267cc140a792a6 diff --git a/LibMatrix b/LibMatrix index b75135d..aaa3204 160000 --- a/LibMatrix +++ b/LibMatrix @@ -1 +1 @@ -Subproject commit b75135d8cdb702423d693558ffaec3f025264b98 +Subproject commit aaa3204704b677b59b60dd2719080ead5a0c1274 diff --git a/MatrixRoomUtils.LibDMSpace/MatrixRoomUtils.LibDMSpace.csproj b/MatrixRoomUtils.LibDMSpace/MatrixRoomUtils.LibDMSpace.csproj index 70b4ffc..f21b154 100644 --- a/MatrixRoomUtils.LibDMSpace/MatrixRoomUtils.LibDMSpace.csproj +++ b/MatrixRoomUtils.LibDMSpace/MatrixRoomUtils.LibDMSpace.csproj @@ -2,9 +2,11 @@ net7.0 - enable enable + enable + true preview + true diff --git a/MatrixRoomUtils.LibDMSpace/StateEvents/DMRoomInfo.cs b/MatrixRoomUtils.LibDMSpace/StateEvents/DMRoomInfo.cs index b88f06a..de5cb26 100644 --- a/MatrixRoomUtils.LibDMSpace/StateEvents/DMRoomInfo.cs +++ b/MatrixRoomUtils.LibDMSpace/StateEvents/DMRoomInfo.cs @@ -5,7 +5,7 @@ using LibMatrix.Interfaces; namespace MatrixRoomUtils.LibDMSpace.StateEvents; [MatrixEvent(EventName = EventId)] -public class DMRoomInfo : EventContent { +public class DMRoomInfo : TimelineEventContent { public const string EventId = "gay.rory.dm_room_info"; [JsonPropertyName("remote_users")] public List RemoteUsers { get; set; } diff --git a/MatrixRoomUtils.LibDMSpace/StateEvents/DMSpaceInfo.cs b/MatrixRoomUtils.LibDMSpace/StateEvents/DMSpaceInfo.cs index 7824324..80eeef9 100644 --- a/MatrixRoomUtils.LibDMSpace/StateEvents/DMSpaceInfo.cs +++ b/MatrixRoomUtils.LibDMSpace/StateEvents/DMSpaceInfo.cs @@ -5,7 +5,7 @@ using LibMatrix.Interfaces; namespace MatrixRoomUtils.LibDMSpace.StateEvents; [MatrixEvent(EventName = EventId)] -public class DMSpaceInfo : EventContent { +public class DMSpaceInfo : TimelineEventContent { public const string EventId = "gay.rory.dm_space_info"; [JsonPropertyName("is_layered")] diff --git a/MatrixRoomUtils.Web/Classes/MRUStorageWrapper.cs b/MatrixRoomUtils.Web/Classes/MRUStorageWrapper.cs index b6836c8..2c3b9ce 100644 --- a/MatrixRoomUtils.Web/Classes/MRUStorageWrapper.cs +++ b/MatrixRoomUtils.Web/Classes/MRUStorageWrapper.cs @@ -43,11 +43,11 @@ public class MRUStorageWrapper(TieredStorageService storageService, HomeserverPr return null; } - return await homeserverProviderService.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken); + return await homeserverProviderService.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); } public async Task GetSession(UserAuth userAuth) { - return await homeserverProviderService.GetAuthenticatedWithToken(userAuth.Homeserver, userAuth.AccessToken); + return await homeserverProviderService.GetAuthenticatedWithToken(userAuth.Homeserver, userAuth.AccessToken, userAuth.Proxy); } public async Task GetCurrentSessionOrNavigate() { diff --git a/MatrixRoomUtils.Web/Classes/RoomInfo.cs b/MatrixRoomUtils.Web/Classes/RoomInfo.cs index a2fa6f5..37973a0 100644 --- a/MatrixRoomUtils.Web/Classes/RoomInfo.cs +++ b/MatrixRoomUtils.Web/Classes/RoomInfo.cs @@ -25,7 +25,18 @@ public class RoomInfo : NotifyPropertyChanged { @event.RawContent = await Room.GetStateAsync(type, stateKey); } catch (MatrixException e) { - if (e is { ErrorCode: "M_NOT_FOUND" }) @event.RawContent = default!; + if (e is { ErrorCode: "M_NOT_FOUND" }) { + if (type == "m.room.name") + @event = new() { + Type = type, + StateKey = stateKey, + TypedContent = new RoomNameEventContent() { + Name = await Room.GetNameOrFallbackAsync() + } + }; + else + @event.RawContent = default!; + } else throw; } @@ -60,7 +71,7 @@ public class RoomInfo : NotifyPropertyChanged { private string? _roomName; private RoomCreateEventContent? _creationEventContent; private string? _roomCreator; - + public string? DefaultRoomName { get; set; } public RoomInfo() { diff --git a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj index 543f8db..5d5568f 100644 --- a/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj +++ b/MatrixRoomUtils.Web/MatrixRoomUtils.Web.csproj @@ -4,9 +4,11 @@ net7.0 enable enable - true true preview + true + + true diff --git a/MatrixRoomUtils.Web/Pages/Dev/DevUtilities.razor b/MatrixRoomUtils.Web/Pages/Dev/DevUtilities.razor index 4b2dc4f..94c51b2 100644 --- a/MatrixRoomUtils.Web/Pages/Dev/DevUtilities.razor +++ b/MatrixRoomUtils.Web/Pages/Dev/DevUtilities.razor @@ -16,7 +16,7 @@ else { Room List @foreach (var room in Rooms) { - + } @@ -37,10 +37,11 @@ else { @code { public List Rooms { get; set; } = new(); + public AuthenticatedHomeserverGeneric? hs { get; set; } protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); - var hs = await MRUStorage.GetCurrentSessionOrNavigate(); + hs = await MRUStorage.GetCurrentSessionOrNavigate(); if (hs == null) return; Rooms = (await hs.GetJoinedRooms()).Select(x => x.RoomId).ToList(); Console.WriteLine("Fetched joined rooms!"); @@ -76,4 +77,4 @@ else { StateHasChanged(); } -} +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor index 59ce70f..c605e7a 100644 --- a/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor +++ b/MatrixRoomUtils.Web/Pages/HSAdmin/HSAdmin.razor @@ -1,20 +1,34 @@ @page "/HSAdmin" @using LibMatrix.Homeservers +@using ArcaneLibs.Extensions

Homeserver Admininistration


-

Synapse tools

-
-Query rooms +@if (Homeserver is null) { +

Homeserver is null...

+} +else { + @if (Homeserver is AuthenticatedHomeserverSynapse) { +

Synapse tools

+
+ Query rooms + } + else { +

Homeserver type @Homeserver.GetType().Name does not have any administration tools in MRU.

+

Server info:

+
@ServerVersionResponse?.ToJson(ignoreNull: true)
+ } +} @code { public AuthenticatedHomeserverGeneric? Homeserver { get; set; } + public ServerVersionResponse? ServerVersionResponse { get; set; } protected override async Task OnInitializedAsync() { Homeserver = await MRUStorage.GetCurrentSessionOrNavigate(); if (Homeserver is null) return; + ServerVersionResponse = await Homeserver.GetServerVersionAsync(); await base.OnInitializedAsync(); } - } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/Index.razor b/MatrixRoomUtils.Web/Pages/Index.razor index 74dd651..804fde3 100644 --- a/MatrixRoomUtils.Web/Pages/Index.razor +++ b/MatrixRoomUtils.Web/Pages/Index.razor @@ -3,6 +3,7 @@ @using LibMatrix @using LibMatrix.Homeservers @using ArcaneLibs.Extensions +@using MatrixRoomUtils.Web.Pages.Dev Index @@ -28,13 +29,18 @@ Small collection of tools to do not-so-everyday things.

@__auth.UserInfo.RoomCount rooms - @__auth.ServerVersion.Server.Name @__auth.ServerVersion.Server.Version + @__auth.ServerVersion.Server.Name @__auth.ServerVersion.Server.Version @if (_auth.Proxy != null) { (proxied via @_auth.Proxy) } else {

Not proxied

} + @if (DEBUG) { +

T=@__auth.Homeserver.GetType().FullName

+

D=@__auth.Homeserver.WhoAmI.DeviceId

+

U=@__auth.Homeserver.WhoAmI.UserId

+ }

@@ -51,10 +57,17 @@ Small collection of tools to do not-so-everyday things. @code { +#if DEBUG + bool DEBUG = true; +#else + bool DEBUG = false; +#endif + private class AuthInfo { public UserAuth UserAuth { get; set; } public UserInfo UserInfo { get; set; } public ServerVersionResponse ServerVersion { get; set; } + public AuthenticatedHomeserverGeneric Homeserver { get; set; } } // private Dictionary _users = new(); @@ -69,7 +82,7 @@ Small collection of tools to do not-so-everyday things. UserInfo userInfo = new(); AuthenticatedHomeserverGeneric hs; try { - hs = await hsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken); + hs = await hsProvider.GetAuthenticatedWithToken(token.Homeserver, token.AccessToken, token.Proxy); } catch (MatrixException e) { if (e.ErrorCode == "M_UNKNOWN_TOKEN") { @@ -88,7 +101,8 @@ Small collection of tools to do not-so-everyday things. _auth.Add(new() { UserInfo = userInfo, UserAuth = token, - ServerVersion = await hs.GetServerVersionAsync() + ServerVersion = await hs.GetServerVersionAsync(), + Homeserver = hs }); // StateHasChanged(); }); @@ -105,7 +119,7 @@ Small collection of tools to do not-so-everyday things. private async Task RemoveUser(UserAuth auth, bool logout = false) { try { if (logout) { - await (await hsProvider.GetAuthenticatedWithToken(auth.Homeserver, auth.AccessToken)).Logout(); + await (await hsProvider.GetAuthenticatedWithToken(auth.Homeserver, auth.AccessToken, auth.Proxy)).Logout(); } } catch (Exception e) { diff --git a/MatrixRoomUtils.Web/Pages/LoginPage.razor b/MatrixRoomUtils.Web/Pages/LoginPage.razor index 1b466c9..c926a93 100644 --- a/MatrixRoomUtils.Web/Pages/LoginPage.razor +++ b/MatrixRoomUtils.Web/Pages/LoginPage.razor @@ -7,15 +7,15 @@ @@: + --> via - + - +
@@ -34,18 +34,18 @@ @foreach (var record in records) { var r = record; - + - + - + - + - + Remove @@ -59,21 +59,20 @@ @code { - readonly List<(string homeserver, string username, string password, string? proxy)> records = new(); - (string homeserver, string username, string password, string? proxy) newRecordInput = ("", "", "", null); + readonly List records = new(); + private LoginStruct newRecordInput = new(); List? LoggedInSessions { get; set; } = new(); async Task Login() { var loginTasks = records.Select(async record => { - var (homeserver, username, password, proxy) = record; - if (LoggedInSessions.Any(x => x.UserId == $"@{username}:{homeserver}" && x.Proxy == proxy)) return; + if (LoggedInSessions.Any(x => x.UserId == $"@{record.Username}:{record.Homeserver}" && x.Proxy == record.Proxy)) return; try { - var result = new UserAuth(await hsProvider.Login(homeserver, username, password, proxy)) { - Proxy = proxy + var result = new UserAuth(await hsProvider.Login(record.Homeserver, record.Username, record.Password, record.Proxy)) { + Proxy = record.Proxy }; if (result == null) { - Console.WriteLine($"Failed to login to {homeserver} as {username}!"); + Console.WriteLine($"Failed to login to {record.Homeserver} as {record.Username}!"); return; } Console.WriteLine($"Obtained access token for {result.UserId}!"); @@ -82,7 +81,7 @@ LoggedInSessions = await MRUStorage.GetAllTokens(); } catch (Exception e) { - Console.WriteLine($"Failed to login to {homeserver} as {username}!"); + Console.WriteLine($"Failed to login to {record.Homeserver} as {record.Username}!"); Console.WriteLine(e); } StateHasChanged(); @@ -104,14 +103,21 @@ if (parts.Length < 3) continue; string? via = parts.Length > 3 ? parts[3] : null; - records.Add((parts[0], parts[1], parts[2], via)); + records.Add(new() { Homeserver = parts[0], Username = parts[1], Password = parts[2], Proxy = via }); } } private async Task AddRecord() { LoggedInSessions = await MRUStorage.GetAllTokens(); records.Add(newRecordInput); - newRecordInput = ("", "", "", null); + newRecordInput = new(); } -} + private class LoginStruct { + public string? Homeserver { get; set; } = ""; + public string? Username { get; set; } = ""; + public string? Password { get; set; } = ""; + public string? Proxy { get; set; } + } + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/ModerationUtilities/UserRoomHistory.razor b/MatrixRoomUtils.Web/Pages/ModerationUtilities/UserRoomHistory.razor new file mode 100644 index 0000000..02dfe44 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/ModerationUtilities/UserRoomHistory.razor @@ -0,0 +1,113 @@ +@page "/UserRoomHistory/{UserId}" +@using LibMatrix.Homeservers +@using LibMatrix +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.RoomTypes +@using ArcaneLibs.Extensions +

UserRoomHistory

+ +Enter mxid: + + +@if (string.IsNullOrWhiteSpace(UserId)) { +

UserId is null!

+} +else { +

Checked @checkedRooms.Count so far...

+ @if (currentHs is not null) { +

Checking rooms from @currentHs.UserId's perspective

+ } + else if (checkedRooms.Count > 1) { +

Done!

+ } + @foreach (var (state, rooms) in matchingStates) { + @state +
+ @foreach (var roomInfo in rooms) { + + } + } +} + +@code { + private string? _userId; + + [Parameter] + public string? UserId { + get => _userId; + set { + _userId = value; + FindMember(value); + } + } + + private List hss = new(); + private AuthenticatedHomeserverGeneric? currentHs { get; set; } + + protected override async Task OnInitializedAsync() { + var hs = await MRUStorage.GetCurrentSessionOrNavigate(); + if (hs is null) return; + var sessions = await MRUStorage.GetAllTokens(); + foreach (var userAuth in sessions) { + var session = await MRUStorage.GetSession(userAuth); + if (session is not null) { + hss.Add(session); + StateHasChanged(); + } + } + + StateHasChanged(); + Console.WriteLine("Rerendered!"); + await base.OnInitializedAsync(); + if (!string.IsNullOrWhiteSpace(UserId)) FindMember(UserId); + } + + public Dictionary> matchingStates = new(); + public List checkedRooms = new(); + private SemaphoreSlim _semaphoreSlim = new(1, 1); + + public async Task FindMember(string mxid) { + await _semaphoreSlim.WaitAsync(); + if (mxid != UserId) { + _semaphoreSlim.Release(); + return; //abort if changed + } + matchingStates.Clear(); + foreach (var homeserver in hss) { + currentHs = homeserver; + var rooms = await homeserver.GetJoinedRooms(); + rooms.RemoveAll(x => checkedRooms.Contains(x.RoomId)); + checkedRooms.AddRange(rooms.Select(x => x.RoomId)); + var tasks = rooms.Select(x => GetMembershipAsync(x, mxid)).ToAsyncEnumerable(); + await foreach (var (room, state) in tasks) { + if (state is null) continue; + if (!matchingStates.ContainsKey(state.Membership)) + matchingStates.Add(state.Membership, new()); + var roomInfo = new RoomInfo() { + Room = room + }; + matchingStates[state.Membership].Add(roomInfo); + roomInfo.StateEvents.Add(new() { + Type = RoomNameEventContent.EventId, + TypedContent = new RoomNameEventContent() { + Name = await room.GetNameOrFallbackAsync(4) + } + }); + StateHasChanged(); + if (mxid != UserId) { + _semaphoreSlim.Release(); + return; //abort if changed + } + } + StateHasChanged(); + } + currentHs = null; + StateHasChanged(); + _semaphoreSlim.Release(); + } + + public async Task<(GenericRoom roomId, RoomMemberEventContent? content)> GetMembershipAsync(GenericRoom room, string mxid) { + return (room, await room.GetStateOrNullAsync(RoomMemberEventContent.EventId, mxid)); + } + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Create.razor b/MatrixRoomUtils.Web/Pages/Rooms/Create.razor index 5823757..08b21dd 100644 --- a/MatrixRoomUtils.Web/Pages/Rooms/Create.razor +++ b/MatrixRoomUtils.Web/Pages/Rooms/Create.razor @@ -88,7 +88,7 @@ Room icon: - +

diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Index.razor b/MatrixRoomUtils.Web/Pages/Rooms/Index.razor index fd32cb3..60f4f62 100644 --- a/MatrixRoomUtils.Web/Pages/Rooms/Index.razor +++ b/MatrixRoomUtils.Web/Pages/Rooms/Index.razor @@ -156,6 +156,7 @@ Status = $"Got {Rooms.Count} rooms so far! {queue.Count} entries in processing queue..."; } RenderContents |= queue.Count == 0; + if (queue.Count > 10) RenderContents = false; await Task.Delay(RenderContents ? 25 : 25); } else { diff --git a/MatrixRoomUtils.Web/Pages/Rooms/Timeline.razor b/MatrixRoomUtils.Web/Pages/Rooms/Timeline.razor index 1f4a923..01bf555 100644 --- a/MatrixRoomUtils.Web/Pages/Rooms/Timeline.razor +++ b/MatrixRoomUtils.Web/Pages/Rooms/Timeline.razor @@ -47,10 +47,14 @@ private StateEventResponse GetProfileEventBefore(StateEventResponse Event) => Events.TakeWhile(x => x != Event).Last(e => e.Type == "m.room.member" && e.StateKey == Event.Sender); private Type ComponentType(StateEvent Event) => Event.TypedContent switch { - RoomMessageEventContent => typeof(TimelineMessageItem), + RoomCanonicalAliasEventContent => typeof(TimelineCanonicalAliasItem), + RoomHistoryVisibilityEventContent => typeof(TimelineHistoryVisibilityItem), + RoomTopicEventContent => typeof(TimelineRoomTopicItem), RoomMemberEventContent => typeof(TimelineMemberItem), + RoomMessageEventContent => typeof(TimelineMessageItem), RoomCreateEventContent => typeof(TimelineRoomCreateItem), + RoomNameEventContent => typeof(TimelineRoomNameItem), _ => typeof(TimelineUnknownItem) - }; + }; } diff --git a/MatrixRoomUtils.Web/Pages/ServerInfo.razor b/MatrixRoomUtils.Web/Pages/ServerInfo.razor new file mode 100644 index 0000000..5b3f1c1 --- /dev/null +++ b/MatrixRoomUtils.Web/Pages/ServerInfo.razor @@ -0,0 +1,235 @@ +@page "/ServerInfo/{Homeserver}" +@using LibMatrix.Homeservers +@using LibMatrix.Responses +@using ArcaneLibs.Extensions +

ServerInfo

+
+@if (ServerVersionResponse is not null) { +

Server version: @ServerVersionResponse.Server.Name @ServerVersionResponse.Server.Version

+
@ServerVersionResponse?.ToJson(ignoreNull: true)
+
+} +@if (ClientVersionsResponse is not null) { +

Client versions:

+
+ JSON data +
@ClientVersionsResponse?.ToJson(ignoreNull: true)
+
+ Spec versions + + + + + + + @foreach (var (version, info) in ClientVersions) { + + + + + + } + + @foreach (var version in ClientVersionsResponse.Versions) { + if (!ClientVersions.ContainsKey(version)) { + + + + + + } + } +
VersionRelease date
@(ClientVersionsResponse.Versions.Contains(version) ? "\u2714" : "\u274c")@info.Name@info.Released
@("\u2714")Unknown version: @version
+ Unstable features + + + + + + + @* @foreach (var (version, info) in ClientVersions) { *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* *@ + @* } *@ + + @foreach (var version in ClientVersionsResponse.UnstableFeatures) { + if (!ClientVersions.ContainsKey(version.Key)) { + + + + + + } + } +
SupportedEnabledName
@("\u2714")@(ClientVersionsResponse.Versions.Contains(version) ? "\u2714" : "\u274c")@info.Released
@("\u2714")@(version.Value ? "\u2714" : "\u274c")@version.Key
+} + + +@code { + + [Parameter] + public string? Homeserver { get; set; } + + public ServerVersionResponse? ServerVersionResponse { get; set; } + public ClientVersionsResponse? ClientVersionsResponse { get; set; } + + protected override async Task OnParametersSetAsync() { + if (Homeserver is not null) { + var rhs = await hsProvider.GetRemoteHomeserver(Homeserver); + ServerVersionResponse = await rhs.GetServerVersionAsync(); + ClientVersionsResponse = await rhs.GetClientVersionsAsync(); + } + base.OnParametersSetAsync(); + } + + private class ClientVersionInfo { + public string Name { get; set; } + public string SpecUrl { get; set; } + public DateTime Released { get; set; } + } + + private Dictionary ClientVersions = new() { + { + "legacy", + new() { + Name = "Legacy: Last draft before formal release of r0.0.0", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/legacy/" + } + }, + { + "r0.0.0", + new() { + Name = "r0.0.0: Initial release: media repo, sync v2", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.0.0/" + } + }, + { + "r0.0.1", + new() { + Name = "r0.0.1: User-interactive authentication, groups, read receipts, presence", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.0.1/" + } + }, + { + "r0.1.0", + new() { + Name = "r0.1.0: Device management, account data, push rules, VoIP", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.1.0/" + } + }, + { + "r0.2.0", + new() { + Name = "r0.2.0: Clarifications", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/client_server/r0.2.0.html" + } + }, + { + "r0.3.0", + new() { + Name = "r0.3.0: Device management", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/client_server/r0.3.0.html" + } + }, + { + "r0.4.0", + new() { + Name = "r0.4.0: Room directory", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.4.0/" + } + }, + { + "r0.5.0", + new() { + Name = "r0.5.0: Push rules, VoIP, groups, read receipts, presence", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.5.0/" + } + }, + { + "r0.6.0", + new() { + Name = "r0.6.0: Unbinding 3PIDs, clean up bindings from register", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.6.0/" + } + }, + { + "r0.6.1", + new(){ + Name = "r0.6.1: Moderation policies, better alias handling", + Released = DateTime.Parse("2014-07-01 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/legacy/r0.6.1/" + } + }, + { + "v1.1", + new() { + Name = "v1.1: Key backup, knocking", + Released = DateTime.Parse("2021-11-09 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/v1.1/" + } + }, { + "v1.2", + new() { + Name = "v1.2: ", + Released = DateTime.Parse("2022-02-02 00:00:00 +0000"), + SpecUrl = "https://spec.matrix.org/v1.2/" + } + }, { + "v1.3", + new() { + Name = "v1.3: ", + Released = DateTime.Parse("2022-06-15 00:00:00 +0100"), + SpecUrl = "https://spec.matrix.org/v1.3/" + } + }, { + "v1.4", + new() { + Name = "v1.4: ", + Released = DateTime.Parse("2022-09-29 00:00:00 +0100"), + SpecUrl = "https://spec.matrix.org/v1.4/" + } + }, { + "v1.5", + new() { + Name = "v1.5: ", + Released = DateTime.Parse("2022-11-17 08:22:11 -0700"), + SpecUrl = "https://spec.matrix.org/v1.5/" + } + }, { + "v1.6", + new () { + Name = "v1.6: ", + Released = DateTime.Parse("2023-02-14 08:25:40 -0700"), + SpecUrl = "https://spec.matrix.org/v1.6" + } + }, { + "v1.7", + new () { + Name = "v1.7: ", + Released = DateTime.Parse("2023-05-25 09:47:21 -0600"), + SpecUrl = "https://spec.matrix.org/v1.7" + } + }, { + "v1.8", + new () { + Name = "v1.8: Room version 11", + Released = DateTime.Parse("2023-08-23 09:23:53 -0600"), + SpecUrl = "https://spec.matrix.org/v1.8" + } + } + }; + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor b/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor index 0ab0bd2..dbf2f5f 100644 --- a/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor +++ b/MatrixRoomUtils.Web/Pages/Tools/KnownHomeserverList.razor @@ -7,51 +7,43 @@
@if (!IsFinished) { -

Loading... Please wait...

- -

@QueryProgress.ProcessedRooms / @QueryProgress.TotalRooms

- @foreach (var (room, state) in QueryProgress.ProcessedUsers.Where(x => !x.Value.IsFinished).OrderByDescending(x => x.Value.Total).ToList()) { - @if (state.Blocked) { -

🔒 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...

- } - else if (state.Slowmode) { -

🐢 @room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...

- } - else { -

@room.RoomId - @state.Processed / @state.Total, @state.Timing.Elapsed elapsed...

- } - - } +

+ Loading... +

} -else { - @foreach (var server in Homeservers.OrderByDescending(x => x.KnownUserCount).ThenBy(x => x.Server).ToList()) { -

@server.Server - @server.KnownUserCount

- } + +@foreach (var (homeserver, members) in counts.OrderByDescending(x => x.Value)) { +

@homeserver - @members

}
@code { - List Homeservers = new(); + Dictionary> homeservers { get; set; } = new(); + Dictionary counts { get; set; } = new(); + // List Homeservers = new(); bool IsFinished { get; set; } - HomeserverInfoQueryProgress QueryProgress { get; set; } = new(); - AuthenticatedHomeserverGeneric hs { get; set; } + // HomeserverInfoQueryProgress QueryProgress { get; set; } = new(); + AuthenticatedHomeserverGeneric? hs { get; set; } + protected override async Task OnInitializedAsync() { hs = await MRUStorage.GetCurrentSessionOrNavigate(); if (hs is null) return; - var sw = Stopwatch.StartNew(); - Homeservers = await GetHomeservers(progressCallback: async progress => { - if (sw.ElapsedMilliseconds > 1000) { - Console.WriteLine("Progress updated..."); - QueryProgress = progress; - StateHasChanged(); - Console.WriteLine("Progress rendered!"); - sw.Restart(); - await Task.Delay(100); - return true; + var fetchTasks = (await hs.GetJoinedRooms()).Select(x=>x.GetMembersByHomeserverAsync()).ToAsyncEnumerable(); + await foreach (var result in fetchTasks) { + foreach (var (resHomeserver, resMembers) in result) { + if (!homeservers.TryAdd(resHomeserver, resMembers)) { + homeservers[resHomeserver].AddRange(resMembers); + } + counts[resHomeserver] = homeservers[resHomeserver].Count; } - Console.WriteLine($"Progress updated, but not rendering because only {sw.ElapsedMilliseconds}ms elapsed since last call..."); - return false; - }); + // StateHasChanged(); + // await Task.Delay(250); + } + + foreach (var resHomeserver in homeservers.Keys) { + homeservers[resHomeserver] = homeservers[resHomeserver].Distinct().ToList(); + counts[resHomeserver] = homeservers[resHomeserver].Count; + } IsFinished = true; StateHasChanged(); @@ -59,64 +51,4 @@ else { await base.OnInitializedAsync(); } - private async Task> GetHomeservers(int memberLimit = 1000, Func>? progressCallback = null) { - HomeserverInfoQueryProgress progress = new(); - List homeServers = new(); - - var rooms = await hs.GetJoinedRooms(); - progress.TotalRooms = rooms.Count; - - var semaphore = new SemaphoreSlim(4); - var tasks = rooms.Select(async room => { - await semaphore.WaitAsync(); - progress.ProcessedUsers.Add(room, new HomeserverInfoQueryProgress.State()); - Console.WriteLine($"Fetching states for room ({rooms.IndexOf(room)}/{rooms.Count}) ({room.RoomId})"); - var states = room.GetMembersAsync(); - await foreach (var state in states) { - if (state.Type is not "m.room.member") continue; - progress.ProcessedUsers[room].Total++; - - if (homeServers.Any(x => x.Server == state.StateKey.Split(':')[1])) continue; - homeServers.Add(new HomeserverInfo { Server = state.StateKey.Split(':')[1] }); - Console.WriteLine($"Added new homeserver {state.StateKey.Split(':')[1]}"); - } - semaphore.Release(); - progress.ProcessedUsers[room].IsFinished = true; - progress.ProcessedRooms++; - if (progressCallback is not null) - await progressCallback.Invoke(progress); - }); - // var results = tasks.ToAsyncEnumerable(); - await Task.WhenAll(tasks); - - Console.WriteLine("Calculating member counts..."); - homeServers.ForEach(x => x.KnownUserCount = x.KnownUsers.Count); - Console.WriteLine(homeServers.First(x => x.Server == "rory.gay").ToJson()); - Console.WriteLine("Recalculated!"); - return homeServers; - } - - class HomeserverInfo { - public string Server { get; set; } - public int? KnownUserCount { get; set; } - public List KnownUsers { get; } = new(); - } - - class HomeserverInfoQueryProgress { - public int ProcessedRooms { get; set; } - public int TotalRooms { get; set; } - public Dictionary ProcessedUsers { get; } = new(); - public List CurrentState { get; set; } = new(); - - public class State { - public int Processed { get; set; } - public int Total { get; set; } - public bool Blocked { get; set; } - public bool Slowmode { get; set; } - public float Progress => (float)Processed / Total; - public bool IsFinished { get; set; } - public Stopwatch Timing { get; } = Stopwatch.StartNew(); - } - } - -} +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Pages/Tools/MediaLocator.razor b/MatrixRoomUtils.Web/Pages/Tools/MediaLocator.razor index 59ec79e..20aa639 100644 --- a/MatrixRoomUtils.Web/Pages/Tools/MediaLocator.razor +++ b/MatrixRoomUtils.Web/Pages/Tools/MediaLocator.razor @@ -94,7 +94,7 @@ lines.ToList().ForEach(async line => { await sem.WaitAsync(); try { - homeservers.Add((await hsResolver.ResolveHomeserverFromWellKnown(line)).client); + homeservers.Add((await hsResolver.ResolveHomeserverFromWellKnown(line)).Client); StateHasChanged(); } catch (Exception e) { diff --git a/MatrixRoomUtils.Web/Pages/User/DMManager.razor b/MatrixRoomUtils.Web/Pages/User/DMManager.razor index 92e1bc2..f753f18 100644 --- a/MatrixRoomUtils.Web/Pages/User/DMManager.razor +++ b/MatrixRoomUtils.Web/Pages/User/DMManager.razor @@ -40,7 +40,14 @@ var roomList = new List(); DMRooms.Add(await Homeserver.GetProfileAsync(userId), roomList); foreach (var room in rooms) { - roomList.Add(new RoomInfo() { Room = Homeserver.GetRoom(room) }); + var roomInfo = new RoomInfo() { Room = Homeserver.GetRoom(room) }; + roomList.Add(roomInfo); + roomInfo.StateEvents.Add(new() { + Type = RoomNameEventContent.EventId, + TypedContent = new RoomNameEventContent() { + Name = await Homeserver.GetRoom(room).GetNameOrFallbackAsync(4) + } + }); } StateHasChanged(); } @@ -51,6 +58,4 @@ await base.OnInitializedAsync(); } - - } \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/MxcImage.razor b/MatrixRoomUtils.Web/Shared/MxcImage.razor new file mode 100644 index 0000000..f54c1f8 --- /dev/null +++ b/MatrixRoomUtils.Web/Shared/MxcImage.razor @@ -0,0 +1,43 @@ + +@code { + private string _mxcUri; + private string _style; + private string _resolvedUri; + + [Parameter] + public string MxcUri { + get => _mxcUri ?? ""; + set { + _mxcUri = value; + UriHasChanged(value); + } + } + + [Parameter] + public string Style { + get => _style; + set { + _style = value; + StateHasChanged(); + } + } + [Parameter] + public RemoteHomeserver? Homeserver { get; set; } + + private string ResolvedUri { + get => _resolvedUri; + set { + _resolvedUri = value; + StateHasChanged(); + } + } + + private async Task UriHasChanged(string value) { + var uri = value[5..].Split('/'); + ResolvedUri = (Homeserver ?? await hsProvider.GetRemoteHomeserver(uri[0])).ResolveMediaUri(value); + } + + [Parameter] + public string Class { get; set; } + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/RoomListItem.razor b/MatrixRoomUtils.Web/Shared/RoomListItem.razor index a24ccad..970526d 100644 --- a/MatrixRoomUtils.Web/Shared/RoomListItem.razor +++ b/MatrixRoomUtils.Web/Shared/RoomListItem.razor @@ -9,14 +9,14 @@ @if (RoomInfo is not null) {
@if (OwnMemberState != null) { - + @(OwnMemberState?.DisplayName ?? GlobalProfile?.DisplayName ?? "Loading...") -> } - +
@RoomInfo.RoomName @if (ChildContent is not null) { @@ -36,7 +36,13 @@ else { public RenderFragment? ChildContent { get; set; } [Parameter] - public RoomInfo? RoomInfo { get; set; } + public RoomInfo? RoomInfo { + get => _roomInfo; + set { + _roomInfo = value; + OnParametersSetAsync(); + } + } [Parameter] public bool ShowOwnProfile { get; set; } = false; @@ -48,42 +54,52 @@ else { public UserProfileResponse? GlobalProfile { get; set; } [Parameter] - public bool LoadData { get; set; } = false; + public bool LoadData { + get => _loadData; + set { + _loadData = value; + OnParametersSetAsync(); + } + } private bool HasOldRoomVersion { get; set; } = false; private bool HasDangerousRoomVersion { get; set; } = false; private static SemaphoreSlim _semaphoreSlim = new(8); + private RoomInfo? _roomInfo; + private bool _loadData = false; private static AuthenticatedHomeserverGeneric? hs { get; set; } protected override async Task OnParametersSetAsync() { - 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" } - }); - RoomInfo.StateEvents.Add(new() { - Type = "m.room.name", - TypedContent = new RoomNameEventContent() { - Name = "M_FORBIDDEN: Are you a member of this room? " + RoomInfo.Room.RoomId - } - }); + if (RoomInfo != null) { + 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" } + }); + RoomInfo.StateEvents.Add(new() { + Type = "m.room.name", + TypedContent = new RoomNameEventContent() { + Name = "M_FORBIDDEN: Are you a member of this room? " + RoomInfo.Room.RoomId + } + }); + } } } } @@ -170,5 +186,4 @@ else { // } // } -} - +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor index 9efeaab..8d608e3 100644 --- a/MatrixRoomUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/BaseTimelineItem.razor @@ -1,5 +1,7 @@ @using LibMatrix +@using LibMatrix.EventTypes.Spec.State @using LibMatrix.Homeservers +@using LibMatrix.Responses

BaseTimelineItem

@code { @@ -13,4 +15,19 @@ [Parameter] public AuthenticatedHomeserverGeneric Homeserver { get; set; } -} + public List EventsBefore => Events.TakeWhile(e => e.EventId != Event.EventId).ToList(); + + public List MatchingEventsBefore => EventsBefore.Where(x => x.Type == Event.Type && x.StateKey == Event.StateKey).ToList(); + + public StateEventResponse? PreviousState => MatchingEventsBefore.LastOrDefault(); + + public RoomMemberEventContent? CurrentSenderMemberEventContent => EventsBefore.LastOrDefault(x => x.Type == "m.room.member" && x.StateKey == Event.Sender)? + .TypedContent as RoomMemberEventContent; + + public UserProfileResponse CurrentSenderProfile => new() { DisplayName = CurrentSenderMemberEventContent?.DisplayName, AvatarUrl = CurrentSenderMemberEventContent?.AvatarUrl }; + + public bool HasPreviousMessage => EventsBefore.Last() is { Type: "m.room.message" } response && response.Sender == Event.Sender; + + + +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor new file mode 100644 index 0000000..1213432 --- /dev/null +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineCanonicalAliasItem.razor @@ -0,0 +1,27 @@ +@using ArcaneLibs.Extensions +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.Responses +@inherits BaseTimelineItem + +@if (currentEventContent is not null) { + @if (previousEventContent is null) { + set the room alias to "@currentEventContent.Alias" + } + else { + changed the room name from "@previousEventContent.Alias" to "@currentEventContent.Alias" + } +} +else { +
+ Unknown event @Event.Type (@Event.StateKey) +
+            @Event.ToJson()
+        
+
+} + +@code { + private RoomCanonicalAliasEventContent? previousEventContent => PreviousState?.TypedContent as RoomCanonicalAliasEventContent; + + private RoomCanonicalAliasEventContent? currentEventContent => Event.TypedContent as RoomCanonicalAliasEventContent; +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor new file mode 100644 index 0000000..172a38c --- /dev/null +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineHistoryVisibilityItem.razor @@ -0,0 +1,27 @@ +@using ArcaneLibs.Extensions +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.Responses +@inherits BaseTimelineItem + +@if (currentEventContent is not null) { + @if (previousEventContent is null) { + set the history visibility to "@currentEventContent.HistoryVisibility" + } + else { + changed the history visibility from "@previousEventContent.HistoryVisibility" to "@currentEventContent.HistoryVisibility" + } +} +else { +
+ Unknown event @Event.Type (@Event.StateKey) +
+            @Event.ToJson()
+        
+
+} + +@code { + private RoomHistoryVisibilityEventContent? previousEventContent => PreviousState?.TypedContent as RoomHistoryVisibilityEventContent; + + private RoomHistoryVisibilityEventContent? currentEventContent => Event.TypedContent as RoomHistoryVisibilityEventContent; +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor index ed4dceb..3b18b95 100644 --- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMemberItem.razor @@ -15,7 +15,12 @@ @Event.StateKey changed their display name to @(roomMemberData.DisplayName ?? Event.Sender) break; case "join": - joined + @if (prevRoomMemberData is null) { + joined + } + else { + changed their profile to + } break; case "leave": @Event.StateKey left @@ -43,5 +48,6 @@ else { @code { private RoomMemberEventContent? roomMemberData => Event.TypedContent as RoomMemberEventContent; + private RoomMemberEventContent? prevRoomMemberData => PreviousState?.TypedContent as RoomMemberEventContent; } diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor index 8073406..81956b0 100644 --- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineMessageItem.razor @@ -1,10 +1,34 @@ @using ArcaneLibs.Extensions +@using LibMatrix.EventTypes.Spec @inherits BaseTimelineItem -
-    @Event.RawContent?.ToJson(indent: false)
-
+ + @if (!HasPreviousMessage) { + :
+ } + @switch (currentEventContent.MessageType) { + case "m.text": { + @foreach (var line in currentEventContent.Body.Split('\n')) { + @line
+ } + break; + } + case "m.image": { + @currentEventContent.Body
+ + break; + } + default: { +
+               @Event.RawContent?.ToJson(indent: false)
+            
+ break; + } + } +
@code { + private RoomMessageEventContent? previousEventContent => PreviousState?.TypedContent as RoomMessageEventContent; -} + private RoomMessageEventContent? currentEventContent => Event.TypedContent as RoomMessageEventContent; +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor index 2d05151..f3e6c7e 100644 --- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomCreateItem.razor @@ -2,11 +2,11 @@ @using LibMatrix.EventTypes.Spec.State @inherits BaseTimelineItem -

+ @Event.Sender created the room with room version @CreationEventContent.RoomVersion - @(CreationEventContent.Federate ?? false ? "and" : "without") federating with other servers.
+ @(CreationEventContent.Federate ?? true ? "and" : "without") federating with other servers.
This room is of type @(CreationEventContent.Type ?? "Untyped room (usually a chat room)") -

+
     @Event.RawContent?.ToJson(indent: false)
 
diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor new file mode 100644 index 0000000..eeec3de --- /dev/null +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomNameItem.razor @@ -0,0 +1,27 @@ +@using ArcaneLibs.Extensions +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.Responses +@inherits BaseTimelineItem + +@if (currentEventContent is not null) { + @if (previousEventContent is null) { + set the room name to "@currentEventContent.Name" + } + else { + changed the room name from "@previousEventContent.Name" to "@currentEventContent.Name" + } +} +else { +
+ Unknown event @Event.Type (@Event.StateKey) +
+            @Event.ToJson()
+        
+
+} + +@code { + private RoomNameEventContent? previousEventContent => PreviousState?.TypedContent as RoomNameEventContent; + + private RoomNameEventContent? currentEventContent => Event.TypedContent as RoomNameEventContent; +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor new file mode 100644 index 0000000..7ef17a8 --- /dev/null +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineRoomTopicItem.razor @@ -0,0 +1,37 @@ +@using ArcaneLibs.Extensions +@using LibMatrix.EventTypes.Spec.State +@using LibMatrix.Responses +@inherits BaseTimelineItem + +@if (currentEventContent is not null) { + @if (previousEventContent is null) { + set the room topic to
+
+            @currentEventContent.Topic
+        
+ } + else { + changed the room topic from
+
+            @previousEventContent.Topic
+        

+ to
+
+            @currentEventContent.Topic
+        
+ } +} +else { +
+ Unknown event @Event.Type (@Event.StateKey) +
+            @Event.ToJson()
+        
+
+} + +@code { + private RoomTopicEventContent? previousEventContent => PreviousState?.TypedContent as RoomTopicEventContent; + + private RoomTopicEventContent? currentEventContent => Event.TypedContent as RoomTopicEventContent; +} \ No newline at end of file diff --git a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor index 1ab530d..4f05b30 100644 --- a/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor +++ b/MatrixRoomUtils.Web/Shared/TimelineComponents/TimelineUnknownItem.razor @@ -6,7 +6,7 @@ Unknown event type:
@Event.Type
-
@Event.ToJson()
+
@Event.ToJson(ignoreNull: true)
diff --git a/MatrixRoomUtils.Web/_Imports.razor b/MatrixRoomUtils.Web/_Imports.razor index 91b69fb..0d07b3a 100644 --- a/MatrixRoomUtils.Web/_Imports.razor +++ b/MatrixRoomUtils.Web/_Imports.razor @@ -11,8 +11,8 @@ @using MatrixRoomUtils.Web @using MatrixRoomUtils.Web.Classes @using MatrixRoomUtils.Web.Shared - @using ArcaneLibs.Blazor.Components +@using LibMatrix.Homeservers @inject NavigationManager NavigationManager @inject MRUStorageWrapper MRUStorage diff --git a/MatrixRoomUtils.sln.DotSettings.user b/MatrixRoomUtils.sln.DotSettings.user index b15cbb5..7597038 100644 --- a/MatrixRoomUtils.sln.DotSettings.user +++ b/MatrixRoomUtils.sln.DotSettings.user @@ -44,6 +44,12 @@ <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;LibMatrix&gt; #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> <Project Location="/home/root@Rory/git/Matrix/MatrixRoomUtils" Presentation="&lt;LibMatrix&gt;" /> </SessionState> + True + True + True + + + diff --git a/MxApiExtensions b/MxApiExtensions index cb719c3..2e8aa30 160000 --- a/MxApiExtensions +++ b/MxApiExtensions @@ -1 +1 @@ -Subproject commit cb719c315e225ba97e32b2dca7d9b184755234cc +Subproject commit 2e8aa30daa4a33fa33622bccb344dfc24483e320 -- cgit 1.5.1