mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-25 20:11:49 +03:00
Simplify handling of syncing versions
Currently whenever a channel changes we send a huge amount of data to each member. This is the first step in reducing that Co-Authored-By: Max <max@zed.dev> Co-Authored-By: bennetbo <bennetbo@gmx.de>
This commit is contained in:
parent
b72c037199
commit
716221cd38
@ -29,35 +29,47 @@ pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
|
|||||||
|
|
||||||
pub type ChannelId = u64;
|
pub type ChannelId = u64;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
struct NotesVersion {
|
||||||
|
epoch: u64,
|
||||||
|
version: clock::Global,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ChannelStore {
|
pub struct ChannelStore {
|
||||||
pub channel_index: ChannelIndex,
|
pub channel_index: ChannelIndex,
|
||||||
channel_invitations: Vec<Arc<Channel>>,
|
channel_invitations: Vec<Arc<Channel>>,
|
||||||
channel_participants: HashMap<ChannelId, Vec<Arc<User>>>,
|
channel_participants: HashMap<ChannelId, Vec<Arc<User>>>,
|
||||||
observed_chat_messages: HashMap<ChannelId, u64>,
|
channel_states: HashMap<ChannelId, ChannelState>,
|
||||||
observed_notes_versions: HashMap<ChannelId, proto::NotesVersion>,
|
|
||||||
outgoing_invites: HashSet<(ChannelId, UserId)>,
|
outgoing_invites: HashSet<(ChannelId, UserId)>,
|
||||||
update_channels_tx: mpsc::UnboundedSender<proto::UpdateChannels>,
|
update_channels_tx: mpsc::UnboundedSender<proto::UpdateChannels>,
|
||||||
opened_buffers: HashMap<ChannelId, OpenedModelHandle<ChannelBuffer>>,
|
opened_buffers: HashMap<ChannelId, OpenedModelHandle<ChannelBuffer>>,
|
||||||
opened_chats: HashMap<ChannelId, OpenedModelHandle<ChannelChat>>,
|
opened_chats: HashMap<ChannelId, OpenedModelHandle<ChannelChat>>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
user_store: Model<UserStore>,
|
user_store: Model<UserStore>,
|
||||||
_rpc_subscription: Subscription,
|
_rpc_subscriptions: [Subscription; 2],
|
||||||
_watch_connection_status: Task<Option<()>>,
|
_watch_connection_status: Task<Option<()>>,
|
||||||
disconnect_channel_buffers_task: Option<Task<()>>,
|
disconnect_channel_buffers_task: Option<Task<()>>,
|
||||||
_update_channels: Task<()>,
|
_update_channels: Task<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
pub id: ChannelId,
|
pub id: ChannelId,
|
||||||
pub name: SharedString,
|
pub name: SharedString,
|
||||||
pub visibility: proto::ChannelVisibility,
|
pub visibility: proto::ChannelVisibility,
|
||||||
pub role: proto::ChannelRole,
|
pub role: proto::ChannelRole,
|
||||||
pub latest_message_id: Option<u64>,
|
|
||||||
pub latest_note_version: Option<proto::NotesVersion>,
|
|
||||||
pub parent_path: Vec<u64>,
|
pub parent_path: Vec<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ChannelState {
|
||||||
|
latest_chat_message: Option<u64>,
|
||||||
|
latest_notes_versions: Option<NotesVersion>,
|
||||||
|
observed_chat_message: Option<u64>,
|
||||||
|
observed_notes_versions: Option<NotesVersion>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
pub fn link(&self) -> String {
|
pub fn link(&self) -> String {
|
||||||
RELEASE_CHANNEL.link_prefix().to_owned()
|
RELEASE_CHANNEL.link_prefix().to_owned()
|
||||||
@ -179,7 +191,7 @@ impl ChannelStore {
|
|||||||
update_channels_tx,
|
update_channels_tx,
|
||||||
client,
|
client,
|
||||||
user_store,
|
user_store,
|
||||||
_rpc_subscription: rpc_subscription,
|
_rpc_subscriptions: rpc_subscriptions,
|
||||||
_watch_connection_status: watch_connection_status,
|
_watch_connection_status: watch_connection_status,
|
||||||
disconnect_channel_buffers_task: None,
|
disconnect_channel_buffers_task: None,
|
||||||
_update_channels: cx.spawn(|this, mut cx| async move {
|
_update_channels: cx.spawn(|this, mut cx| async move {
|
||||||
@ -199,8 +211,7 @@ impl ChannelStore {
|
|||||||
.await
|
.await
|
||||||
.log_err();
|
.log_err();
|
||||||
}),
|
}),
|
||||||
observed_chat_messages: Default::default(),
|
channel_states: Default::default(),
|
||||||
observed_notes_versions: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,39 +323,16 @@ impl ChannelStore {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_channel_buffer_changed(&self, channel_id: ChannelId) -> Option<bool> {
|
pub fn has_channel_buffer_changed(&self, channel_id: ChannelId) -> bool {
|
||||||
self.channel_index
|
self.channel_states
|
||||||
.by_id()
|
|
||||||
.get(&channel_id)
|
.get(&channel_id)
|
||||||
.map(|channel| channel.unseen_note_version.is_some())
|
.is_some_and(|state| state.has_channel_buffer_changed())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_new_messages(&self, channel_id: ChannelId) -> Option<bool> {
|
pub fn has_new_messages(&self, channel_id: ChannelId) -> bool {
|
||||||
self.channel_index
|
self.channel_states
|
||||||
.by_id()
|
|
||||||
.get(&channel_id)
|
.get(&channel_id)
|
||||||
.map(|channel| channel.unseen_message_id.is_some())
|
.is_some_and(|state| state.has_new_messages())
|
||||||
}
|
|
||||||
|
|
||||||
pub fn notes_changed(
|
|
||||||
&mut self,
|
|
||||||
channel_id: ChannelId,
|
|
||||||
epoch: u64,
|
|
||||||
version: &clock::Global,
|
|
||||||
cx: &mut ModelContext<Self>,
|
|
||||||
) {
|
|
||||||
self.channel_index.note_changed(channel_id, epoch, version);
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_message(
|
|
||||||
&mut self,
|
|
||||||
channel_id: ChannelId,
|
|
||||||
message_id: u64,
|
|
||||||
cx: &mut ModelContext<Self>,
|
|
||||||
) {
|
|
||||||
self.channel_index.new_message(channel_id, message_id);
|
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acknowledge_message_id(
|
pub fn acknowledge_message_id(
|
||||||
@ -353,8 +341,23 @@ impl ChannelStore {
|
|||||||
message_id: u64,
|
message_id: u64,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.channel_index
|
self.channel_states
|
||||||
.acknowledge_message_id(channel_id, message_id);
|
.entry(channel_id)
|
||||||
|
.or_insert_with(|| Default::default())
|
||||||
|
.acknowledge_message_id(message_id);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_latest_message_id(
|
||||||
|
&mut self,
|
||||||
|
channel_id: ChannelId,
|
||||||
|
message_id: u64,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) {
|
||||||
|
self.channel_states
|
||||||
|
.entry(channel_id)
|
||||||
|
.or_insert_with(|| Default::default())
|
||||||
|
.update_latest_message_id(message_id);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,9 +368,25 @@ impl ChannelStore {
|
|||||||
version: &clock::Global,
|
version: &clock::Global,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.channel_index
|
self.channel_states
|
||||||
.acknowledge_note_version(channel_id, epoch, version);
|
.entry(channel_id)
|
||||||
cx.notify();
|
.or_insert_with(|| Default::default())
|
||||||
|
.acknowledge_notes_version(epoch, version);
|
||||||
|
cx.notify()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_latest_notes_version(
|
||||||
|
&mut self,
|
||||||
|
channel_id: ChannelId,
|
||||||
|
epoch: u64,
|
||||||
|
version: &clock::Global,
|
||||||
|
cx: &mut ModelContext<Self>,
|
||||||
|
) {
|
||||||
|
self.channel_states
|
||||||
|
.entry(channel_id)
|
||||||
|
.or_insert_with(|| Default::default())
|
||||||
|
.update_latest_notes_version(epoch, version);
|
||||||
|
cx.notify()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_channel_chat(
|
pub fn open_channel_chat(
|
||||||
@ -755,15 +774,24 @@ impl ChannelStore {
|
|||||||
|
|
||||||
async fn handle_update_user_channels(
|
async fn handle_update_user_channels(
|
||||||
this: Model<Self>,
|
this: Model<Self>,
|
||||||
message: TypedEnvelope<proto::ObservedChannelMessage>,
|
message: TypedEnvelope<proto::UpdateUserChannels>,
|
||||||
_: Arc<Client>,
|
_: Arc<Client>,
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
this.update(&mut cx, |this, _| {
|
this.update(&mut cx, |this, cx| {
|
||||||
// this.seen_channel_message_ids
|
for buffer_version in message.payload.observed_channel_buffer_version {
|
||||||
// .insert(message.channel_id, message.message_id);
|
let version = language::proto::deserialize_version(&buffer_version.version);
|
||||||
cx.notify();
|
this.acknowledge_notes_version(
|
||||||
})?;
|
buffer_version.channel_id,
|
||||||
|
buffer_version.epoch,
|
||||||
|
&version,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for message_id in message.payload.observed_channel_message_id {
|
||||||
|
this.acknowledge_message_id(message_id.channel_id, message_id.message_id, cx);
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_connect(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
fn handle_connect(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
||||||
@ -938,8 +966,8 @@ impl ChannelStore {
|
|||||||
|
|
||||||
let channels_changed = !payload.channels.is_empty()
|
let channels_changed = !payload.channels.is_empty()
|
||||||
|| !payload.delete_channels.is_empty()
|
|| !payload.delete_channels.is_empty()
|
||||||
|| !payload.unseen_channel_messages.is_empty()
|
|| !payload.latest_channel_message_ids.is_empty()
|
||||||
|| !payload.unseen_channel_buffer_changes.is_empty();
|
|| !payload.latest_channel_buffer_versions.is_empty();
|
||||||
|
|
||||||
if channels_changed {
|
if channels_changed {
|
||||||
if !payload.delete_channels.is_empty() {
|
if !payload.delete_channels.is_empty() {
|
||||||
@ -980,20 +1008,19 @@ impl ChannelStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for unseen_buffer_change in payload.unseen_channel_buffer_changes {
|
for latest_buffer_version in payload.latest_channel_buffer_versions {
|
||||||
let version = language::proto::deserialize_version(&unseen_buffer_change.version);
|
let version = language::proto::deserialize_version(&latest_buffer_version.version);
|
||||||
index.note_changed(
|
self.channel_states
|
||||||
unseen_buffer_change.channel_id,
|
.entry(latest_buffer_version.channel_id)
|
||||||
unseen_buffer_change.epoch,
|
.or_default()
|
||||||
&version,
|
.update_latest_notes_version(latest_buffer_version.epoch, &version)
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for unseen_channel_message in payload.unseen_channel_messages {
|
for latest_channel_message in payload.latest_channel_message_ids {
|
||||||
index.new_messages(
|
self.channel_states
|
||||||
unseen_channel_message.channel_id,
|
.entry(latest_channel_message.channel_id)
|
||||||
unseen_channel_message.message_id,
|
.or_default()
|
||||||
);
|
.update_latest_message_id(latest_channel_message.message_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,3 +1069,65 @@ impl ChannelStore {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ChannelState {
|
||||||
|
fn has_channel_buffer_changed(&self) -> bool {
|
||||||
|
if let Some(latest_version) = &self.latest_notes_versions {
|
||||||
|
if let Some(observed_version) = &self.observed_notes_versions {
|
||||||
|
latest_version.epoch > observed_version.epoch
|
||||||
|
|| latest_version
|
||||||
|
.version
|
||||||
|
.changed_since(&observed_version.version)
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_new_messages(&self) -> bool {
|
||||||
|
let latest_message_id = self.latest_chat_message;
|
||||||
|
let observed_message_id = self.observed_chat_message;
|
||||||
|
|
||||||
|
latest_message_id.is_some_and(|latest_message_id| {
|
||||||
|
latest_message_id > observed_message_id.unwrap_or_default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn acknowledge_message_id(&mut self, message_id: u64) {
|
||||||
|
let observed = self.observed_chat_message.get_or_insert(message_id);
|
||||||
|
*observed = (*observed).max(message_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_latest_message_id(&mut self, message_id: u64) {
|
||||||
|
self.latest_chat_message =
|
||||||
|
Some(message_id.max(self.latest_chat_message.unwrap_or_default()));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn acknowledge_notes_version(&mut self, epoch: u64, version: &clock::Global) {
|
||||||
|
if let Some(existing) = &mut self.observed_notes_versions {
|
||||||
|
if existing.epoch == epoch {
|
||||||
|
existing.version.join(version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.observed_notes_versions = Some(NotesVersion {
|
||||||
|
epoch,
|
||||||
|
version: version.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_latest_notes_version(&mut self, epoch: u64, version: &clock::Global) {
|
||||||
|
if let Some(existing) = &mut self.latest_notes_versions {
|
||||||
|
if existing.epoch == epoch {
|
||||||
|
existing.version.join(version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.latest_notes_versions = Some(NotesVersion {
|
||||||
|
epoch,
|
||||||
|
version: version.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -37,43 +37,6 @@ impl ChannelIndex {
|
|||||||
channels_by_id: &mut self.channels_by_id,
|
channels_by_id: &mut self.channels_by_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn acknowledge_note_version(
|
|
||||||
&mut self,
|
|
||||||
channel_id: ChannelId,
|
|
||||||
epoch: u64,
|
|
||||||
version: &clock::Global,
|
|
||||||
) {
|
|
||||||
if let Some(channel) = self.channels_by_id.get_mut(&channel_id) {
|
|
||||||
let channel = Arc::make_mut(channel);
|
|
||||||
if let Some((unseen_epoch, unseen_version)) = &channel.unseen_note_version {
|
|
||||||
if epoch > *unseen_epoch
|
|
||||||
|| epoch == *unseen_epoch && version.observed_all(unseen_version)
|
|
||||||
{
|
|
||||||
channel.unseen_note_version = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn acknowledge_message_id(&mut self, channel_id: ChannelId, message_id: u64) {
|
|
||||||
if let Some(channel) = self.channels_by_id.get_mut(&channel_id) {
|
|
||||||
let channel = Arc::make_mut(channel);
|
|
||||||
if let Some(unseen_message_id) = channel.unseen_message_id {
|
|
||||||
if message_id >= unseen_message_id {
|
|
||||||
channel.unseen_message_id = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn note_changed(&mut self, channel_id: ChannelId, epoch: u64, version: &clock::Global) {
|
|
||||||
insert_note_changed(&mut self.channels_by_id, channel_id, epoch, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_message(&mut self, channel_id: ChannelId, message_id: u64) {
|
|
||||||
insert_new_message(&mut self.channels_by_id, channel_id, message_id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A guard for ensuring that the paths index maintains its sort and uniqueness
|
/// A guard for ensuring that the paths index maintains its sort and uniqueness
|
||||||
@ -85,14 +48,6 @@ pub struct ChannelPathsInsertGuard<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ChannelPathsInsertGuard<'a> {
|
impl<'a> ChannelPathsInsertGuard<'a> {
|
||||||
pub fn note_changed(&mut self, channel_id: ChannelId, epoch: u64, version: &clock::Global) {
|
|
||||||
insert_note_changed(self.channels_by_id, channel_id, epoch, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_messages(&mut self, channel_id: ChannelId, message_id: u64) {
|
|
||||||
insert_new_message(self.channels_by_id, channel_id, message_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&mut self, channel_proto: proto::Channel) -> bool {
|
pub fn insert(&mut self, channel_proto: proto::Channel) -> bool {
|
||||||
let mut ret = false;
|
let mut ret = false;
|
||||||
if let Some(existing_channel) = self.channels_by_id.get_mut(&channel_proto.id) {
|
if let Some(existing_channel) = self.channels_by_id.get_mut(&channel_proto.id) {
|
||||||
@ -114,8 +69,6 @@ impl<'a> ChannelPathsInsertGuard<'a> {
|
|||||||
role: channel_proto.role(),
|
role: channel_proto.role(),
|
||||||
name: channel_proto.name.into(),
|
name: channel_proto.name.into(),
|
||||||
parent_path: channel_proto.parent_path,
|
parent_path: channel_proto.parent_path,
|
||||||
latest_message_id: channel_proto.latest_message_id,
|
|
||||||
latest_note_version: channel_proto.latest_note_version,
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
self.insert_root(channel_proto.id);
|
self.insert_root(channel_proto.id);
|
||||||
@ -153,32 +106,3 @@ fn channel_path_sorting_key<'a>(
|
|||||||
.filter_map(|id| Some(channels_by_id.get(id)?.name.as_ref()))
|
.filter_map(|id| Some(channels_by_id.get(id)?.name.as_ref()))
|
||||||
.chain(name)
|
.chain(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_note_changed(
|
|
||||||
channels_by_id: &mut BTreeMap<ChannelId, Arc<Channel>>,
|
|
||||||
channel_id: u64,
|
|
||||||
epoch: u64,
|
|
||||||
version: &clock::Global,
|
|
||||||
) {
|
|
||||||
if let Some(channel) = channels_by_id.get_mut(&channel_id) {
|
|
||||||
let unseen_version = Arc::make_mut(channel)
|
|
||||||
.unseen_note_version
|
|
||||||
.get_or_insert((0, clock::Global::new()));
|
|
||||||
if epoch > unseen_version.0 {
|
|
||||||
*unseen_version = (epoch, version.clone());
|
|
||||||
} else {
|
|
||||||
unseen_version.1.join(version);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_new_message(
|
|
||||||
channels_by_id: &mut BTreeMap<ChannelId, Arc<Channel>>,
|
|
||||||
channel_id: u64,
|
|
||||||
message_id: u64,
|
|
||||||
) {
|
|
||||||
if let Some(channel) = channels_by_id.get_mut(&channel_id) {
|
|
||||||
let unseen_message_id = Arc::make_mut(channel).unseen_message_id.get_or_insert(0);
|
|
||||||
*unseen_message_id = message_id.max(*unseen_message_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -748,18 +748,11 @@ impl Database {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn unseen_channel_buffer_changes(
|
pub async fn latest_channel_buffer_changes(
|
||||||
&self,
|
&self,
|
||||||
user_id: UserId,
|
|
||||||
channel_ids: &[ChannelId],
|
channel_ids: &[ChannelId],
|
||||||
tx: &DatabaseTransaction,
|
tx: &DatabaseTransaction,
|
||||||
) -> Result<Vec<proto::UnseenChannelBufferChange>> {
|
) -> Result<Vec<proto::ChannelBufferVersion>> {
|
||||||
#[derive(Debug, Clone, Copy, EnumIter, DeriveColumn)]
|
|
||||||
enum QueryIds {
|
|
||||||
ChannelId,
|
|
||||||
Id,
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut channel_ids_by_buffer_id = HashMap::default();
|
let mut channel_ids_by_buffer_id = HashMap::default();
|
||||||
let mut rows = buffer::Entity::find()
|
let mut rows = buffer::Entity::find()
|
||||||
.filter(buffer::Column::ChannelId.is_in(channel_ids.iter().copied()))
|
.filter(buffer::Column::ChannelId.is_in(channel_ids.iter().copied()))
|
||||||
@ -771,51 +764,23 @@ impl Database {
|
|||||||
}
|
}
|
||||||
drop(rows);
|
drop(rows);
|
||||||
|
|
||||||
let mut observed_edits_by_buffer_id = HashMap::default();
|
|
||||||
let mut rows = observed_buffer_edits::Entity::find()
|
|
||||||
.filter(observed_buffer_edits::Column::UserId.eq(user_id))
|
|
||||||
.filter(
|
|
||||||
observed_buffer_edits::Column::BufferId
|
|
||||||
.is_in(channel_ids_by_buffer_id.keys().copied()),
|
|
||||||
)
|
|
||||||
.stream(&*tx)
|
|
||||||
.await?;
|
|
||||||
while let Some(row) = rows.next().await {
|
|
||||||
let row = row?;
|
|
||||||
observed_edits_by_buffer_id.insert(row.buffer_id, row);
|
|
||||||
}
|
|
||||||
drop(rows);
|
|
||||||
|
|
||||||
let latest_operations = self
|
let latest_operations = self
|
||||||
.get_latest_operations_for_buffers(channel_ids_by_buffer_id.keys().copied(), &*tx)
|
.get_latest_operations_for_buffers(channel_ids_by_buffer_id.keys().copied(), &*tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut changes = Vec::default();
|
Ok(latest_operations
|
||||||
for latest in latest_operations {
|
.iter()
|
||||||
if let Some(observed) = observed_edits_by_buffer_id.get(&latest.buffer_id) {
|
.flat_map(|op| {
|
||||||
if (
|
Some(proto::ChannelBufferVersion {
|
||||||
observed.epoch,
|
channel_id: channel_ids_by_buffer_id.get(&op.buffer_id)?.to_proto(),
|
||||||
observed.lamport_timestamp,
|
epoch: op.epoch as u64,
|
||||||
observed.replica_id,
|
|
||||||
) >= (latest.epoch, latest.lamport_timestamp, latest.replica_id)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(channel_id) = channel_ids_by_buffer_id.get(&latest.buffer_id) {
|
|
||||||
changes.push(proto::UnseenChannelBufferChange {
|
|
||||||
channel_id: channel_id.to_proto(),
|
|
||||||
epoch: latest.epoch as u64,
|
|
||||||
version: vec![proto::VectorClockEntry {
|
version: vec![proto::VectorClockEntry {
|
||||||
replica_id: latest.replica_id as u32,
|
replica_id: op.replica_id as u32,
|
||||||
timestamp: latest.lamport_timestamp as u32,
|
timestamp: op.lamport_timestamp as u32,
|
||||||
}],
|
}],
|
||||||
});
|
})
|
||||||
}
|
})
|
||||||
}
|
.collect())
|
||||||
|
|
||||||
Ok(changes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the latest operations for the buffers with the specified IDs.
|
/// Returns the latest operations for the buffers with the specified IDs.
|
||||||
|
@ -687,8 +687,8 @@ impl Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let channel_ids = channels.iter().map(|c| c.id).collect::<Vec<_>>();
|
let channel_ids = channels.iter().map(|c| c.id).collect::<Vec<_>>();
|
||||||
let channel_buffer_changes = self
|
let latest_buffer_versions = self
|
||||||
.unseen_channel_buffer_changes(user_id, &channel_ids, &*tx)
|
.latest_channel_buffer_changes(&channel_ids, &*tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let latest_messages = self.latest_channel_messages(&channel_ids, &*tx).await?;
|
let latest_messages = self.latest_channel_messages(&channel_ids, &*tx).await?;
|
||||||
@ -696,7 +696,7 @@ impl Database {
|
|||||||
Ok(ChannelsForUser {
|
Ok(ChannelsForUser {
|
||||||
channels,
|
channels,
|
||||||
channel_participants,
|
channel_participants,
|
||||||
latest_buffer_versions: channel_buffer_changes,
|
latest_buffer_versions,
|
||||||
latest_channel_messages: latest_messages,
|
latest_channel_messages: latest_messages,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -398,6 +398,10 @@ impl Database {
|
|||||||
write!(&mut values, "({})", id).unwrap();
|
write!(&mut values, "({})", id).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if values.is_empty() {
|
||||||
|
return Ok(Vec::default());
|
||||||
|
}
|
||||||
|
|
||||||
let sql = format!(
|
let sql = format!(
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -330,8 +330,7 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||||||
.transaction(|tx| {
|
.transaction(|tx| {
|
||||||
let buffers = &buffers;
|
let buffers = &buffers;
|
||||||
async move {
|
async move {
|
||||||
db.unseen_channel_buffer_changes(
|
db.latest_channel_buffer_changes(
|
||||||
observer_id,
|
|
||||||
&[
|
&[
|
||||||
buffers[0].channel_id,
|
buffers[0].channel_id,
|
||||||
buffers[1].channel_id,
|
buffers[1].channel_id,
|
||||||
@ -348,12 +347,12 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||||||
pretty_assertions::assert_eq!(
|
pretty_assertions::assert_eq!(
|
||||||
buffer_changes,
|
buffer_changes,
|
||||||
[
|
[
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
rpc::proto::ChannelBufferVersion {
|
||||||
channel_id: buffers[0].channel_id.to_proto(),
|
channel_id: buffers[0].channel_id.to_proto(),
|
||||||
epoch: 0,
|
epoch: 0,
|
||||||
version: serialize_version(&text_buffers[0].version()),
|
version: serialize_version(&text_buffers[0].version()),
|
||||||
},
|
},
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
rpc::proto::ChannelBufferVersion {
|
||||||
channel_id: buffers[1].channel_id.to_proto(),
|
channel_id: buffers[1].channel_id.to_proto(),
|
||||||
epoch: 1,
|
epoch: 1,
|
||||||
version: serialize_version(&text_buffers[1].version())
|
version: serialize_version(&text_buffers[1].version())
|
||||||
@ -362,99 +361,7 @@ async fn test_channel_buffers_last_operations(db: &Database) {
|
|||||||
== buffer_changes[1].version.first().unwrap().replica_id)
|
== buffer_changes[1].version.first().unwrap().replica_id)
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
},
|
},
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
rpc::proto::ChannelBufferVersion {
|
||||||
channel_id: buffers[2].channel_id.to_proto(),
|
|
||||||
epoch: 0,
|
|
||||||
version: serialize_version(&text_buffers[2].version()),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
db.observe_buffer_version(
|
|
||||||
buffers[1].id,
|
|
||||||
observer_id,
|
|
||||||
1,
|
|
||||||
serialize_version(&text_buffers[1].version()).as_slice(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let buffer_changes = db
|
|
||||||
.transaction(|tx| {
|
|
||||||
let buffers = &buffers;
|
|
||||||
async move {
|
|
||||||
db.unseen_channel_buffer_changes(
|
|
||||||
observer_id,
|
|
||||||
&[
|
|
||||||
buffers[0].channel_id,
|
|
||||||
buffers[1].channel_id,
|
|
||||||
buffers[2].channel_id,
|
|
||||||
],
|
|
||||||
&*tx,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
buffer_changes,
|
|
||||||
[
|
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
|
||||||
channel_id: buffers[0].channel_id.to_proto(),
|
|
||||||
epoch: 0,
|
|
||||||
version: serialize_version(&text_buffers[0].version()),
|
|
||||||
},
|
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
|
||||||
channel_id: buffers[2].channel_id.to_proto(),
|
|
||||||
epoch: 0,
|
|
||||||
version: serialize_version(&text_buffers[2].version()),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Observe an earlier version of the buffer.
|
|
||||||
db.observe_buffer_version(
|
|
||||||
buffers[1].id,
|
|
||||||
observer_id,
|
|
||||||
1,
|
|
||||||
&[rpc::proto::VectorClockEntry {
|
|
||||||
replica_id: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
}],
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let buffer_changes = db
|
|
||||||
.transaction(|tx| {
|
|
||||||
let buffers = &buffers;
|
|
||||||
async move {
|
|
||||||
db.unseen_channel_buffer_changes(
|
|
||||||
observer_id,
|
|
||||||
&[
|
|
||||||
buffers[0].channel_id,
|
|
||||||
buffers[1].channel_id,
|
|
||||||
buffers[2].channel_id,
|
|
||||||
],
|
|
||||||
&*tx,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
buffer_changes,
|
|
||||||
[
|
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
|
||||||
channel_id: buffers[0].channel_id.to_proto(),
|
|
||||||
epoch: 0,
|
|
||||||
version: serialize_version(&text_buffers[0].version()),
|
|
||||||
},
|
|
||||||
rpc::proto::UnseenChannelBufferChange {
|
|
||||||
channel_id: buffers[2].channel_id.to_proto(),
|
channel_id: buffers[2].channel_id.to_proto(),
|
||||||
epoch: 0,
|
epoch: 0,
|
||||||
version: serialize_version(&text_buffers[2].version()),
|
version: serialize_version(&text_buffers[2].version()),
|
||||||
|
@ -235,11 +235,10 @@ async fn test_unseen_channel_messages(db: &Arc<Database>) {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let second_message = db
|
let _ = db
|
||||||
.create_channel_message(channel_1, user, "1_2", &[], OffsetDateTime::now_utc(), 2)
|
.create_channel_message(channel_1, user, "1_2", &[], OffsetDateTime::now_utc(), 2)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap();
|
||||||
.message_id;
|
|
||||||
|
|
||||||
let third_message = db
|
let third_message = db
|
||||||
.create_channel_message(channel_1, user, "1_3", &[], OffsetDateTime::now_utc(), 3)
|
.create_channel_message(channel_1, user, "1_3", &[], OffsetDateTime::now_utc(), 3)
|
||||||
@ -258,97 +257,27 @@ async fn test_unseen_channel_messages(db: &Arc<Database>) {
|
|||||||
.message_id;
|
.message_id;
|
||||||
|
|
||||||
// Check that observer has new messages
|
// Check that observer has new messages
|
||||||
let unseen_messages = db
|
let latest_messages = db
|
||||||
.transaction(|tx| async move {
|
.transaction(|tx| async move {
|
||||||
db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
|
db.latest_channel_messages(&[channel_1, channel_2], &*tx)
|
||||||
.await
|
.await
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
unseen_messages,
|
latest_messages,
|
||||||
[
|
[
|
||||||
rpc::proto::UnseenChannelMessage {
|
rpc::proto::ChannelMessageId {
|
||||||
channel_id: channel_1.to_proto(),
|
channel_id: channel_1.to_proto(),
|
||||||
message_id: third_message.to_proto(),
|
message_id: third_message.to_proto(),
|
||||||
},
|
},
|
||||||
rpc::proto::UnseenChannelMessage {
|
rpc::proto::ChannelMessageId {
|
||||||
channel_id: channel_2.to_proto(),
|
channel_id: channel_2.to_proto(),
|
||||||
message_id: fourth_message.to_proto(),
|
message_id: fourth_message.to_proto(),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Observe the second message
|
|
||||||
db.observe_channel_message(channel_1, observer, second_message)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Make sure the observer still has a new message
|
|
||||||
let unseen_messages = db
|
|
||||||
.transaction(|tx| async move {
|
|
||||||
db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
unseen_messages,
|
|
||||||
[
|
|
||||||
rpc::proto::UnseenChannelMessage {
|
|
||||||
channel_id: channel_1.to_proto(),
|
|
||||||
message_id: third_message.to_proto(),
|
|
||||||
},
|
|
||||||
rpc::proto::UnseenChannelMessage {
|
|
||||||
channel_id: channel_2.to_proto(),
|
|
||||||
message_id: fourth_message.to_proto(),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Observe the third message,
|
|
||||||
db.observe_channel_message(channel_1, observer, third_message)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Make sure the observer does not have a new method
|
|
||||||
let unseen_messages = db
|
|
||||||
.transaction(|tx| async move {
|
|
||||||
db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
unseen_messages,
|
|
||||||
[rpc::proto::UnseenChannelMessage {
|
|
||||||
channel_id: channel_2.to_proto(),
|
|
||||||
message_id: fourth_message.to_proto(),
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Observe the second message again, should not regress our observed state
|
|
||||||
db.observe_channel_message(channel_1, observer, second_message)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Make sure the observer does not have a new message
|
|
||||||
let unseen_messages = db
|
|
||||||
.transaction(|tx| async move {
|
|
||||||
db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
|
|
||||||
.await
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
unseen_messages,
|
|
||||||
[rpc::proto::UnseenChannelMessage {
|
|
||||||
channel_id: channel_2.to_proto(),
|
|
||||||
message_id: fourth_message.to_proto(),
|
|
||||||
}]
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test_both_dbs!(
|
test_both_dbs!(
|
||||||
|
@ -2842,27 +2842,25 @@ async fn update_channel_buffer(
|
|||||||
|
|
||||||
let pool = &*session.connection_pool().await;
|
let pool = &*session.connection_pool().await;
|
||||||
|
|
||||||
todo!()
|
broadcast(
|
||||||
|
None,
|
||||||
// broadcast(
|
non_collaborators
|
||||||
// None,
|
.iter()
|
||||||
// non_collaborators
|
.flat_map(|user_id| pool.user_connection_ids(*user_id)),
|
||||||
// .iter()
|
|peer_id| {
|
||||||
// .flat_map(|user_id| pool.user_connection_ids(*user_id)),
|
session.peer.send(
|
||||||
// |peer_id| {
|
peer_id.into(),
|
||||||
// session.peer.send(
|
proto::UpdateChannels {
|
||||||
// peer_id.into(),
|
latest_channel_buffer_versions: vec![proto::ChannelBufferVersion {
|
||||||
// proto::UpdateChannels {
|
channel_id: channel_id.to_proto(),
|
||||||
// unseen_channel_buffer_changes: vec![proto::UnseenChannelBufferChange {
|
epoch: epoch as u64,
|
||||||
// channel_id: channel_id.to_proto(),
|
version: version.clone(),
|
||||||
// epoch: epoch as u64,
|
}],
|
||||||
// version: version.clone(),
|
..Default::default()
|
||||||
// }],
|
},
|
||||||
// ..Default::default()
|
)
|
||||||
// },
|
},
|
||||||
// )
|
);
|
||||||
// },
|
|
||||||
// );
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -3039,7 +3037,7 @@ async fn send_channel_message(
|
|||||||
session.peer.send(
|
session.peer.send(
|
||||||
peer_id.into(),
|
peer_id.into(),
|
||||||
proto::UpdateChannels {
|
proto::UpdateChannels {
|
||||||
unseen_channel_messages: vec![proto::UnseenChannelMessage {
|
latest_channel_message_ids: vec![proto::ChannelMessageId {
|
||||||
channel_id: channel_id.to_proto(),
|
channel_id: channel_id.to_proto(),
|
||||||
message_id: message_id.to_proto(),
|
message_id: message_id.to_proto(),
|
||||||
}],
|
}],
|
||||||
|
@ -637,7 +637,6 @@ async fn test_channel_buffer_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_channel_buffer_changed(channel_id)
|
.has_channel_buffer_changed(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
assert!(has_buffer_changed);
|
assert!(has_buffer_changed);
|
||||||
|
|
||||||
@ -655,7 +654,6 @@ async fn test_channel_buffer_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_channel_buffer_changed(channel_id)
|
.has_channel_buffer_changed(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
assert!(!has_buffer_changed);
|
assert!(!has_buffer_changed);
|
||||||
|
|
||||||
@ -672,7 +670,6 @@ async fn test_channel_buffer_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_channel_buffer_changed(channel_id)
|
.has_channel_buffer_changed(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
assert!(!has_buffer_changed);
|
assert!(!has_buffer_changed);
|
||||||
|
|
||||||
@ -687,7 +684,6 @@ async fn test_channel_buffer_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_channel_buffer_changed(channel_id)
|
.has_channel_buffer_changed(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
assert!(!has_buffer_changed);
|
assert!(!has_buffer_changed);
|
||||||
|
|
||||||
@ -714,7 +710,6 @@ async fn test_channel_buffer_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_channel_buffer_changed(channel_id)
|
.has_channel_buffer_changed(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
assert!(has_buffer_changed);
|
assert!(has_buffer_changed);
|
||||||
}
|
}
|
||||||
|
@ -313,7 +313,6 @@ async fn test_channel_message_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_new_messages(channel_id)
|
.has_new_messages(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(b_has_messages);
|
assert!(b_has_messages);
|
||||||
@ -341,7 +340,6 @@ async fn test_channel_message_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_new_messages(channel_id)
|
.has_new_messages(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(!b_has_messages);
|
assert!(!b_has_messages);
|
||||||
@ -359,7 +357,6 @@ async fn test_channel_message_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_new_messages(channel_id)
|
.has_new_messages(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(!b_has_messages);
|
assert!(!b_has_messages);
|
||||||
@ -382,7 +379,6 @@ async fn test_channel_message_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_new_messages(channel_id)
|
.has_new_messages(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(b_has_messages);
|
assert!(b_has_messages);
|
||||||
@ -402,7 +398,6 @@ async fn test_channel_message_changes(
|
|||||||
.channel_store()
|
.channel_store()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.has_new_messages(channel_id)
|
.has_new_messages(channel_id)
|
||||||
.unwrap()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(b_has_messages);
|
assert!(b_has_messages);
|
||||||
|
@ -183,7 +183,7 @@ impl ChannelView {
|
|||||||
} else {
|
} else {
|
||||||
self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
let channel_buffer = self.channel_buffer.read(cx);
|
let channel_buffer = self.channel_buffer.read(cx);
|
||||||
store.notes_changed(
|
store.update_latest_notes_version(
|
||||||
channel_buffer.channel_id,
|
channel_buffer.channel_id,
|
||||||
channel_buffer.epoch(),
|
channel_buffer.epoch(),
|
||||||
&channel_buffer.buffer().read(cx).version(),
|
&channel_buffer.buffer().read(cx).version(),
|
||||||
|
@ -266,7 +266,7 @@ impl ChatPanel {
|
|||||||
} => {
|
} => {
|
||||||
if !self.active {
|
if !self.active {
|
||||||
self.channel_store.update(cx, |store, cx| {
|
self.channel_store.update(cx, |store, cx| {
|
||||||
store.new_message(*channel_id, *message_id, cx)
|
store.update_latest_message_id(*channel_id, *message_id, cx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2219,17 +2219,16 @@ impl CollabPanel {
|
|||||||
Some(call_channel == channel_id)
|
Some(call_channel == channel_id)
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let is_public = self
|
let channel_store = self.channel_store.read(cx);
|
||||||
.channel_store
|
let is_public = channel_store
|
||||||
.read(cx)
|
|
||||||
.channel_for_id(channel_id)
|
.channel_for_id(channel_id)
|
||||||
.map(|channel| channel.visibility)
|
.map(|channel| channel.visibility)
|
||||||
== Some(proto::ChannelVisibility::Public);
|
== Some(proto::ChannelVisibility::Public);
|
||||||
let disclosed =
|
let disclosed =
|
||||||
has_children.then(|| !self.collapsed_channels.binary_search(&channel.id).is_ok());
|
has_children.then(|| !self.collapsed_channels.binary_search(&channel.id).is_ok());
|
||||||
|
|
||||||
let has_messages_notification = channel.unseen_message_id.is_some();
|
let has_messages_notification = channel_store.has_new_messages(channel_id);
|
||||||
let has_notes_notification = channel.unseen_note_version.is_some();
|
let has_notes_notification = channel_store.has_channel_buffer_changed(channel_id);
|
||||||
|
|
||||||
const FACEPILE_LIMIT: usize = 3;
|
const FACEPILE_LIMIT: usize = 3;
|
||||||
let participants = self.channel_store.read(cx).channel_participants(channel_id);
|
let participants = self.channel_store.read(cx).channel_participants(channel_id);
|
||||||
|
Loading…
Reference in New Issue
Block a user