diff --git a/crates/call/src/call.rs b/crates/call/src/call.rs index 3257906386..87d2e9aa78 100644 --- a/crates/call/src/call.rs +++ b/crates/call/src/call.rs @@ -239,7 +239,8 @@ impl ActiveCall { if result.is_ok() { this.update(&mut cx, |this, cx| this.report_call_event("invite", cx))?; } else { - // TODO: Resport collaboration error + //TODO: report collaboration error + log::error!("invite failed: {:?}", result); } this.update(&mut cx, |this, cx| { diff --git a/crates/collab/src/tests/channel_message_tests.rs b/crates/collab/src/tests/channel_message_tests.rs index 5870bd1938..e59aa3c705 100644 --- a/crates/collab/src/tests/channel_message_tests.rs +++ b/crates/collab/src/tests/channel_message_tests.rs @@ -1,7 +1,9 @@ use crate::{rpc::RECONNECT_TIMEOUT, tests::TestServer}; use channel::{ChannelChat, ChannelMessageId, MessageParams}; +use collab_ui::chat_panel::ChatPanel; use gpui::{BackgroundExecutor, Model, TestAppContext}; use rpc::Notification; +use workspace::dock::Panel; #[gpui::test] async fn test_basic_channel_messages( @@ -273,135 +275,135 @@ fn assert_messages(chat: &Model, messages: &[&str], cx: &mut TestAp ); } -//todo!(collab_ui) -// #[gpui::test] -// async fn test_channel_message_changes( -// executor: BackgroundExecutor, -// cx_a: &mut TestAppContext, -// cx_b: &mut TestAppContext, -// ) { -// let mut server = TestServer::start(&executor).await; -// let client_a = server.create_client(cx_a, "user_a").await; -// let client_b = server.create_client(cx_b, "user_b").await; +#[gpui::test] +async fn test_channel_message_changes( + executor: BackgroundExecutor, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + let mut server = TestServer::start(executor.clone()).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; -// let channel_id = server -// .make_channel( -// "the-channel", -// None, -// (&client_a, cx_a), -// &mut [(&client_b, cx_b)], -// ) -// .await; + let channel_id = server + .make_channel( + "the-channel", + None, + (&client_a, cx_a), + &mut [(&client_b, cx_b)], + ) + .await; -// // Client A sends a message, client B should see that there is a new message. -// let channel_chat_a = client_a -// .channel_store() -// .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx)) -// .await -// .unwrap(); + // Client A sends a message, client B should see that there is a new message. + let channel_chat_a = client_a + .channel_store() + .update(cx_a, |store, cx| store.open_channel_chat(channel_id, cx)) + .await + .unwrap(); -// channel_chat_a -// .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap()) -// .await -// .unwrap(); + channel_chat_a + .update(cx_a, |c, cx| c.send_message("one".into(), cx).unwrap()) + .await + .unwrap(); -// executor.run_until_parked(); + executor.run_until_parked(); -// let b_has_messages = cx_b.read_with(|cx| { -// client_b -// .channel_store() -// .read(cx) -// .has_new_messages(channel_id) -// .unwrap() -// }); + let b_has_messages = cx_b.update(|cx| { + client_b + .channel_store() + .read(cx) + .has_new_messages(channel_id) + .unwrap() + }); -// assert!(b_has_messages); + assert!(b_has_messages); -// // Opening the chat should clear the changed flag. -// cx_b.update(|cx| { -// collab_ui::init(&client_b.app_state, cx); -// }); -// let project_b = client_b.build_empty_local_project(cx_b); -// let workspace_b = client_b.build_workspace(&project_b, cx_b).root(cx_b); -// let chat_panel_b = workspace_b.update(cx_b, |workspace, cx| ChatPanel::new(workspace, cx)); -// chat_panel_b -// .update(cx_b, |chat_panel, cx| { -// chat_panel.set_active(true, cx); -// chat_panel.select_channel(channel_id, None, cx) -// }) -// .await -// .unwrap(); + // Opening the chat should clear the changed flag. + cx_b.update(|cx| { + collab_ui::init(&client_b.app_state, cx); + }); + let project_b = client_b.build_empty_local_project(cx_b); + let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b); -// executor.run_until_parked(); + let chat_panel_b = workspace_b.update(cx_b, |workspace, cx| ChatPanel::new(workspace, cx)); + chat_panel_b + .update(cx_b, |chat_panel, cx| { + chat_panel.set_active(true, cx); + chat_panel.select_channel(channel_id, None, cx) + }) + .await + .unwrap(); -// let b_has_messages = cx_b.read_with(|cx| { -// client_b -// .channel_store() -// .read(cx) -// .has_new_messages(channel_id) -// .unwrap() -// }); + executor.run_until_parked(); -// assert!(!b_has_messages); + let b_has_messages = cx_b.update(|cx| { + client_b + .channel_store() + .read(cx) + .has_new_messages(channel_id) + .unwrap() + }); -// // Sending a message while the chat is open should not change the flag. -// channel_chat_a -// .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap()) -// .await -// .unwrap(); + assert!(!b_has_messages); -// executor.run_until_parked(); + // Sending a message while the chat is open should not change the flag. + channel_chat_a + .update(cx_a, |c, cx| c.send_message("two".into(), cx).unwrap()) + .await + .unwrap(); -// let b_has_messages = cx_b.read_with(|cx| { -// client_b -// .channel_store() -// .read(cx) -// .has_new_messages(channel_id) -// .unwrap() -// }); + executor.run_until_parked(); -// assert!(!b_has_messages); + let b_has_messages = cx_b.update(|cx| { + client_b + .channel_store() + .read(cx) + .has_new_messages(channel_id) + .unwrap() + }); -// // Sending a message while the chat is closed should change the flag. -// chat_panel_b.update(cx_b, |chat_panel, cx| { -// chat_panel.set_active(false, cx); -// }); + assert!(!b_has_messages); -// // Sending a message while the chat is open should not change the flag. -// channel_chat_a -// .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap()) -// .await -// .unwrap(); + // Sending a message while the chat is closed should change the flag. + chat_panel_b.update(cx_b, |chat_panel, cx| { + chat_panel.set_active(false, cx); + }); -// executor.run_until_parked(); + // Sending a message while the chat is open should not change the flag. + channel_chat_a + .update(cx_a, |c, cx| c.send_message("three".into(), cx).unwrap()) + .await + .unwrap(); -// let b_has_messages = cx_b.read_with(|cx| { -// client_b -// .channel_store() -// .read(cx) -// .has_new_messages(channel_id) -// .unwrap() -// }); + executor.run_until_parked(); -// assert!(b_has_messages); + let b_has_messages = cx_b.update(|cx| { + client_b + .channel_store() + .read(cx) + .has_new_messages(channel_id) + .unwrap() + }); -// // Closing the chat should re-enable change tracking -// cx_b.update(|_| drop(chat_panel_b)); + assert!(b_has_messages); -// channel_chat_a -// .update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap()) -// .await -// .unwrap(); + // Closing the chat should re-enable change tracking + cx_b.update(|_| drop(chat_panel_b)); -// executor.run_until_parked(); + channel_chat_a + .update(cx_a, |c, cx| c.send_message("four".into(), cx).unwrap()) + .await + .unwrap(); -// let b_has_messages = cx_b.read_with(|cx| { -// client_b -// .channel_store() -// .read(cx) -// .has_new_messages(channel_id) -// .unwrap() -// }); + executor.run_until_parked(); -// assert!(b_has_messages); -// } + let b_has_messages = cx_b.update(|cx| { + client_b + .channel_store() + .read(cx) + .has_new_messages(channel_id) + .unwrap() + }); + + assert!(b_has_messages); +} diff --git a/crates/collab_ui/src/collab_ui.rs b/crates/collab_ui/src/collab_ui.rs index 3c0473e67d..c8230620b4 100644 --- a/crates/collab_ui/src/collab_ui.rs +++ b/crates/collab_ui/src/collab_ui.rs @@ -111,7 +111,6 @@ fn notification_window_options( let screen_bounds = screen.bounds(); let size: Size = window_size.into(); - // todo!() use content bounds instead of screen.bounds and get rid of magics in point's 2nd argument. let bounds = gpui::Bounds:: { origin: screen_bounds.upper_right() - point( diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index 05aa381627..dbd58b0acc 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -1043,7 +1043,7 @@ mod tests { #[gpui::test(iterations = 100)] async fn test_random_wraps(cx: &mut gpui::TestAppContext, mut rng: StdRng) { - // todo!() this test is flaky + // todo this test is flaky init_test(cx); cx.background_executor.set_block_on_ticks(0..=50); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 7b33a3239d..1791fcc292 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1017,7 +1017,6 @@ impl EditorElement { .chars_at(cursor_position) .next() .and_then(|(character, _)| { - // todo!() currently shape_line panics if text conatins newlines let text = if character == '\n' { SharedString::from(" ") } else { diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index d49eb9ee60..0fe36084c2 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -312,7 +312,7 @@ impl FileFinderDelegate { cx: &mut ViewContext, ) -> Self { cx.observe(&project, |file_finder, _, cx| { - //todo!() We should probably not re-render on every project anything + //todo We should probably not re-render on every project anything file_finder .picker .update(cx, |picker, cx| picker.refresh(cx)) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 6d03a3b5cd..479e6acab2 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -269,6 +269,7 @@ unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const C sel!(windowShouldClose:), window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL, ); + decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel)); decl.add_method( @@ -685,9 +686,6 @@ impl Drop for MacWindow { this.executor .spawn(async move { unsafe { - // todo!() this panic()s when you click the red close button - // unless should_close returns false. - // (luckliy in zed it always returns false) window.close(); } }) @@ -1116,7 +1114,7 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: // we don't match cmd/fn because they don't seem to use IME modifiers: Default::default(), key: ime_text.clone().unwrap(), - ime_key: None, // todo!("handle IME key") + ime_key: None, }, }; handled = callback(InputEvent::KeyDown(event_with_ime_text)); @@ -1570,6 +1568,9 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS replacement_range, text: text.to_string(), }); + if text.to_string().to_ascii_lowercase() != pending_key_down.0.keystroke.key { + pending_key_down.0.keystroke.ime_key = Some(text.to_string()); + } window_state.lock().pending_key_down = Some(pending_key_down); } } diff --git a/crates/gpui/src/text_system/line_wrapper.rs b/crates/gpui/src/text_system/line_wrapper.rs index 79013adbb2..f6963dbfd4 100644 --- a/crates/gpui/src/text_system/line_wrapper.rs +++ b/crates/gpui/src/text_system/line_wrapper.rs @@ -137,7 +137,7 @@ impl Boundary { #[cfg(test)] mod tests { use super::*; - use crate::{font, TestAppContext, TestDispatcher}; + use crate::{font, TestAppContext, TestDispatcher, TextRun, WrapBoundary}; use rand::prelude::*; #[test] @@ -206,75 +206,70 @@ mod tests { }); } - // todo!("move this to a test on TextSystem::layout_text") - // todo! repeat this test - // #[test] - // fn test_wrap_shaped_line() { - // App::test().run(|cx| { - // let text_system = cx.text_system().clone(); + // For compatibility with the test macro + use crate as gpui; - // let normal = TextRun { - // len: 0, - // font: font("Helvetica"), - // color: Default::default(), - // underline: Default::default(), - // }; - // let bold = TextRun { - // len: 0, - // font: font("Helvetica").bold(), - // color: Default::default(), - // underline: Default::default(), - // }; + #[crate::test] + fn test_wrap_shaped_line(cx: &mut TestAppContext) { + cx.update(|cx| { + let text_system = cx.text_system().clone(); - // impl TextRun { - // fn with_len(&self, len: usize) -> Self { - // let mut this = self.clone(); - // this.len = len; - // this - // } - // } + let normal = TextRun { + len: 0, + font: font("Helvetica"), + color: Default::default(), + underline: Default::default(), + background_color: None, + }; + let bold = TextRun { + len: 0, + font: font("Helvetica").bold(), + color: Default::default(), + underline: Default::default(), + background_color: None, + }; - // let text = "aa bbb cccc ddddd eeee".into(); - // let lines = text_system - // .layout_text( - // &text, - // px(16.), - // &[ - // normal.with_len(4), - // bold.with_len(5), - // normal.with_len(6), - // bold.with_len(1), - // normal.with_len(7), - // ], - // None, - // ) - // .unwrap(); - // let line = &lines[0]; + impl TextRun { + fn with_len(&self, len: usize) -> Self { + let mut this = self.clone(); + this.len = len; + this + } + } - // let mut wrapper = LineWrapper::new( - // text_system.font_id(&normal.font).unwrap(), - // px(16.), - // text_system.platform_text_system.clone(), - // ); - // assert_eq!( - // wrapper - // .wrap_shaped_line(&text, &line, px(72.)) - // .collect::>(), - // &[ - // ShapedBoundary { - // run_ix: 1, - // glyph_ix: 3 - // }, - // ShapedBoundary { - // run_ix: 2, - // glyph_ix: 3 - // }, - // ShapedBoundary { - // run_ix: 4, - // glyph_ix: 2 - // } - // ], - // ); - // }); - // } + let text = "aa bbb cccc ddddd eeee".into(); + let lines = text_system + .shape_text( + text, + px(16.), + &[ + normal.with_len(4), + bold.with_len(5), + normal.with_len(6), + bold.with_len(1), + normal.with_len(7), + ], + Some(px(72.)), + ) + .unwrap(); + + assert_eq!( + lines[0].layout.wrap_boundaries(), + &[ + WrapBoundary { + run_ix: 1, + glyph_ix: 3 + }, + WrapBoundary { + run_ix: 2, + glyph_ix: 3 + }, + WrapBoundary { + run_ix: 4, + glyph_ix: 2 + } + ], + ); + }); + } } diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 187f28c14b..10c8651924 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -1904,7 +1904,16 @@ impl<'a> WindowContext<'a> { let mut this = self.to_async(); self.window .platform_window - .on_should_close(Box::new(move || this.update(|_, cx| f(cx)).unwrap_or(true))) + .on_should_close(Box::new(move || { + this.update(|_, cx| { + // Ensure that the window is removed from the app if it's been closed. + if f(cx) { + cx.remove_window(); + } + false + }) + .unwrap_or(true) + })) } } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 7ef21c42ed..f7e36fe696 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -1130,7 +1130,6 @@ mod tests { #[gpui::test] async fn test_search_simple(cx: &mut TestAppContext) { let (editor, search_bar, cx) = init_test(cx); - // todo! osiewicz: these tests asserted on background color as well, that should be brought back. let display_points_of = |background_highlights: Vec<(Range, Hsla)>| { background_highlights .into_iter() @@ -1395,7 +1394,6 @@ mod tests { }) .await .unwrap(); - // todo! osiewicz: these tests previously asserted on background color highlights; that should be introduced back. let display_points_of = |background_highlights: Vec<(Range, Hsla)>| { background_highlights .into_iter() diff --git a/crates/theme/src/styles/players.rs b/crates/theme/src/styles/players.rs index b2b797db08..508b091b8b 100644 --- a/crates/theme/src/styles/players.rs +++ b/crates/theme/src/styles/players.rs @@ -22,7 +22,7 @@ pub struct PlayerColors(pub Vec); impl Default for PlayerColors { /// Don't use this! /// We have to have a default to be `[refineable::Refinable]`. - /// todo!("Find a way to not need this for Refinable") + /// TODO "Find a way to not need this for Refinable" fn default() -> Self { Self::dark() } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 38e0bec14e..c2725eef64 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -148,6 +148,7 @@ pub fn initialize_workspace(app_state: Arc, cx: &mut AppContext) { cx.on_window_should_close(move |cx| { handle .update(cx, |workspace, cx| { + // We'll handle closing asynchoronously workspace.close_window(&Default::default(), cx); false })