chore: fix rooms out of order while loading (#139)

* fix room out of order while loading

* .

* .
This commit is contained in:
reya
2025-09-03 09:16:36 +07:00
committed by GitHub
parent d392602ed6
commit d8edac0bb9
7 changed files with 150 additions and 126 deletions

View File

@@ -19,4 +19,3 @@ smol.workspace = true
log.workspace = true
fuzzy-matcher = "0.3.7"
hashbrown = "0.15"

View File

@@ -1,4 +1,5 @@
use std::cmp::Reverse;
use std::collections::{HashMap, HashSet};
use anyhow::Error;
use common::event::EventUtils;
@@ -6,7 +7,6 @@ use fuzzy_matcher::skim::SkimMatcherV2;
use fuzzy_matcher::FuzzyMatcher;
use global::nostr_client;
use gpui::{App, AppContext, Context, Entity, EventEmitter, Global, Task, WeakEntity, Window};
use hashbrown::{HashMap, HashSet};
use itertools::Itertools;
use nostr_sdk::prelude::*;
use room::RoomKind;
@@ -251,9 +251,15 @@ impl Registry {
/// Reset the registry.
pub fn reset(&mut self, cx: &mut Context<Self>) {
self.rooms = vec![];
// Reset the loading status (default: true)
self.loading = true;
// Clear the current identity
self.identity = None;
// Clear all current rooms
self.rooms.clear();
cx.notify();
}
@@ -262,12 +268,13 @@ impl Registry {
log::info!("Starting to load chat rooms...");
// Get the contact bypass setting
let contact_bypass = AppSettings::get_contact_bypass(cx);
let bypass_setting = AppSettings::get_contact_bypass(cx);
let task: Task<Result<HashSet<Room>, Error>> = cx.background_spawn(async move {
let client = nostr_client();
let signer = client.signer().await?;
let public_key = signer.get_public_key().await?;
let contacts = client.database().contacts_public_keys(public_key).await?;
// Get messages sent by the user
let send = Filter::new()
@@ -300,13 +307,12 @@ impl Registry {
public_keys.retain(|pk| pk != &public_key);
// Bypass screening flag
let mut bypass = false;
let mut bypassed = false;
// If user enabled bypass screening for contacts
// Check if room's members are in contact with current user
if contact_bypass {
let contacts = client.database().contacts_public_keys(public_key).await?;
bypass = public_keys.iter().any(|k| contacts.contains(k));
// If the user has enabled bypass screening in settings,
// check if any of the room's members are contacts of the current user
if bypass_setting {
bypassed = public_keys.iter().any(|k| contacts.contains(k));
}
// Check if the current user has sent at least one message to this room
@@ -321,7 +327,7 @@ impl Registry {
// Create a new room
let room = Room::new(&event).rearrange_by(public_key);
if is_ongoing || bypass {
if is_ongoing || bypassed {
rooms.insert(room.kind(RoomKind::Ongoing));
} else {
rooms.insert(room);
@@ -349,23 +355,28 @@ impl Registry {
}
pub(crate) fn extend_rooms(&mut self, rooms: HashSet<Room>, cx: &mut Context<Self>) {
let mut room_map: HashMap<u64, usize> = HashMap::with_capacity(self.rooms.len());
for (index, room) in self.rooms.iter().enumerate() {
room_map.insert(room.read(cx).id, index);
}
let mut room_map: HashMap<u64, usize> = self
.rooms
.iter()
.enumerate()
.map(|(idx, room)| (room.read(cx).id, idx))
.collect();
for new_room in rooms.into_iter() {
// Check if we already have a room with this ID
if let Some(&index) = room_map.get(&new_room.id) {
self.rooms[index].update(cx, |this, cx| {
*this = new_room;
cx.notify();
if new_room.created_at > this.created_at {
*this = new_room;
cx.notify();
}
});
} else {
let new_index = self.rooms.len();
room_map.insert(new_room.id, new_index);
let new_room_id = new_room.id;
self.rooms.push(cx.new(|_| new_room));
let new_index = self.rooms.len();
room_map.insert(new_room_id, new_index);
}
}
}
@@ -418,9 +429,13 @@ impl Registry {
};
if let Some(room) = self.rooms.iter().find(|room| room.read(cx).id == id) {
let is_new_event = event.created_at > room.read(cx).created_at;
// Update room
room.update(cx, |this, cx| {
this.created_at(event.created_at, cx);
if is_new_event {
this.created_at(event.created_at, cx);
}
// Set this room is ongoing if the new message is from current user
if author == identity {
@@ -433,8 +448,10 @@ impl Registry {
});
});
// Re-sort the rooms registry by their created at
self.sort(cx);
// Resort all rooms in the registry by their created at (after updated)
if is_new_event {
self.sort(cx);
}
} else {
let room = Room::new(&event)
.kind(RoomKind::default())

View File

@@ -2,16 +2,37 @@ use std::hash::Hash;
use nostr_sdk::prelude::*;
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum Message {
User(RenderedMessage),
System,
System(Timestamp),
}
impl Message {
pub fn user(user: impl Into<RenderedMessage>) -> Self {
Self::User(user.into())
}
pub fn system() -> Self {
Self::System(Timestamp::default())
}
}
impl Ord for Message {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match (self, other) {
(Message::User(a), Message::User(b)) => a.cmp(b),
(Message::System(a), Message::System(b)) => a.cmp(b),
(Message::User(a), Message::System(b)) => a.created_at.cmp(b),
(Message::System(a), Message::User(b)) => a.cmp(&b.created_at),
}
}
}
impl PartialOrd for Message {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Clone)]