# frozen_string_literal: true class NotificationsController < ApplicationController before_action :authenticate_user! TYPE_MAPPINGS = { "answer" => Notification::QuestionAnswered.name, "comment" => Notification::Commented.name, "commentsmile" => Notification::CommentSmiled.name, "relationship" => Notification::StartedFollowing.name, "smile" => Notification::Smiled.name }.freeze def index @type = TYPE_MAPPINGS[params[:type]] || params[:type] @notifications = cursored_notifications_for(type: @type, last_id: params[:last_id]) paginate_notifications @counters = count_unread_by_type mark_notifications_as_read respond_to do |format| format.html format.turbo_stream { render layout: false, status: :see_other } end end def read current_user.notifications.where(new: true).update_all(new: false) # rubocop:disable Rails/SkipsModelValidations current_user.touch(:notifications_updated_at) respond_to do |format| format.turbo_stream do render "navigation/notifications", locals: { notifications: [], notification_count: nil } end end end private def paginate_notifications @notifications_last_id = @notifications.map(&:id).min @more_data_available = !cursored_notifications_for(type: @type, last_id: @notifications_last_id, size: 1).count.zero? end def count_unread_by_type Notification.where(recipient: current_user, new: true) .group(:target_type) .count(:target_type) end # rubocop:disable Rails/SkipsModelValidations def mark_notifications_as_read # using .dup to not modify @notifications -- useful in tests updated = @notifications&.dup&.update_all(new: false) current_user.touch(:notifications_updated_at) if updated.positive? end # rubocop:enable Rails/SkipsModelValidations def cursored_notifications_for(type:, last_id:, size: nil) cursor_params = { last_id: last_id, size: size }.compact case type when "all" Notification.cursored_for(current_user, **cursor_params) when "new" Notification.cursored_for(current_user, new: true, **cursor_params) else Notification.cursored_for_type(current_user, type, **cursor_params) end end end