mirror of
https://github.com/discourse/discourse.git
synced 2024-11-30 15:40:51 +08:00
1fa21ed415
Right now the experimental user menu sorts notifications the same way that the old menu does: unread high-priority notifications are shown first in reverse-chronological order followed by everything else also in reverse-chronological order. However, since the experimental user menu has dedicated tabs for some notification types and each tab displays a badge with the count of unread notifications in the tab, we feel like it makes sense to change how notifications are sorted in the experimental user menu to this: 1. unread high-priority notifications 2. unread regular notifications 3. all read notifications (both high-priority and regular) 4. within each group, notifications are sorted in reverse-chronological order (i.e. newest is shown first). This new sorting logic applies to all tabs in the experimental user menu, however it doesn't change anything in the old menu. With this change, if a tab in the experimental user menu shows an unread notification badge for a really old notification, it will be surfaced to the top and prevents confusing scenarios where a user sees an unread notification badge on a tab, but the tab doesn't show the unread notification because it's too old to make it to the list. Internal topic: t72199.
144 lines
4.4 KiB
Ruby
144 lines
4.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class NotificationsController < ApplicationController
|
|
|
|
requires_login
|
|
before_action :ensure_admin, only: [:create, :update, :destroy]
|
|
before_action :set_notification, only: [:update, :destroy]
|
|
|
|
def index
|
|
user =
|
|
if params[:username] && !params[:recent]
|
|
user_record = User.find_by(username: params[:username].to_s)
|
|
raise Discourse::NotFound if !user_record
|
|
user_record
|
|
else
|
|
current_user
|
|
end
|
|
|
|
guardian.ensure_can_see_notifications!(user)
|
|
|
|
if notification_types = params[:filter_by_types]&.split(",").presence
|
|
notification_types.map! do |type|
|
|
Notification.types[type.to_sym] || (
|
|
raise Discourse::InvalidParameters.new("invalid notification type: #{type}")
|
|
)
|
|
end
|
|
end
|
|
|
|
if params[:recent].present?
|
|
limit = (params[:limit] || 15).to_i
|
|
limit = 50 if limit > 50
|
|
|
|
if SiteSetting.enable_experimental_sidebar_hamburger
|
|
notifications = Notification.prioritized_list(current_user, count: limit, types: notification_types)
|
|
else
|
|
notifications = Notification.recent_report(current_user, limit, notification_types)
|
|
end
|
|
|
|
if notifications.present? && !(params.has_key?(:silent) || @readonly_mode)
|
|
if changed = current_user.bump_last_seen_notification!
|
|
current_user.reload
|
|
current_user.publish_notifications_state
|
|
end
|
|
end
|
|
|
|
if !params.has_key?(:silent) && params[:bump_last_seen_reviewable] && !@readonly_mode
|
|
current_user_id = current_user.id
|
|
Scheduler::Defer.later "bump last seen reviewable for user" do
|
|
# we lookup current_user again in the background thread to avoid
|
|
# concurrency issues where the objects returned by the current_user
|
|
# and/or methods are changed by the time the deferred block is
|
|
# executed
|
|
user = User.find_by(id: current_user_id)
|
|
next if user.blank?
|
|
new_guardian = Guardian.new(user)
|
|
if new_guardian.can_see_review_queue?
|
|
user.bump_last_seen_reviewable!
|
|
end
|
|
end
|
|
end
|
|
|
|
render_json_dump(
|
|
notifications: serialize_data(notifications, NotificationSerializer),
|
|
seen_notification_id: current_user.seen_notification_id
|
|
)
|
|
else
|
|
offset = params[:offset].to_i
|
|
|
|
notifications = Notification.where(user_id: user.id)
|
|
.visible
|
|
.includes(:topic)
|
|
.order(created_at: :desc)
|
|
|
|
notifications = notifications.where(read: true) if params[:filter] == "read"
|
|
|
|
notifications = notifications.where(read: false) if params[:filter] == "unread"
|
|
|
|
total_rows = notifications.dup.count
|
|
notifications = notifications.offset(offset).limit(60)
|
|
render_json_dump(notifications: serialize_data(notifications, NotificationSerializer),
|
|
total_rows_notifications: total_rows,
|
|
seen_notification_id: user.seen_notification_id,
|
|
load_more_notifications: notifications_path(username: user.username, offset: offset + 60, filter: params[:filter]))
|
|
end
|
|
|
|
end
|
|
|
|
def mark_read
|
|
if params[:id]
|
|
Notification.read(current_user, [params[:id].to_i])
|
|
else
|
|
if types = params[:dismiss_types]&.split(",").presence
|
|
invalid = []
|
|
types.map! do |type|
|
|
type_id = Notification.types[type.to_sym]
|
|
invalid << type if !type_id
|
|
type_id
|
|
end
|
|
if invalid.size > 0
|
|
raise Discourse::InvalidParameters.new("invalid notification types: #{invalid.inspect}")
|
|
end
|
|
end
|
|
|
|
Notification.read_types(current_user, types)
|
|
current_user.bump_last_seen_notification!
|
|
end
|
|
|
|
current_user.reload
|
|
current_user.publish_notifications_state
|
|
|
|
render json: success_json
|
|
end
|
|
|
|
def create
|
|
@notification = Notification.consolidate_or_create!(notification_params)
|
|
render_notification
|
|
end
|
|
|
|
def update
|
|
@notification.update!(notification_params)
|
|
render_notification
|
|
end
|
|
|
|
def destroy
|
|
@notification.destroy!
|
|
render json: success_json
|
|
end
|
|
|
|
private
|
|
|
|
def set_notification
|
|
@notification = Notification.find(params[:id])
|
|
end
|
|
|
|
def notification_params
|
|
params.permit(:notification_type, :user_id, :data, :read, :topic_id, :post_number, :post_action_id)
|
|
end
|
|
|
|
def render_notification
|
|
render_json_dump(NotificationSerializer.new(@notification, scope: guardian, root: false))
|
|
end
|
|
|
|
end
|