feat(todo,app): files attached to tasks and comments

Halkyon's ADR 0043, D1, D3, D5 and D8: any file up to 100 MB, attached to
a task's description or to a comment, sealed as everything of Todo's.

Server: the attachment table, synced and sealed as the others, with the
sealed file's hash readable for the store; todoFiles hands halkyon_base
its rows, readable by their space's members, and takes sealed files
alone; the files no attachment names go daily. Its tests hold downloads
to the row's space, refuse a readable file and prune what no live row
names. Migration attachments: CREATE TABLE "attachment" with its indexes
and the foreign key to its space, cascading as every synced table's.

App: AttachmentRepository seals each file for its row, keeps it sealed
and opened in the person's folder, uploads it after each sync and fetches
it as it shows, both held back by Without files on mobile data but for a
file tapped. Under the description and a comment's text, a row of them:
pictures as thumbnails opening full-size, other files as chips opening in
the system's app, else saved; the paperclip beside the description and in the comment's
composer adds them, the composer holding them until it is sent. A task deleted takes its files
and its comments' along, a comment its own.

halkyon_app opens a file in the system's app (FileOpener): on Android
through its plugin and a FileProvider of its own class, sharing the
cache's halkyon_opened/ folder alone; on the desktop as a file: URI.

Whats-New: Attach files to a task's description or a comment with the paperclip: pictures show as thumbnails, other files open in their app.
Whats-New-De: Hänge mit der Büroklammer Dateien an die Beschreibung einer Aufgabe oder an einen Kommentar: Bilder erscheinen als Vorschau, andere Dateien öffnen sich in ihrer App.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-11 01:17:22 +01:00
commit 3ca4b4308d
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
8 changed files with 23300 additions and 62 deletions

View file

@ -0,0 +1,806 @@
{
"__className__": "serverpod.DatabaseDefinition",
"schemaVersion": 2,
"moduleName": "halkyon_todo",
"tables": [
{
"__className__": "serverpod.TableDefinition",
"name": "attachment",
"dartName": "Attachment",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "sha256",
"fieldName": "sha256",
"columnType": 0,
"isNullable": false,
"dartType": "String"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "attachment_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "attachment_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
},
{
"__className__": "serverpod.IndexDefinition",
"indexName": "attachment_hash_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
},
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "sha256"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "content_key",
"dartName": "ContentKey",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "dataKeyId",
"fieldName": "dataKeyId",
"columnType": 0,
"isNullable": false,
"dartType": "String"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "sealedKey",
"fieldName": "sealedKey",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "content_key_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "content_key_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "label",
"dartName": "Label",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "label_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "label_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "project",
"dartName": "Project",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "project_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "project_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "saved_filter",
"dartName": "SavedFilter",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "saved_filter_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "saved_filter_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "section",
"dartName": "Section",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "section_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "section_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "task",
"dartName": "Task",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "task_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "task_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "task_comment",
"dartName": "TaskComment",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "task_comment_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "task_comment_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
},
{
"__className__": "serverpod.TableDefinition",
"name": "todo_settings",
"dartName": "TodoSettings",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "todo_settings_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "todo_settings_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
}
],
"installedModules": [
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "halkyon_base",
"version": "20261110225132890-file-store"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod",
"version": "20260824182259319"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod_auth_idp",
"version": "20260924105404509"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod_offline_sync",
"version": "20260914143806119"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "halkyon_oidc",
"version": "20261023180644988"
},
{
"__className__": "serverpod.DatabaseMigrationVersion",
"module": "serverpod_auth_core",
"version": "20260924105232991"
}
],
"migrationApiVersion": 1
}

View file

@ -0,0 +1,121 @@
{
"__className__": "serverpod.DatabaseMigration",
"actions": [
{
"__className__": "serverpod.DatabaseMigrationAction",
"type": "createTable",
"createTable": {
"__className__": "serverpod.TableDefinition",
"name": "attachment",
"dartName": "Attachment",
"module": "halkyon_todo",
"schema": "public",
"columns": [
{
"__className__": "serverpod.ColumnDefinition",
"name": "id",
"fieldName": "id",
"columnType": 7,
"isNullable": false,
"columnDefault": "random_v7",
"dartType": "UuidValue?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "spaceId",
"fieldName": "spaceId",
"columnType": 6,
"isNullable": true,
"dartType": "int?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "sha256",
"fieldName": "sha256",
"columnType": 0,
"isNullable": false,
"dartType": "String"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "keyId",
"fieldName": "keyId",
"columnType": 0,
"isNullable": true,
"dartType": "String?"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "payload",
"fieldName": "payload",
"columnType": 5,
"isNullable": false,
"dartType": "dart:typed_data:ByteData"
},
{
"__className__": "serverpod.ColumnDefinition",
"name": "nonce",
"fieldName": "nonce",
"columnType": 5,
"isNullable": true,
"dartType": "dart:typed_data:ByteData?"
}
],
"foreignKeys": [
{
"__className__": "serverpod.ForeignKeyDefinition",
"constraintName": "attachment_fk_0",
"columns": [
"spaceId"
],
"referenceTable": "offline_sync_spaces",
"referenceTableSchema": "public",
"referenceColumns": [
"id"
],
"onUpdate": 3,
"onDelete": 4
}
],
"indexes": [
{
"__className__": "serverpod.IndexDefinition",
"indexName": "attachment_space_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
},
{
"__className__": "serverpod.IndexDefinition",
"indexName": "attachment_hash_idx",
"elements": [
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "spaceId"
},
{
"__className__": "serverpod.IndexElementDefinition",
"type": 0,
"definition": "sha256"
}
],
"type": "btree",
"isUnique": false,
"isPrimary": false
}
],
"managed": true
}
}
],
"warnings": [],
"migrationApiVersion": 1
}

View file

@ -10,6 +10,7 @@ part '20261101180755366-settings/migration.dart';
part '20261106183802735-filters/migration.dart';
part '20261106184947570-comments/migration.dart';
part '20261110225635732-file-store/migration.dart';
part '20261110231607673-attachments/migration.dart';
/// Migration registry for the client-side database.
class MigrationRegistry {
@ -22,6 +23,7 @@ class MigrationRegistry {
_Migration20261106183802735_filters(),
_Migration20261106184947570_comments(),
_Migration20261110225635732_file_store(),
_Migration20261110231607673_attachments(),
];
/// List of all client-side database migration versions.

View file

@ -0,0 +1,705 @@
/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:typed_data' as _idt;
import 'package:serverpod_client/serverpod_client.dart' as _isc;
import 'package:serverpod_database/serverpod_database.dart' as _isd;
/// A file attached to a task's description or to a comment (Halkyon's ADR
/// 0043, D8): its name, media type and size, and what it is attached to, in
/// its sealed payload (ADR 0033, D5); the file itself is sealed too, kept
/// in halkyon_base's store (D2) and fetched when shown. The instance sees
/// that it exists, its size and the sealed file's hash, not what it is
/// attached to. Never changed: deleted with what it is attached to, or on
/// its own. Synced.
abstract class Attachment
implements _isd.TableRow<_isc.UuidValue?>, _isc.ProtocolSerialization {
Attachment._({
this.id,
this.spaceId,
required this.sha256,
this.keyId,
required this.payload,
this.nonce,
});
factory Attachment({
_isc.UuidValue? id,
int? spaceId,
required String sha256,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) = _AttachmentImpl;
factory Attachment.fromJson(Map<String, dynamic> jsonSerialization) {
return Attachment(
id: jsonSerialization['id'] == null
? null
: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['id']),
spaceId: jsonSerialization['spaceId'] as int?,
sha256: jsonSerialization['sha256'] as String,
keyId: jsonSerialization['keyId'] as String?,
payload: _isc.ByteDataJsonExtension.fromJson(
jsonSerialization['payload'],
),
nonce: jsonSerialization['nonce'] == null
? null
: _isc.ByteDataJsonExtension.fromJson(jsonSerialization['nonce']),
);
}
static final t = AttachmentTable();
static const db = AttachmentRepository._();
@override
_isc.UuidValue? id;
/// The space owning this row. Maintained by the sync engine.
int? spaceId;
/// The sealed file's SHA-256, in lowercase hex: its name in the store,
/// which the server reads to serve it and to count and prune the files
/// (`todo_files.dart`). The hash of sealed bytes says nothing of the file.
String sha256;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
String? keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
_idt.ByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
_idt.ByteData? nonce;
@override
_isd.Table<_isc.UuidValue?> get table => t;
/// Returns a shallow copy of this [Attachment]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
Attachment copyWith({
_isc.UuidValue? id,
int? spaceId,
String? sha256,
String? keyId,
_idt.ByteData? payload,
_idt.ByteData? nonce,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'Attachment',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
'sha256': sha256,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'Attachment',
if (id != null) 'id': id?.toJson(),
if (spaceId != null) 'spaceId': spaceId,
'sha256': sha256,
if (keyId != null) 'keyId': keyId,
'payload': payload.toJson(),
if (nonce != null) 'nonce': nonce?.toJson(),
};
}
static AttachmentInclude include() {
return AttachmentInclude._();
}
static AttachmentIncludeList includeList({
_isd.WhereExpressionBuilder<AttachmentTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<AttachmentTable>? orderBy,
_isd.OrderByListBuilder<AttachmentTable>? orderByList,
AttachmentInclude? include,
}) {
return AttachmentIncludeList._(
where: where,
limit: limit,
offset: offset,
orderBy: orderBy?.call(Attachment.t),
orderByList: orderByList?.call(Attachment.t),
include: include,
);
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _Undefined {}
class _AttachmentImpl extends Attachment {
_AttachmentImpl({
_isc.UuidValue? id,
int? spaceId,
required String sha256,
String? keyId,
required _idt.ByteData payload,
_idt.ByteData? nonce,
}) : super._(
id: id,
spaceId: spaceId,
sha256: sha256,
keyId: keyId,
payload: payload,
nonce: nonce,
);
/// Returns a shallow copy of this [Attachment]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
Attachment copyWith({
Object? id = _Undefined,
Object? spaceId = _Undefined,
String? sha256,
Object? keyId = _Undefined,
_idt.ByteData? payload,
Object? nonce = _Undefined,
}) {
return Attachment(
id: id is _isc.UuidValue? ? id : this.id,
spaceId: spaceId is int? ? spaceId : this.spaceId,
sha256: sha256 ?? this.sha256,
keyId: keyId is String? ? keyId : this.keyId,
payload: payload ?? this.payload.clone(),
nonce: nonce is _idt.ByteData? ? nonce : this.nonce?.clone(),
);
}
}
class AttachmentUpdateTable extends _isd.UpdateTable<AttachmentTable> {
AttachmentUpdateTable(super.table);
_isd.ColumnValue<int, int> spaceId(int? value) => _isd.ColumnValue(
table.spaceId,
value,
);
_isd.ColumnValue<String, String> sha256(String value) => _isd.ColumnValue(
table.sha256,
value,
);
_isd.ColumnValue<String, String> keyId(String? value) => _isd.ColumnValue(
table.keyId,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> payload(_idt.ByteData value) =>
_isd.ColumnValue(
table.payload,
value,
);
_isd.ColumnValue<_idt.ByteData, _idt.ByteData> nonce(_idt.ByteData? value) =>
_isd.ColumnValue(
table.nonce,
value,
);
}
class AttachmentTable extends _isd.Table<_isc.UuidValue?> {
AttachmentTable({super.tableRelation}) : super(tableName: 'attachment') {
updateTable = AttachmentUpdateTable(this);
spaceId = _isd.ColumnInt(
'spaceId',
this,
);
sha256 = _isd.ColumnString(
'sha256',
this,
);
keyId = _isd.ColumnString(
'keyId',
this,
);
payload = _isd.ColumnByteData(
'payload',
this,
);
nonce = _isd.ColumnByteData(
'nonce',
this,
);
}
late final AttachmentUpdateTable updateTable;
/// The space owning this row. Maintained by the sync engine.
late final _isd.ColumnInt spaceId;
/// The sealed file's SHA-256, in lowercase hex: its name in the store,
/// which the server reads to serve it and to count and prune the files
/// (`todo_files.dart`). The hash of sealed bytes says nothing of the file.
late final _isd.ColumnString sha256;
/// The key it is sealed with (ADR 0002's envelope); never null in Todo,
/// where everything is sealed.
late final _isd.ColumnString keyId;
/// The content, sealed: UTF-8 JSON with a `schemaVersion` once opened.
late final _isd.ColumnByteData payload;
/// The sealing's nonce (ADR 0002's envelope).
late final _isd.ColumnByteData nonce;
@override
List<_isd.Column> get columns => [
id,
spaceId,
sha256,
keyId,
payload,
nonce,
];
}
class AttachmentInclude extends _isd.IncludeObject {
AttachmentInclude._();
@override
Map<String, _isd.Include?> get includes => {};
@override
_isd.Table<_isc.UuidValue?> get table => Attachment.t;
}
class AttachmentIncludeList extends _isd.IncludeList {
AttachmentIncludeList._({
_isd.WhereExpressionBuilder<AttachmentTable>? where,
super.limit,
super.offset,
super.orderBy,
super.orderByList,
super.include,
}) {
super.where = where?.call(Attachment.t);
}
@override
Map<String, _isd.Include?> get includes => include?.includes ?? {};
@override
_isd.Table<_isc.UuidValue?> get table => Attachment.t;
}
class AttachmentRepository {
const AttachmentRepository._();
/// Returns a list of [Attachment]s matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order of the items use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// The maximum number of items can be set by [limit]. If no limit is set,
/// all items matching the query will be returned.
///
/// [offset] defines how many items to skip, after which [limit] (or all)
/// items are read from the database.
///
/// ```dart
/// var persons = await Persons.db.find(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.firstName,
/// limit: 100,
/// );
/// ```
Future<List<Attachment>> find(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<AttachmentTable>? where,
int? limit,
int? offset,
_isd.OrderByBuilder<AttachmentTable>? orderBy,
_isd.OrderByListBuilder<AttachmentTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.find<Attachment>(
where: where?.call(Attachment.t),
orderBy: orderBy?.call(Attachment.t),
orderByList: orderByList?.call(Attachment.t),
limit: limit,
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Returns the first matching [Attachment] matching the given query parameters.
///
/// Use [where] to specify which items to include in the return value.
/// If none is specified, all items will be returned.
///
/// To specify the order use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// [offset] defines how many items to skip, after which the next one will be picked.
///
/// ```dart
/// var youngestPerson = await Persons.db.findFirstRow(
/// session,
/// where: (t) => t.lastName.equals('Jones'),
/// orderBy: (t) => t.age,
/// );
/// ```
Future<Attachment?> findFirstRow(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<AttachmentTable>? where,
int? offset,
_isd.OrderByBuilder<AttachmentTable>? orderBy,
_isd.OrderByListBuilder<AttachmentTable>? orderByList,
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findFirstRow<Attachment>(
where: where?.call(Attachment.t),
orderBy: orderBy?.call(Attachment.t),
orderByList: orderByList?.call(Attachment.t),
offset: offset,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Finds a single [Attachment] by its [id] or null if no such row exists.
Future<Attachment?> findById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
_isd.Transaction? transaction,
_isd.LockMode? lockMode,
_isd.LockBehavior? lockBehavior,
}) async {
return session.db.findById<Attachment>(
id,
transaction: transaction,
lockMode: lockMode,
lockBehavior: lockBehavior,
);
}
/// Inserts all [Attachment]s in the list and returns the inserted rows.
///
/// The returned [Attachment]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails to
/// insert, none of the rows will be inserted.
///
/// If [ignoreConflicts] is set to `true`, rows that conflict with existing
/// rows are silently skipped, and only the successfully inserted rows are
/// returned.
///
/// If [noReturn] is set to `true`, the inserted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Attachment>> insert(
_isd.DatabaseSession session,
List<Attachment> rows, {
_isd.Transaction? transaction,
bool ignoreConflicts = false,
bool noReturn = false,
}) async {
return session.db.insert<Attachment>(
rows,
transaction: transaction,
ignoreConflicts: ignoreConflicts,
noReturn: noReturn,
);
}
/// Inserts a single [Attachment] and returns the inserted row.
///
/// The returned [Attachment] will have its `id` field set.
Future<Attachment> insertRow(
_isd.DatabaseSession session,
Attachment row, {
_isd.Transaction? transaction,
}) async {
return session.db.insertRow<Attachment>(
row,
transaction: transaction,
);
}
/// Upserts all [Attachment]s in the list and returns the resulting rows.
///
/// If a row conflicts on the given [conflictColumns], the existing row is
/// updated with the new values. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies to rows matching the
/// given expression. Conflicting rows that don't match are skipped and not
/// returned, so the resulting list may be shorter than [rows].
///
/// The returned [Attachment]s will have their `id` fields set.
///
/// This is an atomic operation, meaning that if one of the rows fails,
/// none of the rows will be affected.
///
/// If [noReturn] is set to `true`, the resulting rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Attachment>> upsert(
_isd.DatabaseSession session,
List<Attachment> rows, {
required _isd.ColumnSelections<AttachmentTable> conflictColumns,
_isd.ColumnSelections<AttachmentTable>? updateColumns,
_isd.WhereExpressionBuilder<AttachmentTable>? updateWhere,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.upsert<Attachment>(
rows,
conflictColumns: conflictColumns(Attachment.t),
updateColumns: updateColumns?.call(Attachment.t),
updateWhere: updateWhere?.call(Attachment.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Upserts a single [Attachment] and returns the resulting row.
///
/// If the row conflicts on the given [conflictColumns], the existing row is
/// updated. Otherwise, a new row is inserted.
///
/// If [updateColumns] is provided, only those columns will be updated on
/// conflict. If null, all non-conflict, non-id columns are updated.
///
/// If [updateWhere] is provided, the update only applies when the existing
/// row matches the expression. Returns `null` if no row was affected — for
/// example when [updateWhere] does not match the conflicting row.
///
/// The returned [Attachment] will have its `id` field set.
Future<Attachment?> upsertRow(
_isd.DatabaseSession session,
Attachment row, {
required _isd.ColumnSelections<AttachmentTable> conflictColumns,
_isd.ColumnSelections<AttachmentTable>? updateColumns,
_isd.WhereExpressionBuilder<AttachmentTable>? updateWhere,
_isd.Transaction? transaction,
}) async {
return session.db.upsertRow<Attachment>(
row,
conflictColumns: conflictColumns(Attachment.t),
updateColumns: updateColumns?.call(Attachment.t),
updateWhere: updateWhere?.call(Attachment.t),
transaction: transaction,
);
}
/// Updates all [Attachment]s in the list and returns the updated rows. If
/// [columns] is provided, only those columns will be updated. Defaults to
/// all columns.
/// This is an atomic operation, meaning that if one of the rows fails to
/// update, none of the rows will be updated.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Attachment>> update(
_isd.DatabaseSession session,
List<Attachment> rows, {
_isd.ColumnSelections<AttachmentTable>? columns,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.update<Attachment>(
rows,
columns: columns?.call(Attachment.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Updates a single [Attachment]. The row needs to have its id set.
/// Optionally, a list of [columns] can be provided to only update those
/// columns. Defaults to all columns.
Future<Attachment> updateRow(
_isd.DatabaseSession session,
Attachment row, {
_isd.ColumnSelections<AttachmentTable>? columns,
_isd.Transaction? transaction,
}) async {
return session.db.updateRow<Attachment>(
row,
columns: columns?.call(Attachment.t),
transaction: transaction,
);
}
/// Updates a single [Attachment] by its [id] with the specified [columnValues].
/// Returns the updated row or null if no row with the given id exists.
Future<Attachment?> updateById(
_isd.DatabaseSession session,
_isc.UuidValue id, {
required _isd.ColumnValueListBuilder<AttachmentUpdateTable> columnValues,
_isd.Transaction? transaction,
}) async {
return session.db.updateById<Attachment>(
id,
columnValues: columnValues(Attachment.t.updateTable),
transaction: transaction,
);
}
/// Updates all [Attachment]s matching the [where] expression with the specified [columnValues].
/// Returns the list of updated rows.
///
/// If [noReturn] is set to `true`, the updated rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Attachment>> updateWhere(
_isd.DatabaseSession session, {
required _isd.ColumnValueListBuilder<AttachmentUpdateTable> columnValues,
required _isd.WhereExpressionBuilder<AttachmentTable> where,
int? limit,
int? offset,
_isd.OrderByBuilder<AttachmentTable>? orderBy,
_isd.OrderByListBuilder<AttachmentTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.updateWhere<Attachment>(
columnValues: columnValues(Attachment.t.updateTable),
where: where(Attachment.t),
limit: limit,
offset: offset,
orderBy: orderBy?.call(Attachment.t),
orderByList: orderByList?.call(Attachment.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes all [Attachment]s in the list and returns the deleted rows.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// This is an atomic operation, meaning that if one of the rows fail to
/// be deleted, none of the rows will be deleted.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Attachment>> delete(
_isd.DatabaseSession session,
List<Attachment> rows, {
_isd.OrderByBuilder<AttachmentTable>? orderBy,
_isd.OrderByListBuilder<AttachmentTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.delete<Attachment>(
rows,
orderBy: orderBy?.call(Attachment.t),
orderByList: orderByList?.call(Attachment.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Deletes a single [Attachment].
Future<Attachment> deleteRow(
_isd.DatabaseSession session,
Attachment row, {
_isd.Transaction? transaction,
}) async {
return session.db.deleteRow<Attachment>(
row,
transaction: transaction,
);
}
/// Deletes all rows matching the [where] expression.
///
/// To specify the order of the returned rows use [orderBy] or [orderByList]
/// when sorting by multiple columns.
///
/// If [noReturn] is set to `true`, the deleted rows are not read back from
/// the database and an empty list is returned. This avoids the overhead of
/// transferring and deserializing the rows when the result is not needed.
Future<List<Attachment>> deleteWhere(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<AttachmentTable> where,
_isd.OrderByBuilder<AttachmentTable>? orderBy,
_isd.OrderByListBuilder<AttachmentTable>? orderByList,
_isd.Transaction? transaction,
bool noReturn = false,
}) async {
return session.db.deleteWhere<Attachment>(
where: where(Attachment.t),
orderBy: orderBy?.call(Attachment.t),
orderByList: orderByList?.call(Attachment.t),
transaction: transaction,
noReturn: noReturn,
);
}
/// Counts the number of rows matching the [where] expression. If omitted,
/// will return the count of all rows in the table.
Future<int> count(
_isd.DatabaseSession session, {
_isd.WhereExpressionBuilder<AttachmentTable>? where,
int? limit,
_isd.Transaction? transaction,
}) async {
return session.db.count<Attachment>(
where: where?.call(Attachment.t),
limit: limit,
transaction: transaction,
);
}
/// Acquires row-level locks on [Attachment] rows matching the [where] expression.
Future<void> lockRows(
_isd.DatabaseSession session, {
required _isd.WhereExpressionBuilder<AttachmentTable> where,
required _isd.LockMode lockMode,
required _isd.Transaction transaction,
_isd.LockBehavior lockBehavior = _isd.LockBehavior.wait,
}) async {
return session.db.lockRows<Attachment>(
where: where(Attachment.t),
lockMode: lockMode,
lockBehavior: lockBehavior,
transaction: transaction,
);
}
}

View file

@ -25,6 +25,7 @@ import 'package:serverpod_client/serverpod_client.dart' as _isc;
import 'package:serverpod_database/serverpod_database.dart' as _isd;
import 'package:serverpod_offline_sync_client/serverpod_offline_sync_client.dart'
as _ipulbpi2;
import 'attachment/attachment.dart' as _imhw6pbz;
import 'comment/task_comment.dart' as _i68ws957;
import 'filter/saved_filter.dart' as _i9q9fhid;
import 'label/label.dart' as _ivak08z4;
@ -39,6 +40,7 @@ import 'settings/todo_settings.dart' as _icak60vd;
import 'task/task.dart' as _ib4f8uyw;
import 'weather/forecast_hour.dart' as _i1l0g3o2;
import 'weather/weather_refused.dart' as _ieu1vbq0;
export 'attachment/attachment.dart';
export 'comment/task_comment.dart';
export 'filter/saved_filter.dart';
export 'label/label.dart';
@ -64,6 +66,96 @@ class Protocol extends _isd.DatabaseSerializationManager {
static final Protocol _instance = Protocol._().._registerHostProtocols();
static List<_isd.TableDefinition> get targetTableDefinitions => [
_isd.TableDefinition(
name: 'attachment',
dartName: 'Attachment',
schema: 'public',
module: 'halkyon_todo',
columns: [
_isd.ColumnDefinition(
name: 'id',
columnType: _isd.ColumnType.uuid,
isNullable: false,
dartType: 'UuidValue?',
columnDefault: 'random_v7',
),
_isd.ColumnDefinition(
name: 'spaceId',
columnType: _isd.ColumnType.bigint,
isNullable: true,
dartType: 'int?',
),
_isd.ColumnDefinition(
name: 'sha256',
columnType: _isd.ColumnType.text,
isNullable: false,
dartType: 'String',
),
_isd.ColumnDefinition(
name: 'keyId',
columnType: _isd.ColumnType.text,
isNullable: true,
dartType: 'String?',
),
_isd.ColumnDefinition(
name: 'payload',
columnType: _isd.ColumnType.bytea,
isNullable: false,
dartType: 'dart:typed_data:ByteData',
),
_isd.ColumnDefinition(
name: 'nonce',
columnType: _isd.ColumnType.bytea,
isNullable: true,
dartType: 'dart:typed_data:ByteData?',
),
],
foreignKeys: [
_isd.ForeignKeyDefinition(
constraintName: 'attachment_fk_0',
columns: ['spaceId'],
referenceTable: 'offline_sync_spaces',
referenceTableSchema: 'public',
referenceColumns: ['id'],
onUpdate: _isd.ForeignKeyAction.noAction,
onDelete: _isd.ForeignKeyAction.cascade,
matchType: null,
),
],
indexes: [
_isd.IndexDefinition(
indexName: 'attachment_space_idx',
tableSpace: null,
elements: [
_isd.IndexElementDefinition(
type: _isd.IndexElementDefinitionType.column,
definition: 'spaceId',
),
],
type: 'btree',
isUnique: false,
isPrimary: false,
),
_isd.IndexDefinition(
indexName: 'attachment_hash_idx',
tableSpace: null,
elements: [
_isd.IndexElementDefinition(
type: _isd.IndexElementDefinitionType.column,
definition: 'spaceId',
),
_isd.IndexElementDefinition(
type: _isd.IndexElementDefinitionType.column,
definition: 'sha256',
),
],
type: 'btree',
isUnique: false,
isPrimary: false,
),
],
managed: true,
),
_isd.TableDefinition(
name: 'content_key',
dartName: 'ContentKey',
@ -643,6 +735,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
}
}
if (t == _imhw6pbz.Attachment) {
return _imhw6pbz.Attachment.fromJson(data) as T;
}
if (t == _i68ws957.TaskComment) {
return _i68ws957.TaskComment.fromJson(data) as T;
}
@ -685,6 +780,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (t == _ieu1vbq0.WeatherRefused) {
return _ieu1vbq0.WeatherRefused.fromJson(data) as T;
}
if (t == _isc.getType<_imhw6pbz.Attachment?>()) {
return (data != null ? _imhw6pbz.Attachment.fromJson(data) : null) as T;
}
if (t == _isc.getType<_i68ws957.TaskComment?>()) {
return (data != null ? _i68ws957.TaskComment.fromJson(data) : null) as T;
}
@ -763,6 +861,7 @@ class Protocol extends _isd.DatabaseSerializationManager {
static String? getClassNameForType(Type type) {
return switch (type) {
_imhw6pbz.Attachment => 'Attachment',
_i68ws957.TaskComment => 'TaskComment',
_i9q9fhid.SavedFilter => 'SavedFilter',
_ivak08z4.Label => 'Label',
@ -794,6 +893,8 @@ class Protocol extends _isd.DatabaseSerializationManager {
}
switch (data) {
case _imhw6pbz.Attachment():
return 'Attachment';
case _i68ws957.TaskComment():
return 'TaskComment';
case _i9q9fhid.SavedFilter():
@ -858,6 +959,9 @@ class Protocol extends _isd.DatabaseSerializationManager {
if (dataClassName is! String) {
return super.deserializeByClassName(data);
}
if (dataClassName == 'Attachment') {
return deserialize<_imhw6pbz.Attachment>(data['data']);
}
if (dataClassName == 'TaskComment') {
return deserialize<_i68ws957.TaskComment>(data['data']);
}
@ -979,6 +1083,8 @@ class Protocol extends _isd.DatabaseSerializationManager {
}
}
switch (t) {
case _imhw6pbz.Attachment:
return _imhw6pbz.Attachment.t;
case _i68ws957.TaskComment:
return _i68ws957.TaskComment.t;
case _i9q9fhid.SavedFilter:

View file

@ -11,6 +11,7 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_database/serverpod_database.dart' as _isd;
import 'attachment/attachment.dart' as _imhw6pbz;
import 'comment/task_comment.dart' as _i68ws957;
import 'filter/saved_filter.dart' as _i9q9fhid;
import 'label/label.dart' as _ivak08z4;
@ -24,6 +25,7 @@ import 'task/task.dart' as _ib4f8uyw;
/// `serverpod_offline_sync` package, including the ones owned by modules and
/// shared packages.
final List<_isd.Table> syncTables = [
_imhw6pbz.Attachment.t,
_imed3x5d.ContentKey.t,
_ivak08z4.Label.t,
_i9c44spp.Project.t,