Detailed changes
@@ -43,7 +43,7 @@ pub type ChannelData = (Channel, ChannelPath);
pub struct Channel {
pub id: ChannelId,
pub name: String,
- pub has_changed: bool,
+ pub has_note_changed: bool,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
@@ -200,19 +200,27 @@ impl ChannelStore {
) -> Task<Result<ModelHandle<ChannelBuffer>>> {
let client = self.client.clone();
let user_store = self.user_store.clone();
- self.open_channel_resource(
+ let open_channel_buffer = self.open_channel_resource(
channel_id,
|this| &mut this.opened_buffers,
|channel, cx| ChannelBuffer::new(channel, client, user_store, cx),
cx,
- )
+ );
+ cx.spawn(|this, mut cx| async move {
+ let buffer = open_channel_buffer.await?;
+ this.update(&mut cx, |this, cx| {
+ this.channel_index.clear_note_changed(channel_id);
+ cx.notify();
+ });
+ Ok(buffer)
+ })
}
pub fn has_channel_buffer_changed(&self, channel_id: ChannelId) -> Option<bool> {
self.channel_index
.by_id()
.get(&channel_id)
- .map(|channel| channel.has_changed)
+ .map(|channel| channel.has_note_changed)
}
pub fn open_channel_chat(
@@ -787,7 +795,7 @@ impl ChannelStore {
Arc::new(Channel {
id: channel.id,
name: channel.name,
- has_changed: false,
+ has_note_changed: false,
}),
),
}
@@ -825,7 +833,7 @@ impl ChannelStore {
}
for id_changed in payload.notes_changed {
- index.has_changed(id_changed);
+ index.note_changed(id_changed);
}
for edge in payload.insert_edge {
@@ -38,6 +38,12 @@ impl ChannelIndex {
channels_by_id: &mut self.channels_by_id,
}
}
+
+ pub fn clear_note_changed(&mut self, channel_id: ChannelId) {
+ if let Some(channel) = self.channels_by_id.get_mut(&channel_id) {
+ Arc::make_mut(channel).has_note_changed = false;
+ }
+ }
}
impl Deref for ChannelIndex {
@@ -76,9 +82,9 @@ impl<'a> ChannelPathsInsertGuard<'a> {
}
}
- pub fn has_changed(&mut self, channel_id: ChannelId) {
+ pub fn note_changed(&mut self, channel_id: ChannelId) {
if let Some(channel) = self.channels_by_id.get_mut(&channel_id) {
- Arc::make_mut(channel).has_changed = true;
+ Arc::make_mut(channel).has_note_changed = true;
}
}
@@ -91,7 +97,7 @@ impl<'a> ChannelPathsInsertGuard<'a> {
Arc::new(Channel {
id: channel_proto.id,
name: channel_proto.name,
- has_changed: false,
+ has_note_changed: false,
}),
);
self.insert_root(channel_proto.id);
@@ -445,7 +445,7 @@ fn channel(id: u64, name: &'static str) -> Channel {
Channel {
id,
name: name.to_string(),
- has_changed: false,
+ has_note_changed: false,
}
}
@@ -786,6 +786,7 @@ async fn test_channel_buffer_changes(
.await
.unwrap();
+ // Client A makes an edit, and client B should see that the note has changed.
channel_buffer_a.update(cx_a, |buffer, cx| {
buffer.buffer().update(cx, |buffer, cx| {
buffer.edit([(0..0, "1")], None, cx);
@@ -802,6 +803,66 @@ async fn test_channel_buffer_changes(
});
assert!(has_buffer_changed);
+
+ // Opening the buffer should clear the changed flag.
+ let channel_buffer_b = client_b
+ .channel_store()
+ .update(cx_b, |store, cx| store.open_channel_buffer(channel_id, cx))
+ .await
+ .unwrap();
+ deterministic.run_until_parked();
+
+ let has_buffer_changed = cx_b.read(|cx| {
+ client_b
+ .channel_store()
+ .read(cx)
+ .has_channel_buffer_changed(channel_id)
+ .unwrap()
+ });
+
+ assert!(!has_buffer_changed);
+
+ // Editing the channel while the buffer is open shuold not show that the buffer has changed.
+ channel_buffer_a.update(cx_a, |buffer, cx| {
+ buffer.buffer().update(cx, |buffer, cx| {
+ buffer.edit([(0..0, "2")], None, cx);
+ })
+ });
+ deterministic.run_until_parked();
+
+ let has_buffer_changed = cx_b.read(|cx| {
+ client_b
+ .channel_store()
+ .read(cx)
+ .has_channel_buffer_changed(channel_id)
+ .unwrap()
+ });
+
+ assert!(!has_buffer_changed);
+
+ // Closing the buffer should re-enable change tracking
+ cx_b.update(|_| {
+ drop(channel_buffer_b);
+ });
+
+ deterministic.run_until_parked();
+
+ channel_buffer_a.update(cx_a, |buffer, cx| {
+ buffer.buffer().update(cx, |buffer, cx| {
+ buffer.edit([(0..0, "3")], None, cx);
+ })
+ });
+ deterministic.run_until_parked();
+
+ let has_buffer_changed = cx_b.read(|cx| {
+ client_b
+ .channel_store()
+ .read(cx)
+ .has_channel_buffer_changed(channel_id)
+ .unwrap()
+ });
+
+ assert!(has_buffer_changed);
}
#[track_caller]
@@ -1774,6 +1774,7 @@ impl CollabPanel {
const FACEPILE_LIMIT: usize = 3;
enum ChannelCall {}
+ enum ChannelNote {}
let mut is_dragged_over = false;
if cx
@@ -1820,7 +1821,7 @@ impl CollabPanel {
channel.name.clone(),
theme
.channel_name
- .in_state(channel.has_changed)
+ .in_state(channel.has_note_changed)
.text
.clone(),
)
@@ -1863,6 +1864,8 @@ impl CollabPanel {
.with_color(theme.channel_hash.color)
.constrained()
.with_width(theme.channel_hash.width)
+ .contained()
+ .with_margin_right(theme.channel_hash.container.margin.left)
.into_any()
} else {
Empty::new().into_any()
@@ -1872,6 +1875,34 @@ impl CollabPanel {
this.join_channel_call(channel_id, cx);
}),
)
+ .with_child(
+ MouseEventHandler::new::<ChannelNote, _>(ix, cx, move |_, cx| {
+ let participants =
+ self.channel_store.read(cx).channel_participants(channel_id);
+ if participants.is_empty() {
+ if channel.has_note_changed {
+ Svg::new("icons/terminal.svg")
+ .with_color(theme.channel_note_active_color)
+ .constrained()
+ .with_width(theme.channel_hash.width)
+ .into_any()
+ } else if row_hovered {
+ Svg::new("icons/terminal.svg")
+ .with_color(theme.channel_hash.color)
+ .constrained()
+ .with_width(theme.channel_hash.width)
+ .into_any()
+ } else {
+ Empty::new().into_any()
+ }
+ } else {
+ Empty::new().into_any()
+ }
+ })
+ .on_click(MouseButton::Left, move |_, this, cx| {
+ this.open_channel_notes(&OpenChannelNotes { channel_id }, cx);
+ }),
+ )
.align_children_center()
.styleable_component()
.disclosable(
@@ -238,6 +238,7 @@ pub struct CollabPanel {
pub log_in_button: Interactive<ContainedText>,
pub channel_editor: ContainerStyle,
pub channel_hash: Icon,
+ pub channel_note_active_color: Color,
pub tabbed_modal: TabbedModal,
pub contact_finder: ContactFinder,
pub channel_modal: ChannelModal,
@@ -194,6 +194,7 @@ export default function contacts_panel(): any {
},
user_query_editor: filter_input,
channel_hash: icon_style,
+ channel_note_active_color: foreground(layer, "active"),
user_query_editor_height: 33,
add_contact_button: header_icon_button,
add_channel_button: header_icon_button,