Get more of chat panel compiling, but lots of todos
This commit is contained in:
parent
6955579f19
commit
213ed2028c
12 changed files with 1058 additions and 992 deletions
|
@ -8,7 +8,8 @@ use collections::{hash_map, HashMap, HashSet};
|
|||
use db::RELEASE_CHANNEL;
|
||||
use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt};
|
||||
use gpui::{
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task, WeakModel,
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, SharedString, Task,
|
||||
WeakModel,
|
||||
};
|
||||
use rpc::{
|
||||
proto::{self, ChannelVisibility},
|
||||
|
@ -46,7 +47,7 @@ pub struct ChannelStore {
|
|||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Channel {
|
||||
pub id: ChannelId,
|
||||
pub name: String,
|
||||
pub name: SharedString,
|
||||
pub visibility: proto::ChannelVisibility,
|
||||
pub role: proto::ChannelRole,
|
||||
pub unseen_note_version: Option<(u64, clock::Global)>,
|
||||
|
@ -895,14 +896,16 @@ impl ChannelStore {
|
|||
.channel_invitations
|
||||
.binary_search_by_key(&channel.id, |c| c.id)
|
||||
{
|
||||
Ok(ix) => Arc::make_mut(&mut self.channel_invitations[ix]).name = channel.name,
|
||||
Ok(ix) => {
|
||||
Arc::make_mut(&mut self.channel_invitations[ix]).name = channel.name.into()
|
||||
}
|
||||
Err(ix) => self.channel_invitations.insert(
|
||||
ix,
|
||||
Arc::new(Channel {
|
||||
id: channel.id,
|
||||
visibility: channel.visibility(),
|
||||
role: channel.role(),
|
||||
name: channel.name,
|
||||
name: channel.name.into(),
|
||||
unseen_note_version: None,
|
||||
unseen_message_id: None,
|
||||
parent_path: channel.parent_path,
|
||||
|
|
|
@ -104,7 +104,7 @@ impl<'a> ChannelPathsInsertGuard<'a> {
|
|||
|
||||
existing_channel.visibility = channel_proto.visibility();
|
||||
existing_channel.role = channel_proto.role();
|
||||
existing_channel.name = channel_proto.name;
|
||||
existing_channel.name = channel_proto.name.into();
|
||||
} else {
|
||||
self.channels_by_id.insert(
|
||||
channel_proto.id,
|
||||
|
@ -112,7 +112,7 @@ impl<'a> ChannelPathsInsertGuard<'a> {
|
|||
id: channel_proto.id,
|
||||
visibility: channel_proto.visibility(),
|
||||
role: channel_proto.role(),
|
||||
name: channel_proto.name,
|
||||
name: channel_proto.name.into(),
|
||||
unseen_note_version: None,
|
||||
unseen_message_id: None,
|
||||
parent_path: channel_proto.parent_path,
|
||||
|
@ -146,11 +146,11 @@ fn channel_path_sorting_key<'a>(
|
|||
let (parent_path, name) = channels_by_id
|
||||
.get(&id)
|
||||
.map_or((&[] as &[_], None), |channel| {
|
||||
(channel.parent_path.as_slice(), Some(channel.name.as_str()))
|
||||
(channel.parent_path.as_slice(), Some(channel.name.as_ref()))
|
||||
});
|
||||
parent_path
|
||||
.iter()
|
||||
.filter_map(|id| Some(channels_by_id.get(id)?.name.as_str()))
|
||||
.filter_map(|id| Some(channels_by_id.get(id)?.name.as_ref()))
|
||||
.chain(name)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use call::ActiveCall;
|
|||
use channel::{ChannelId, ChannelMembership, ChannelStore};
|
||||
use client::User;
|
||||
use futures::future::try_join_all;
|
||||
use gpui::{BackgroundExecutor, Model, TestAppContext};
|
||||
use gpui::{BackgroundExecutor, Model, SharedString, TestAppContext};
|
||||
use rpc::{
|
||||
proto::{self, ChannelRole},
|
||||
RECEIVE_TIMEOUT,
|
||||
|
@ -46,13 +46,13 @@ async fn test_core_channels(
|
|||
&[
|
||||
ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
ExpectedChannel {
|
||||
id: channel_b_id,
|
||||
name: "channel-b".to_string(),
|
||||
name: "channel-b".into(),
|
||||
depth: 1,
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
|
@ -92,7 +92,7 @@ async fn test_core_channels(
|
|||
cx_b,
|
||||
&[ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Member,
|
||||
}],
|
||||
|
@ -140,13 +140,13 @@ async fn test_core_channels(
|
|||
&[
|
||||
ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
role: ChannelRole::Member,
|
||||
depth: 0,
|
||||
},
|
||||
ExpectedChannel {
|
||||
id: channel_b_id,
|
||||
name: "channel-b".to_string(),
|
||||
name: "channel-b".into(),
|
||||
role: ChannelRole::Member,
|
||||
depth: 1,
|
||||
},
|
||||
|
@ -168,19 +168,19 @@ async fn test_core_channels(
|
|||
&[
|
||||
ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
role: ChannelRole::Member,
|
||||
depth: 0,
|
||||
},
|
||||
ExpectedChannel {
|
||||
id: channel_b_id,
|
||||
name: "channel-b".to_string(),
|
||||
name: "channel-b".into(),
|
||||
role: ChannelRole::Member,
|
||||
depth: 1,
|
||||
},
|
||||
ExpectedChannel {
|
||||
id: channel_c_id,
|
||||
name: "channel-c".to_string(),
|
||||
name: "channel-c".into(),
|
||||
role: ChannelRole::Member,
|
||||
depth: 2,
|
||||
},
|
||||
|
@ -211,19 +211,19 @@ async fn test_core_channels(
|
|||
&[
|
||||
ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
ExpectedChannel {
|
||||
id: channel_b_id,
|
||||
name: "channel-b".to_string(),
|
||||
name: "channel-b".into(),
|
||||
depth: 1,
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
ExpectedChannel {
|
||||
id: channel_c_id,
|
||||
name: "channel-c".to_string(),
|
||||
name: "channel-c".into(),
|
||||
depth: 2,
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
|
@ -245,7 +245,7 @@ async fn test_core_channels(
|
|||
cx_a,
|
||||
&[ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Admin,
|
||||
}],
|
||||
|
@ -255,7 +255,7 @@ async fn test_core_channels(
|
|||
cx_b,
|
||||
&[ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Admin,
|
||||
}],
|
||||
|
@ -278,7 +278,7 @@ async fn test_core_channels(
|
|||
cx_a,
|
||||
&[ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a".to_string(),
|
||||
name: "channel-a".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Admin,
|
||||
}],
|
||||
|
@ -309,7 +309,7 @@ async fn test_core_channels(
|
|||
cx_a,
|
||||
&[ExpectedChannel {
|
||||
id: channel_a_id,
|
||||
name: "channel-a-renamed".to_string(),
|
||||
name: "channel-a-renamed".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Admin,
|
||||
}],
|
||||
|
@ -418,7 +418,7 @@ async fn test_channel_room(
|
|||
cx_b,
|
||||
&[ExpectedChannel {
|
||||
id: zed_id,
|
||||
name: "zed".to_string(),
|
||||
name: "zed".into(),
|
||||
depth: 0,
|
||||
role: ChannelRole::Member,
|
||||
}],
|
||||
|
@ -680,7 +680,7 @@ async fn test_permissions_update_while_invited(
|
|||
&[ExpectedChannel {
|
||||
depth: 0,
|
||||
id: rust_id,
|
||||
name: "rust".to_string(),
|
||||
name: "rust".into(),
|
||||
role: ChannelRole::Member,
|
||||
}],
|
||||
);
|
||||
|
@ -708,7 +708,7 @@ async fn test_permissions_update_while_invited(
|
|||
&[ExpectedChannel {
|
||||
depth: 0,
|
||||
id: rust_id,
|
||||
name: "rust".to_string(),
|
||||
name: "rust".into(),
|
||||
role: ChannelRole::Member,
|
||||
}],
|
||||
);
|
||||
|
@ -747,7 +747,7 @@ async fn test_channel_rename(
|
|||
&[ExpectedChannel {
|
||||
depth: 0,
|
||||
id: rust_id,
|
||||
name: "rust-archive".to_string(),
|
||||
name: "rust-archive".into(),
|
||||
role: ChannelRole::Admin,
|
||||
}],
|
||||
);
|
||||
|
@ -759,7 +759,7 @@ async fn test_channel_rename(
|
|||
&[ExpectedChannel {
|
||||
depth: 0,
|
||||
id: rust_id,
|
||||
name: "rust-archive".to_string(),
|
||||
name: "rust-archive".into(),
|
||||
role: ChannelRole::Member,
|
||||
}],
|
||||
);
|
||||
|
@ -888,7 +888,7 @@ async fn test_lost_channel_creation(
|
|||
&[ExpectedChannel {
|
||||
depth: 0,
|
||||
id: channel_id,
|
||||
name: "x".to_string(),
|
||||
name: "x".into(),
|
||||
role: ChannelRole::Member,
|
||||
}],
|
||||
);
|
||||
|
@ -912,13 +912,13 @@ async fn test_lost_channel_creation(
|
|||
ExpectedChannel {
|
||||
depth: 0,
|
||||
id: channel_id,
|
||||
name: "x".to_string(),
|
||||
name: "x".into(),
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
ExpectedChannel {
|
||||
depth: 1,
|
||||
id: subchannel_id,
|
||||
name: "subchannel".to_string(),
|
||||
name: "subchannel".into(),
|
||||
role: ChannelRole::Admin,
|
||||
},
|
||||
],
|
||||
|
@ -943,13 +943,13 @@ async fn test_lost_channel_creation(
|
|||
ExpectedChannel {
|
||||
depth: 0,
|
||||
id: channel_id,
|
||||
name: "x".to_string(),
|
||||
name: "x".into(),
|
||||
role: ChannelRole::Member,
|
||||
},
|
||||
ExpectedChannel {
|
||||
depth: 1,
|
||||
id: subchannel_id,
|
||||
name: "subchannel".to_string(),
|
||||
name: "subchannel".into(),
|
||||
role: ChannelRole::Member,
|
||||
},
|
||||
],
|
||||
|
@ -1221,13 +1221,13 @@ async fn test_channel_membership_notifications(
|
|||
ExpectedChannel {
|
||||
depth: 0,
|
||||
id: zed_channel,
|
||||
name: "zed".to_string(),
|
||||
name: "zed".into(),
|
||||
role: ChannelRole::Guest,
|
||||
},
|
||||
ExpectedChannel {
|
||||
depth: 1,
|
||||
id: vim_channel,
|
||||
name: "vim".to_string(),
|
||||
name: "vim".into(),
|
||||
role: ChannelRole::Member,
|
||||
},
|
||||
],
|
||||
|
@ -1250,13 +1250,13 @@ async fn test_channel_membership_notifications(
|
|||
ExpectedChannel {
|
||||
depth: 0,
|
||||
id: zed_channel,
|
||||
name: "zed".to_string(),
|
||||
name: "zed".into(),
|
||||
role: ChannelRole::Guest,
|
||||
},
|
||||
ExpectedChannel {
|
||||
depth: 1,
|
||||
id: vim_channel,
|
||||
name: "vim".to_string(),
|
||||
name: "vim".into(),
|
||||
role: ChannelRole::Guest,
|
||||
},
|
||||
],
|
||||
|
@ -1476,7 +1476,7 @@ async fn test_channel_moving(
|
|||
struct ExpectedChannel {
|
||||
depth: usize,
|
||||
id: ChannelId,
|
||||
name: String,
|
||||
name: SharedString,
|
||||
role: ChannelRole,
|
||||
}
|
||||
|
||||
|
@ -1515,7 +1515,7 @@ fn assert_channels(
|
|||
.ordered_channels()
|
||||
.map(|(depth, channel)| ExpectedChannel {
|
||||
depth,
|
||||
name: channel.name.clone(),
|
||||
name: channel.name.clone().into(),
|
||||
id: channel.id,
|
||||
role: channel.role,
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::db::ChannelRole;
|
|||
use super::{run_randomized_test, RandomizedTest, TestClient, TestError, TestServer, UserTestPlan};
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use gpui::{BackgroundExecutor, TestAppContext};
|
||||
use gpui::{BackgroundExecutor, SharedString, TestAppContext};
|
||||
use rand::prelude::*;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::{
|
||||
|
@ -30,13 +30,13 @@ struct RandomChannelBufferTest;
|
|||
#[derive(Clone, Serialize, Deserialize)]
|
||||
enum ChannelBufferOperation {
|
||||
JoinChannelNotes {
|
||||
channel_name: String,
|
||||
channel_name: SharedString,
|
||||
},
|
||||
LeaveChannelNotes {
|
||||
channel_name: String,
|
||||
channel_name: SharedString,
|
||||
},
|
||||
EditChannelNotes {
|
||||
channel_name: String,
|
||||
channel_name: SharedString,
|
||||
edits: Vec<(Range<usize>, Arc<str>)>,
|
||||
},
|
||||
Noop,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,9 @@ use channel::{ChannelId, ChannelMembership, ChannelStore, MessageParams};
|
|||
use client::UserId;
|
||||
use collections::HashMap;
|
||||
use editor::{AnchorRangeExt, Editor};
|
||||
use gpui::{AnyView, AsyncAppContext, Model, Render, Task, View, ViewContext, WeakView};
|
||||
use gpui::{
|
||||
AnyView, AsyncWindowContext, Model, Render, SharedString, Task, View, ViewContext, WeakView,
|
||||
};
|
||||
use language::{language_settings::SoftWrap, Buffer, BufferSnapshot, LanguageRegistry};
|
||||
use lazy_static::lazy_static;
|
||||
use project::search::SearchQuery;
|
||||
|
@ -46,15 +48,14 @@ impl MessageEditor {
|
|||
cx.subscribe(&buffer, Self::on_buffer_event).detach();
|
||||
|
||||
let markdown = language_registry.language_for_name("Markdown");
|
||||
cx.app_context()
|
||||
.spawn(|mut cx| async move {
|
||||
let markdown = markdown.await?;
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.set_language(Some(markdown), cx)
|
||||
});
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
let markdown = markdown.await?;
|
||||
buffer.update(&mut cx, |buffer, cx| {
|
||||
buffer.set_language(Some(markdown), cx)
|
||||
});
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
|
||||
Self {
|
||||
editor,
|
||||
|
@ -69,7 +70,7 @@ impl MessageEditor {
|
|||
pub fn set_channel(
|
||||
&mut self,
|
||||
channel_id: u64,
|
||||
channel_name: Option<String>,
|
||||
channel_name: Option<SharedString>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
|
@ -137,7 +138,9 @@ impl MessageEditor {
|
|||
if let language::Event::Reparsed | language::Event::Edited = event {
|
||||
let buffer = buffer.read(cx).snapshot();
|
||||
self.mentions_task = Some(cx.spawn(|this, cx| async move {
|
||||
cx.background().timer(MENTIONS_DEBOUNCE_INTERVAL).await;
|
||||
cx.background_executor()
|
||||
.timer(MENTIONS_DEBOUNCE_INTERVAL)
|
||||
.await;
|
||||
Self::find_mentions(this, buffer, cx).await;
|
||||
}));
|
||||
}
|
||||
|
@ -146,10 +149,10 @@ impl MessageEditor {
|
|||
async fn find_mentions(
|
||||
this: WeakView<MessageEditor>,
|
||||
buffer: BufferSnapshot,
|
||||
mut cx: AsyncAppContext,
|
||||
mut cx: AsyncWindowContext,
|
||||
) {
|
||||
let (buffer, ranges) = cx
|
||||
.background()
|
||||
.background_executor()
|
||||
.spawn(async move {
|
||||
let ranges = MENTIONS_SEARCH.search(&buffer, None).await;
|
||||
(buffer, ranges)
|
||||
|
@ -186,6 +189,10 @@ impl MessageEditor {
|
|||
})
|
||||
.ok();
|
||||
}
|
||||
|
||||
pub(crate) fn focus_handle(&self, cx: &gpui::AppContext) -> gpui::FocusHandle {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for MessageEditor {
|
||||
|
@ -196,98 +203,98 @@ impl Render for MessageEditor {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use client::{Client, User, UserStore};
|
||||
use gpui::{TestAppContext, WindowHandle};
|
||||
use language::{Language, LanguageConfig};
|
||||
use rpc::proto;
|
||||
use settings::SettingsStore;
|
||||
use util::{http::FakeHttpClient, test::marked_text_ranges};
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use super::*;
|
||||
// use client::{Client, User, UserStore};
|
||||
// use gpui::{TestAppContext, WindowHandle};
|
||||
// use language::{Language, LanguageConfig};
|
||||
// use rpc::proto;
|
||||
// use settings::SettingsStore;
|
||||
// use util::{http::FakeHttpClient, test::marked_text_ranges};
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_message_editor(cx: &mut TestAppContext) {
|
||||
let editor = init_test(cx);
|
||||
let editor = editor.root(cx);
|
||||
// #[gpui::test]
|
||||
// async fn test_message_editor(cx: &mut TestAppContext) {
|
||||
// let editor = init_test(cx);
|
||||
// let editor = editor.root(cx);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.set_members(
|
||||
vec![
|
||||
ChannelMembership {
|
||||
user: Arc::new(User {
|
||||
github_login: "a-b".into(),
|
||||
id: 101,
|
||||
avatar: None,
|
||||
}),
|
||||
kind: proto::channel_member::Kind::Member,
|
||||
role: proto::ChannelRole::Member,
|
||||
},
|
||||
ChannelMembership {
|
||||
user: Arc::new(User {
|
||||
github_login: "C_D".into(),
|
||||
id: 102,
|
||||
avatar: None,
|
||||
}),
|
||||
kind: proto::channel_member::Kind::Member,
|
||||
role: proto::ChannelRole::Member,
|
||||
},
|
||||
],
|
||||
cx,
|
||||
);
|
||||
// editor.update(cx, |editor, cx| {
|
||||
// editor.set_members(
|
||||
// vec![
|
||||
// ChannelMembership {
|
||||
// user: Arc::new(User {
|
||||
// github_login: "a-b".into(),
|
||||
// id: 101,
|
||||
// avatar: None,
|
||||
// }),
|
||||
// kind: proto::channel_member::Kind::Member,
|
||||
// role: proto::ChannelRole::Member,
|
||||
// },
|
||||
// ChannelMembership {
|
||||
// user: Arc::new(User {
|
||||
// github_login: "C_D".into(),
|
||||
// id: 102,
|
||||
// avatar: None,
|
||||
// }),
|
||||
// kind: proto::channel_member::Kind::Member,
|
||||
// role: proto::ChannelRole::Member,
|
||||
// },
|
||||
// ],
|
||||
// cx,
|
||||
// );
|
||||
|
||||
editor.editor.update(cx, |editor, cx| {
|
||||
editor.set_text("Hello, @a-b! Have you met @C_D?", cx)
|
||||
});
|
||||
});
|
||||
// editor.editor.update(cx, |editor, cx| {
|
||||
// editor.set_text("Hello, @a-b! Have you met @C_D?", cx)
|
||||
// });
|
||||
// });
|
||||
|
||||
cx.foreground().advance_clock(MENTIONS_DEBOUNCE_INTERVAL);
|
||||
// cx.foreground().advance_clock(MENTIONS_DEBOUNCE_INTERVAL);
|
||||
|
||||
editor.update(cx, |editor, cx| {
|
||||
let (text, ranges) = marked_text_ranges("Hello, «@a-b»! Have you met «@C_D»?", false);
|
||||
assert_eq!(
|
||||
editor.take_message(cx),
|
||||
MessageParams {
|
||||
text,
|
||||
mentions: vec![(ranges[0].clone(), 101), (ranges[1].clone(), 102)],
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
// editor.update(cx, |editor, cx| {
|
||||
// let (text, ranges) = marked_text_ranges("Hello, «@a-b»! Have you met «@C_D»?", false);
|
||||
// assert_eq!(
|
||||
// editor.take_message(cx),
|
||||
// MessageParams {
|
||||
// text,
|
||||
// mentions: vec![(ranges[0].clone(), 101), (ranges[1].clone(), 102)],
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
|
||||
fn init_test(cx: &mut TestAppContext) -> WindowHandle<MessageEditor> {
|
||||
cx.foreground().forbid_parking();
|
||||
// fn init_test(cx: &mut TestAppContext) -> WindowHandle<MessageEditor> {
|
||||
// cx.foreground().forbid_parking();
|
||||
|
||||
cx.update(|cx| {
|
||||
let http = FakeHttpClient::with_404_response();
|
||||
let client = Client::new(http.clone(), cx);
|
||||
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
|
||||
cx.set_global(SettingsStore::test(cx));
|
||||
theme::init((), cx);
|
||||
language::init(cx);
|
||||
editor::init(cx);
|
||||
client::init(&client, cx);
|
||||
channel::init(&client, user_store, cx);
|
||||
});
|
||||
// cx.update(|cx| {
|
||||
// let http = FakeHttpClient::with_404_response();
|
||||
// let client = Client::new(http.clone(), cx);
|
||||
// let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http, cx));
|
||||
// cx.set_global(SettingsStore::test(cx));
|
||||
// theme::init((), cx);
|
||||
// language::init(cx);
|
||||
// editor::init(cx);
|
||||
// client::init(&client, cx);
|
||||
// channel::init(&client, user_store, cx);
|
||||
// });
|
||||
|
||||
let language_registry = Arc::new(LanguageRegistry::test());
|
||||
language_registry.add(Arc::new(Language::new(
|
||||
LanguageConfig {
|
||||
name: "Markdown".into(),
|
||||
..Default::default()
|
||||
},
|
||||
Some(tree_sitter_markdown::language()),
|
||||
)));
|
||||
// let language_registry = Arc::new(LanguageRegistry::test());
|
||||
// language_registry.add(Arc::new(Language::new(
|
||||
// LanguageConfig {
|
||||
// name: "Markdown".into(),
|
||||
// ..Default::default()
|
||||
// },
|
||||
// Some(tree_sitter_markdown::language()),
|
||||
// )));
|
||||
|
||||
let editor = cx.add_window(|cx| {
|
||||
MessageEditor::new(
|
||||
language_registry,
|
||||
ChannelStore::global(cx),
|
||||
cx.add_view(|cx| Editor::auto_height(4, cx)),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
cx.foreground().run_until_parked();
|
||||
editor
|
||||
}
|
||||
}
|
||||
// let editor = cx.add_window(|cx| {
|
||||
// MessageEditor::new(
|
||||
// language_registry,
|
||||
// ChannelStore::global(cx),
|
||||
// cx.add_view(|cx| Editor::auto_height(4, cx)),
|
||||
// cx,
|
||||
// )
|
||||
// });
|
||||
// cx.foreground().run_until_parked();
|
||||
// editor
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -852,7 +852,7 @@ impl CollabPanel {
|
|||
.extend(channel_store.ordered_channels().enumerate().map(
|
||||
|(ix, (_, channel))| StringMatchCandidate {
|
||||
id: ix,
|
||||
string: channel.name.clone(),
|
||||
string: channel.name.clone().into(),
|
||||
char_bag: channel.name.chars().collect(),
|
||||
},
|
||||
));
|
||||
|
@ -2262,7 +2262,7 @@ impl CollabPanel {
|
|||
}
|
||||
};
|
||||
|
||||
Some(channel.name.as_str())
|
||||
Some(channel.name.as_ref())
|
||||
});
|
||||
|
||||
if let Some(name) = channel_name {
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::{rc::Rc, sync::Arc};
|
|||
use call::{report_call_event_for_room, ActiveCall, Room};
|
||||
pub use collab_panel::CollabPanel;
|
||||
pub use collab_titlebar_item::CollabTitlebarItem;
|
||||
use feature_flags::{ChannelsAlpha, FeatureFlagAppExt};
|
||||
use gpui::{
|
||||
actions, point, AppContext, GlobalPixels, Pixels, PlatformDisplay, Size, Task, WindowBounds,
|
||||
WindowKind, WindowOptions,
|
||||
|
@ -157,6 +158,6 @@ fn notification_window_options(
|
|||
// .into_any()
|
||||
// }
|
||||
|
||||
// fn is_channels_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool {
|
||||
// cx.is_staff() || cx.has_flag::<ChannelsAlpha>()
|
||||
// }
|
||||
fn is_channels_feature_enabled(cx: &gpui::WindowContext<'_>) -> bool {
|
||||
cx.is_staff() || cx.has_flag::<ChannelsAlpha>()
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use smallvec::SmallVec;
|
|||
use smol::future::FutureExt;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub use test_context::*;
|
||||
use time::UtcOffset;
|
||||
|
||||
use crate::{
|
||||
current_platform, image_cache::ImageCache, init_app_menus, Action, ActionRegistry, Any,
|
||||
|
@ -536,6 +537,10 @@ impl AppContext {
|
|||
self.platform.restart()
|
||||
}
|
||||
|
||||
pub fn local_timezone(&self) -> UtcOffset {
|
||||
self.platform.local_timezone()
|
||||
}
|
||||
|
||||
pub(crate) fn push_effect(&mut self, effect: Effect) {
|
||||
match &effect {
|
||||
Effect::Notify { emitter } => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
px, AnyElement, AvailableSpace, BorrowAppContext, DispatchPhase, Element, IntoElement, Pixels,
|
||||
Point, ScrollWheelEvent, Size, Style, StyleRefinement, ViewContext, WindowContext,
|
||||
Point, ScrollWheelEvent, Size, Style, StyleRefinement, WindowContext,
|
||||
};
|
||||
use collections::VecDeque;
|
||||
use std::{cell::RefCell, ops::Range, rc::Rc};
|
||||
|
@ -26,14 +26,14 @@ struct StateInner {
|
|||
render_item: Box<dyn FnMut(usize, &mut WindowContext) -> AnyElement>,
|
||||
items: SumTree<ListItem>,
|
||||
logical_scroll_top: Option<ListOffset>,
|
||||
orientation: Orientation,
|
||||
alignment: ListAlignment,
|
||||
overdraw: Pixels,
|
||||
#[allow(clippy::type_complexity)]
|
||||
scroll_handler: Option<Box<dyn FnMut(&ListScrollEvent, &mut WindowContext)>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Orientation {
|
||||
pub enum ListAlignment {
|
||||
Top,
|
||||
Bottom,
|
||||
}
|
||||
|
@ -70,28 +70,23 @@ struct UnrenderedCount(usize);
|
|||
struct Height(Pixels);
|
||||
|
||||
impl ListState {
|
||||
pub fn new<F, V>(
|
||||
pub fn new<F>(
|
||||
element_count: usize,
|
||||
orientation: Orientation,
|
||||
orientation: ListAlignment,
|
||||
overdraw: Pixels,
|
||||
cx: &mut ViewContext<V>,
|
||||
mut render_item: F,
|
||||
render_item: F,
|
||||
) -> Self
|
||||
where
|
||||
F: 'static + FnMut(&mut V, usize, &mut ViewContext<V>) -> AnyElement,
|
||||
V: 'static,
|
||||
F: 'static + FnMut(usize, &mut WindowContext) -> AnyElement,
|
||||
{
|
||||
let mut items = SumTree::new();
|
||||
items.extend((0..element_count).map(|_| ListItem::Unrendered), &());
|
||||
let view = cx.view().clone();
|
||||
Self(Rc::new(RefCell::new(StateInner {
|
||||
last_layout_width: None,
|
||||
render_item: Box::new(move |ix, cx| {
|
||||
view.update(cx, |view, cx| render_item(view, ix, cx))
|
||||
}),
|
||||
render_item: Box::new(render_item),
|
||||
items,
|
||||
logical_scroll_top: None,
|
||||
orientation,
|
||||
alignment: orientation,
|
||||
overdraw,
|
||||
scroll_handler: None,
|
||||
})))
|
||||
|
@ -179,7 +174,7 @@ impl StateInner {
|
|||
.max(px(0.))
|
||||
.min(scroll_max);
|
||||
|
||||
if self.orientation == Orientation::Bottom && new_scroll_top == scroll_max {
|
||||
if self.alignment == ListAlignment::Bottom && new_scroll_top == scroll_max {
|
||||
self.logical_scroll_top = None;
|
||||
} else {
|
||||
let mut cursor = self.items.cursor::<ListItemSummary>();
|
||||
|
@ -208,12 +203,12 @@ impl StateInner {
|
|||
|
||||
fn logical_scroll_top(&self) -> ListOffset {
|
||||
self.logical_scroll_top
|
||||
.unwrap_or_else(|| match self.orientation {
|
||||
Orientation::Top => ListOffset {
|
||||
.unwrap_or_else(|| match self.alignment {
|
||||
ListAlignment::Top => ListOffset {
|
||||
item_ix: 0,
|
||||
offset_in_item: px(0.),
|
||||
},
|
||||
Orientation::Bottom => ListOffset {
|
||||
ListAlignment::Bottom => ListOffset {
|
||||
item_ix: self.items.summary().count,
|
||||
offset_in_item: px(0.),
|
||||
},
|
||||
|
@ -344,12 +339,12 @@ impl Element for List {
|
|||
offset_in_item: rendered_height - bounds.size.height,
|
||||
};
|
||||
|
||||
match state.orientation {
|
||||
Orientation::Top => {
|
||||
match state.alignment {
|
||||
ListAlignment::Top => {
|
||||
scroll_top.offset_in_item = scroll_top.offset_in_item.max(px(0.));
|
||||
state.logical_scroll_top = Some(scroll_top);
|
||||
}
|
||||
Orientation::Bottom => {
|
||||
ListAlignment::Bottom => {
|
||||
scroll_top = ListOffset {
|
||||
item_ix: cursor.start().0,
|
||||
offset_in_item: rendered_height - bounds.size.height,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#[macro_use]
|
||||
mod action;
|
||||
mod app;
|
||||
|
||||
mod assets;
|
||||
mod color;
|
||||
mod element;
|
||||
|
@ -15,6 +16,7 @@ mod keymap;
|
|||
mod platform;
|
||||
pub mod prelude;
|
||||
mod scene;
|
||||
mod shared_string;
|
||||
mod style;
|
||||
mod styled;
|
||||
mod subscription;
|
||||
|
@ -57,6 +59,7 @@ pub use scene::*;
|
|||
pub use serde;
|
||||
pub use serde_derive;
|
||||
pub use serde_json;
|
||||
pub use shared_string::*;
|
||||
pub use smallvec;
|
||||
pub use smol::Timer;
|
||||
pub use style::*;
|
||||
|
@ -76,6 +79,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::{
|
||||
any::{Any, TypeId},
|
||||
borrow::{Borrow, BorrowMut},
|
||||
sync::Arc,
|
||||
};
|
||||
use taffy::TaffyLayoutEngine;
|
||||
|
||||
|
@ -210,61 +214,3 @@ impl<T> Flatten<T> for Result<T> {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deref, DerefMut, Eq, PartialEq, Hash, Clone)]
|
||||
pub struct SharedString(ArcCow<'static, str>);
|
||||
|
||||
impl Default for SharedString {
|
||||
fn default() -> Self {
|
||||
Self(ArcCow::Owned("".into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for SharedString {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for SharedString {
|
||||
fn borrow(&self) -> &str {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SharedString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SharedString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<ArcCow<'static, str>>> From<T> for SharedString {
|
||||
fn from(value: T) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SharedString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SharedString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Ok(SharedString::from(s))
|
||||
}
|
||||
}
|
||||
|
|
101
crates/gpui2/src/shared_string.rs
Normal file
101
crates/gpui2/src/shared_string.rs
Normal file
|
@ -0,0 +1,101 @@
|
|||
use derive_more::{Deref, DerefMut};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{borrow::Borrow, sync::Arc};
|
||||
use util::arc_cow::ArcCow;
|
||||
|
||||
#[derive(Deref, DerefMut, Eq, PartialEq, Hash, Clone)]
|
||||
pub struct SharedString(ArcCow<'static, str>);
|
||||
|
||||
impl Default for SharedString {
|
||||
fn default() -> Self {
|
||||
Self(ArcCow::Owned("".into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for SharedString {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for SharedString {
|
||||
fn borrow(&self) -> &str {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for SharedString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SharedString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for SharedString {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self.as_ref() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<SharedString> for String {
|
||||
fn eq(&self, other: &SharedString) -> bool {
|
||||
self == other.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for SharedString {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.as_ref() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for SharedString {
|
||||
fn eq(&self, other: &&'a str) -> bool {
|
||||
self.as_ref() == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Arc<str>> for SharedString {
|
||||
fn into(self) -> Arc<str> {
|
||||
match self.0 {
|
||||
ArcCow::Borrowed(borrowed) => Arc::from(borrowed),
|
||||
ArcCow::Owned(owned) => owned.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<ArcCow<'static, str>>> From<T> for SharedString {
|
||||
fn from(value: T) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for SharedString {
|
||||
fn into(self) -> String {
|
||||
self.0.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for SharedString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SharedString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Ok(SharedString::from(s))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue