Add channel note indicator and clear changed status

This commit is contained in:
Mikayla 2023-10-01 19:53:32 -07:00
parent 9ba975d6ad
commit e0ff7ba180
No known key found for this signature in database
6 changed files with 119 additions and 11 deletions

View file

@ -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 {

View file

@ -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);

View file

@ -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]

View file

@ -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(

View file

@ -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,

View file

@ -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,