Files
fizzy/saas/app/models/notification/push/native.rb
T
Rosa Gutierrez 05819f84a2 Refactor notification push system with registry pattern
Replace NotificationPusher with a cleaner architecture:

- Add Notification::Pushable concern with push target registry
- Add Notification::Push base class with template methods
- Add Notification::Push::Web for web push (OSS)
- Add Notification::Push::Native for native push (SaaS)
- Add Notification::WebPushJob and Notification::NativePushJob

Key design:
- Registry pattern: Notification.register_push_target(:web)
- Template method: push calls should_push? then perform_push
- Subclasses override should_push? (with super) and perform_push
- Each target handles its own job enqueueing

Also:
- Add Notification#pushable? for checking push eligibility
- Add Notification#identity delegation to user
- Reorganize tests to match new class structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Tidy up saas engine a bit more
2026-02-25 19:31:13 +01:00

80 lines
2.1 KiB
Ruby

class Notification::Push::Native < Notification::Push
def self.push_later(notification)
Notification::NativePushJob.perform_later(notification)
end
private
def should_push?
super && devices.any?
end
def perform_push
native_notification(build_payload).deliver_later_to(devices)
end
def devices
@devices ||= notification.identity.devices
end
def native_notification(payload)
ApplicationPushNotification
.with_apple(
aps: {
category: notification_category,
"mutable-content": 1,
"interruption-level": interruption_level
}
)
.with_google(
android: { notification: nil }
)
.with_data(
title: payload[:title],
body: payload[:body],
url: payload[:url],
account_id: notification.account.external_account_id,
avatar_url: creator_avatar_url,
card_id: card&.id,
card_title: card&.title,
creator_name: notification.creator.name,
category: notification_category
)
.new(
title: payload[:title],
body: payload[:body],
badge: notification.user.notifications.unread.count,
sound: "default",
thread_id: card&.id,
high_priority: assignment_notification?
)
end
def notification_category
case notification.source
when Event
case notification.source.action
when "card_assigned" then "assignment"
when "comment_created" then "comment"
else "card"
end
when Mention
"mention"
else
"default"
end
end
def interruption_level
assignment_notification? ? "time-sensitive" : "active"
end
def assignment_notification?
notification.source.is_a?(Event) && notification.source.action == "card_assigned"
end
def creator_avatar_url
return unless notification.creator.respond_to?(:avatar) && notification.creator.avatar.attached?
Rails.application.routes.url_helpers.url_for(notification.creator.avatar)
end
end