Improve payload format of Web Push API now that it's open (#7521)
> Good lord what is happening in there Previously the contents of the Web Push API payloads closely resembled the structure of JavaScript's [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification). But now that the API is open to non-browser apps, and given that there is no required coupling between contents of the payload and a Notification object, here is how I changed the payload: ```json { "access_token": "...", "preferred_locale": "en", "notification_id": "12345", "notification_type": "follow", "title": "So and so followed you", "body": "This is my bio", "icon": "https://example.com/avatar.png" } ``` The title, body and icon attributes are included as a fallback so you can construct a minimal notification if you cannot perform a network request to the API to get more data.
This commit is contained in:
parent
1951ff41b3
commit
4b94e9c65e
76 changed files with 217 additions and 623 deletions
|
@ -2,168 +2,37 @@
|
|||
|
||||
class Web::NotificationSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
include StreamEntriesHelper
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
|
||||
class DataSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
include StreamEntriesHelper
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
attributes :access_token, :preferred_locale, :notification_id,
|
||||
:notification_type, :icon, :title, :body
|
||||
|
||||
attributes :content, :nsfw, :url, :actions,
|
||||
:access_token, :message, :dir
|
||||
|
||||
def content
|
||||
decoder.decode(strip_tags(body))
|
||||
end
|
||||
|
||||
def dir
|
||||
rtl?(body) ? 'rtl' : 'ltr'
|
||||
end
|
||||
|
||||
def nsfw
|
||||
return if object.target_status.nil?
|
||||
object.target_status.spoiler_text.presence
|
||||
end
|
||||
|
||||
def url
|
||||
case object.type
|
||||
when :mention
|
||||
web_url("statuses/#{object.target_status.id}")
|
||||
when :follow
|
||||
web_url("accounts/#{object.from_account.id}")
|
||||
when :favourite
|
||||
web_url("statuses/#{object.target_status.id}")
|
||||
when :reblog
|
||||
web_url("statuses/#{object.target_status.id}")
|
||||
end
|
||||
end
|
||||
|
||||
def actions
|
||||
return @actions if defined?(@actions)
|
||||
|
||||
@actions = []
|
||||
|
||||
if object.type == :mention
|
||||
@actions << expand_action if collapsed?
|
||||
@actions << favourite_action
|
||||
@actions << reblog_action if rebloggable?
|
||||
end
|
||||
|
||||
@actions
|
||||
end
|
||||
|
||||
def access_token
|
||||
return if actions.empty?
|
||||
current_push_subscription.associated_access_token
|
||||
end
|
||||
|
||||
def message
|
||||
I18n.t('push_notifications.group.title')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def body
|
||||
case object.type
|
||||
when :mention
|
||||
object.target_status.text
|
||||
when :follow
|
||||
object.from_account.note
|
||||
when :favourite
|
||||
object.target_status.text
|
||||
when :reblog
|
||||
object.target_status.text
|
||||
end
|
||||
end
|
||||
|
||||
def decoder
|
||||
@decoder ||= HTMLEntities.new
|
||||
end
|
||||
|
||||
def expand_action
|
||||
{
|
||||
title: I18n.t('push_notifications.mention.action_expand'),
|
||||
icon: full_asset_url('web-push-icon_expand.png', skip_pipeline: true),
|
||||
todo: 'expand',
|
||||
action: 'expand',
|
||||
}
|
||||
end
|
||||
|
||||
def favourite_action
|
||||
{
|
||||
title: I18n.t('push_notifications.mention.action_favourite'),
|
||||
icon: full_asset_url('web-push-icon_favourite.png', skip_pipeline: true),
|
||||
todo: 'request',
|
||||
method: 'POST',
|
||||
action: "/api/v1/statuses/#{object.target_status.id}/favourite",
|
||||
}
|
||||
end
|
||||
|
||||
def reblog_action
|
||||
{
|
||||
title: I18n.t('push_notifications.mention.action_boost'),
|
||||
icon: full_asset_url('web-push-icon_reblog.png', skip_pipeline: true),
|
||||
todo: 'request',
|
||||
method: 'POST',
|
||||
action: "/api/v1/statuses/#{object.target_status.id}/reblog",
|
||||
}
|
||||
end
|
||||
|
||||
def collapsed?
|
||||
!object.target_status.nil? && (object.target_status.sensitive? || object.target_status.spoiler_text.present?)
|
||||
end
|
||||
|
||||
def rebloggable?
|
||||
!object.target_status.nil? && !object.target_status.hidden?
|
||||
end
|
||||
def access_token
|
||||
current_push_subscription.associated_access_token
|
||||
end
|
||||
|
||||
attributes :title, :image, :badge, :tag,
|
||||
:timestamp, :icon
|
||||
|
||||
has_one :data, serializer: DataSerializer
|
||||
|
||||
def title
|
||||
case object.type
|
||||
when :mention
|
||||
I18n.t('push_notifications.mention.title', name: name)
|
||||
when :follow
|
||||
I18n.t('push_notifications.follow.title', name: name)
|
||||
when :favourite
|
||||
I18n.t('push_notifications.favourite.title', name: name)
|
||||
when :reblog
|
||||
I18n.t('push_notifications.reblog.title', name: name)
|
||||
end
|
||||
def preferred_locale
|
||||
current_push_subscription.associated_user&.locale || I18n.default_locale
|
||||
end
|
||||
|
||||
def image
|
||||
return if object.target_status.nil? || object.target_status.media_attachments.empty?
|
||||
full_asset_url(object.target_status.media_attachments.first.file.url(:small))
|
||||
end
|
||||
|
||||
def badge
|
||||
full_asset_url('badge.png', skip_pipeline: true)
|
||||
end
|
||||
|
||||
def tag
|
||||
def notification_id
|
||||
object.id
|
||||
end
|
||||
|
||||
def timestamp
|
||||
object.created_at
|
||||
def notification_type
|
||||
object.type
|
||||
end
|
||||
|
||||
def icon
|
||||
object.from_account.avatar_static_url
|
||||
full_asset_url(object.from_account.avatar_static_url)
|
||||
end
|
||||
|
||||
def data
|
||||
object
|
||||
def title
|
||||
I18n.t("notification_mailer.#{object.type}.subject", name: object.from_account.display_name.presence || object.from_account.username)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def name
|
||||
display_name(object.from_account)
|
||||
def body
|
||||
truncate(strip_tags(object.target_status&.spoiler_text&.presence || object.target_status&.text || object.from_account.note), length: 140)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue