| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When a user clicks "send a test notification," Pilcrow delivers a push message (with a fixed payload) to all active subscriptions. The included client then displays this as a notification, using browser APIs to do so. This lets us verify that push notification works, end to end - and it appears to.
The API endpoint for sending a test notification is not documented. I didn't feel it prudent to extensively document an endpoint that is intended to be temporary and whose side effects are very much subject to change. However, for posterity, the endpoint is
POST /api/push/ping
{}
and the push message payload is
ping
Subscriptions with permanent delivery failures are nuked when we encounter them. Subscriptions with temporary failures cause the `ping` endpoint to return an internal server error, and are not retried. We'll likely want retry logic - including retry logic to handle server restarts - for any more serious use, but for a smoke test, giving up immediately is fine.
To make the push implementation testable, `App` is now generic over it. Tests use a dummy implementation that stores sent messages in memory. This has some significant limitations, documented in the test suite, but it beats sending real notifications to nowhere in tests.
|
| |
|
|
|
|
| |
Once a user has set up a push subscription, the client will re-establish it as needed whenever possible, falling back to manual intervention only when it is unable to create a push subscription.
This change imposes some architectural changes to the client, though they're not huge: the `session` type now includes a body of state (`push`) whose methods also call into the Pilcrow API. Previously, calls to the API were not made within the `session` types, and were instead only made by page and layout code, but orchestrating that for the push subscription lifecycle proved too complex to deal with. This is an experimental alternative, but it might be something we explore further in the future.
|
| |
|
|
| |
Existing client state, stored in local storage, is migrated to new keys (that mention "conversation" instead of "channel" where appropriate) the first time the client loads.
|
| |
|
|
| |
This is a **breaking change** for essentially all clients. Thankfully, there's presently just the one, so we don't need to go to much effort to accommoate that; the client is modified in this commit to adapt, users can reload their client, and life will go on.
|
| | |
|
| |
|
|
|
|
|
|
| |
This was actually two issues in one!
Issue 1: `isRetryable` did not consider whether we got a response or not. It assumed that the presence of a request in the error signaled that the error was definitely due to network issues, when in fact it's the presence of a request _and_ the absence of a response. That's my misreading of the Axios docs; the replacement `isRetryable` is more thorough.
Issue 2: operations in the outbox queue that fail with an exception stop the outbox drain process from making further progress, _and_ they stay in the queue. The outbox now dequeues jobs that throw an exception, and restarts itself if it terminates with a non-empty queue. The code that does this is _heinous_, but it seems to work well enough… Words I'm sure I won't come to regret.
|
| | |
|
| |
|
|
|
|
| |
This is intended to transparently resume the session (using `boot` to start over) after more serious connection interruptions. It interacts with the heartbeat timeout: we let the browser try to reconnect through `EventSource` on its own for up to 30 seconds, before intervening, closing the event source, and starting attempts to call `boot`.
This covers both initial boot, which will now hang if the server is unavailable (sorry), and reconnection after an event timeout. No other operations are retried (particularly, sending a message is _not_ retried).
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
It's amazing what you can learn by skimming the docs.
|
| |
|
|
| |
Even when they get mapped to snake_case searchParams.
|
| |
|
|
| |
This also fixes some rendering jank with the message timestamp chip.
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
On Safari (iOS and macOS), the permissions prompt can only be done during a user gesture; mounting is sufficiently disconnected from any user gestures that it's not allowed. The browser raises an exception, which, since it is unhandled, then leaks out and interrupts SvelteKit's element unmounting, leading to the whole UI being duplicated when switching channels (the old UI is not unmounted).
|
| | |
|
| |
|
|
|
|
| |
This was causing problems for changing passwords: if the user didn't type anything in the "original password" field, the code path to sending that field to the server was just straight-up omitting the field from the message, rather than setting it to empty string, causing a 422 Unprocessable Entity.
On investigation we had latent bugs related to this in a bunch of spots.
|
| |
|
|
| |
The protocol here re-checks the caller's password, as a "I left myself logged in" anti-pranking check.
|
| | |
|
| | |
|
| |
|
|
| |
I've also aligned channel creation with this (it's 409 Conflict). To make server setup more distinct, it now returns 503 Service Unavailable if setup has not been completed.
|
| | |
|
| |
|
|
| |
This - in passing - fixes the problem where the client failed to subscribe after logging in, by causing the whole subscription process to be re-run when returning to the main interface.
|
| | |
|
| |
|