Files
fizzy/app/models/notification_pusher.rb
T
Fernando Olivares 3c54cd84fc Add native push notification infrastructure
- Add action_push_native gem and SaaS configuration
- Add device registration API and UI
- Add User::Devices concern
- Add NotificationPusher::Native for push delivery
- Add tests and fixtures for native push
2026-02-25 19:31:13 +01:00

129 lines
3.2 KiB
Ruby

class NotificationPusher
include Rails.application.routes.url_helpers
include ExcerptHelper
attr_reader :notification
def initialize(notification)
@notification = notification
end
def push
return unless should_push?
build_payload.tap do |payload|
push_to_web(payload)
end
end
private
def should_push?
push_destination? &&
!notification.creator.system? &&
notification.user.active? &&
notification.account.active?
end
def push_destination?
notification.user.push_subscriptions.any?
end
def build_payload
case notification.source_type
when "Event"
build_event_payload
when "Mention"
build_mention_payload
else
build_default_payload
end
end
def build_event_payload
event = notification.source
card = event.card
base_payload = {
title: card_notification_title(card),
path: card_path(card)
}
case event.action
when "comment_created"
base_payload.merge(
title: "RE: #{base_payload[:title]}",
body: comment_notification_body(event),
path: card_path_with_comment_anchor(event.eventable)
)
when "card_assigned"
base_payload.merge(
body: "Assigned to you by #{event.creator.name}"
)
when "card_published"
base_payload.merge(
body: "Added by #{event.creator.name}"
)
when "card_closed"
base_payload.merge(
body: card.closure ? "Moved to Done by #{event.creator.name}" : "Closed by #{event.creator.name}"
)
when "card_reopened"
base_payload.merge(
body: "Reopened by #{event.creator.name}"
)
else
base_payload.merge(
body: event.creator.name
)
end
end
def build_mention_payload
mention = notification.source
card = mention.card
{
title: "#{mention.mentioner.first_name} mentioned you",
body: format_excerpt(mention.source.mentionable_content, length: 200),
path: card_path(card)
}
end
def build_default_payload
{
title: "New notification",
body: "You have a new notification",
path: notifications_path(script_name: notification.account.slug)
}
end
def push_to_web(payload)
subscriptions = notification.user.push_subscriptions
enqueue_payload_for_delivery(payload, subscriptions)
end
def enqueue_payload_for_delivery(payload, subscriptions)
Rails.configuration.x.web_push_pool.queue(payload, subscriptions)
end
def card_notification_title(card)
card.title.presence || "Card #{card.number}"
end
def comment_notification_body(event)
format_excerpt(event.eventable.body, length: 200)
end
def card_path(card)
Rails.application.routes.url_helpers.card_path(card, script_name: notification.account.slug)
end
def card_path_with_comment_anchor(comment)
Rails.application.routes.url_helpers.card_path(
comment.card,
anchor: ActionView::RecordIdentifier.dom_id(comment),
script_name: notification.account.slug
)
end
end