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 @@
+<img class="@Class" src="@ResolvedUri" style="@Style"/>
+@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) {
<div class="roomListItem @(HasDangerousRoomVersion ? "dangerousRoomVersion" : HasOldRoomVersion ? "oldRoomVersion" : "")" id="@RoomInfo.Room.RoomId">
@if (OwnMemberState != null) {
- <img class="avatar32 @(OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? "highlightChange" : "") @(ChildContent is not null ? "vcenter" : "")"
- src="@(hs.ResolveMediaUri(OwnMemberState.AvatarUrl ?? GlobalProfile.AvatarUrl) ?? "/icon-192.png")"/>
+ <MxcImage Class="@("avatar32" + (OwnMemberState?.AvatarUrl != GlobalProfile?.AvatarUrl ? " highlightChange" : "") + (ChildContent is not null ? " vcenter" : ""))"
+ 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>
}
- <img class="avatar32" src="@hs?.ResolveMediaUri(RoomInfo.RoomIcon)" style="@(ChildContent is not null ? "vertical-align: middle;" : "")"/>
+ <MxcImage Class="avatar32" 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) {
@@ -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 (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;
+ 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
- }
- });
+ 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
<h3>BaseTimelineItem</h3>
@code {
@@ -13,4 +15,19 @@
[Parameter]
public AuthenticatedHomeserverGeneric Homeserver { get; set; }
-}
+ public List<StateEventResponse> EventsBefore => Events.TakeWhile(e => e.EventId != Event.EventId).ToList();
+
+ public List<StateEventResponse> 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) {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> set the room alias to "@currentEventContent.Alias"</i>
+ }
+ else {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> changed the room name from "@previousEventContent.Alias" to "@currentEventContent.Alias"</i>
+ }
+}
+else {
+ <details>
+ <summary>Unknown event @Event.Type (@Event.StateKey)</summary>
+ <pre>
+ @Event.ToJson()
+ </pre>
+ </details>
+}
+
+@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) {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> set the history visibility to "@currentEventContent.HistoryVisibility"</i>
+ }
+ else {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> changed the history visibility from "@previousEventContent.HistoryVisibility" to "@currentEventContent.HistoryVisibility"</i>
+ }
+}
+else {
+ <details>
+ <summary>Unknown event @Event.Type (@Event.StateKey)</summary>
+ <pre>
+ @Event.ToJson()
+ </pre>
+ </details>
+}
+
+@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 @@
<i>@Event.StateKey changed their display name to @(roomMemberData.DisplayName ?? Event.Sender)</i>
break;
case "join":
- <i><InlineUserItem User="@(new UserProfileResponse())" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> joined</i>
+ @if (prevRoomMemberData is null) {
+ <i><InlineUserItem User="@(new UserProfileResponse() { DisplayName = roomMemberData.DisplayName, AvatarUrl = roomMemberData.AvatarUrl })" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> joined</i>
+ }
+ else {
+ <i><InlineUserItem User="@(new UserProfileResponse() { DisplayName = prevRoomMemberData.DisplayName, AvatarUrl = prevRoomMemberData.AvatarUrl })" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> changed their profile to <InlineUserItem User="@(new UserProfileResponse() { DisplayName = roomMemberData.DisplayName, AvatarUrl = roomMemberData.AvatarUrl })" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem></i>
+ }
break;
case "leave":
<i>@Event.StateKey left</i>
@@ -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
-<pre>
- @Event.RawContent?.ToJson(indent: false)
-</pre>
+<span>
+ @if (!HasPreviousMessage) {
+ <span><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem>:</span><br/>
+ }
+ @switch (currentEventContent.MessageType) {
+ case "m.text": {
+ @foreach (var line in currentEventContent.Body.Split('\n')) {
+ <span>@line</span><br/>
+ }
+ break;
+ }
+ case "m.image": {
+ <i>@currentEventContent.Body</i><br/>
+ <img src="@Homeserver.ResolveMediaUri(currentEventContent.Url)">
+ break;
+ }
+ default: {
+ <pre>
+ @Event.RawContent?.ToJson(indent: false)
+ </pre>
+ break;
+ }
+ }
+</span>
@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
-<p>
+<i>
@Event.Sender created the room with room version @CreationEventContent.RoomVersion
- @(CreationEventContent.Federate ?? false ? "and" : "without") federating with other servers.<br/>
+ @(CreationEventContent.Federate ?? true ? "and" : "without") federating with other servers.<br/>
This room is of type @(CreationEventContent.Type ?? "Untyped room (usually a chat room)")
-</p>
+</i>
<pre>
@Event.RawContent?.ToJson(indent: false)
</pre>
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) {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> set the room name to "@currentEventContent.Name"</i>
+ }
+ else {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> changed the room name from "@previousEventContent.Name" to "@currentEventContent.Name"</i>
+ }
+}
+else {
+ <details>
+ <summary>Unknown event @Event.Type (@Event.StateKey)</summary>
+ <pre>
+ @Event.ToJson()
+ </pre>
+ </details>
+}
+
+@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) {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> set the room topic to</i><br/>
+ <pre>
+ @currentEventContent.Topic
+ </pre>
+ }
+ else {
+ <i><InlineUserItem User="@CurrentSenderProfile" Homeserver="@Homeserver" UserId="@Event.StateKey"></InlineUserItem> changed the room topic from</i><br/>
+ <pre>
+ @previousEventContent.Topic
+ </pre><br/>
+ <i>to</i><br/>
+ <pre>
+ @currentEventContent.Topic
+ </pre>
+ }
+}
+else {
+ <details>
+ <summary>Unknown event @Event.Type (@Event.StateKey)</summary>
+ <pre>
+ @Event.ToJson()
+ </pre>
+ </details>
+}
+
+@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 @@
<summary>
<i style="color: red;">Unknown event type: <pre style="display: inline;">@Event.Type</pre></i>
</summary>
- <pre>@Event.ToJson()</pre>
+ <pre>@Event.ToJson(ignoreNull: true)</pre>
</details>
</div>
|