Only raise notifications for new messages (#663)
This commit is contained in:
parent
04360b212f
commit
173d996de3
9 changed files with 86 additions and 22 deletions
|
|
@ -200,12 +200,10 @@ class AndroidPushFallbackWorker(context: Context, params: WorkerParameters) : Wo
|
|||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
|
||||
)
|
||||
|
||||
val body = "New activity"
|
||||
|
||||
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
|
||||
.setSmallIcon(android.R.drawable.stat_notify_chat)
|
||||
.setContentTitle("Flotilla")
|
||||
.setContentText(body)
|
||||
.setContentText("New message")
|
||||
.setAutoCancel(true)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setContentIntent(pendingIntent)
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ the story catalog in <code>e2e/USER_STORIES.md</code>.</p>
|
|||
<tr>
|
||||
<td>Push notifications</td>
|
||||
<td><span class="status s-ok">Implemented</span></td>
|
||||
<td><code>app/push/</code>, <code>settings/alerts</code>; web, FCM/APNs and Android fallback. US-086, US-120</td>
|
||||
<td><code>app/push/</code>, <code>settings/alerts</code>; web, FCM/APNs and Android fallback. US-086, US-120, US-136</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Threads</td>
|
||||
|
|
|
|||
|
|
@ -1675,6 +1675,18 @@ Acceptance:
|
|||
- Its body is the words bob wrote rather than the quote his reply is prepended
|
||||
with, and a url in it is named by its host instead of spelled out.
|
||||
|
||||
### US-136 — Be notified about messages and nothing else
|
||||
|
||||
As alice, I want notifications to be about what people say to me, so that a
|
||||
space with busy boards does not buzz my phone all day.
|
||||
|
||||
Acceptance:
|
||||
|
||||
- With push notifications on and the tab in the background, a message from bob
|
||||
in a room alice is in raises one.
|
||||
- A thread bob starts in the same room raises none, however much of it reaches
|
||||
her client.
|
||||
|
||||
### US-105 — Land on the home page
|
||||
|
||||
As a new user, I want the home page to route me somewhere useful, so that I'm
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import {
|
|||
expect,
|
||||
message,
|
||||
messageActions,
|
||||
modalForm,
|
||||
noteEditor,
|
||||
openRoomDetail,
|
||||
pageBar,
|
||||
pathPattern,
|
||||
|
|
@ -867,3 +869,59 @@ test("US-120 read what a notification says", async ({seed, as}) => {
|
|||
body: "sunday, the notice is at a link to harbor.example",
|
||||
})
|
||||
})
|
||||
|
||||
test("US-136 hear about a new message and not about a new thread", async ({seed, as}) => {
|
||||
const scenario = await seed(({relay, user}) => {
|
||||
const space = relay("space")
|
||||
|
||||
space.room("general", {name: "General"})
|
||||
space.join(user.alice, "general")
|
||||
space.join(user.bob, "general")
|
||||
space.profile(user.alice, {name: "Alice Anchor"})
|
||||
space.profile(user.bob, {name: "Bob Barnacle"})
|
||||
})
|
||||
|
||||
const space = scenario.space("space")
|
||||
|
||||
// The tab has to be in the background before a notification is raised at all.
|
||||
const alice = await as(users.alice, "/settings/alerts", {
|
||||
context: {permissions: ["notifications"]},
|
||||
})
|
||||
|
||||
await settingRow(alice, "Enable push notifications").getByRole("checkbox").check()
|
||||
await alice.getByRole("button", {name: "Save Changes"}).click()
|
||||
|
||||
await expect(alice.getByRole("alert")).toContainText("Your settings have been saved!")
|
||||
|
||||
await spaceNavItem(alice, space.name).click()
|
||||
await roomLink(alice, "General").click()
|
||||
|
||||
await expect(alice).toHaveURL(pathPattern(roomPath(space.url, "general")))
|
||||
|
||||
const notifications = await captureNotifications(alice)
|
||||
|
||||
const bob = await as(users.bob, `${spacePath(space.url)}/threads`)
|
||||
const board = bob
|
||||
.locator("section")
|
||||
.filter({has: bob.getByRole("heading", {name: "General", exact: true})})
|
||||
|
||||
await board.getByRole("button", {name: "Create", exact: true}).click()
|
||||
|
||||
const threadForm = modalForm(bob, "Create a Thread")
|
||||
|
||||
await threadForm.getByPlaceholder("What is this thread about?").fill("the dock is closing")
|
||||
await noteEditor(threadForm).pressSequentially("sunday, apparently")
|
||||
await threadForm.getByRole("button", {name: "Create Thread"}).click()
|
||||
|
||||
await expect(board.getByRole("row").filter({hasText: "the dock is closing"})).toBeVisible()
|
||||
|
||||
// Alice holds the thread before bob says anything, so a notification for it would be here by now.
|
||||
await contentNavItem(alice, "Threads").click()
|
||||
await expect(alice.getByRole("row").filter({hasText: "the dock is closing"})).toBeVisible()
|
||||
|
||||
await postTo(bob, "General", "when does the dock close?")
|
||||
|
||||
await expect
|
||||
.poll(() => notifications)
|
||||
.toEqual([{title: "New message", body: "when does the dock close?"}])
|
||||
})
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ test("US-086 configure alerts", async ({seed, as}) => {
|
|||
|
||||
const page = await as(users.alice, "/settings/alerts")
|
||||
|
||||
const sound = settingToggle(page, "Play sound for new activity")
|
||||
const sound = settingToggle(page, "Play sound for new messages")
|
||||
const alertTypes = page.locator("div.card").filter({has: page.getByText("Alert Types")})
|
||||
|
||||
await expect(sound).toBeChecked()
|
||||
|
|
@ -98,7 +98,7 @@ test("US-086 configure alerts", async ({seed, as}) => {
|
|||
await waitForToastToClear(page)
|
||||
await page.reload()
|
||||
|
||||
await expect(settingToggle(page, "Play sound for new activity")).not.toBeChecked()
|
||||
await expect(settingToggle(page, "Play sound for new messages")).not.toBeChecked()
|
||||
await expect(reminders).toHaveCount(2)
|
||||
await expect(reminders.nth(1).locator("input")).toHaveValue("1440")
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<div class="flex flex-col gap-1">
|
||||
<strong>Enable notifications for this space</strong>
|
||||
<p class="text-xs opacity-75">
|
||||
Get notified about new activity in this space. You can change this later in settings.
|
||||
Get notified about new messages in this space. You can change this later in settings.
|
||||
</p>
|
||||
</div>
|
||||
<input type="checkbox" class="toggle" bind:checked={notifications} />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import {writable} from "svelte/store"
|
||||
import type {Subscriber, Unsubscriber} from "svelte/store"
|
||||
import {Capacitor} from "@capacitor/core"
|
||||
import {assoc, call, ms, now, on, parseJson, poll, spec, throttle, uniq} from "@welshman/lib"
|
||||
import {call, ms, now, on, parseJson, poll, spec, throttle, uniq} from "@welshman/lib"
|
||||
import {LOCAL_RELAY_URL} from "@welshman/net"
|
||||
import type {RepositoryUpdate} from "@welshman/net"
|
||||
import {
|
||||
|
|
@ -19,7 +19,7 @@ import {merged, withGetter} from "@welshman/store"
|
|||
import {User} from "@welshman/app"
|
||||
import {navigate} from "@app/modal"
|
||||
import {app, messagingRelayLists, network, roomLists} from "@app/core"
|
||||
import {DM_KINDS, CONTENT_KINDS, makeCommentFilter} from "@app/content"
|
||||
import {DM_KINDS} from "@app/content"
|
||||
import {getMutedRooms, notificationSettings, shouldNotify, userSettingsValues} from "@app/settings"
|
||||
import {makeEventPath, goToChat, goToSpace} from "@app/routes"
|
||||
|
||||
|
|
@ -47,10 +47,6 @@ export interface IPushAdapter {
|
|||
}
|
||||
|
||||
export const onNotification = call(() => {
|
||||
const allFilters = [
|
||||
{kinds: [MESSAGE, ...CONTENT_KINDS, ...DM_KINDS]},
|
||||
makeCommentFilter(CONTENT_KINDS),
|
||||
]
|
||||
const subscribers: Subscriber<TrustedEvent>[] = []
|
||||
|
||||
let unsubscribe: Unsubscriber | undefined
|
||||
|
|
@ -62,7 +58,7 @@ export const onNotification = call(() => {
|
|||
let unsubscribeRepository: Unsubscriber | undefined
|
||||
const unsubscribeApp = app.subscribe($app => {
|
||||
unsubscribeRepository?.()
|
||||
const filters = allFilters.map(assoc("since", now()))
|
||||
const filters = [{kinds: [MESSAGE, ...DM_KINDS], since: now()}]
|
||||
unsubscribeRepository = on($app.repository, "update", ({added}: RepositoryUpdate) => {
|
||||
const $pubkey = $app.user?.pubkey
|
||||
|
||||
|
|
@ -163,7 +159,7 @@ export const syncRelaySubscriptions = (
|
|||
userSettingsValues,
|
||||
]).subscribe(
|
||||
throttle(3000, ([$spaceUrls, {spaces, mentions}, $settings]) => {
|
||||
const baseFilters = [{kinds: [MESSAGE, ...CONTENT_KINDS]}, makeCommentFilter(CONTENT_KINDS)]
|
||||
const baseFilter = {kinds: [MESSAGE]}
|
||||
|
||||
for (const url of $spaceUrls) {
|
||||
const {notify = true, exceptions = []} = $settings.alerts.find(spec({url})) || {}
|
||||
|
|
@ -178,18 +174,18 @@ export const syncRelaySubscriptions = (
|
|||
if (skipped.length > 0) {
|
||||
ignore.push({"#h": skipped})
|
||||
}
|
||||
filters.push(...baseFilters)
|
||||
filters.push(baseFilter)
|
||||
} else {
|
||||
const included = exceptions.filter(h => !muted.includes(h))
|
||||
|
||||
if (included.length > 0) {
|
||||
filters.push(...baseFilters.map(f => ({...f, "#h": included})))
|
||||
filters.push({...baseFilter, "#h": included})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mentions) {
|
||||
filters.push(...baseFilters.map(f => ({...f, "#p": [$pubkey]})))
|
||||
filters.push({...baseFilter, "#p": [$pubkey]})
|
||||
}
|
||||
|
||||
sync(url, "spaces", filters, ignore)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export class WebNotifications implements IPushAdapter {
|
|||
preview || "Someone tagged you in a message.",
|
||||
)
|
||||
} else if (spaces) {
|
||||
this._notify(event, "New activity", preview || "Someone posted a new message.")
|
||||
this._notify(event, "New message", preview || "Someone posted a new message.")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@
|
|||
{#if !Capacitor.isNativePlatform()}
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>Play sound for new activity</p>
|
||||
<p>Play sound for new messages</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<ToggleInput bind:checked={settings.sound} />
|
||||
|
|
@ -131,7 +131,7 @@
|
|||
<strong class="text-lg">Alert Types</strong>
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>Notify me about new activity</p>
|
||||
<p>Notify me about new messages in my spaces</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<ToggleInput bind:checked={settings.spaces} />
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
</FieldInline>
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>Notify me about new messages</p>
|
||||
<p>Notify me about new direct messages</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<ToggleInput bind:checked={settings.messages} />
|
||||
|
|
|
|||
Loading…
Reference in a new issue