Make the app an installable PWA with phone layout and Web Push

Add a generated manifest, icon set, offline page and service worker that never caches authenticated HTML, plus install and update UI. Turn the rail into a drawer below md with container-query internals, dvh and safe-area handling, and reconnect the socket after visibility/network changes. Add Web Push subscriptions, presence-aware delivery, notification settings and tests.
This commit is contained in:
2026-10-19 17:12:16 +01:00
parent 61098a114c
commit dbfe48796b
100 changed files with 3573 additions and 117 deletions
+88
View File
@@ -2077,6 +2077,94 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
},
],
},
{
tableName: "user_presence",
fields: [
{
fieldName: "user_id",
fieldDescription: `The user. One row each`,
dataType: "INTEGER",
unique: true,
foreignKey: {
cascadeDelete: true,
destinationTableName: "users",
destinationTableColumnName: "id",
destinationTableColumnType: "INTEGER",
foreignKeyName: "user_presence_user_fk",
},
},
{
fieldName: "last_seen_at",
fieldDescription: `Unix timestamp of the last open socket or keepalive, for skipping push notifications while the app is open`,
dataType: "INTEGER",
},
],
indexes: [
{
indexName: "idx_user_presence_last_seen_at",
indexTableFields: ["last_seen_at"],
},
],
},
{
tableName: "push_subscriptions",
fields: [
{
fieldName: "user_id",
fieldDescription: `The user the device belongs to`,
dataType: "INTEGER",
foreignKey: {
cascadeDelete: true,
destinationTableName: "users",
destinationTableColumnName: "id",
destinationTableColumnType: "INTEGER",
foreignKeyName: "push_subscriptions_user_fk",
},
},
{
fieldName: "endpoint",
fieldDescription: `The push service URL the browser gave. Unique: one device, one row`,
dataType: "TEXT",
unique: true,
},
{
fieldName: "p256dh",
fieldDescription: `The subscription's public key`,
dataType: "TEXT",
},
{
fieldName: "auth",
fieldDescription: `The subscription's auth secret`,
dataType: "TEXT",
},
{
fieldName: "user_agent",
fieldDescription: `What the device said it was, for the settings list`,
dataType: "TEXT",
},
{
fieldName: "platform",
fieldDescription: `The browser's platform, for the settings list`,
dataType: "TEXT",
},
{
fieldName: "last_used_at",
fieldDescription: `Unix timestamp of the last notification sent to it`,
dataType: "INTEGER",
},
{
fieldName: "last_error",
fieldDescription: `Why the last send failed, if it did`,
dataType: "TEXT",
},
],
indexes: [
{
indexName: "idx_push_subscriptions_user_id",
indexTableFields: ["user_id"],
},
],
},
{
tableName: "envs",
fields: [