Skip to content

Commit 5fa55c4

Browse files
committed
fix: Fix expensive channel sidebar build by grouping joined threads once
1 parent e4db579 commit 5fa55c4

1 file changed

Lines changed: 27 additions & 14 deletions

File tree

src/tui/state/channels.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,25 @@ impl DashboardState {
777777
ActiveGuildScope::Unset | ActiveGuildScope::DirectMessages => BTreeMap::new(),
778778
};
779779

780+
// Group joined threads by parent channel once. Looking them up per entry
781+
// avoids rescanning every channel for each row, which made sidebar
782+
// building O(N^2) and stuttered navigation on large guilds.
783+
let mut joined_threads_by_parent: BTreeMap<Id<ChannelMarker>, Vec<&ChannelState>> =
784+
BTreeMap::new();
785+
for channel in &channels {
786+
if channel.is_thread() && channel.current_user_joined_thread {
787+
if let Some(parent_id) = channel.parent_id {
788+
joined_threads_by_parent
789+
.entry(parent_id)
790+
.or_default()
791+
.push(*channel);
792+
}
793+
}
794+
}
795+
for threads in joined_threads_by_parent.values_mut() {
796+
sort_thread_channels(threads);
797+
}
798+
780799
let category_ids: HashSet<Id<ChannelMarker>> = channels
781800
.iter()
782801
.filter(|channel| channel.is_category())
@@ -804,6 +823,7 @@ impl DashboardState {
804823
root,
805824
ChannelBranch::None,
806825
&voice_participants_by_channel,
826+
&joined_threads_by_parent,
807827
);
808828
continue;
809829
}
@@ -842,6 +862,7 @@ impl DashboardState {
842862
child,
843863
branch,
844864
&voice_participants_by_channel,
865+
&joined_threads_by_parent,
845866
);
846867
}
847868
}
@@ -860,9 +881,12 @@ impl DashboardState {
860881
state: &'a ChannelState,
861882
branch: ChannelBranch,
862883
voice_participants_by_channel: &BTreeMap<Id<ChannelMarker>, Vec<VoiceParticipantState>>,
884+
joined_threads_by_parent: &BTreeMap<Id<ChannelMarker>, Vec<&'a ChannelState>>,
863885
) {
864886
entries.push(ChannelPaneEntry::Channel { state, branch });
865-
self.push_joined_thread_entries(entries, state.id, branch);
887+
if let Some(threads) = joined_threads_by_parent.get(&state.id) {
888+
Self::push_joined_thread_entries(entries, threads, branch);
889+
}
866890
if !state.is_voice() {
867891
return;
868892
}
@@ -878,23 +902,12 @@ impl DashboardState {
878902
}
879903

880904
fn push_joined_thread_entries<'a>(
881-
&'a self,
882905
entries: &mut Vec<ChannelPaneEntry<'a>>,
883-
parent_id: Id<ChannelMarker>,
906+
threads: &[&'a ChannelState],
884907
parent_branch: ChannelBranch,
885908
) {
886-
let mut threads: Vec<&ChannelState> = self
887-
.channels()
888-
.into_iter()
889-
.filter(|channel| {
890-
channel.is_thread()
891-
&& channel.parent_id == Some(parent_id)
892-
&& channel.current_user_joined_thread
893-
})
894-
.collect();
895-
sort_thread_channels(&mut threads);
896909
let last_child_index = threads.len().saturating_sub(1);
897-
entries.extend(threads.into_iter().enumerate().map(|(index, state)| {
910+
entries.extend(threads.iter().enumerate().map(|(index, &state)| {
898911
let branch = if index == last_child_index {
899912
ChannelBranch::Last
900913
} else {

0 commit comments

Comments
 (0)