11class TopicsController < ApplicationController
2- before_action :set_topic , only : [ :show , :aware , :read_all ]
3- before_action :require_authentication , only : [ :aware , :aware_bulk , :aware_all , :read_all ]
2+ before_action :set_topic , only : [ :show , :aware , :read_all , :star , :unstar ]
3+ before_action :require_authentication , only : [ :aware , :aware_bulk , :aware_all , :read_all , :star , :unstar ]
44 before_action :require_team_membership , only : [ :index , :new_topics_count ]
55
66 def index
@@ -45,7 +45,10 @@ def show
4545 build_participants_sidebar_data ( messages_scope )
4646 build_thread_outline ( messages_scope )
4747 load_commitfest_sidebar
48- load_notes if user_signed_in?
48+ if user_signed_in?
49+ load_notes
50+ load_star_state
51+ end
4952 end
5053
5154 def aware
@@ -93,6 +96,30 @@ def read_all
9396 end
9497 end
9598
99+ def star
100+ TopicStar . create! ( user : current_user , topic : @topic )
101+ respond_to do |format |
102+ format . turbo_stream { render :update_star_state }
103+ format . json { render json : { starred : true } }
104+ format . html { redirect_to topic_path ( @topic ) }
105+ end
106+ rescue ActiveRecord ::RecordNotUnique
107+ respond_to do |format |
108+ format . turbo_stream { render :update_star_state }
109+ format . json { render json : { starred : true } }
110+ format . html { redirect_to topic_path ( @topic ) }
111+ end
112+ end
113+
114+ def unstar
115+ TopicStar . where ( user : current_user , topic : @topic ) . destroy_all
116+ respond_to do |format |
117+ format . turbo_stream { render :update_star_state }
118+ format . json { render json : { starred : false } }
119+ format . html { redirect_to topic_path ( @topic ) }
120+ end
121+ end
122+
96123 def search
97124 @search_query = params [ :q ] . to_s . strip
98125
@@ -123,6 +150,7 @@ def user_state
123150 preload_topic_states
124151 preload_note_counts
125152 preload_participation_flags
153+ preload_star_counts
126154
127155 payload = topic_ids . index_with do |tid |
128156 state = @topic_states [ tid ] || { }
@@ -139,6 +167,7 @@ def user_state
139167 team : participation [ :team ] ,
140168 aliases_count : Array ( participation [ :aliases ] ) . size
141169 }
170+ star_data = @topic_star_data &.dig ( tid ) || { starred_by_me : false , team_starrers : [ ] }
142171 {
143172 status : state [ :status ] ,
144173 progress : state [ :progress ] ,
@@ -147,7 +176,8 @@ def user_state
147176 aware_until : state [ :aware_until ] ,
148177 team_readers : readers ,
149178 note_count : @topic_note_counts &.dig ( tid ) . to_i ,
150- participation : participation_payload
179+ participation : participation_payload ,
180+ star : star_data
151181 }
152182 end
153183
@@ -164,6 +194,7 @@ def user_state_frame
164194 preload_note_counts
165195 preload_participation_flags
166196 preload_commitfest_summaries
197+ preload_star_counts
167198
168199 respond_to do |format |
169200 format . turbo_stream
@@ -360,6 +391,44 @@ def preload_note_counts
360391 . count
361392 end
362393
394+ def preload_star_counts
395+ topic_ids = @topics . map ( &:id )
396+ return if topic_ids . empty?
397+ return unless user_signed_in?
398+
399+ my_stars = TopicStar . where ( user : current_user , topic_id : topic_ids )
400+ . pluck ( :topic_id )
401+ . to_set
402+
403+ team_ids = TeamMember . where ( user_id : current_user . id ) . pluck ( :team_id )
404+ team_stars = { }
405+
406+ if team_ids . any?
407+ teammate_ids = TeamMember . where ( team_id : team_ids )
408+ . where . not ( user_id : current_user . id )
409+ . pluck ( :user_id )
410+
411+ if teammate_ids . any?
412+ stars = TopicStar . where ( user_id : teammate_ids , topic_id : topic_ids )
413+ . includes ( user : { person : :default_alias } )
414+
415+ stars . each do |star |
416+ team_stars [ star . topic_id ] ||= [ ]
417+ alias_record = star . user . person &.default_alias || star . user . aliases &.first
418+ team_stars [ star . topic_id ] << alias_record if alias_record
419+ end
420+ end
421+ end
422+
423+ @topic_star_data = { }
424+ @topics . each do |topic |
425+ @topic_star_data [ topic . id ] = {
426+ starred_by_me : my_stars . include? ( topic . id ) ,
427+ team_starrers : team_stars [ topic . id ] || [ ]
428+ }
429+ end
430+ end
431+
363432 def load_visible_tags
364433 @available_note_tags = NoteTag . joins ( :note )
365434 . merge ( Note . active . visible_to ( current_user ) )
@@ -553,6 +622,18 @@ def apply_filters(base_query)
553622 member_alias_ids = Alias . where ( person_id : member_person_ids ) . select ( :id )
554623 base_query = base_query . where ( id : Message . where ( sender_id : member_alias_ids ) . select ( :topic_id ) )
555624 end
625+ when "starred_by_me"
626+ if current_user_id
627+ base_query = base_query . joins ( :topic_stars )
628+ . where ( topic_stars : { user_id : current_user_id } )
629+ end
630+ when "starred_by_team"
631+ if team_id && current_user_id
632+ member_ids = TeamMember . where ( team_id : team_id ) . select ( :user_id )
633+ base_query = base_query . joins ( :topic_stars )
634+ . where ( topic_stars : { user_id : member_ids } )
635+ . distinct
636+ end
556637 end
557638 base_query
558639 end
@@ -663,6 +744,10 @@ def load_notes
663744 end
664745 end
665746
747+ def load_star_state
748+ @is_starred = TopicStar . exists? ( user : current_user , topic : @topic )
749+ end
750+
666751 def load_cached_search_results
667752 @viewing_since = viewing_since_param
668753 longpage = params [ :longpage ] . to_i
0 commit comments