From 2b566a31b68f14d51faae61cbfbe359d0691a890 Mon Sep 17 00:00:00 2001 From: Rory& Date: Fri, 22 Mar 2024 16:38:53 +0000 Subject: Changes --- .../Services/RoomStore.cs | 52 ++++++++++++++++------ .../Services/UserStore.cs | 1 - 2 files changed, 39 insertions(+), 14 deletions(-) (limited to 'Tests/LibMatrix.HomeserverEmulator/Services') diff --git a/Tests/LibMatrix.HomeserverEmulator/Services/RoomStore.cs b/Tests/LibMatrix.HomeserverEmulator/Services/RoomStore.cs index 37d9c7d..d2c9e15 100644 --- a/Tests/LibMatrix.HomeserverEmulator/Services/RoomStore.cs +++ b/Tests/LibMatrix.HomeserverEmulator/Services/RoomStore.cs @@ -1,6 +1,8 @@ using System.Collections.Concurrent; using System.Collections.Frozen; +using System.Collections.Immutable; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Security.Cryptography; using System.Text.Json; using System.Text.Json.Nodes; @@ -17,9 +19,9 @@ namespace LibMatrix.HomeserverEmulator.Services; public class RoomStore { public ConcurrentBag _rooms = new(); private Dictionary _roomsById = new(); - + public RoomStore(HSEConfiguration config) { - if(config.StoreData) { + if (config.StoreData) { var path = Path.Combine(config.DataStoragePath, "rooms"); if (!Directory.Exists(path)) Directory.CreateDirectory(path); foreach (var file in Directory.GetFiles(path)) { @@ -29,7 +31,7 @@ public class RoomStore { } else Console.WriteLine("Data storage is disabled, not loading rooms from disk"); - + RebuildIndexes(); } @@ -78,7 +80,7 @@ public class RoomStore { public class Room : NotifyPropertyChanged { private CancellationTokenSource _debounceCts = new(); private ObservableCollection _timeline; - private ObservableDictionary> _accountData; + private ObservableDictionary> _accountData; public Room(string roomId) { if (string.IsNullOrWhiteSpace(roomId)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(roomId)); @@ -98,12 +100,23 @@ public class RoomStore { set { if (Equals(value, _timeline)) return; _timeline = new(value); - _timeline.CollectionChanged += (sender, args) => SaveDebounced(); + _timeline.CollectionChanged += (sender, args) => { + if (args.Action == NotifyCollectionChangedAction.Add) { + foreach (StateEventResponse state in args.NewItems) { + if (state.StateKey is not null) + // we want state to be deduplicated by type and key, and we want the latest state to be the one that is returned + RebuildState(); + } + } + + SaveDebounced(); + }; + RebuildState(); OnPropertyChanged(); } } - public ObservableDictionary> AccountData { + public ObservableDictionary> AccountData { get => _accountData; set { if (Equals(value, _accountData)) return; @@ -113,6 +126,9 @@ public class RoomStore { } } + public ImmutableList JoinedMembers => + State.Where(s => s is { Type: RoomMemberEventContent.EventId, TypedContent: RoomMemberEventContent { Membership: "join" } }).ToImmutableList(); + internal StateEventResponse SetStateInternal(StateEvent request) { var state = new StateEventResponse() { Type = request.Type, @@ -121,14 +137,16 @@ public class RoomStore { RoomId = RoomId, OriginServerTs = DateTimeOffset.Now.ToUnixTimeMilliseconds(), Sender = "", - RawContent = request.RawContent ?? (request.TypedContent is not null ? new JsonObject() : JsonSerializer.Deserialize(JsonSerializer.Serialize(request.TypedContent))) + RawContent = request.RawContent ?? (request.TypedContent is not null + ? new JsonObject() + : JsonSerializer.Deserialize(JsonSerializer.Serialize(request.TypedContent))) }; Timeline.Add(state); - if(state.StateKey is not null) - // we want state to be deduplicated by type and key, and we want the latest state to be the one that is returned - State = Timeline.Where(s => s.Type == state.Type && s.StateKey == state.StateKey) + if (state.StateKey is not null) + // we want state to be deduplicated by type and key, and we want the latest state to be the one that is returned + State = Timeline.Where(s => s.StateKey != null) .OrderByDescending(s => s.OriginServerTs) - .DistinctBy(x=>(x.Type, x.StateKey)) + .DistinctBy(x => (x.Type, x.StateKey)) .ToFrozenSet(); return state; } @@ -145,7 +163,7 @@ public class RoomStore { state.Sender = userId; return state; } - + public async Task SaveDebounced() { if (!HSEConfiguration.Current.StoreData) return; await _debounceCts.CancelAsync(); @@ -153,12 +171,20 @@ public class RoomStore { try { await Task.Delay(250, _debounceCts.Token); // Ensure all state events are in the timeline - State.Where(s=>!Timeline.Contains(s)).ToList().ForEach(s => Timeline.Add(s)); + State.Where(s => !Timeline.Contains(s)).ToList().ForEach(s => Timeline.Add(s)); var path = Path.Combine(HSEConfiguration.Current.DataStoragePath, "rooms", $"{RoomId}.json"); Console.WriteLine($"Saving room {RoomId} to {path}!"); await File.WriteAllTextAsync(path, this.ToJson(ignoreNull: true)); } catch (TaskCanceledException) { } } + + private void RebuildState() { + State = Timeline //.Where(s => s.Type == state.Type && s.StateKey == state.StateKey) + .Where(x => x.StateKey != null) + .OrderByDescending(s => s.OriginServerTs) + .DistinctBy(x => (x.Type, x.StateKey)) + .ToFrozenSet(); + } } } \ No newline at end of file diff --git a/Tests/LibMatrix.HomeserverEmulator/Services/UserStore.cs b/Tests/LibMatrix.HomeserverEmulator/Services/UserStore.cs index faf0046..4f238a0 100644 --- a/Tests/LibMatrix.HomeserverEmulator/Services/UserStore.cs +++ b/Tests/LibMatrix.HomeserverEmulator/Services/UserStore.cs @@ -187,7 +187,6 @@ public class UserStore { public class SyncRoomPosition { public int TimelinePosition { get; set; } - public int StatePosition { get; set; } public int AccountDataPosition { get; set; } } } -- cgit 1.4.1