mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
Add channel note indicator and clear changed status
This commit is contained in:
parent
9ba975d6ad
commit
e0ff7ba180
6 changed files with 119 additions and 11 deletions
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue