@@ -303,7 +303,6 @@ pub struct CollabPanel {
project: Model<Project>,
match_candidates: Vec<StringMatchCandidate>,
scroll_handle: ScrollHandle,
- // list_state: ListState<Self>,
subscriptions: Vec<Subscription>,
collapsed_sections: Vec<Section>,
collapsed_channels: Vec<ChannelId>,
@@ -590,7 +589,6 @@ impl CollabPanel {
client: workspace.app_state().client.clone(),
// context_menu_on_selected: true,
drag_target_channel: ChannelDragTarget::None,
- // list_state,
};
this.update_entries(false, cx);
@@ -706,9 +704,9 @@ impl CollabPanel {
let query = self.filter_editor.read(cx).text(cx);
let executor = cx.background_executor().clone();
- // let prev_selected_entry = self.selection.and_then(|ix| self.entries.get(ix).cloned());
- let _old_entries = mem::take(&mut self.entries);
- // let mut scroll_to_top = false;
+ let prev_selected_entry = self.selection.and_then(|ix| self.entries.get(ix).cloned());
+ let old_entries = mem::take(&mut self.entries);
+ let scroll_to_top = false;
// if let Some(room) = ActiveCall::global(cx).read(cx).room() {
// self.entries.push(ListEntry::Header(Section::ActiveCall));
@@ -1075,71 +1073,62 @@ impl CollabPanel {
self.entries.push(ListEntry::ContactPlaceholder);
}
- // if select_same_item {
- // if let Some(prev_selected_entry) = prev_selected_entry {
- // self.selection.take();
- // for (ix, entry) in self.entries.iter().enumerate() {
- // if *entry == prev_selected_entry {
- // self.selection = Some(ix);
- // break;
- // }
- // }
- // }
- // } else {
- // self.selection = self.selection.and_then(|prev_selection| {
- // if self.entries.is_empty() {
- // None
- // } else {
- // Some(prev_selection.min(self.entries.len() - 1))
- // }
- // });
- // }
+ if select_same_item {
+ if let Some(prev_selected_entry) = prev_selected_entry {
+ self.selection.take();
+ for (ix, entry) in self.entries.iter().enumerate() {
+ if *entry == prev_selected_entry {
+ self.selection = Some(ix);
+ self.scroll_handle.scroll_to_item(ix);
+ break;
+ }
+ }
+ }
+ } else {
+ self.selection = self.selection.and_then(|prev_selection| {
+ if self.entries.is_empty() {
+ None
+ } else {
+ let ix = prev_selection.min(self.entries.len() - 1);
+ self.scroll_handle.scroll_to_item(ix);
+ Some(ix)
+ }
+ });
+ }
- // let old_scroll_top = self.list_state.logical_scroll_top();
-
- // self.list_state.reset(self.entries.len());
-
- // if scroll_to_top {
- // self.list_state.scroll_to(ListOffset::default());
- // } else {
- // // Attempt to maintain the same scroll position.
- // if let Some(old_top_entry) = old_entries.get(old_scroll_top.item_ix) {
- // let new_scroll_top = self
- // .entries
- // .iter()
- // .position(|entry| entry == old_top_entry)
- // .map(|item_ix| ListOffset {
- // item_ix,
- // offset_in_item: old_scroll_top.offset_in_item,
- // })
- // .or_else(|| {
- // let entry_after_old_top = old_entries.get(old_scroll_top.item_ix + 1)?;
- // let item_ix = self
- // .entries
- // .iter()
- // .position(|entry| entry == entry_after_old_top)?;
- // Some(ListOffset {
- // item_ix,
- // offset_in_item: 0.,
- // })
- // })
- // .or_else(|| {
- // let entry_before_old_top =
- // old_entries.get(old_scroll_top.item_ix.saturating_sub(1))?;
- // let item_ix = self
- // .entries
- // .iter()
- // .position(|entry| entry == entry_before_old_top)?;
- // Some(ListOffset {
- // item_ix,
- // offset_in_item: 0.,
- // })
- // });
+ if scroll_to_top {
+ self.scroll_handle.scroll_to_item(0)
+ } else {
+ let (old_index, old_offset) = self.scroll_handle.logical_scroll_top();
+ // Attempt to maintain the same scroll position.
+ if let Some(old_top_entry) = old_entries.get(old_index) {
+ let (new_index, new_offset) = self
+ .entries
+ .iter()
+ .position(|entry| entry == old_top_entry)
+ .map(|item_ix| (item_ix, old_offset))
+ .or_else(|| {
+ let entry_after_old_top = old_entries.get(old_index + 1)?;
+ let item_ix = self
+ .entries
+ .iter()
+ .position(|entry| entry == entry_after_old_top)?;
+ Some((item_ix, px(0.)))
+ })
+ .or_else(|| {
+ let entry_before_old_top = old_entries.get(old_index.saturating_sub(1))?;
+ let item_ix = self
+ .entries
+ .iter()
+ .position(|entry| entry == entry_before_old_top)?;
+ Some((item_ix, px(0.)))
+ })
+ .unwrap_or_else(|| (old_index, old_offset));
- // self.list_state
- // .scroll_to(new_scroll_top.unwrap_or(old_scroll_top));
- // }
- // }
+ self.scroll_handle
+ .set_logical_scroll_top(new_index, new_offset);
+ }
+ }
cx.notify();
}
@@ -3430,106 +3419,106 @@ impl FocusableView for CollabPanel {
}
}
-// impl PartialEq for ListEntry {
-// fn eq(&self, other: &Self) -> bool {
-// match self {
-// ListEntry::Header(section_1) => {
-// if let ListEntry::Header(section_2) = other {
-// return section_1 == section_2;
-// }
-// }
-// ListEntry::CallParticipant { user: user_1, .. } => {
-// if let ListEntry::CallParticipant { user: user_2, .. } = other {
-// return user_1.id == user_2.id;
-// }
-// }
-// ListEntry::ParticipantProject {
-// project_id: project_id_1,
-// ..
-// } => {
-// if let ListEntry::ParticipantProject {
-// project_id: project_id_2,
-// ..
-// } = other
-// {
-// return project_id_1 == project_id_2;
-// }
-// }
-// ListEntry::ParticipantScreen {
-// peer_id: peer_id_1, ..
-// } => {
-// if let ListEntry::ParticipantScreen {
-// peer_id: peer_id_2, ..
-// } = other
-// {
-// return peer_id_1 == peer_id_2;
-// }
-// }
-// ListEntry::Channel {
-// channel: channel_1, ..
-// } => {
-// if let ListEntry::Channel {
-// channel: channel_2, ..
-// } = other
-// {
-// return channel_1.id == channel_2.id;
-// }
-// }
-// ListEntry::ChannelNotes { channel_id } => {
-// if let ListEntry::ChannelNotes {
-// channel_id: other_id,
-// } = other
-// {
-// return channel_id == other_id;
-// }
-// }
-// ListEntry::ChannelChat { channel_id } => {
-// if let ListEntry::ChannelChat {
-// channel_id: other_id,
-// } = other
-// {
-// return channel_id == other_id;
-// }
-// }
-// ListEntry::ChannelInvite(channel_1) => {
-// if let ListEntry::ChannelInvite(channel_2) = other {
-// return channel_1.id == channel_2.id;
-// }
-// }
-// ListEntry::IncomingRequest(user_1) => {
-// if let ListEntry::IncomingRequest(user_2) = other {
-// return user_1.id == user_2.id;
-// }
-// }
-// ListEntry::OutgoingRequest(user_1) => {
-// if let ListEntry::OutgoingRequest(user_2) = other {
-// return user_1.id == user_2.id;
-// }
-// }
-// ListEntry::Contact {
-// contact: contact_1, ..
-// } => {
-// if let ListEntry::Contact {
-// contact: contact_2, ..
-// } = other
-// {
-// return contact_1.user.id == contact_2.user.id;
-// }
-// }
-// ListEntry::ChannelEditor { depth } => {
-// if let ListEntry::ChannelEditor { depth: other_depth } = other {
-// return depth == other_depth;
-// }
-// }
-// ListEntry::ContactPlaceholder => {
-// if let ListEntry::ContactPlaceholder = other {
-// return true;
-// }
-// }
-// }
-// false
-// }
-// }
+impl PartialEq for ListEntry {
+ fn eq(&self, other: &Self) -> bool {
+ match self {
+ ListEntry::Header(section_1) => {
+ if let ListEntry::Header(section_2) = other {
+ return section_1 == section_2;
+ }
+ }
+ // ListEntry::CallParticipant { user: user_1, .. } => {
+ // if let ListEntry::CallParticipant { user: user_2, .. } = other {
+ // return user_1.id == user_2.id;
+ // }
+ // }
+ // ListEntry::ParticipantProject {
+ // project_id: project_id_1,
+ // ..
+ // } => {
+ // if let ListEntry::ParticipantProject {
+ // project_id: project_id_2,
+ // ..
+ // } = other
+ // {
+ // return project_id_1 == project_id_2;
+ // }
+ // }
+ // ListEntry::ParticipantScreen {
+ // peer_id: peer_id_1, ..
+ // } => {
+ // if let ListEntry::ParticipantScreen {
+ // peer_id: peer_id_2, ..
+ // } = other
+ // {
+ // return peer_id_1 == peer_id_2;
+ // }
+ // }
+ ListEntry::Channel {
+ channel: channel_1, ..
+ } => {
+ if let ListEntry::Channel {
+ channel: channel_2, ..
+ } = other
+ {
+ return channel_1.id == channel_2.id;
+ }
+ }
+ // ListEntry::ChannelNotes { channel_id } => {
+ // if let ListEntry::ChannelNotes {
+ // channel_id: other_id,
+ // } = other
+ // {
+ // return channel_id == other_id;
+ // }
+ // }
+ // ListEntry::ChannelChat { channel_id } => {
+ // if let ListEntry::ChannelChat {
+ // channel_id: other_id,
+ // } = other
+ // {
+ // return channel_id == other_id;
+ // }
+ // }
+ // ListEntry::ChannelInvite(channel_1) => {
+ // if let ListEntry::ChannelInvite(channel_2) = other {
+ // return channel_1.id == channel_2.id;
+ // }
+ // }
+ ListEntry::IncomingRequest(user_1) => {
+ if let ListEntry::IncomingRequest(user_2) = other {
+ return user_1.id == user_2.id;
+ }
+ }
+ ListEntry::OutgoingRequest(user_1) => {
+ if let ListEntry::OutgoingRequest(user_2) = other {
+ return user_1.id == user_2.id;
+ }
+ }
+ ListEntry::Contact {
+ contact: contact_1, ..
+ } => {
+ if let ListEntry::Contact {
+ contact: contact_2, ..
+ } = other
+ {
+ return contact_1.user.id == contact_2.user.id;
+ }
+ }
+ ListEntry::ChannelEditor { depth } => {
+ if let ListEntry::ChannelEditor { depth: other_depth } = other {
+ return depth == other_depth;
+ }
+ }
+ ListEntry::ContactPlaceholder => {
+ if let ListEntry::ContactPlaceholder = other {
+ return true;
+ }
+ }
+ }
+ false
+ }
+}
// fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element<CollabPanel> {
// Svg::new(svg_path)
@@ -636,12 +636,20 @@ impl Element for Div {
let mut state = scroll_handle.0.borrow_mut();
state.child_bounds = Vec::with_capacity(element_state.child_layout_ids.len());
state.bounds = bounds;
+ let requested = state.requested_scroll_top.take();
- for child_layout_id in &element_state.child_layout_ids {
+ for (ix, child_layout_id) in element_state.child_layout_ids.iter().enumerate() {
let child_bounds = cx.layout_bounds(*child_layout_id);
child_min = child_min.min(&child_bounds.origin);
child_max = child_max.max(&child_bounds.lower_right());
- state.child_bounds.push(child_bounds)
+ state.child_bounds.push(child_bounds);
+
+ if let Some(requested) = requested.as_ref() {
+ if requested.0 == ix {
+ *state.offset.borrow_mut() =
+ bounds.origin - (child_bounds.origin - point(px(0.), requested.1));
+ }
+ }
}
(child_max - child_min).into()
} else {
@@ -1460,6 +1468,7 @@ struct ScrollHandleState {
offset: Rc<RefCell<Point<Pixels>>>,
bounds: Bounds<Pixels>,
child_bounds: Vec<Bounds<Pixels>>,
+ requested_scroll_top: Option<(usize, Pixels)>,
}
#[derive(Clone)]
@@ -1513,4 +1522,22 @@ impl ScrollHandle {
state.offset.borrow_mut().y = state.bounds.bottom() - bounds.bottom();
}
}
+
+ pub fn logical_scroll_top(&self) -> (usize, Pixels) {
+ let ix = self.top_item();
+ let state = self.0.borrow();
+
+ if let Some(child_bounds) = state.child_bounds.get(ix) {
+ (
+ ix,
+ child_bounds.top() + state.offset.borrow().y - state.bounds.top(),
+ )
+ } else {
+ (ix, px(0.))
+ }
+ }
+
+ pub fn set_logical_scroll_top(&self, ix: usize, px: Pixels) {
+ self.0.borrow_mut().requested_scroll_top = Some((ix, px));
+ }
}