discourse/app/models/topic_notifier.rb
Mark VanLandingham 1e5e20ffc5
FEATURE: Notification/tracking changes for nested replies (#39750)
Reply consolidation by bucket for nested view. Replies under the same
parent now collapse into one notification ("3 new replies in your topic"
/ "to your post"). Clicking lands you at that bucket's level with
sort=new&collapse_replies=true so you only see the new content. Flat
topics keep the existing single-row consolidated shape (specs guard
against regression). Root posts that don't explicitly reply to
anyone resolve to the OP, so the OP still gets notified for fresh roots
in their own topic.
                                                                  
Auto-Track instead of auto-Watch for the OP. PMs and flat topics are
unchanged.
  
Topic-list "new replies" dot. Replaces the unread/new count badges for
nested topics when there's new content since the user's last visit. The
count-based UI doesn't fit nested's read pattern.
                                                                  
collapse_replies=true URL param. On the nested view, starts replies
hidden behind an Expand button. Set automatically by consolidated
notifications.

---------

Co-authored-by: Rafael Silva <xfalcox@gmail.com>
2026-05-07 12:33:56 -05:00

48 lines
1.1 KiB
Ruby

# frozen_string_literal: true
class TopicNotifier
def initialize(topic)
@topic = topic
end
{
watch!: :watching,
track!: :tracking,
regular!: :regular,
mute!: :muted,
}.each_pair do |method_name, level|
define_method method_name do |user_id|
change_level user_id, level
end
end
def watch_topic!(user_id, reason = :created_topic)
change_level user_id, :watching, reason
end
def track_topic!(user_id, reason = :created_topic)
change_level user_id, :tracking, reason
end
# Enable/disable the mute on the topic
def toggle_mute(user_id)
change_level user_id, (muted?(user_id) ? levels[:regular] : levels[:muted])
end
def muted?(user_id)
tu = @topic.topic_users.find_by(user_id: user_id)
tu && tu.notification_level == levels[:muted]
end
private
def levels
@notification_levels ||= TopicUser.notification_levels
end
def change_level(user_id, level, reason = nil)
attrs = { notification_level: levels[level] }
attrs.merge!(notifications_reason_id: TopicUser.notification_reasons[reason]) if reason
TopicUser.change(user_id, @topic.id, attrs)
end
end