diff --git a/android/app/src/main/java/social/flotilla/notifications/AndroidPushFallbackWorker.kt b/android/app/src/main/java/social/flotilla/notifications/AndroidPushFallbackWorker.kt
index 0bd79e4f..420cd8bb 100644
--- a/android/app/src/main/java/social/flotilla/notifications/AndroidPushFallbackWorker.kt
+++ b/android/app/src/main/java/social/flotilla/notifications/AndroidPushFallbackWorker.kt
@@ -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)
diff --git a/docs/feature_matrix.html b/docs/feature_matrix.html
index e18b063c..0aa9f2fa 100644
--- a/docs/feature_matrix.html
+++ b/docs/feature_matrix.html
@@ -156,7 +156,7 @@ the story catalog in e2e/USER_STORIES.md.
Push notifications
Implemented
-
app/push/, settings/alerts; web, FCM/APNs and Android fallback. US-086, US-120
+
app/push/, settings/alerts; web, FCM/APNs and Android fallback. US-086, US-120, US-136
Threads
diff --git a/e2e/USER_STORIES.md b/e2e/USER_STORIES.md
index 1075ec44..d546033f 100644
--- a/e2e/USER_STORIES.md
+++ b/e2e/USER_STORIES.md
@@ -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
diff --git a/e2e/specs/notifications.spec.ts b/e2e/specs/notifications.spec.ts
index d2629232..557cf5ec 100644
--- a/e2e/specs/notifications.spec.ts
+++ b/e2e/specs/notifications.spec.ts
@@ -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?"}])
+})
diff --git a/e2e/specs/settings.spec.ts b/e2e/specs/settings.spec.ts
index c80a2418..59b0e045 100644
--- a/e2e/specs/settings.spec.ts
+++ b/e2e/specs/settings.spec.ts
@@ -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")
})
diff --git a/src/app/components/SpaceJoinNotifications.svelte b/src/app/components/SpaceJoinNotifications.svelte
index 055cdd88..1e171942 100644
--- a/src/app/components/SpaceJoinNotifications.svelte
+++ b/src/app/components/SpaceJoinNotifications.svelte
@@ -11,7 +11,7 @@
Enable notifications for this space
- 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.
diff --git a/src/app/push/adapters/common.ts b/src/app/push/adapters/common.ts
index 1d618941..b33d407e 100644
--- a/src/app/push/adapters/common.ts
+++ b/src/app/push/adapters/common.ts
@@ -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[] = []
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)
diff --git a/src/app/push/adapters/web.ts b/src/app/push/adapters/web.ts
index 5c60fee2..d935aa72 100644
--- a/src/app/push/adapters/web.ts
+++ b/src/app/push/adapters/web.ts
@@ -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.")
}
}
})
diff --git a/src/routes/settings/alerts/+page.svelte b/src/routes/settings/alerts/+page.svelte
index 9463ccf4..ef67b007 100644
--- a/src/routes/settings/alerts/+page.svelte
+++ b/src/routes/settings/alerts/+page.svelte
@@ -108,7 +108,7 @@
{#if !Capacitor.isNativePlatform()}
{#snippet label()}
-