diff --git a/crates/chat_ui/src/lib.rs b/crates/chat_ui/src/lib.rs index 9b03442..27d5380 100644 --- a/crates/chat_ui/src/lib.rs +++ b/crates/chat_ui/src/lib.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::collections::{BTreeMap, HashSet}; use std::sync::{Arc, RwLock}; pub use actions::*; @@ -53,8 +53,8 @@ pub struct ChatPanel { /// Message list state list_state: ListState, - /// All messages - messages: BTreeSet, + /// All messages (sorted by created_at) + messages: Vec, /// Mapping message ids to their rendered texts rendered_texts_by_id: BTreeMap, @@ -98,7 +98,7 @@ impl ChatPanel { let reports_by_id = Arc::new(RwLock::new(BTreeMap::new())); // Define list of messages - let messages = BTreeSet::default(); + let messages = Vec::new(); let list_state = ListState::new(messages.len(), ListAlignment::Bottom, px(1024.)); // Get room id and name @@ -424,9 +424,10 @@ impl ChatPanel { E: Into, { let old_len = self.messages.len(); + let msg: Message = m.into(); - // Extend the messages list with the new events - if self.messages.insert(m.into()) { + if let Err(pos) = self.messages.binary_search(&msg) { + self.messages.insert(pos, msg); self.list_state.splice(old_len..old_len, 1); if scroll { @@ -778,10 +779,8 @@ impl ChatPanel { return true; } - let mut iter = self.messages.iter(); - - if let Some(previous) = iter.nth(ix - 1) - && let Some(current) = iter.next() + if let Some(previous) = self.messages.get(ix - 1) + && let Some(current) = self.messages.get(ix) { if current.author != previous.author { return true; @@ -804,7 +803,7 @@ impl ChatPanel { window: &mut Window, cx: &mut Context, ) -> AnyElement { - if let Some(message) = self.messages.iter().nth(ix) { + if let Some(message) = self.messages.get(ix) { let persons = PersonRegistry::global(cx); let show_author = self.is_group_start(ix); let text = self diff --git a/crates/workspace/src/lib.rs b/crates/workspace/src/lib.rs index d066ba4..1159f54 100644 --- a/crates/workspace/src/lib.rs +++ b/crates/workspace/src/lib.rs @@ -220,27 +220,6 @@ impl Workspace { }), ); - subscriptions.push( - // Observe the chat registry. - // Deferred via spawn to avoid potential re-entrancy if - // cx.observe fires synchronously during a chat.update. - cx.observe(&chat, move |this, chat, cx| { - let ids = this.panel_ids(cx); - let chat = chat.downgrade(); - cx.spawn(async move |this, cx| -> anyhow::Result<()> { - if let Some(chat) = chat.upgrade() { - this.update(cx, |_this, cx| { - chat.update(cx, |chat, cx| { - chat.refresh_rooms(&ids, cx); - }); - })?; - } - Ok(()) - }) - .detach(); - }), - ); - cx.defer_in(window, |this, window, cx| { let dock = this.dock.downgrade(); let greeter = Arc::new(greeter::init(window, cx)); @@ -277,17 +256,6 @@ impl Workspace { } } - /// Get all panel ids - fn panel_ids(&self, cx: &App) -> Vec { - self.dock - .read(cx) - .items - .panel_ids(cx) - .into_iter() - .filter_map(|panel| panel.parse::().ok()) - .collect() - } - /// Handle command events fn on_command(&mut self, command: &Command, window: &mut Window, cx: &mut Context) { match command { diff --git a/web/src/lib.rs b/web/src/lib.rs index 1398480..e9e4d72 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -31,8 +31,20 @@ pub fn run() -> Result<(), JsValue> { #[cfg(target_family = "wasm")] gpui_platform::web_init(); + #[cfg(not(target_family = "wasm"))] + let app = gpui_platform::application(); + #[cfg(target_family = "wasm")] + let app = { + let app = gpui_platform::single_threaded_web(); - gpui_platform::application().run(|cx| { + // Temporary fix: intentionally leak the `Rc` to keep the application alive + struct WasmApplication(std::rc::Rc); + let wasm_app = unsafe { std::mem::transmute::(app) }; + std::mem::forget(wasm_app.0.clone()); + unsafe { std::mem::transmute::(wasm_app) } + }; + + app.run(|cx| { // Open the root window cx.open_window(WindowOptions::default(), |window, cx| { // Initialize components