Improved push notifications
This commit is contained in:
parent
92a540e024
commit
460d90d957
@ -1,10 +1,10 @@
|
|||||||
package notifications
|
package notifications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/aerogo/aero"
|
"github.com/aerogo/aero"
|
||||||
|
"github.com/animenotifier/arn"
|
||||||
"github.com/animenotifier/notify.moe/utils"
|
"github.com/animenotifier/notify.moe/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,13 +16,13 @@ func Test(ctx *aero.Context) string {
|
|||||||
return ctx.Error(http.StatusBadRequest, "Not logged in", nil)
|
return ctx.Error(http.StatusBadRequest, "Not logged in", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sub := range user.PushSubscriptions().Items {
|
notification := &arn.Notification{
|
||||||
err := sub.SendNotification("Yay, it works!")
|
Title: "Anime Notifier",
|
||||||
|
Message: "Yay, it works!",
|
||||||
if err != nil {
|
Icon: "https://" + ctx.App.Config.Domain + "/images/brand/300",
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user.SendNotification(notification)
|
||||||
|
|
||||||
return "ok"
|
return "ok"
|
||||||
}
|
}
|
||||||
|
@ -26,19 +26,19 @@ component Settings(user *arn.User)
|
|||||||
Icon("bell")
|
Icon("bell")
|
||||||
span Notifications
|
span Notifications
|
||||||
|
|
||||||
.widget-input
|
#enable-notifications.widget-input
|
||||||
label Enable:
|
label Enable:
|
||||||
button.action(data-action="enableNotifications", data-trigger="click")
|
button.action(data-action="enableNotifications", data-trigger="click")
|
||||||
Icon("toggle-on")
|
Icon("toggle-off")
|
||||||
span Enable notifications
|
span Enable notifications
|
||||||
|
|
||||||
.widget-input
|
#disable-notifications.widget-input
|
||||||
label Disable:
|
label Disable:
|
||||||
button.action(data-action="disableNotifications", data-trigger="click")
|
button.action(data-action="disableNotifications", data-trigger="click")
|
||||||
Icon("toggle-off")
|
Icon("toggle-on")
|
||||||
span Disable notifications
|
span Disable notifications
|
||||||
|
|
||||||
.widget-input
|
#test-notification.widget-input
|
||||||
label Test:
|
label Test:
|
||||||
button.action(data-action="testNotification", data-trigger="click")
|
button.action(data-action="testNotification", data-trigger="click")
|
||||||
Icon("paper-plane")
|
Icon("paper-plane")
|
||||||
|
@ -215,13 +215,15 @@ export function search(arn: AnimeNotifier, search: HTMLInputElement, e: Keyboard
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enable notifications
|
// Enable notifications
|
||||||
export function enableNotifications(arn: AnimeNotifier, button: HTMLElement) {
|
export async function enableNotifications(arn: AnimeNotifier, button: HTMLElement) {
|
||||||
arn.pushManager.subscribe(arn.user.dataset.id)
|
await arn.pushManager.subscribe(arn.user.dataset.id)
|
||||||
|
arn.updatePushUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable notifications
|
// Disable notifications
|
||||||
export function disableNotifications(arn: AnimeNotifier, button: HTMLElement) {
|
export async function disableNotifications(arn: AnimeNotifier, button: HTMLElement) {
|
||||||
arn.pushManager.unsubscribe(arn.user.dataset.id)
|
await arn.pushManager.unsubscribe(arn.user.dataset.id)
|
||||||
|
arn.updatePushUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test notification
|
// Test notification
|
||||||
|
@ -111,7 +111,7 @@ export class AnimeNotifier {
|
|||||||
this.pushManager = new PushManager()
|
this.pushManager = new PushManager()
|
||||||
}
|
}
|
||||||
|
|
||||||
onContentLoaded() {
|
async onContentLoaded() {
|
||||||
// Stop watching all the objects from the previous page.
|
// Stop watching all the objects from the previous page.
|
||||||
this.visibilityObserver.disconnect()
|
this.visibilityObserver.disconnect()
|
||||||
|
|
||||||
@ -120,9 +120,11 @@ export class AnimeNotifier {
|
|||||||
Promise.resolve().then(() => this.lazyLoadImages()),
|
Promise.resolve().then(() => this.lazyLoadImages()),
|
||||||
Promise.resolve().then(() => this.displayLocalDates()),
|
Promise.resolve().then(() => this.displayLocalDates()),
|
||||||
Promise.resolve().then(() => this.setSelectBoxValue()),
|
Promise.resolve().then(() => this.setSelectBoxValue()),
|
||||||
Promise.resolve().then(() => this.assignActions())
|
Promise.resolve().then(() => this.assignActions()),
|
||||||
|
Promise.resolve().then(() => this.updatePushUI())
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Apply page title
|
||||||
let headers = document.getElementsByTagName("h1")
|
let headers = document.getElementsByTagName("h1")
|
||||||
|
|
||||||
if(this.app.currentPath === "/" || headers.length === 0) {
|
if(this.app.currentPath === "/" || headers.length === 0) {
|
||||||
@ -134,6 +136,22 @@ export class AnimeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updatePushUI() {
|
||||||
|
if(!this.pushManager.pushSupported) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let subscription = await this.pushManager.subscription()
|
||||||
|
|
||||||
|
if(subscription) {
|
||||||
|
this.app.find("enable-notifications").style.display = "none"
|
||||||
|
this.app.find("disable-notifications").style.display = "flex"
|
||||||
|
} else {
|
||||||
|
this.app.find("enable-notifications").style.display = "flex"
|
||||||
|
this.app.find("disable-notifications").style.display = "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onIdle() {
|
onIdle() {
|
||||||
this.pushAnalytics()
|
this.pushAnalytics()
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,21 @@ export class PushManager {
|
|||||||
this.pushSupported = ("serviceWorker" in navigator) && ("PushManager" in window)
|
this.pushSupported = ("serviceWorker" in navigator) && ("PushManager" in window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async subscription(): Promise<PushSubscription> {
|
||||||
|
if(!this.pushSupported) {
|
||||||
|
return Promise.resolve(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
let registration = await navigator.serviceWorker.ready
|
||||||
|
let subscription = await registration.pushManager.getSubscription()
|
||||||
|
|
||||||
|
if(subscription) {
|
||||||
|
return Promise.resolve(subscription)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(null)
|
||||||
|
}
|
||||||
|
|
||||||
async subscribe(userId: string) {
|
async subscribe(userId: string) {
|
||||||
if(!this.pushSupported) {
|
if(!this.pushSupported) {
|
||||||
return
|
return
|
||||||
@ -59,6 +74,7 @@ export class PushManager {
|
|||||||
p256dh: key,
|
p256dh: key,
|
||||||
auth: secret,
|
auth: secret,
|
||||||
platform: navigator.platform,
|
platform: navigator.platform,
|
||||||
|
userAgent: navigator.userAgent,
|
||||||
screen: {
|
screen: {
|
||||||
width: window.screen.width,
|
width: window.screen.width,
|
||||||
height: window.screen.height
|
height: window.screen.height
|
||||||
|
@ -17,8 +17,25 @@ self.addEventListener("install", (evt: InstallEvent) => {
|
|||||||
self.addEventListener("activate", (evt: any) => {
|
self.addEventListener("activate", (evt: any) => {
|
||||||
console.log("Service worker activate")
|
console.log("Service worker activate")
|
||||||
|
|
||||||
|
// Delete old cache
|
||||||
|
let cacheWhitelist = [CACHE]
|
||||||
|
|
||||||
|
let deleteOldCache = caches.keys().then(keyList => {
|
||||||
|
return Promise.all(keyList.map(key => {
|
||||||
|
if(cacheWhitelist.indexOf(key) === -1) {
|
||||||
|
return caches.delete(key)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
let immediateClaim = (self as any).clients.claim()
|
||||||
|
|
||||||
|
// Immediate claim
|
||||||
evt.waitUntil(
|
evt.waitUntil(
|
||||||
(self as any).clients.claim()
|
Promise.all([
|
||||||
|
deleteOldCache,
|
||||||
|
immediateClaim
|
||||||
|
])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -111,11 +128,13 @@ self.addEventListener("fetch", async (evt: FetchEvent) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.addEventListener("push", (evt: PushEvent) => {
|
self.addEventListener("push", (evt: PushEvent) => {
|
||||||
var payload = evt.data ? evt.data.text() : "no payload"
|
var payload = evt.data ? evt.data.json() : {}
|
||||||
|
|
||||||
evt.waitUntil(
|
evt.waitUntil(
|
||||||
(self as any).registration.showNotification("beta.notify.moe Service Worker", {
|
(self as any).registration.showNotification(payload.title, {
|
||||||
body: payload
|
body: payload.message,
|
||||||
|
icon: payload.icon,
|
||||||
|
image: payload.image
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
1
tests.go
1
tests.go
@ -185,6 +185,7 @@ var routeTests = map[string][]string{
|
|||||||
"/import/myanimelist/animelist/finish": nil,
|
"/import/myanimelist/animelist/finish": nil,
|
||||||
"/import/kitsu/animelist": nil,
|
"/import/kitsu/animelist": nil,
|
||||||
"/import/kitsu/animelist/finish": nil,
|
"/import/kitsu/animelist/finish": nil,
|
||||||
|
"/api/test/notification": nil,
|
||||||
"/anime/:id/edit": nil,
|
"/anime/:id/edit": nil,
|
||||||
"/new/thread": nil,
|
"/new/thread": nil,
|
||||||
"/new/soundtrack": nil,
|
"/new/soundtrack": nil,
|
||||||
|
Loading…
Reference in New Issue
Block a user