track is_private for tabs; add clsoe all private tabs button; close private tabs before exit;
This commit is contained in:
@@ -0,0 +1,427 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"description": "This file contains a serialized version of schema entities for drift.",
|
||||||
|
"version": "1.3.0"
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"store_date_time_values_as_text": false
|
||||||
|
},
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"id": 0,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "container",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"getter_name": "id",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "PRIMARY KEY NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"getter_name": "name",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "color",
|
||||||
|
"getter_name": "color",
|
||||||
|
"moor_type": "int",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [],
|
||||||
|
"type_converter": {
|
||||||
|
"dart_expr": "const ColorConverter()",
|
||||||
|
"dart_type_name": "Color"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "metadata",
|
||||||
|
"getter_name": "metadata",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [],
|
||||||
|
"type_converter": {
|
||||||
|
"dart_expr": "const ContainerMetadataConverter()",
|
||||||
|
"dart_type_name": "ContainerMetadata"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"references": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "tab",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"getter_name": "id",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "PRIMARY KEY NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parent_id",
|
||||||
|
"getter_name": "parentId",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "REFERENCES tab(id)ON DELETE SET NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "container_id",
|
||||||
|
"getter_name": "containerId",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "REFERENCES container(id)ON DELETE CASCADE",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
{
|
||||||
|
"foreign_key": {
|
||||||
|
"to": {
|
||||||
|
"table": "container",
|
||||||
|
"column": "id"
|
||||||
|
},
|
||||||
|
"initially_deferred": false,
|
||||||
|
"on_update": null,
|
||||||
|
"on_delete": "cascade"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "order_key",
|
||||||
|
"getter_name": "orderKey",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"getter_name": "url",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [],
|
||||||
|
"type_converter": {
|
||||||
|
"dart_expr": "const UriConverterNullable()",
|
||||||
|
"dart_type_name": "Uri?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"getter_name": "title",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_private",
|
||||||
|
"getter_name": "isPrivate",
|
||||||
|
"moor_type": "bool",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_probably_readerable",
|
||||||
|
"getter_name": "isProbablyReaderable",
|
||||||
|
"moor_type": "bool",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "extracted_content_markdown",
|
||||||
|
"getter_name": "extractedContentMarkdown",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "extracted_content_plain",
|
||||||
|
"getter_name": "extractedContentPlain",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "full_content_markdown",
|
||||||
|
"getter_name": "fullContentMarkdown",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "full_content_plain",
|
||||||
|
"getter_name": "fullContentPlain",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "timestamp",
|
||||||
|
"getter_name": "timestamp",
|
||||||
|
"moor_type": "dateTime",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"references": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "tab_fts",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "title",
|
||||||
|
"getter_name": "title",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "url",
|
||||||
|
"getter_name": "url",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "extracted_content_plain",
|
||||||
|
"getter_name": "extractedContentPlain",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "full_content_plain",
|
||||||
|
"getter_name": "fullContentPlain",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": true,
|
||||||
|
"create_virtual_stmt": "CREATE VIRTUAL TABLE \"tab_fts\" USING fts5(title, url, extracted_content_plain, full_content_plain, content=tab, tokenize=\"trigram\")",
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"references": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"type": "trigger",
|
||||||
|
"data": {
|
||||||
|
"on": 1,
|
||||||
|
"references_in_body": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"name": "tab_maintain_parent_chain_on_delete",
|
||||||
|
"sql": "CREATE TRIGGER tab_maintain_parent_chain_on_delete BEFORE DELETE ON tab BEGIN\n -- Update all children of the deleted row to point to its parent\n UPDATE tab \n SET parent_id = OLD.parent_id \n WHERE parent_id = OLD.id;\nEND;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"references": [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"type": "trigger",
|
||||||
|
"data": {
|
||||||
|
"on": 1,
|
||||||
|
"references_in_body": [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"name": "tab_after_insert",
|
||||||
|
"sql": "CREATE TRIGGER tab_after_insert AFTER INSERT ON tab BEGIN\n INSERT INTO \n tab_fts(rowid, title, url, extracted_content_plain, full_content_plain) \n VALUES (new.rowid, new.title, new.url, new.extracted_content_plain, new.full_content_plain);\nEND;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"references": [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"type": "trigger",
|
||||||
|
"data": {
|
||||||
|
"on": 1,
|
||||||
|
"references_in_body": [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"name": "tab_after_delete",
|
||||||
|
"sql": "CREATE TRIGGER tab_after_delete AFTER DELETE ON tab BEGIN\n INSERT INTO \n tab_fts(tab_fts, rowid, title, url, extracted_content_plain, full_content_plain) \n VALUES('delete', old.rowid, old.title, old.url, old.extracted_content_plain, old.full_content_plain);\nEND;"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"references": [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"type": "trigger",
|
||||||
|
"data": {
|
||||||
|
"on": 1,
|
||||||
|
"references_in_body": [
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
"name": "tab_after_update",
|
||||||
|
"sql": "CREATE TRIGGER tab_after_update AFTER UPDATE ON tab BEGIN\n INSERT INTO \n tab_fts(tab_fts, rowid, title, url, extracted_content_plain, full_content_plain) \n VALUES('delete', old.rowid, old.title, old.url, old.extracted_content_plain, old.full_content_plain);\n INSERT INTO \n tab_fts(rowid, title, url, extracted_content_plain, full_content_plain) \n VALUES (new.rowid, new.title, new.url, new.extracted_content_plain, new.full_content_plain);\nEND;"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fixed_sql": [
|
||||||
|
{
|
||||||
|
"name": "container",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"container\" (\"id\" TEXT PRIMARY KEY NOT NULL, \"name\" TEXT, \"color\" INTEGER NOT NULL, \"metadata\" TEXT);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tab",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"tab\" (\"id\" TEXT PRIMARY KEY NOT NULL, \"parent_id\" TEXT REFERENCES tab(id)ON DELETE SET NULL, \"container_id\" TEXT REFERENCES container(id)ON DELETE CASCADE, \"order_key\" TEXT NOT NULL, \"url\" TEXT, \"title\" TEXT, \"is_private\" INTEGER, \"is_probably_readerable\" INTEGER, \"extracted_content_markdown\" TEXT, \"extracted_content_plain\" TEXT, \"full_content_markdown\" TEXT, \"full_content_plain\" TEXT, \"timestamp\" INTEGER NOT NULL);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tab_fts",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE VIRTUAL TABLE IF NOT EXISTS \"tab_fts\" USING fts5(title, url, extracted_content_plain, full_content_plain, content=tab, tokenize=\"trigram\");"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tab_maintain_parent_chain_on_delete",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TRIGGER tab_maintain_parent_chain_on_delete BEFORE DELETE ON tab BEGIN UPDATE tab SET parent_id = OLD.parent_id WHERE parent_id = OLD.id;END"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tab_after_insert",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TRIGGER tab_after_insert AFTER INSERT ON tab BEGIN INSERT INTO tab_fts (\"rowid\", title, url, extracted_content_plain, full_content_plain) VALUES (new.\"rowid\", new.title, new.url, new.extracted_content_plain, new.full_content_plain);END"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tab_after_delete",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TRIGGER tab_after_delete AFTER DELETE ON tab BEGIN INSERT INTO tab_fts (tab_fts, \"rowid\", title, url, extracted_content_plain, full_content_plain) VALUES ('delete', old.\"rowid\", old.title, old.url, old.extracted_content_plain, old.full_content_plain);END"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tab_after_update",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TRIGGER tab_after_update AFTER UPDATE ON tab BEGIN INSERT INTO tab_fts (tab_fts, \"rowid\", title, url, extracted_content_plain, full_content_plain) VALUES ('delete', old.\"rowid\", old.title, old.url, old.extracted_content_plain, old.full_content_plain);INSERT INTO tab_fts (\"rowid\", title, url, extracted_content_plain, full_content_plain) VALUES (new.\"rowid\", new.title, new.url, new.extracted_content_plain, new.full_content_plain);END"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@ class TabRepository extends _$TabRepository {
|
|||||||
},
|
},
|
||||||
parentId: Value(parentId),
|
parentId: Value(parentId),
|
||||||
containerId: Value(assingedContainer.value?.id),
|
containerId: Value(assingedContainer.value?.id),
|
||||||
|
isPrivate: Value(private),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (launchedFromIntent) {
|
if (launchedFromIntent) {
|
||||||
@@ -102,7 +103,7 @@ class TabRepository extends _$TabRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> duplicateTab({
|
Future<String> duplicateTab({
|
||||||
required String? selectTabId,
|
required String selectTabId,
|
||||||
String? containerId,
|
String? containerId,
|
||||||
bool selectTab = true,
|
bool selectTab = true,
|
||||||
}) async {
|
}) async {
|
||||||
@@ -124,6 +125,9 @@ class TabRepository extends _$TabRepository {
|
|||||||
},
|
},
|
||||||
parentId: const Value.absent(),
|
parentId: const Value.absent(),
|
||||||
containerId: Value(containerData?.id),
|
containerId: Value(containerData?.id),
|
||||||
|
isPrivate: Value(
|
||||||
|
await tabDao.getTabIsPrivate(selectTabId).getSingleOrNull(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +382,7 @@ class TabRepository extends _$TabRepository {
|
|||||||
tabId,
|
tabId,
|
||||||
parentId: const Value.absent(),
|
parentId: const Value.absent(),
|
||||||
containerId: Value(containerId),
|
containerId: Value(containerId),
|
||||||
|
isPrivate: const Value.absent(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ final class TabRepositoryProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$tabRepositoryHash() => r'7af24e759044d1b1b471cdf90a3eb38eef06f61b';
|
String _$tabRepositoryHash() => r'0411e8b3fa9c3e344106f8fa8178bd6eb613309a';
|
||||||
|
|
||||||
abstract class _$TabRepository extends $Notifier<void> {
|
abstract class _$TabRepository extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
+58
-3
@@ -219,8 +219,8 @@ class TabViewHeader extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
MenuItemButton(
|
MenuItemButton(
|
||||||
leadingIcon: const Icon(MdiIcons.closeBoxMultiple),
|
leadingIcon: const Icon(MdiIcons.closeCircle),
|
||||||
child: const Text('Close All'),
|
child: const Text('Close All Tabs'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final result = await showDialog<bool?>(
|
final result = await showDialog<bool?>(
|
||||||
context: context,
|
context: context,
|
||||||
@@ -256,7 +256,62 @@ class TabViewHeader extends HookConsumerWidget {
|
|||||||
|
|
||||||
final count = await ref
|
final count = await ref
|
||||||
.read(tabDataRepositoryProvider.notifier)
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
.closeAllTabsByContainer(container);
|
.closeContainerTabs(container);
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
ui_helper.showTabUndoClose(
|
||||||
|
context,
|
||||||
|
ref
|
||||||
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
.undoClose,
|
||||||
|
count: count,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
MenuItemButton(
|
||||||
|
leadingIcon: const Icon(MdiIcons.incognitoCircleOff),
|
||||||
|
child: const Text('Close Private Tabs'),
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await showDialog<bool?>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
icon: const Icon(Icons.warning),
|
||||||
|
title: const Text('Close All Private Tabs'),
|
||||||
|
content: const Text(
|
||||||
|
'Are you sure you want to close all displayed private tabs?',
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, false);
|
||||||
|
},
|
||||||
|
child: const Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
},
|
||||||
|
child: const Text('Close'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == true) {
|
||||||
|
final container = ref.read(
|
||||||
|
selectedContainerProvider,
|
||||||
|
);
|
||||||
|
|
||||||
|
final count = await ref
|
||||||
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
|
.closeContainerTabs(
|
||||||
|
container,
|
||||||
|
includeRegular: false,
|
||||||
|
);
|
||||||
|
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ui_helper.showTabUndoClose(
|
ui_helper.showTabUndoClose(
|
||||||
|
|||||||
@@ -72,7 +72,31 @@ class ContainerDao extends DatabaseAccessor<TabDatabase>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Selectable<String> getContainerTabIds(String? containerId) {
|
Selectable<String> getAllTabIds({
|
||||||
|
bool includeRegular = true,
|
||||||
|
bool includePrivate = true,
|
||||||
|
}) {
|
||||||
|
final query = selectOnly(db.tab)..addColumns([db.tab.id]);
|
||||||
|
|
||||||
|
if (!includeRegular) {
|
||||||
|
query.where(
|
||||||
|
db.tab.isPrivate.isNotNull() & db.tab.isPrivate.isNotValue(false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!includePrivate) {
|
||||||
|
query.where(
|
||||||
|
db.tab.isPrivate.isNotNull() & db.tab.isPrivate.isNotValue(true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.map((row) => row.read(db.tab.id)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
Selectable<String> getContainerTabIds(
|
||||||
|
String? containerId, {
|
||||||
|
bool includeRegular = true,
|
||||||
|
bool includePrivate = true,
|
||||||
|
}) {
|
||||||
final query = selectOnly(db.tab)
|
final query = selectOnly(db.tab)
|
||||||
..addColumns([db.tab.id])
|
..addColumns([db.tab.id])
|
||||||
..where(
|
..where(
|
||||||
@@ -82,6 +106,17 @@ class ContainerDao extends DatabaseAccessor<TabDatabase>
|
|||||||
)
|
)
|
||||||
..orderBy([OrderingTerm.asc(db.tab.orderKey)]);
|
..orderBy([OrderingTerm.asc(db.tab.orderKey)]);
|
||||||
|
|
||||||
|
if (!includeRegular) {
|
||||||
|
query.where(
|
||||||
|
db.tab.isPrivate.isNotNull() & db.tab.isPrivate.isNotValue(false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!includePrivate) {
|
||||||
|
query.where(
|
||||||
|
db.tab.isPrivate.isNotNull() & db.tab.isPrivate.isNotValue(true),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return query.map((row) => row.read(db.tab.id)!);
|
return query.map((row) => row.read(db.tab.id)!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,14 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
|||||||
SingleOrNullSelectable<TabData> getTabDataById(String id) =>
|
SingleOrNullSelectable<TabData> getTabDataById(String id) =>
|
||||||
db.tab.select()..where((t) => t.id.equals(id));
|
db.tab.select()..where((t) => t.id.equals(id));
|
||||||
|
|
||||||
|
SingleOrNullSelectable<bool?> getTabIsPrivate(String tabId) {
|
||||||
|
final query = selectOnly(db.tab)
|
||||||
|
..addColumns([db.tab.isPrivate])
|
||||||
|
..where(db.tab.id.equals(tabId));
|
||||||
|
|
||||||
|
return query.map((row) => row.read(db.tab.isPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
Selectable<String> getAllTabIds() {
|
Selectable<String> getAllTabIds() {
|
||||||
final query = selectOnly(db.tab)
|
final query = selectOnly(db.tab)
|
||||||
..addColumns([db.tab.id])
|
..addColumns([db.tab.id])
|
||||||
@@ -97,6 +105,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
|||||||
|
|
||||||
Future<String> upsertContainerTabTransactional(
|
Future<String> upsertContainerTabTransactional(
|
||||||
Future<String> Function() createTab, {
|
Future<String> Function() createTab, {
|
||||||
|
required Value<bool?> isPrivate,
|
||||||
required Value<String?> parentId,
|
required Value<String?> parentId,
|
||||||
Value<String?> containerId = const Value.absent(),
|
Value<String?> containerId = const Value.absent(),
|
||||||
Value<String?> orderKey = const Value.absent(),
|
Value<String?> orderKey = const Value.absent(),
|
||||||
@@ -113,6 +122,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
|||||||
parentId: parentId,
|
parentId: parentId,
|
||||||
timestamp: DateTime.now(),
|
timestamp: DateTime.now(),
|
||||||
containerId: containerId,
|
containerId: containerId,
|
||||||
|
isPrivate: isPrivate,
|
||||||
orderKey: currentOrderKey,
|
orderKey: currentOrderKey,
|
||||||
),
|
),
|
||||||
onConflict: DoUpdate(
|
onConflict: DoUpdate(
|
||||||
@@ -131,6 +141,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
|||||||
//Upsert an tab only if there is no container assigned yet
|
//Upsert an tab only if there is no container assigned yet
|
||||||
Future<String> upsertUnassignedTab(
|
Future<String> upsertUnassignedTab(
|
||||||
String tabId, {
|
String tabId, {
|
||||||
|
required Value<bool?> isPrivate,
|
||||||
required Value<String?> parentId,
|
required Value<String?> parentId,
|
||||||
Value<String?> containerId = const Value.absent(),
|
Value<String?> containerId = const Value.absent(),
|
||||||
Value<String?> orderKey = const Value.absent(),
|
Value<String?> orderKey = const Value.absent(),
|
||||||
@@ -147,6 +158,7 @@ class TabDao extends DatabaseAccessor<TabDatabase> with $TabDaoMixin {
|
|||||||
timestamp: DateTime.now(),
|
timestamp: DateTime.now(),
|
||||||
containerId: containerId,
|
containerId: containerId,
|
||||||
orderKey: currentOrderKey,
|
orderKey: currentOrderKey,
|
||||||
|
isPrivate: isPrivate,
|
||||||
),
|
),
|
||||||
mode: InsertMode.insertOrIgnore,
|
mode: InsertMode.insertOrIgnore,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -18,17 +18,19 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift/internal/versioned_schema.dart';
|
||||||
import 'package:drift_dev/api/migrations_native.dart';
|
import 'package:drift_dev/api/migrations_native.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/data/database/daos/container.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/data/database/daos/container.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/data/database/daos/tab.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/data/database/daos/tab.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.drift.dart';
|
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.drift.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.steps.dart';
|
||||||
import 'package:weblibre/features/search/domain/fts_tokenizer.dart';
|
import 'package:weblibre/features/search/domain/fts_tokenizer.dart';
|
||||||
|
|
||||||
@DriftDatabase(include: {'definitions.drift'}, daos: [ContainerDao, TabDao])
|
@DriftDatabase(include: {'definitions.drift'}, daos: [ContainerDao, TabDao])
|
||||||
class TabDatabase extends $TabDatabase with TrigramQueryBuilderMixin {
|
class TabDatabase extends $TabDatabase with TrigramQueryBuilderMixin {
|
||||||
@override
|
@override
|
||||||
final int schemaVersion = 2;
|
final int schemaVersion = 3;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final int ftsTokenLimit = 10;
|
final int ftsTokenLimit = 10;
|
||||||
@@ -47,7 +49,39 @@ class TabDatabase extends $TabDatabase with TrigramQueryBuilderMixin {
|
|||||||
await customStatement('PRAGMA foreign_keys = ON');
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
await definitionsDrift.optimizeFtsIndex();
|
await definitionsDrift.optimizeFtsIndex();
|
||||||
},
|
},
|
||||||
|
onUpgrade: (m, from, to) async {
|
||||||
|
// Following the advice from https://drift.simonbinder.eu/Migrations/api/#general-tips
|
||||||
|
await customStatement('PRAGMA foreign_keys = OFF');
|
||||||
|
|
||||||
|
await transaction(
|
||||||
|
() => VersionedSchema.runMigrationSteps(
|
||||||
|
migrator: m,
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
steps: _upgrade,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (kDebugMode) {
|
||||||
|
final wrongForeignKeys = await customSelect(
|
||||||
|
'PRAGMA foreign_key_check',
|
||||||
|
).get();
|
||||||
|
assert(
|
||||||
|
wrongForeignKeys.isEmpty,
|
||||||
|
'${wrongForeignKeys.map((e) => e.data)}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await customStatement('PRAGMA foreign_keys = ON');
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
TabDatabase(super.e);
|
TabDatabase(super.e);
|
||||||
|
|
||||||
|
static final _upgrade = migrationSteps(
|
||||||
|
from2To3: (m, schema) async {
|
||||||
|
final tabAtV3 = schema.tab;
|
||||||
|
await m.addColumn(tabAtV3, tabAtV3.isPrivate);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,288 @@
|
|||||||
|
// dart format width=80
|
||||||
|
import 'package:drift/internal/versioned_schema.dart' as i0;
|
||||||
|
import 'package:drift/drift.dart' as i1;
|
||||||
|
import 'package:drift/drift.dart'; // ignore_for_file: type=lint,unused_import
|
||||||
|
|
||||||
|
// GENERATED BY drift_dev, DO NOT MODIFY.
|
||||||
|
final class Schema3 extends i0.VersionedSchema {
|
||||||
|
Schema3({required super.database}) : super(version: 3);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
container,
|
||||||
|
tab,
|
||||||
|
tabFts,
|
||||||
|
tabMaintainParentChainOnDelete,
|
||||||
|
tabAfterInsert,
|
||||||
|
tabAfterDelete,
|
||||||
|
tabAfterUpdate,
|
||||||
|
];
|
||||||
|
late final Shape0 container = Shape0(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'container',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_0, _column_1, _column_2, _column_3],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape1 tab = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'tab',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_0,
|
||||||
|
_column_4,
|
||||||
|
_column_5,
|
||||||
|
_column_6,
|
||||||
|
_column_7,
|
||||||
|
_column_8,
|
||||||
|
_column_9,
|
||||||
|
_column_10,
|
||||||
|
_column_11,
|
||||||
|
_column_12,
|
||||||
|
_column_13,
|
||||||
|
_column_14,
|
||||||
|
_column_15,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape2 tabFts = Shape2(
|
||||||
|
source: i0.VersionedVirtualTable(
|
||||||
|
entityName: 'tab_fts',
|
||||||
|
moduleAndArgs:
|
||||||
|
'fts5(title, url, extracted_content_plain, full_content_plain, content=tab, tokenize="trigram")',
|
||||||
|
columns: [_column_8, _column_7, _column_12, _column_14],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Trigger tabMaintainParentChainOnDelete = i1.Trigger(
|
||||||
|
'CREATE TRIGGER tab_maintain_parent_chain_on_delete BEFORE DELETE ON tab BEGIN UPDATE tab SET parent_id = OLD.parent_id WHERE parent_id = OLD.id;END',
|
||||||
|
'tab_maintain_parent_chain_on_delete',
|
||||||
|
);
|
||||||
|
final i1.Trigger tabAfterInsert = i1.Trigger(
|
||||||
|
'CREATE TRIGGER tab_after_insert AFTER INSERT ON tab BEGIN INSERT INTO tab_fts ("rowid", title, url, extracted_content_plain, full_content_plain) VALUES (new."rowid", new.title, new.url, new.extracted_content_plain, new.full_content_plain);END',
|
||||||
|
'tab_after_insert',
|
||||||
|
);
|
||||||
|
final i1.Trigger tabAfterDelete = i1.Trigger(
|
||||||
|
'CREATE TRIGGER tab_after_delete AFTER DELETE ON tab BEGIN INSERT INTO tab_fts (tab_fts, "rowid", title, url, extracted_content_plain, full_content_plain) VALUES (\'delete\', old."rowid", old.title, old.url, old.extracted_content_plain, old.full_content_plain);END',
|
||||||
|
'tab_after_delete',
|
||||||
|
);
|
||||||
|
final i1.Trigger tabAfterUpdate = i1.Trigger(
|
||||||
|
'CREATE TRIGGER tab_after_update AFTER UPDATE ON tab BEGIN INSERT INTO tab_fts (tab_fts, "rowid", title, url, extracted_content_plain, full_content_plain) VALUES (\'delete\', old."rowid", old.title, old.url, old.extracted_content_plain, old.full_content_plain);INSERT INTO tab_fts ("rowid", title, url, extracted_content_plain, full_content_plain) VALUES (new."rowid", new.title, new.url, new.extracted_content_plain, new.full_content_plain);END',
|
||||||
|
'tab_after_update',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Shape0 extends i0.VersionedTable {
|
||||||
|
Shape0({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get name =>
|
||||||
|
columnsByName['name']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get color =>
|
||||||
|
columnsByName['color']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get metadata =>
|
||||||
|
columnsByName['metadata']! as i1.GeneratedColumn<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_0(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'id',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: 'PRIMARY KEY NOT NULL',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_1(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'name',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<int> _column_2(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'color',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
$customConstraints: 'NOT NULL',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_3(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'metadata',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
|
||||||
|
class Shape1 extends i0.VersionedTable {
|
||||||
|
Shape1({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get id =>
|
||||||
|
columnsByName['id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get parentId =>
|
||||||
|
columnsByName['parent_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get containerId =>
|
||||||
|
columnsByName['container_id']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get orderKey =>
|
||||||
|
columnsByName['order_key']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get url =>
|
||||||
|
columnsByName['url']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get isPrivate =>
|
||||||
|
columnsByName['is_private']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<int> get isProbablyReaderable =>
|
||||||
|
columnsByName['is_probably_readerable']! as i1.GeneratedColumn<int>;
|
||||||
|
i1.GeneratedColumn<String> get extractedContentMarkdown =>
|
||||||
|
columnsByName['extracted_content_markdown']!
|
||||||
|
as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get extractedContentPlain =>
|
||||||
|
columnsByName['extracted_content_plain']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get fullContentMarkdown =>
|
||||||
|
columnsByName['full_content_markdown']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get fullContentPlain =>
|
||||||
|
columnsByName['full_content_plain']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<int> get timestamp =>
|
||||||
|
columnsByName['timestamp']! as i1.GeneratedColumn<int>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<String> _column_4(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'parent_id',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: 'REFERENCES tab(id)ON DELETE SET NULL',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_5(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'container_id',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: 'REFERENCES container(id)ON DELETE CASCADE',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_6(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'order_key',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: 'NOT NULL',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_7(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'url',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_8(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'title',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<int> _column_9(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'is_private',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<int> _column_10(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'is_probably_readerable',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_11(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'extracted_content_markdown',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_12(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'extracted_content_plain',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_13(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'full_content_markdown',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_14(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<String>(
|
||||||
|
'full_content_plain',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<int> _column_15(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'timestamp',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
$customConstraints: 'NOT NULL',
|
||||||
|
);
|
||||||
|
|
||||||
|
class Shape2 extends i0.VersionedVirtualTable {
|
||||||
|
Shape2({required super.source, required super.alias}) : super.aliased();
|
||||||
|
i1.GeneratedColumn<String> get title =>
|
||||||
|
columnsByName['title']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get url =>
|
||||||
|
columnsByName['url']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get extractedContentPlain =>
|
||||||
|
columnsByName['extracted_content_plain']! as i1.GeneratedColumn<String>;
|
||||||
|
i1.GeneratedColumn<String> get fullContentPlain =>
|
||||||
|
columnsByName['full_content_plain']! as i1.GeneratedColumn<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
|
}) {
|
||||||
|
return (currentVersion, database) async {
|
||||||
|
switch (currentVersion) {
|
||||||
|
case 2:
|
||||||
|
final schema = Schema3(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from2To3(migrator, schema);
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.OnUpgrade stepByStep({
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
|
}) => i0.VersionedSchema.stepByStepHelper(
|
||||||
|
step: migrationSteps(from2To3: from2To3),
|
||||||
|
);
|
||||||
@@ -19,6 +19,7 @@ CREATE TABLE tab(
|
|||||||
order_key TEXT NOT NULL,
|
order_key TEXT NOT NULL,
|
||||||
url TEXT MAPPED BY `const UriConverterNullable()`,
|
url TEXT MAPPED BY `const UriConverterNullable()`,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
|
is_private BOOL,
|
||||||
is_probably_readerable BOOL,
|
is_probably_readerable BOOL,
|
||||||
extracted_content_markdown TEXT,
|
extracted_content_markdown TEXT,
|
||||||
extracted_content_plain TEXT,
|
extracted_content_plain TEXT,
|
||||||
@@ -141,6 +142,7 @@ queryTabsBasic WITH TabQueryResult:
|
|||||||
SELECT
|
SELECT
|
||||||
t.id,
|
t.id,
|
||||||
t.container_id,
|
t.container_id,
|
||||||
|
t.is_private,
|
||||||
t.title,
|
t.title,
|
||||||
CAST(t.url AS TEXT) AS url,
|
CAST(t.url AS TEXT) AS url,
|
||||||
t.url AS clean_url,
|
t.url AS clean_url,
|
||||||
@@ -168,6 +170,7 @@ queryTabsFullContent WITH TabQueryResult:
|
|||||||
SELECT
|
SELECT
|
||||||
t.id,
|
t.id,
|
||||||
t.container_id,
|
t.container_id,
|
||||||
|
t.is_private,
|
||||||
highlight(tab_fts, 0, :beforeMatch, :afterMatch) AS title,
|
highlight(tab_fts, 0, :beforeMatch, :afterMatch) AS title,
|
||||||
highlight(tab_fts, 1, :beforeMatch, :afterMatch) AS url,
|
highlight(tab_fts, 1, :beforeMatch, :afterMatch) AS url,
|
||||||
snippet(tab_fts, 2, :beforeMatch, :afterMatch, :ellipsis, :snippetLength) AS extracted_content,
|
snippet(tab_fts, 2, :beforeMatch, :afterMatch, :ellipsis, :snippetLength) AS extracted_content,
|
||||||
|
|||||||
@@ -326,6 +326,7 @@ typedef $TabCreateCompanionBuilder =
|
|||||||
required String orderKey,
|
required String orderKey,
|
||||||
i0.Value<Uri?> url,
|
i0.Value<Uri?> url,
|
||||||
i0.Value<String?> title,
|
i0.Value<String?> title,
|
||||||
|
i0.Value<bool?> isPrivate,
|
||||||
i0.Value<bool?> isProbablyReaderable,
|
i0.Value<bool?> isProbablyReaderable,
|
||||||
i0.Value<String?> extractedContentMarkdown,
|
i0.Value<String?> extractedContentMarkdown,
|
||||||
i0.Value<String?> extractedContentPlain,
|
i0.Value<String?> extractedContentPlain,
|
||||||
@@ -342,6 +343,7 @@ typedef $TabUpdateCompanionBuilder =
|
|||||||
i0.Value<String> orderKey,
|
i0.Value<String> orderKey,
|
||||||
i0.Value<Uri?> url,
|
i0.Value<Uri?> url,
|
||||||
i0.Value<String?> title,
|
i0.Value<String?> title,
|
||||||
|
i0.Value<bool?> isPrivate,
|
||||||
i0.Value<bool?> isProbablyReaderable,
|
i0.Value<bool?> isProbablyReaderable,
|
||||||
i0.Value<String?> extractedContentMarkdown,
|
i0.Value<String?> extractedContentMarkdown,
|
||||||
i0.Value<String?> extractedContentPlain,
|
i0.Value<String?> extractedContentPlain,
|
||||||
@@ -418,6 +420,11 @@ class $TabFilterComposer extends i0.Composer<i0.GeneratedDatabase, i3.Tab> {
|
|||||||
builder: (column) => i0.ColumnFilters(column),
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<bool> get isPrivate => $composableBuilder(
|
||||||
|
column: $table.isPrivate,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
i0.ColumnFilters<bool> get isProbablyReaderable => $composableBuilder(
|
i0.ColumnFilters<bool> get isProbablyReaderable => $composableBuilder(
|
||||||
column: $table.isProbablyReaderable,
|
column: $table.isProbablyReaderable,
|
||||||
builder: (column) => i0.ColumnFilters(column),
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
@@ -509,6 +516,11 @@ class $TabOrderingComposer extends i0.Composer<i0.GeneratedDatabase, i3.Tab> {
|
|||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<bool> get isPrivate => $composableBuilder(
|
||||||
|
column: $table.isPrivate,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
i0.ColumnOrderings<bool> get isProbablyReaderable => $composableBuilder(
|
i0.ColumnOrderings<bool> get isProbablyReaderable => $composableBuilder(
|
||||||
column: $table.isProbablyReaderable,
|
column: $table.isProbablyReaderable,
|
||||||
builder: (column) => i0.ColumnOrderings(column),
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
@@ -590,6 +602,9 @@ class $TabAnnotationComposer extends i0.Composer<i0.GeneratedDatabase, i3.Tab> {
|
|||||||
i0.GeneratedColumn<String> get title =>
|
i0.GeneratedColumn<String> get title =>
|
||||||
$composableBuilder(column: $table.title, builder: (column) => column);
|
$composableBuilder(column: $table.title, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<bool> get isPrivate =>
|
||||||
|
$composableBuilder(column: $table.isPrivate, builder: (column) => column);
|
||||||
|
|
||||||
i0.GeneratedColumn<bool> get isProbablyReaderable => $composableBuilder(
|
i0.GeneratedColumn<bool> get isProbablyReaderable => $composableBuilder(
|
||||||
column: $table.isProbablyReaderable,
|
column: $table.isProbablyReaderable,
|
||||||
builder: (column) => column,
|
builder: (column) => column,
|
||||||
@@ -680,6 +695,7 @@ class $TabTableManager
|
|||||||
i0.Value<String> orderKey = const i0.Value.absent(),
|
i0.Value<String> orderKey = const i0.Value.absent(),
|
||||||
i0.Value<Uri?> url = const i0.Value.absent(),
|
i0.Value<Uri?> url = const i0.Value.absent(),
|
||||||
i0.Value<String?> title = const i0.Value.absent(),
|
i0.Value<String?> title = const i0.Value.absent(),
|
||||||
|
i0.Value<bool?> isPrivate = const i0.Value.absent(),
|
||||||
i0.Value<bool?> isProbablyReaderable = const i0.Value.absent(),
|
i0.Value<bool?> isProbablyReaderable = const i0.Value.absent(),
|
||||||
i0.Value<String?> extractedContentMarkdown =
|
i0.Value<String?> extractedContentMarkdown =
|
||||||
const i0.Value.absent(),
|
const i0.Value.absent(),
|
||||||
@@ -696,6 +712,7 @@ class $TabTableManager
|
|||||||
orderKey: orderKey,
|
orderKey: orderKey,
|
||||||
url: url,
|
url: url,
|
||||||
title: title,
|
title: title,
|
||||||
|
isPrivate: isPrivate,
|
||||||
isProbablyReaderable: isProbablyReaderable,
|
isProbablyReaderable: isProbablyReaderable,
|
||||||
extractedContentMarkdown: extractedContentMarkdown,
|
extractedContentMarkdown: extractedContentMarkdown,
|
||||||
extractedContentPlain: extractedContentPlain,
|
extractedContentPlain: extractedContentPlain,
|
||||||
@@ -712,6 +729,7 @@ class $TabTableManager
|
|||||||
required String orderKey,
|
required String orderKey,
|
||||||
i0.Value<Uri?> url = const i0.Value.absent(),
|
i0.Value<Uri?> url = const i0.Value.absent(),
|
||||||
i0.Value<String?> title = const i0.Value.absent(),
|
i0.Value<String?> title = const i0.Value.absent(),
|
||||||
|
i0.Value<bool?> isPrivate = const i0.Value.absent(),
|
||||||
i0.Value<bool?> isProbablyReaderable = const i0.Value.absent(),
|
i0.Value<bool?> isProbablyReaderable = const i0.Value.absent(),
|
||||||
i0.Value<String?> extractedContentMarkdown =
|
i0.Value<String?> extractedContentMarkdown =
|
||||||
const i0.Value.absent(),
|
const i0.Value.absent(),
|
||||||
@@ -728,6 +746,7 @@ class $TabTableManager
|
|||||||
orderKey: orderKey,
|
orderKey: orderKey,
|
||||||
url: url,
|
url: url,
|
||||||
title: title,
|
title: title,
|
||||||
|
isPrivate: isPrivate,
|
||||||
isProbablyReaderable: isProbablyReaderable,
|
isProbablyReaderable: isProbablyReaderable,
|
||||||
extractedContentMarkdown: extractedContentMarkdown,
|
extractedContentMarkdown: extractedContentMarkdown,
|
||||||
extractedContentPlain: extractedContentPlain,
|
extractedContentPlain: extractedContentPlain,
|
||||||
@@ -1219,6 +1238,14 @@ class Tab extends i0.Table with i0.TableInfo<Tab, i3.TabData> {
|
|||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
$customConstraints: '',
|
$customConstraints: '',
|
||||||
);
|
);
|
||||||
|
late final i0.GeneratedColumn<bool> isPrivate = i0.GeneratedColumn<bool>(
|
||||||
|
'is_private',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i0.DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
$customConstraints: '',
|
||||||
|
);
|
||||||
late final i0.GeneratedColumn<bool> isProbablyReaderable =
|
late final i0.GeneratedColumn<bool> isProbablyReaderable =
|
||||||
i0.GeneratedColumn<bool>(
|
i0.GeneratedColumn<bool>(
|
||||||
'is_probably_readerable',
|
'is_probably_readerable',
|
||||||
@@ -1281,6 +1308,7 @@ class Tab extends i0.Table with i0.TableInfo<Tab, i3.TabData> {
|
|||||||
orderKey,
|
orderKey,
|
||||||
url,
|
url,
|
||||||
title,
|
title,
|
||||||
|
isPrivate,
|
||||||
isProbablyReaderable,
|
isProbablyReaderable,
|
||||||
extractedContentMarkdown,
|
extractedContentMarkdown,
|
||||||
extractedContentPlain,
|
extractedContentPlain,
|
||||||
@@ -1325,6 +1353,10 @@ class Tab extends i0.Table with i0.TableInfo<Tab, i3.TabData> {
|
|||||||
i0.DriftSqlType.string,
|
i0.DriftSqlType.string,
|
||||||
data['${effectivePrefix}title'],
|
data['${effectivePrefix}title'],
|
||||||
),
|
),
|
||||||
|
isPrivate: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.bool,
|
||||||
|
data['${effectivePrefix}is_private'],
|
||||||
|
),
|
||||||
isProbablyReaderable: attachedDatabase.typeMapping.read(
|
isProbablyReaderable: attachedDatabase.typeMapping.read(
|
||||||
i0.DriftSqlType.bool,
|
i0.DriftSqlType.bool,
|
||||||
data['${effectivePrefix}is_probably_readerable'],
|
data['${effectivePrefix}is_probably_readerable'],
|
||||||
@@ -1370,6 +1402,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
final String orderKey;
|
final String orderKey;
|
||||||
final Uri? url;
|
final Uri? url;
|
||||||
final String? title;
|
final String? title;
|
||||||
|
final bool? isPrivate;
|
||||||
final bool? isProbablyReaderable;
|
final bool? isProbablyReaderable;
|
||||||
final String? extractedContentMarkdown;
|
final String? extractedContentMarkdown;
|
||||||
final String? extractedContentPlain;
|
final String? extractedContentPlain;
|
||||||
@@ -1383,6 +1416,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
required this.orderKey,
|
required this.orderKey,
|
||||||
this.url,
|
this.url,
|
||||||
this.title,
|
this.title,
|
||||||
|
this.isPrivate,
|
||||||
this.isProbablyReaderable,
|
this.isProbablyReaderable,
|
||||||
this.extractedContentMarkdown,
|
this.extractedContentMarkdown,
|
||||||
this.extractedContentPlain,
|
this.extractedContentPlain,
|
||||||
@@ -1407,6 +1441,9 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
if (!nullToAbsent || title != null) {
|
if (!nullToAbsent || title != null) {
|
||||||
map['title'] = i0.Variable<String>(title);
|
map['title'] = i0.Variable<String>(title);
|
||||||
}
|
}
|
||||||
|
if (!nullToAbsent || isPrivate != null) {
|
||||||
|
map['is_private'] = i0.Variable<bool>(isPrivate);
|
||||||
|
}
|
||||||
if (!nullToAbsent || isProbablyReaderable != null) {
|
if (!nullToAbsent || isProbablyReaderable != null) {
|
||||||
map['is_probably_readerable'] = i0.Variable<bool>(isProbablyReaderable);
|
map['is_probably_readerable'] = i0.Variable<bool>(isProbablyReaderable);
|
||||||
}
|
}
|
||||||
@@ -1442,6 +1479,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
orderKey: serializer.fromJson<String>(json['order_key']),
|
orderKey: serializer.fromJson<String>(json['order_key']),
|
||||||
url: serializer.fromJson<Uri?>(json['url']),
|
url: serializer.fromJson<Uri?>(json['url']),
|
||||||
title: serializer.fromJson<String?>(json['title']),
|
title: serializer.fromJson<String?>(json['title']),
|
||||||
|
isPrivate: serializer.fromJson<bool?>(json['is_private']),
|
||||||
isProbablyReaderable: serializer.fromJson<bool?>(
|
isProbablyReaderable: serializer.fromJson<bool?>(
|
||||||
json['is_probably_readerable'],
|
json['is_probably_readerable'],
|
||||||
),
|
),
|
||||||
@@ -1470,6 +1508,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
'order_key': serializer.toJson<String>(orderKey),
|
'order_key': serializer.toJson<String>(orderKey),
|
||||||
'url': serializer.toJson<Uri?>(url),
|
'url': serializer.toJson<Uri?>(url),
|
||||||
'title': serializer.toJson<String?>(title),
|
'title': serializer.toJson<String?>(title),
|
||||||
|
'is_private': serializer.toJson<bool?>(isPrivate),
|
||||||
'is_probably_readerable': serializer.toJson<bool?>(isProbablyReaderable),
|
'is_probably_readerable': serializer.toJson<bool?>(isProbablyReaderable),
|
||||||
'extracted_content_markdown': serializer.toJson<String?>(
|
'extracted_content_markdown': serializer.toJson<String?>(
|
||||||
extractedContentMarkdown,
|
extractedContentMarkdown,
|
||||||
@@ -1490,6 +1529,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
String? orderKey,
|
String? orderKey,
|
||||||
i0.Value<Uri?> url = const i0.Value.absent(),
|
i0.Value<Uri?> url = const i0.Value.absent(),
|
||||||
i0.Value<String?> title = const i0.Value.absent(),
|
i0.Value<String?> title = const i0.Value.absent(),
|
||||||
|
i0.Value<bool?> isPrivate = const i0.Value.absent(),
|
||||||
i0.Value<bool?> isProbablyReaderable = const i0.Value.absent(),
|
i0.Value<bool?> isProbablyReaderable = const i0.Value.absent(),
|
||||||
i0.Value<String?> extractedContentMarkdown = const i0.Value.absent(),
|
i0.Value<String?> extractedContentMarkdown = const i0.Value.absent(),
|
||||||
i0.Value<String?> extractedContentPlain = const i0.Value.absent(),
|
i0.Value<String?> extractedContentPlain = const i0.Value.absent(),
|
||||||
@@ -1503,6 +1543,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
orderKey: orderKey ?? this.orderKey,
|
orderKey: orderKey ?? this.orderKey,
|
||||||
url: url.present ? url.value : this.url,
|
url: url.present ? url.value : this.url,
|
||||||
title: title.present ? title.value : this.title,
|
title: title.present ? title.value : this.title,
|
||||||
|
isPrivate: isPrivate.present ? isPrivate.value : this.isPrivate,
|
||||||
isProbablyReaderable: isProbablyReaderable.present
|
isProbablyReaderable: isProbablyReaderable.present
|
||||||
? isProbablyReaderable.value
|
? isProbablyReaderable.value
|
||||||
: this.isProbablyReaderable,
|
: this.isProbablyReaderable,
|
||||||
@@ -1530,6 +1571,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
orderKey: data.orderKey.present ? data.orderKey.value : this.orderKey,
|
orderKey: data.orderKey.present ? data.orderKey.value : this.orderKey,
|
||||||
url: data.url.present ? data.url.value : this.url,
|
url: data.url.present ? data.url.value : this.url,
|
||||||
title: data.title.present ? data.title.value : this.title,
|
title: data.title.present ? data.title.value : this.title,
|
||||||
|
isPrivate: data.isPrivate.present ? data.isPrivate.value : this.isPrivate,
|
||||||
isProbablyReaderable: data.isProbablyReaderable.present
|
isProbablyReaderable: data.isProbablyReaderable.present
|
||||||
? data.isProbablyReaderable.value
|
? data.isProbablyReaderable.value
|
||||||
: this.isProbablyReaderable,
|
: this.isProbablyReaderable,
|
||||||
@@ -1558,6 +1600,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
..write('orderKey: $orderKey, ')
|
..write('orderKey: $orderKey, ')
|
||||||
..write('url: $url, ')
|
..write('url: $url, ')
|
||||||
..write('title: $title, ')
|
..write('title: $title, ')
|
||||||
|
..write('isPrivate: $isPrivate, ')
|
||||||
..write('isProbablyReaderable: $isProbablyReaderable, ')
|
..write('isProbablyReaderable: $isProbablyReaderable, ')
|
||||||
..write('extractedContentMarkdown: $extractedContentMarkdown, ')
|
..write('extractedContentMarkdown: $extractedContentMarkdown, ')
|
||||||
..write('extractedContentPlain: $extractedContentPlain, ')
|
..write('extractedContentPlain: $extractedContentPlain, ')
|
||||||
@@ -1576,6 +1619,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
orderKey,
|
orderKey,
|
||||||
url,
|
url,
|
||||||
title,
|
title,
|
||||||
|
isPrivate,
|
||||||
isProbablyReaderable,
|
isProbablyReaderable,
|
||||||
extractedContentMarkdown,
|
extractedContentMarkdown,
|
||||||
extractedContentPlain,
|
extractedContentPlain,
|
||||||
@@ -1593,6 +1637,7 @@ class TabData extends i0.DataClass implements i0.Insertable<i3.TabData> {
|
|||||||
other.orderKey == this.orderKey &&
|
other.orderKey == this.orderKey &&
|
||||||
other.url == this.url &&
|
other.url == this.url &&
|
||||||
other.title == this.title &&
|
other.title == this.title &&
|
||||||
|
other.isPrivate == this.isPrivate &&
|
||||||
other.isProbablyReaderable == this.isProbablyReaderable &&
|
other.isProbablyReaderable == this.isProbablyReaderable &&
|
||||||
other.extractedContentMarkdown == this.extractedContentMarkdown &&
|
other.extractedContentMarkdown == this.extractedContentMarkdown &&
|
||||||
other.extractedContentPlain == this.extractedContentPlain &&
|
other.extractedContentPlain == this.extractedContentPlain &&
|
||||||
@@ -1608,6 +1653,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
final i0.Value<String> orderKey;
|
final i0.Value<String> orderKey;
|
||||||
final i0.Value<Uri?> url;
|
final i0.Value<Uri?> url;
|
||||||
final i0.Value<String?> title;
|
final i0.Value<String?> title;
|
||||||
|
final i0.Value<bool?> isPrivate;
|
||||||
final i0.Value<bool?> isProbablyReaderable;
|
final i0.Value<bool?> isProbablyReaderable;
|
||||||
final i0.Value<String?> extractedContentMarkdown;
|
final i0.Value<String?> extractedContentMarkdown;
|
||||||
final i0.Value<String?> extractedContentPlain;
|
final i0.Value<String?> extractedContentPlain;
|
||||||
@@ -1622,6 +1668,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
this.orderKey = const i0.Value.absent(),
|
this.orderKey = const i0.Value.absent(),
|
||||||
this.url = const i0.Value.absent(),
|
this.url = const i0.Value.absent(),
|
||||||
this.title = const i0.Value.absent(),
|
this.title = const i0.Value.absent(),
|
||||||
|
this.isPrivate = const i0.Value.absent(),
|
||||||
this.isProbablyReaderable = const i0.Value.absent(),
|
this.isProbablyReaderable = const i0.Value.absent(),
|
||||||
this.extractedContentMarkdown = const i0.Value.absent(),
|
this.extractedContentMarkdown = const i0.Value.absent(),
|
||||||
this.extractedContentPlain = const i0.Value.absent(),
|
this.extractedContentPlain = const i0.Value.absent(),
|
||||||
@@ -1637,6 +1684,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
required String orderKey,
|
required String orderKey,
|
||||||
this.url = const i0.Value.absent(),
|
this.url = const i0.Value.absent(),
|
||||||
this.title = const i0.Value.absent(),
|
this.title = const i0.Value.absent(),
|
||||||
|
this.isPrivate = const i0.Value.absent(),
|
||||||
this.isProbablyReaderable = const i0.Value.absent(),
|
this.isProbablyReaderable = const i0.Value.absent(),
|
||||||
this.extractedContentMarkdown = const i0.Value.absent(),
|
this.extractedContentMarkdown = const i0.Value.absent(),
|
||||||
this.extractedContentPlain = const i0.Value.absent(),
|
this.extractedContentPlain = const i0.Value.absent(),
|
||||||
@@ -1654,6 +1702,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
i0.Expression<String>? orderKey,
|
i0.Expression<String>? orderKey,
|
||||||
i0.Expression<String>? url,
|
i0.Expression<String>? url,
|
||||||
i0.Expression<String>? title,
|
i0.Expression<String>? title,
|
||||||
|
i0.Expression<bool>? isPrivate,
|
||||||
i0.Expression<bool>? isProbablyReaderable,
|
i0.Expression<bool>? isProbablyReaderable,
|
||||||
i0.Expression<String>? extractedContentMarkdown,
|
i0.Expression<String>? extractedContentMarkdown,
|
||||||
i0.Expression<String>? extractedContentPlain,
|
i0.Expression<String>? extractedContentPlain,
|
||||||
@@ -1669,6 +1718,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
if (orderKey != null) 'order_key': orderKey,
|
if (orderKey != null) 'order_key': orderKey,
|
||||||
if (url != null) 'url': url,
|
if (url != null) 'url': url,
|
||||||
if (title != null) 'title': title,
|
if (title != null) 'title': title,
|
||||||
|
if (isPrivate != null) 'is_private': isPrivate,
|
||||||
if (isProbablyReaderable != null)
|
if (isProbablyReaderable != null)
|
||||||
'is_probably_readerable': isProbablyReaderable,
|
'is_probably_readerable': isProbablyReaderable,
|
||||||
if (extractedContentMarkdown != null)
|
if (extractedContentMarkdown != null)
|
||||||
@@ -1690,6 +1740,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
i0.Value<String>? orderKey,
|
i0.Value<String>? orderKey,
|
||||||
i0.Value<Uri?>? url,
|
i0.Value<Uri?>? url,
|
||||||
i0.Value<String?>? title,
|
i0.Value<String?>? title,
|
||||||
|
i0.Value<bool?>? isPrivate,
|
||||||
i0.Value<bool?>? isProbablyReaderable,
|
i0.Value<bool?>? isProbablyReaderable,
|
||||||
i0.Value<String?>? extractedContentMarkdown,
|
i0.Value<String?>? extractedContentMarkdown,
|
||||||
i0.Value<String?>? extractedContentPlain,
|
i0.Value<String?>? extractedContentPlain,
|
||||||
@@ -1705,6 +1756,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
orderKey: orderKey ?? this.orderKey,
|
orderKey: orderKey ?? this.orderKey,
|
||||||
url: url ?? this.url,
|
url: url ?? this.url,
|
||||||
title: title ?? this.title,
|
title: title ?? this.title,
|
||||||
|
isPrivate: isPrivate ?? this.isPrivate,
|
||||||
isProbablyReaderable: isProbablyReaderable ?? this.isProbablyReaderable,
|
isProbablyReaderable: isProbablyReaderable ?? this.isProbablyReaderable,
|
||||||
extractedContentMarkdown:
|
extractedContentMarkdown:
|
||||||
extractedContentMarkdown ?? this.extractedContentMarkdown,
|
extractedContentMarkdown ?? this.extractedContentMarkdown,
|
||||||
@@ -1738,6 +1790,9 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
if (title.present) {
|
if (title.present) {
|
||||||
map['title'] = i0.Variable<String>(title.value);
|
map['title'] = i0.Variable<String>(title.value);
|
||||||
}
|
}
|
||||||
|
if (isPrivate.present) {
|
||||||
|
map['is_private'] = i0.Variable<bool>(isPrivate.value);
|
||||||
|
}
|
||||||
if (isProbablyReaderable.present) {
|
if (isProbablyReaderable.present) {
|
||||||
map['is_probably_readerable'] = i0.Variable<bool>(
|
map['is_probably_readerable'] = i0.Variable<bool>(
|
||||||
isProbablyReaderable.value,
|
isProbablyReaderable.value,
|
||||||
@@ -1779,6 +1834,7 @@ class TabCompanion extends i0.UpdateCompanion<i3.TabData> {
|
|||||||
..write('orderKey: $orderKey, ')
|
..write('orderKey: $orderKey, ')
|
||||||
..write('url: $url, ')
|
..write('url: $url, ')
|
||||||
..write('title: $title, ')
|
..write('title: $title, ')
|
||||||
|
..write('isPrivate: $isPrivate, ')
|
||||||
..write('isProbablyReaderable: $isProbablyReaderable, ')
|
..write('isProbablyReaderable: $isProbablyReaderable, ')
|
||||||
..write('extractedContentMarkdown: $extractedContentMarkdown, ')
|
..write('extractedContentMarkdown: $extractedContentMarkdown, ')
|
||||||
..write('extractedContentPlain: $extractedContentPlain, ')
|
..write('extractedContentPlain: $extractedContentPlain, ')
|
||||||
@@ -2161,13 +2217,14 @@ class DefinitionsDrift extends i7.ModularAccessor {
|
|||||||
|
|
||||||
i0.Selectable<i8.TabQueryResult> queryTabsBasic({required String query}) {
|
i0.Selectable<i8.TabQueryResult> queryTabsBasic({required String query}) {
|
||||||
return customSelect(
|
return customSelect(
|
||||||
'WITH weights AS (SELECT 10.0 AS title_weight, 5.0 AS url_weight) SELECT t.id, t.container_id, t.title, CAST(t.url AS TEXT) AS url, t.url AS clean_url, bm25(tab_fts, weights.title_weight, weights.url_weight) AS weighted_rank FROM tab_fts AS fts INNER JOIN tab AS t ON t."rowid" = fts."rowid" CROSS JOIN weights WHERE fts.title LIKE ?1 OR fts.url LIKE ?1 ORDER BY weighted_rank ASC, t.timestamp DESC',
|
'WITH weights AS (SELECT 10.0 AS title_weight, 5.0 AS url_weight) SELECT t.id, t.container_id, t.is_private, t.title, CAST(t.url AS TEXT) AS url, t.url AS clean_url, bm25(tab_fts, weights.title_weight, weights.url_weight) AS weighted_rank FROM tab_fts AS fts INNER JOIN tab AS t ON t."rowid" = fts."rowid" CROSS JOIN weights WHERE fts.title LIKE ?1 OR fts.url LIKE ?1 ORDER BY weighted_rank ASC, t.timestamp DESC',
|
||||||
variables: [i0.Variable<String>(query)],
|
variables: [i0.Variable<String>(query)],
|
||||||
readsFrom: {tab, tabFts},
|
readsFrom: {tab, tabFts},
|
||||||
).map(
|
).map(
|
||||||
(i0.QueryRow row) => i8.TabQueryResult(
|
(i0.QueryRow row) => i8.TabQueryResult(
|
||||||
id: row.read<String>('id'),
|
id: row.read<String>('id'),
|
||||||
containerId: row.readNullable<String>('container_id'),
|
containerId: row.readNullable<String>('container_id'),
|
||||||
|
isPrivate: row.readNullable<bool>('is_private'),
|
||||||
title: row.readNullable<String>('title'),
|
title: row.readNullable<String>('title'),
|
||||||
url: row.readNullable<String>('url'),
|
url: row.readNullable<String>('url'),
|
||||||
cleanUrl: i3.Tab.$converterurl.fromSql(
|
cleanUrl: i3.Tab.$converterurl.fromSql(
|
||||||
@@ -2186,7 +2243,7 @@ class DefinitionsDrift extends i7.ModularAccessor {
|
|||||||
required String query,
|
required String query,
|
||||||
}) {
|
}) {
|
||||||
return customSelect(
|
return customSelect(
|
||||||
'WITH weights AS (SELECT 10.0 AS title_weight, 5.0 AS url_weight, 3.0 AS extracted_weight, 1.0 AS full_weight) SELECT t.id, t.container_id, highlight(tab_fts, 0, ?1, ?2) AS title, highlight(tab_fts, 1, ?1, ?2) AS url, snippet(tab_fts, 2, ?1, ?2, ?3, ?4) AS extracted_content, snippet(tab_fts, 3, ?1, ?2, ?3, ?4) AS full_content, t.url AS clean_url,(bm25(tab_fts, weights.title_weight, weights.url_weight, weights.extracted_weight, weights.full_weight))AS weighted_rank FROM tab_fts(?5)AS fts INNER JOIN tab AS t ON t."rowid" = fts."rowid" CROSS JOIN weights ORDER BY weighted_rank ASC, t.timestamp DESC',
|
'WITH weights AS (SELECT 10.0 AS title_weight, 5.0 AS url_weight, 3.0 AS extracted_weight, 1.0 AS full_weight) SELECT t.id, t.container_id, t.is_private, highlight(tab_fts, 0, ?1, ?2) AS title, highlight(tab_fts, 1, ?1, ?2) AS url, snippet(tab_fts, 2, ?1, ?2, ?3, ?4) AS extracted_content, snippet(tab_fts, 3, ?1, ?2, ?3, ?4) AS full_content, t.url AS clean_url,(bm25(tab_fts, weights.title_weight, weights.url_weight, weights.extracted_weight, weights.full_weight))AS weighted_rank FROM tab_fts(?5)AS fts INNER JOIN tab AS t ON t."rowid" = fts."rowid" CROSS JOIN weights ORDER BY weighted_rank ASC, t.timestamp DESC',
|
||||||
variables: [
|
variables: [
|
||||||
i0.Variable<String>(beforeMatch),
|
i0.Variable<String>(beforeMatch),
|
||||||
i0.Variable<String>(afterMatch),
|
i0.Variable<String>(afterMatch),
|
||||||
@@ -2199,6 +2256,7 @@ class DefinitionsDrift extends i7.ModularAccessor {
|
|||||||
(i0.QueryRow row) => i8.TabQueryResult(
|
(i0.QueryRow row) => i8.TabQueryResult(
|
||||||
id: row.read<String>('id'),
|
id: row.read<String>('id'),
|
||||||
containerId: row.readNullable<String>('container_id'),
|
containerId: row.readNullable<String>('container_id'),
|
||||||
|
isPrivate: row.readNullable<bool>('is_private'),
|
||||||
title: row.readNullable<String>('title'),
|
title: row.readNullable<String>('title'),
|
||||||
url: row.readNullable<String>('url'),
|
url: row.readNullable<String>('url'),
|
||||||
cleanUrl: i3.Tab.$converterurl.fromSql(
|
cleanUrl: i3.Tab.$converterurl.fromSql(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import 'package:fast_equatable/fast_equatable.dart';
|
|||||||
class TabQueryResult with FastEquatable {
|
class TabQueryResult with FastEquatable {
|
||||||
final String id;
|
final String id;
|
||||||
final String? containerId;
|
final String? containerId;
|
||||||
|
final bool? isPrivate;
|
||||||
|
|
||||||
final String? title;
|
final String? title;
|
||||||
final Uri? cleanUrl;
|
final Uri? cleanUrl;
|
||||||
@@ -35,6 +36,7 @@ class TabQueryResult with FastEquatable {
|
|||||||
TabQueryResult({
|
TabQueryResult({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.containerId,
|
required this.containerId,
|
||||||
|
required this.isPrivate,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.url,
|
required this.url,
|
||||||
required this.cleanUrl,
|
required this.cleanUrl,
|
||||||
@@ -47,6 +49,7 @@ class TabQueryResult with FastEquatable {
|
|||||||
List<Object?> get hashParameters => [
|
List<Object?> get hashParameters => [
|
||||||
id,
|
id,
|
||||||
containerId,
|
containerId,
|
||||||
|
isPrivate,
|
||||||
title,
|
title,
|
||||||
cleanUrl,
|
cleanUrl,
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -85,9 +85,7 @@ class ContainerRepository extends _$ContainerRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteContainer(String id) async {
|
Future<void> deleteContainer(String id) async {
|
||||||
await ref
|
await ref.read(tabDataRepositoryProvider.notifier).closeContainerTabs(id);
|
||||||
.read(tabDataRepositoryProvider.notifier)
|
|
||||||
.closeAllTabsByContainer(id);
|
|
||||||
|
|
||||||
return ref.read(tabDatabaseProvider).containerDao.deleteContainer(id);
|
return ref.read(tabDatabaseProvider).containerDao.deleteContainer(id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ final class ContainerRepositoryProvider
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$containerRepositoryHash() =>
|
String _$containerRepositoryHash() =>
|
||||||
r'8c9252a49a096c29279ad3066f6e5936e15524b2';
|
r'2a377774f9f18604bb90cb1a8eb7cda5f944c601';
|
||||||
|
|
||||||
abstract class _$ContainerRepository extends $Notifier<void> {
|
abstract class _$ContainerRepository extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
@@ -73,11 +73,39 @@ class TabDataRepository extends _$TabDataRepository {
|
|||||||
.assignOrderKey(tabId, orderKey: orderKey);
|
.assignOrderKey(tabId, orderKey: orderKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> closeAllTabsByContainer(String? containerId) async {
|
Future<int> closeAllTabs({
|
||||||
|
bool includeRegular = true,
|
||||||
|
bool includePrivate = true,
|
||||||
|
}) async {
|
||||||
final tabIds = await ref
|
final tabIds = await ref
|
||||||
.read(tabDatabaseProvider)
|
.read(tabDatabaseProvider)
|
||||||
.containerDao
|
.containerDao
|
||||||
.getContainerTabIds(containerId)
|
.getAllTabIds(
|
||||||
|
includeRegular: includeRegular,
|
||||||
|
includePrivate: includePrivate,
|
||||||
|
)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
if (tabIds.isNotEmpty) {
|
||||||
|
await ref.read(tabRepositoryProvider.notifier).closeTabs(tabIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabIds.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> closeContainerTabs(
|
||||||
|
String? containerId, {
|
||||||
|
bool includeRegular = true,
|
||||||
|
bool includePrivate = true,
|
||||||
|
}) async {
|
||||||
|
final tabIds = await ref
|
||||||
|
.read(tabDatabaseProvider)
|
||||||
|
.containerDao
|
||||||
|
.getContainerTabIds(
|
||||||
|
containerId,
|
||||||
|
includeRegular: includeRegular,
|
||||||
|
includePrivate: includePrivate,
|
||||||
|
)
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
if (tabIds.isNotEmpty) {
|
if (tabIds.isNotEmpty) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ final class TabDataRepositoryProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$tabDataRepositoryHash() => r'3d9149efb88f256cc826eb538f13331b49438a7c';
|
String _$tabDataRepositoryHash() => r'63ab2765ea5be640d6c6a596852fee0df5a958e4';
|
||||||
|
|
||||||
abstract class _$TabDataRepository extends $Notifier<void> {
|
abstract class _$TabDataRepository extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
@@ -22,10 +22,15 @@ import 'dart:io';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:riverpod/riverpod.dart';
|
import 'package:riverpod/riverpod.dart';
|
||||||
import 'package:weblibre/core/logger.dart';
|
import 'package:weblibre/core/logger.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/tab.dart';
|
||||||
|
|
||||||
Future<void> exitApp(ProviderContainer container) async {
|
Future<void> exitApp(ProviderContainer container) async {
|
||||||
logger.i('Preparing exit');
|
logger.i('Preparing exit');
|
||||||
|
|
||||||
|
await container
|
||||||
|
.read(tabDataRepositoryProvider.notifier)
|
||||||
|
.closeAllTabs(includeRegular: false);
|
||||||
|
|
||||||
await SystemNavigator.pop();
|
await SystemNavigator.pop();
|
||||||
logger.i('SystemNavigator popped');
|
logger.i('SystemNavigator popped');
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// GENERATED CODE, DO NOT EDIT BY HAND.
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift/internal/migrations.dart';
|
||||||
|
import 'schema_v2.dart' as v2;
|
||||||
|
import 'schema_v3.dart' as v3;
|
||||||
|
|
||||||
|
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||||
|
@override
|
||||||
|
GeneratedDatabase databaseForVersion(QueryExecutor db, int version) {
|
||||||
|
switch (version) {
|
||||||
|
case 2:
|
||||||
|
return v2.DatabaseAtV2(db);
|
||||||
|
case 3:
|
||||||
|
return v3.DatabaseAtV3(db);
|
||||||
|
default:
|
||||||
|
throw MissingSchemaException(version, versions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const versions = const [2, 3];
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// ignore_for_file: unused_local_variable, unused_import
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift_dev/api/migrations_native.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/tabs/data/database/database.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'generated/schema.dart';
|
||||||
|
|
||||||
|
import 'generated/schema_v2.dart' as v2;
|
||||||
|
import 'generated/schema_v3.dart' as v3;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
|
||||||
|
late SchemaVerifier verifier;
|
||||||
|
|
||||||
|
setUpAll(() {
|
||||||
|
verifier = SchemaVerifier(GeneratedHelper());
|
||||||
|
});
|
||||||
|
|
||||||
|
group('simple database migrations', () {
|
||||||
|
// These simple tests verify all possible schema updates with a simple (no
|
||||||
|
// data) migration. This is a quick way to ensure that written database
|
||||||
|
// migrations properly alter the schema.
|
||||||
|
const versions = GeneratedHelper.versions;
|
||||||
|
for (final (i, fromVersion) in versions.indexed) {
|
||||||
|
group('from $fromVersion', () {
|
||||||
|
for (final toVersion in versions.skip(i + 1)) {
|
||||||
|
test('to $toVersion', () async {
|
||||||
|
final schema = await verifier.schemaAt(fromVersion);
|
||||||
|
final db = TabDatabase(schema.newConnection());
|
||||||
|
await verifier.migrateAndValidate(db, toVersion);
|
||||||
|
await db.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// The following template shows how to write tests ensuring your migrations
|
||||||
|
// preserve existing data.
|
||||||
|
// Testing this can be useful for migrations that change existing columns
|
||||||
|
// (e.g. by alterating their type or constraints). Migrations that only add
|
||||||
|
// tables or columns typically don't need these advanced tests. For more
|
||||||
|
// information, see https://drift.simonbinder.eu/migrations/tests/#verifying-data-integrity
|
||||||
|
// TODO: This generated template shows how these tests could be written. Adopt
|
||||||
|
// it to your own needs when testing migrations with data integrity.
|
||||||
|
test('migration from v2 to v3 does not corrupt data', () async {
|
||||||
|
// Add data to insert into the old database, and the expected rows after the
|
||||||
|
// migration.
|
||||||
|
// TODO: Fill these lists
|
||||||
|
final oldContainerData = <v2.ContainerData>[];
|
||||||
|
final expectedNewContainerData = <v3.ContainerData>[];
|
||||||
|
|
||||||
|
final oldTabData = <v2.TabData>[];
|
||||||
|
final expectedNewTabData = <v3.TabData>[];
|
||||||
|
|
||||||
|
final oldTabFtsData = <v2.TabFtsData>[];
|
||||||
|
final expectedNewTabFtsData = <v3.TabFtsData>[];
|
||||||
|
|
||||||
|
await verifier.testWithDataIntegrity(
|
||||||
|
oldVersion: 2,
|
||||||
|
newVersion: 3,
|
||||||
|
createOld: v2.DatabaseAtV2.new,
|
||||||
|
createNew: v3.DatabaseAtV3.new,
|
||||||
|
openTestedDatabase: TabDatabase.new,
|
||||||
|
createItems: (batch, oldDb) {
|
||||||
|
batch.insertAll(oldDb.container, oldContainerData);
|
||||||
|
batch.insertAll(oldDb.tab, oldTabData);
|
||||||
|
batch.insertAll(oldDb.tabFts, oldTabFtsData);
|
||||||
|
},
|
||||||
|
validateItems: (newDb) async {
|
||||||
|
expect(
|
||||||
|
expectedNewContainerData,
|
||||||
|
await newDb.select(newDb.container).get(),
|
||||||
|
);
|
||||||
|
expect(expectedNewTabData, await newDb.select(newDb.tab).get());
|
||||||
|
expect(expectedNewTabFtsData, await newDb.select(newDb.tabFts).get());
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user