feat: add poll result push notifications (#1227)

fixes one of the sub-tasks in #1130.

I also went ahead and removed the reply feature, because I cannot get it to work in Android 6.0.1 and I can't find any documentation for it in W3C/WHATWG, so I'm not sure how it is supposed to work.
This commit is contained in:
Nolan Lawson 2019-05-25 15:20:09 -07:00 committed by GitHub
parent a17948cf99
commit 12c5b732ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 100 additions and 92 deletions

View File

@ -4,18 +4,21 @@
{:elseif $notificationPermission === "denied"}
<p role="alert">You have denied permission to show notifications.</p>
{/if}
<form id="push-notification-settings" disabled="{!pushNotificationsSupport}" ref:pushNotificationsForm aria-label="Push notification settings">
<input type="checkbox" id="push-notifications-follow" name="follow" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
<label for="push-notifications-follow">New followers</label>
<br>
<input type="checkbox" id="push-notifications-favourite" name="favourite" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
<label for="push-notifications-favourite">Favorites</label>
<br>
<input type="checkbox" id="push-notifications-reblog" name="reblog" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
<label for="push-notifications-reblog">Boosts</label>
<br>
<input type="checkbox" id="push-notifications-mention" name="mention" disabled="{!pushNotificationsSupport}" on:change="onPushSettingsChange(event)">
<label for="push-notifications-mention">Mentions</label>
<form id="push-notification-settings"
disabled="{!pushNotificationsSupport}"
ref:form
aria-label="Push notification settings">
{#each options as option, i (option.key)}
{#if i > 0}
<br>
{/if}
<input type="checkbox"
id="push-notifications-{option.key}"
name="{option.key}"
disabled="{!pushNotificationsSupport}"
on:change="onPushSettingsChange(event)">
<label for="push-notifications-{option.key}">{option.label}</label>
{/each}
</form>
</div>
<style>
@ -27,11 +30,11 @@
padding: 20px;
line-height: 2em;
}
.push-notifications form[disabled="true"] {
form[disabled="true"] {
opacity: 0.5;
}
.push-notifications p {
margin: 0;
p {
margin: 0 0 10px 0;
}
</style>
<script>
@ -44,30 +47,52 @@
export default {
async oncreate () {
let { instanceName } = this.get()
let { instanceName, options } = this.get()
await updatePushSubscriptionForInstance(instanceName)
const form = this.refs.pushNotificationsForm
const { form } = this.refs
const { pushSubscription } = this.store.get()
form.elements.follow.checked = get(pushSubscription, ['alerts', 'follow'])
form.elements.favourite.checked = get(pushSubscription, ['alerts', 'favourite'])
form.elements.reblog.checked = get(pushSubscription, ['alerts', 'reblog'])
form.elements.mention.checked = get(pushSubscription, ['alerts', 'mention'])
for (let { key } of options) {
form.elements[key].checked = get(pushSubscription, ['alerts', key])
}
},
store: () => store,
data: () => ({
options: [
{
key: 'follow',
label: 'New Followers'
},
{
key: 'favourite',
label: 'Favorites'
},
{
key: 'reblog',
label: 'Boosts'
},
{
key: 'mention',
label: 'Mentions'
},
{
key: 'poll',
label: 'Poll results'
}
]
}),
computed: {
pushNotificationsSupport: ({ $pushNotificationsSupport }) => $pushNotificationsSupport
},
methods: {
async onPushSettingsChange (e) {
const { instanceName } = this.get()
const form = this.refs.pushNotificationsForm
const alerts = {
follow: form.elements.follow.checked,
favourite: form.elements.favourite.checked,
reblog: form.elements.reblog.checked,
mention: form.elements.mention.checked
const { instanceName, options } = this.get()
const { form } = this.refs
const alerts = {}
for (let { key } of options) {
alerts[key] = form.elements[key].checked
}
try {

View File

@ -46,7 +46,7 @@ self.addEventListener('activate', event => {
// delete old asset/ondemand caches
for (let key of keys) {
if (key !== ASSETS &&
!key.startsWith('webpack_assets_')) {
!key.startsWith('webpack_assets_')) {
await caches.delete(key)
}
}
@ -131,86 +131,71 @@ async function showSimpleNotification (data) {
}
async function showRichNotification (data, notification) {
const { origin } = new URL(data.icon)
const { icon, body } = data
const tag = notification.id
const { origin } = self.location
switch (notification.type) {
case 'follow': {
await self.registration.showNotification(data.title, {
icon: data.icon,
body: data.body,
tag: notification.id,
icon,
body,
tag,
data: {
url: `${self.location.origin}/accounts/${notification.account.id}`
url: `${origin}/accounts/${notification.account.id}`
}
})
break
}
case 'mention': {
const actions = [{
action: 'favourite',
title: 'Favourite'
}]
if ('reply' in NotificationEvent.prototype) {
actions.splice(0, 0, {
action: 'reply',
type: 'text',
title: 'Reply'
})
}
if (['public', 'unlisted'].includes(notification.status.visibility)) {
actions.push({
case 'reblog':
case 'favourite':
case 'poll':
await self.registration.showNotification(data.title, {
icon,
body,
tag,
data: {
url: `${origin}/statuses/${notification.status.id}`
}
})
break
case 'mention':
const isPublic = ['public', 'unlisted'].includes(notification.status.visibility)
const actions = [
{
action: 'favourite',
title: 'Favorite'
},
isPublic && {
action: 'reblog',
title: 'Boost'
})
}
}
].filter(Boolean)
await self.registration.showNotification(data.title, {
icon: data.icon,
body: data.body,
tag: notification.id,
icon,
body,
tag,
data: {
instance: origin,
instance: new URL(data.icon).origin,
status_id: notification.status.id,
access_token: data.access_token,
url: `${self.location.origin}/statuses/${notification.status.id}`
url: `${origin}/statuses/${notification.status.id}`
},
actions
})
break
}
case 'reblog': {
await self.registration.showNotification(data.title, {
icon: data.icon,
body: data.body,
tag: notification.id,
data: {
url: `${self.location.origin}/statuses/${notification.status.id}`
}
})
break
}
case 'favourite': {
await self.registration.showNotification(data.title, {
icon: data.icon,
body: data.body,
tag: notification.id,
data: {
url: `${self.location.origin}/statuses/${notification.status.id}`
}
})
break
}
}
}
const cloneNotification = notification => {
const clone = { }
const clone = {}
// Object.assign() does not work with notifications
for (let k in notification) {
clone[k] = notification[k]
if (notification.hasOwnProperty(k)) {
clone[k] = notification[k]
}
}
return clone
@ -227,21 +212,19 @@ const updateNotificationWithoutAction = (notification, action) => {
self.addEventListener('notificationclick', event => {
event.waitUntil((async () => {
switch (event.action) {
case 'reply': {
await post(`${event.notification.data.instance}/api/v1/statuses/`, {
status: event.reply,
in_reply_to_id: event.notification.data.status_id
}, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
await updateNotificationWithoutAction(event.notification, 'reply')
break
}
case 'reblog': {
await post(`${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/reblog`, null, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
const url = `${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/reblog`
await post(url, null, {
'Authorization': `Bearer ${event.notification.data.access_token}`
})
await updateNotificationWithoutAction(event.notification, 'reblog')
break
}
case 'favourite': {
await post(`${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/favourite`, null, { 'Authorization': `Bearer ${event.notification.data.access_token}` })
const url = `${event.notification.data.instance}/api/v1/statuses/${event.notification.data.status_id}/favourite`
await post(url, null, {
'Authorization': `Bearer ${event.notification.data.access_token}`
})
await updateNotificationWithoutAction(event.notification, 'favourite')
break
}