mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-28 04:33:13 +03:00
Add ChannelList to AppState
This commit is contained in:
parent
43bb38206f
commit
5ecedd894d
@ -106,6 +106,7 @@ impl Element for List {
|
||||
}
|
||||
|
||||
fn paint(&mut self, bounds: RectF, _: &mut (), cx: &mut PaintContext) {
|
||||
cx.scene.push_layer(Some(bounds));
|
||||
let state = &mut *self.state.0.lock();
|
||||
let visible_range = state.visible_range(bounds.height());
|
||||
|
||||
@ -119,6 +120,7 @@ impl Element for List {
|
||||
element.paint(origin, cx);
|
||||
item_top += element.size().y();
|
||||
}
|
||||
cx.scene.pop_layer();
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
|
@ -1425,12 +1425,13 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let channels_a = ChannelList::new(client_a, &mut cx_a.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
let channels_a = cx_a.add_model(|cx| ChannelList::new(client_a, cx));
|
||||
channels_a
|
||||
.condition(&mut cx_a, |list, _| list.available_channels().is_some())
|
||||
.await;
|
||||
channels_a.read_with(&cx_a, |list, _| {
|
||||
assert_eq!(
|
||||
list.available_channels(),
|
||||
list.available_channels().unwrap(),
|
||||
&[ChannelDetails {
|
||||
id: channel_id.to_proto(),
|
||||
name: "test-channel".to_string()
|
||||
@ -1448,12 +1449,13 @@ mod tests {
|
||||
})
|
||||
.await;
|
||||
|
||||
let channels_b = ChannelList::new(client_b, &mut cx_b.to_async())
|
||||
.await
|
||||
.unwrap();
|
||||
let channels_b = cx_b.add_model(|cx| ChannelList::new(client_b, cx));
|
||||
channels_b
|
||||
.condition(&mut cx_b, |list, _| list.available_channels().is_some())
|
||||
.await;
|
||||
channels_b.read_with(&cx_b, |list, _| {
|
||||
assert_eq!(
|
||||
list.available_channels(),
|
||||
list.available_channels().unwrap(),
|
||||
&[ChannelDetails {
|
||||
id: channel_id.to_proto(),
|
||||
name: "test-channel".to_string()
|
||||
|
@ -3,9 +3,7 @@ use crate::{
|
||||
util::log_async_errors,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use gpui::{
|
||||
AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, WeakModelHandle,
|
||||
};
|
||||
use gpui::{Entity, ModelContext, ModelHandle, MutableAppContext, WeakModelHandle};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::{hash_map, BTreeSet, HashMap},
|
||||
@ -17,7 +15,7 @@ use zrpc::{
|
||||
};
|
||||
|
||||
pub struct ChannelList {
|
||||
available_channels: Vec<ChannelDetails>,
|
||||
available_channels: Option<Vec<ChannelDetails>>,
|
||||
channels: HashMap<u64, WeakModelHandle<Channel>>,
|
||||
rpc: Arc<Client>,
|
||||
}
|
||||
@ -55,21 +53,32 @@ impl Entity for ChannelList {
|
||||
}
|
||||
|
||||
impl ChannelList {
|
||||
pub async fn new(rpc: Arc<rpc::Client>, cx: &mut AsyncAppContext) -> Result<ModelHandle<Self>> {
|
||||
let response = rpc
|
||||
.request(proto::GetChannels {})
|
||||
.await
|
||||
.context("failed to fetch available channels")?;
|
||||
|
||||
Ok(cx.add_model(|_| Self {
|
||||
available_channels: response.channels.into_iter().map(Into::into).collect(),
|
||||
pub fn new(rpc: Arc<rpc::Client>, cx: &mut ModelContext<Self>) -> Self {
|
||||
cx.spawn(|this, mut cx| {
|
||||
let rpc = rpc.clone();
|
||||
log_async_errors(async move {
|
||||
let response = rpc
|
||||
.request(proto::GetChannels {})
|
||||
.await
|
||||
.context("failed to fetch available channels")?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.available_channels =
|
||||
Some(response.channels.into_iter().map(Into::into).collect());
|
||||
cx.notify();
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
Self {
|
||||
available_channels: None,
|
||||
channels: Default::default(),
|
||||
rpc,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn available_channels(&self) -> &[ChannelDetails] {
|
||||
&self.available_channels
|
||||
pub fn available_channels(&self) -> Option<&[ChannelDetails]> {
|
||||
self.available_channels.as_ref().map(Vec::as_slice)
|
||||
}
|
||||
|
||||
pub fn get_channel(
|
||||
@ -82,8 +91,8 @@ impl ChannelList {
|
||||
hash_map::Entry::Vacant(entry) => {
|
||||
if let Some(details) = self
|
||||
.available_channels
|
||||
.iter()
|
||||
.find(|details| details.id == id)
|
||||
.as_ref()
|
||||
.and_then(|channels| channels.iter().find(|details| details.id == id))
|
||||
{
|
||||
let rpc = self.rpc.clone();
|
||||
let channel = cx.add_model(|cx| Channel::new(details.clone(), rpc, cx));
|
||||
|
@ -1,38 +1,48 @@
|
||||
use crate::Settings;
|
||||
|
||||
use super::channel::{Channel, ChannelList};
|
||||
use super::{
|
||||
channel::{Channel, ChannelList},
|
||||
Settings,
|
||||
};
|
||||
use gpui::{elements::*, Entity, ModelHandle, RenderContext, View, ViewContext};
|
||||
use postage::watch;
|
||||
|
||||
pub struct ChatPanel {
|
||||
// channel_list: ModelHandle<ChannelList>,
|
||||
// active_channel: Option<ModelHandle<Channel>>,
|
||||
channel_list: ModelHandle<ChannelList>,
|
||||
active_channel: Option<ModelHandle<Channel>>,
|
||||
// active_channel_subscription: Subscription,
|
||||
messages: ListState,
|
||||
}
|
||||
|
||||
pub enum Event {}
|
||||
|
||||
impl ChatPanel {
|
||||
pub fn new(settings: watch::Receiver<Settings>) -> Self {
|
||||
let settings = settings.borrow();
|
||||
let mut messages = Vec::new();
|
||||
for i in 0..1000 {
|
||||
messages.push(
|
||||
Container::new(
|
||||
Label::new(
|
||||
format!("This is message {}", i),
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_style(&settings.theme.selector.label)
|
||||
.boxed(),
|
||||
)
|
||||
.boxed(),
|
||||
);
|
||||
}
|
||||
Self {
|
||||
messages: ListState::new(messages),
|
||||
pub fn new(
|
||||
channel_list: ModelHandle<ChannelList>,
|
||||
settings: watch::Receiver<Settings>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
let mut this = Self {
|
||||
channel_list,
|
||||
messages: ListState::new(Vec::new()),
|
||||
active_channel: None,
|
||||
};
|
||||
let channel = this.channel_list.update(cx, |list, cx| {
|
||||
if let Some(channel_id) = list
|
||||
.available_channels()
|
||||
.and_then(|channels| channels.first())
|
||||
.map(|details| details.id)
|
||||
{
|
||||
return list.get_channel(channel_id, cx);
|
||||
}
|
||||
None
|
||||
});
|
||||
if let Some(channel) = channel {
|
||||
this.set_active_channel(channel);
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
pub fn set_active_channel(&mut self, channel: ModelHandle<Channel>) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2596,8 +2596,9 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
editor::Point,
|
||||
language::LanguageRegistry,
|
||||
settings,
|
||||
test::{build_app_state, sample_text},
|
||||
test::{build_settings, sample_text},
|
||||
};
|
||||
use buffer::History;
|
||||
use unindent::Unindent;
|
||||
@ -4120,8 +4121,9 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_select_larger_smaller_syntax_node(mut cx: gpui::TestAppContext) {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let lang = app_state.languages.select_language("z.rs");
|
||||
let settings = cx.read(build_settings);
|
||||
let languages = LanguageRegistry::new();
|
||||
let lang = languages.select_language("z.rs");
|
||||
let text = r#"
|
||||
use mod1::mod2::{mod3, mod4};
|
||||
|
||||
@ -4134,8 +4136,7 @@ mod tests {
|
||||
let history = History::new(text.into());
|
||||
Buffer::from_history(0, history, None, lang.cloned(), cx)
|
||||
});
|
||||
let (_, view) =
|
||||
cx.add_window(|cx| Editor::for_buffer(buffer, app_state.settings.clone(), cx));
|
||||
let (_, view) = cx.add_window(|cx| Editor::for_buffer(buffer, settings.clone(), cx));
|
||||
view.condition(&cx, |view, cx| !view.buffer.read(cx).is_parsing())
|
||||
.await;
|
||||
|
||||
|
@ -2641,7 +2641,7 @@ impl<'a> Into<proto::Operation> for &'a Operation {
|
||||
},
|
||||
),
|
||||
#[cfg(test)]
|
||||
Operation::Test(_) => unimplemented!()
|
||||
Operation::Test(_) => unimplemented!(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -2895,7 +2895,8 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
fs::RealFs,
|
||||
test::{build_app_state, temp_tree},
|
||||
language::LanguageRegistry,
|
||||
test::temp_tree,
|
||||
util::RandomCharIter,
|
||||
worktree::{Worktree, WorktreeHandle as _},
|
||||
};
|
||||
@ -3825,8 +3826,8 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_reparse(mut cx: gpui::TestAppContext) {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let rust_lang = app_state.languages.select_language("test.rs");
|
||||
let languages = LanguageRegistry::new();
|
||||
let rust_lang = languages.select_language("test.rs");
|
||||
assert!(rust_lang.is_some());
|
||||
|
||||
let buffer = cx.add_model(|cx| {
|
||||
@ -3966,8 +3967,8 @@ mod tests {
|
||||
async fn test_enclosing_bracket_ranges(mut cx: gpui::TestAppContext) {
|
||||
use unindent::Unindent as _;
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let rust_lang = app_state.languages.select_language("test.rs");
|
||||
let languages = LanguageRegistry::new();
|
||||
let rust_lang = languages.select_language("test.rs");
|
||||
assert!(rust_lang.is_some());
|
||||
|
||||
let buffer = cx.add_model(|cx| {
|
||||
|
@ -455,7 +455,7 @@ mod tests {
|
||||
editor::init(cx);
|
||||
});
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
@ -515,7 +515,7 @@ mod tests {
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut app_state = cx.read(build_app_state);
|
||||
let mut app_state = cx.update(build_app_state);
|
||||
Arc::get_mut(&mut app_state).unwrap().fs = fs;
|
||||
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
@ -577,7 +577,7 @@ mod tests {
|
||||
fs::create_dir(&dir_path).unwrap();
|
||||
fs::write(&file_path, "").unwrap();
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
@ -624,7 +624,7 @@ mod tests {
|
||||
"dir2": { "a.txt": "" }
|
||||
}));
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
|
||||
workspace
|
||||
|
@ -19,7 +19,8 @@ mod util;
|
||||
pub mod workspace;
|
||||
pub mod worktree;
|
||||
|
||||
use gpui::action;
|
||||
use channel::ChannelList;
|
||||
use gpui::{action, ModelHandle};
|
||||
pub use settings::Settings;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
@ -36,6 +37,7 @@ pub struct AppState {
|
||||
pub themes: Arc<settings::ThemeRegistry>,
|
||||
pub rpc: Arc<rpc::Client>,
|
||||
pub fs: Arc<dyn fs::Fs>,
|
||||
pub channel_list: ModelHandle<ChannelList>,
|
||||
}
|
||||
|
||||
pub fn init(cx: &mut gpui::MutableAppContext) {
|
||||
|
@ -7,7 +7,9 @@ use parking_lot::Mutex;
|
||||
use simplelog::SimpleLogger;
|
||||
use std::{fs, path::PathBuf, sync::Arc};
|
||||
use zed::{
|
||||
self, assets, editor, file_finder,
|
||||
self, assets,
|
||||
channel::ChannelList,
|
||||
editor, file_finder,
|
||||
fs::RealFs,
|
||||
language, menus, rpc, settings, theme_selector,
|
||||
workspace::{self, OpenParams, OpenPaths},
|
||||
@ -25,17 +27,17 @@ fn main() {
|
||||
let languages = Arc::new(language::LanguageRegistry::new());
|
||||
languages.set_theme(&settings.borrow().theme);
|
||||
|
||||
let app_state = AppState {
|
||||
languages: languages.clone(),
|
||||
settings_tx: Arc::new(Mutex::new(settings_tx)),
|
||||
settings,
|
||||
themes,
|
||||
rpc: rpc::Client::new(),
|
||||
fs: Arc::new(RealFs),
|
||||
};
|
||||
|
||||
app.run(move |cx| {
|
||||
let app_state = Arc::new(app_state);
|
||||
let rpc = rpc::Client::new();
|
||||
let app_state = Arc::new(AppState {
|
||||
languages: languages.clone(),
|
||||
settings_tx: Arc::new(Mutex::new(settings_tx)),
|
||||
settings,
|
||||
themes,
|
||||
channel_list: cx.add_model(|cx| ChannelList::new(rpc.clone(), cx)),
|
||||
rpc,
|
||||
fs: Arc::new(RealFs),
|
||||
});
|
||||
|
||||
zed::init(cx);
|
||||
workspace::init(cx);
|
||||
|
@ -1,13 +1,15 @@
|
||||
use crate::{
|
||||
channel::ChannelList,
|
||||
fs::RealFs,
|
||||
language::LanguageRegistry,
|
||||
rpc,
|
||||
settings::{self, ThemeRegistry},
|
||||
time::ReplicaId,
|
||||
AppState,
|
||||
AppState, Settings,
|
||||
};
|
||||
use gpui::{AppContext, Entity, ModelHandle};
|
||||
use gpui::{AppContext, Entity, ModelHandle, MutableAppContext};
|
||||
use parking_lot::Mutex;
|
||||
use postage::watch;
|
||||
use smol::channel;
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
@ -153,16 +155,22 @@ fn write_tree(path: &Path, tree: serde_json::Value) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_app_state(cx: &AppContext) -> Arc<AppState> {
|
||||
pub fn build_settings(cx: &AppContext) -> watch::Receiver<Settings> {
|
||||
settings::channel(&cx.font_cache()).unwrap().1
|
||||
}
|
||||
|
||||
pub fn build_app_state(cx: &mut MutableAppContext) -> Arc<AppState> {
|
||||
let (settings_tx, settings) = settings::channel(&cx.font_cache()).unwrap();
|
||||
let languages = Arc::new(LanguageRegistry::new());
|
||||
let themes = ThemeRegistry::new(());
|
||||
let rpc = rpc::Client::new();
|
||||
Arc::new(AppState {
|
||||
settings_tx: Arc::new(Mutex::new(settings_tx)),
|
||||
settings,
|
||||
themes,
|
||||
languages: languages.clone(),
|
||||
rpc: rpc::Client::new(),
|
||||
channel_list: cx.add_model(|cx| ChannelList::new(rpc.clone(), cx)),
|
||||
rpc,
|
||||
fs: Arc::new(RealFs),
|
||||
})
|
||||
}
|
||||
|
@ -372,8 +372,14 @@ impl Workspace {
|
||||
let mut right_sidebar = Sidebar::new(Side::Right);
|
||||
right_sidebar.add_item(
|
||||
"icons/comment-16.svg",
|
||||
cx.add_view(|_| ChatPanel::new(app_state.settings.clone()))
|
||||
.into(),
|
||||
cx.add_view(|cx| {
|
||||
ChatPanel::new(
|
||||
app_state.channel_list.clone(),
|
||||
app_state.settings.clone(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.into(),
|
||||
);
|
||||
right_sidebar.add_item("icons/user-16.svg", cx.add_view(|_| ProjectBrowser).into());
|
||||
|
||||
@ -1018,7 +1024,7 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_open_paths_action(mut cx: gpui::TestAppContext) {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let dir = temp_tree(json!({
|
||||
"a": {
|
||||
"aa": null,
|
||||
@ -1091,7 +1097,7 @@ mod tests {
|
||||
},
|
||||
}));
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
workspace
|
||||
@ -1195,7 +1201,7 @@ mod tests {
|
||||
fs.insert_file("/dir1/a.txt", "".into()).await.unwrap();
|
||||
fs.insert_file("/dir2/b.txt", "".into()).await.unwrap();
|
||||
|
||||
let mut app_state = cx.read(build_app_state);
|
||||
let mut app_state = cx.update(build_app_state);
|
||||
Arc::get_mut(&mut app_state).unwrap().fs = Arc::new(fs);
|
||||
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
@ -1264,7 +1270,7 @@ mod tests {
|
||||
"a.txt": "",
|
||||
}));
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
@ -1309,7 +1315,7 @@ mod tests {
|
||||
#[gpui::test]
|
||||
async fn test_open_and_save_new_file(mut cx: gpui::TestAppContext) {
|
||||
let dir = TempDir::new("test-new-file").unwrap();
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let (_, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
@ -1408,7 +1414,7 @@ mod tests {
|
||||
async fn test_new_empty_workspace(mut cx: gpui::TestAppContext) {
|
||||
cx.update(init);
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
cx.dispatch_global_action(OpenNew(app_state));
|
||||
let window_id = *cx.window_ids().first().unwrap();
|
||||
let workspace = cx.root_view::<Workspace>(window_id).unwrap();
|
||||
@ -1454,7 +1460,7 @@ mod tests {
|
||||
},
|
||||
}));
|
||||
|
||||
let app_state = cx.read(build_app_state);
|
||||
let app_state = cx.update(build_app_state);
|
||||
let (window_id, workspace) = cx.add_window(|cx| Workspace::new(&app_state, cx));
|
||||
workspace
|
||||
.update(&mut cx, |workspace, cx| {
|
||||
|
@ -2640,13 +2640,12 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_save_file(mut cx: gpui::TestAppContext) {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let dir = temp_tree(json!({
|
||||
"file1": "the old contents",
|
||||
}));
|
||||
let tree = Worktree::open_local(
|
||||
dir.path(),
|
||||
app_state.languages.clone(),
|
||||
Arc::new(LanguageRegistry::new()),
|
||||
Arc::new(RealFs),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
@ -2668,7 +2667,6 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_save_in_single_file_worktree(mut cx: gpui::TestAppContext) {
|
||||
let app_state = cx.read(build_app_state);
|
||||
let dir = temp_tree(json!({
|
||||
"file1": "the old contents",
|
||||
}));
|
||||
@ -2676,7 +2674,7 @@ mod tests {
|
||||
|
||||
let tree = Worktree::open_local(
|
||||
file_path.clone(),
|
||||
app_state.languages.clone(),
|
||||
Arc::new(LanguageRegistry::new()),
|
||||
Arc::new(RealFs),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user