customize quick tab switcher buttons
This commit is contained in:
@@ -0,0 +1,651 @@
|
|||||||
|
{
|
||||||
|
"_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": "setting",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "key",
|
||||||
|
"getter_name": "key",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "PRIMARY KEY NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "partition_key",
|
||||||
|
"getter_name": "partitionKey",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "value",
|
||||||
|
"getter_name": "value",
|
||||||
|
"moor_type": "any",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": [],
|
||||||
|
"strict": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "proxy_profile",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"getter_name": "id",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL PRIMARY KEY",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"getter_name": "name",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "type",
|
||||||
|
"getter_name": "type",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [],
|
||||||
|
"type_converter": {
|
||||||
|
"dart_expr": "const EnumNameConverter<SingboxProxyProfileType>(SingboxProxyProfileType.values)",
|
||||||
|
"dart_type_name": "SingboxProxyProfileType"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "config_json",
|
||||||
|
"getter_name": "configJson",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dns_override_json",
|
||||||
|
"getter_name": "dnsOverrideJson",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "created_at",
|
||||||
|
"getter_name": "createdAt",
|
||||||
|
"moor_type": "dateTime",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL DEFAULT CURRENT_TIMESTAMP",
|
||||||
|
"default_dart": "const CustomExpression('CURRENT_TIMESTAMP')",
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "updated_at",
|
||||||
|
"getter_name": "updatedAt",
|
||||||
|
"moor_type": "dateTime",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL DEFAULT CURRENT_TIMESTAMP",
|
||||||
|
"default_dart": "const CustomExpression('CURRENT_TIMESTAMP')",
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"references": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"type": "index",
|
||||||
|
"data": {
|
||||||
|
"on": 1,
|
||||||
|
"name": "idx_proxy_profile_updated_at",
|
||||||
|
"sql": "CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile(updated_at);",
|
||||||
|
"unique": false,
|
||||||
|
"columns": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "icon_cache",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "origin",
|
||||||
|
"getter_name": "origin",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "PRIMARY KEY NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon_data",
|
||||||
|
"getter_name": "iconData",
|
||||||
|
"moor_type": "blob",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fetch_date",
|
||||||
|
"getter_name": "fetchDate",
|
||||||
|
"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": 4,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "onboarding",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "revision",
|
||||||
|
"getter_name": "revision",
|
||||||
|
"moor_type": "int",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "completion_date",
|
||||||
|
"getter_name": "completionDate",
|
||||||
|
"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": 5,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "riverpod",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "key",
|
||||||
|
"getter_name": "key",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "PRIMARY KEY NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "json",
|
||||||
|
"getter_name": "json",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "expireAt",
|
||||||
|
"getter_name": "expireAt",
|
||||||
|
"moor_type": "dateTime",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "destroyKey",
|
||||||
|
"getter_name": "destroyKey",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": true,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "toolbar_button_configs",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "button_id",
|
||||||
|
"getter_name": "buttonId",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL PRIMARY KEY",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "order_key",
|
||||||
|
"getter_name": "orderKey",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_visible",
|
||||||
|
"getter_name": "isVisible",
|
||||||
|
"moor_type": "bool",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL DEFAULT TRUE",
|
||||||
|
"default_dart": "const CustomExpression('TRUE')",
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fallback_id",
|
||||||
|
"getter_name": "fallbackId",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "REFERENCES toolbar_button_configs(button_id)ON DELETE SET NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"references": [
|
||||||
|
6
|
||||||
|
],
|
||||||
|
"type": "index",
|
||||||
|
"data": {
|
||||||
|
"on": 6,
|
||||||
|
"name": "idx_toolbar_order_key",
|
||||||
|
"sql": "CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs(order_key);",
|
||||||
|
"unique": false,
|
||||||
|
"columns": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "quick_switcher_button_configs",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "button_id",
|
||||||
|
"getter_name": "buttonId",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL PRIMARY KEY",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"primary-key"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "order_key",
|
||||||
|
"getter_name": "orderKey",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "is_visible",
|
||||||
|
"getter_name": "isVisible",
|
||||||
|
"moor_type": "bool",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL DEFAULT FALSE",
|
||||||
|
"default_dart": "const CustomExpression('FALSE')",
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fallback_id",
|
||||||
|
"getter_name": "fallbackId",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "REFERENCES quick_switcher_button_configs(button_id)ON DELETE SET NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"references": [
|
||||||
|
8
|
||||||
|
],
|
||||||
|
"type": "index",
|
||||||
|
"data": {
|
||||||
|
"on": 8,
|
||||||
|
"name": "idx_quick_switcher_order_key",
|
||||||
|
"sql": "CREATE INDEX idx_quick_switcher_order_key ON quick_switcher_button_configs(order_key);",
|
||||||
|
"unique": false,
|
||||||
|
"columns": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"references": [],
|
||||||
|
"type": "table",
|
||||||
|
"data": {
|
||||||
|
"name": "search_tokens",
|
||||||
|
"was_declared_in_moor": true,
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"getter_name": "id",
|
||||||
|
"moor_type": "int",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "PRIMARY KEY AUTOINCREMENT",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": [
|
||||||
|
"auto-increment"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "token",
|
||||||
|
"getter_name": "token",
|
||||||
|
"moor_type": "blob",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inserted_at",
|
||||||
|
"getter_name": "insertedAt",
|
||||||
|
"moor_type": "dateTime",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "issuer_key_version",
|
||||||
|
"getter_name": "issuerKeyVersion",
|
||||||
|
"moor_type": "string",
|
||||||
|
"nullable": false,
|
||||||
|
"customConstraints": "NOT NULL",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "reserved_at",
|
||||||
|
"getter_name": "reservedAt",
|
||||||
|
"moor_type": "dateTime",
|
||||||
|
"nullable": true,
|
||||||
|
"customConstraints": "",
|
||||||
|
"default_dart": null,
|
||||||
|
"default_client_dart": null,
|
||||||
|
"dsl_features": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"is_virtual": false,
|
||||||
|
"without_rowid": false,
|
||||||
|
"constraints": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"references": [
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"type": "index",
|
||||||
|
"data": {
|
||||||
|
"on": 10,
|
||||||
|
"name": "idx_search_tokens_inserted_at",
|
||||||
|
"sql": "CREATE INDEX idx_search_tokens_inserted_at ON search_tokens(inserted_at);",
|
||||||
|
"unique": false,
|
||||||
|
"columns": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"references": [
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"type": "index",
|
||||||
|
"data": {
|
||||||
|
"on": 10,
|
||||||
|
"name": "idx_search_tokens_reserved_at",
|
||||||
|
"sql": "CREATE INDEX idx_search_tokens_reserved_at ON search_tokens(reserved_at);",
|
||||||
|
"unique": false,
|
||||||
|
"columns": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fixed_sql": [
|
||||||
|
{
|
||||||
|
"name": "setting",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"setting\" (\"key\" TEXT PRIMARY KEY NOT NULL, \"partition_key\" TEXT, \"value\" ANY) STRICT;"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "proxy_profile",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"proxy_profile\" (\"id\" TEXT NOT NULL PRIMARY KEY, \"name\" TEXT NOT NULL, \"type\" TEXT NOT NULL, \"config_json\" TEXT NOT NULL, \"dns_override_json\" TEXT, \"created_at\" INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP, \"updated_at\" INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_proxy_profile_updated_at",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile (updated_at)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "icon_cache",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"icon_cache\" (\"origin\" TEXT PRIMARY KEY NOT NULL, \"icon_data\" BLOB NOT NULL, \"fetch_date\" INTEGER NOT NULL);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "onboarding",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"onboarding\" (\"revision\" INTEGER NOT NULL, \"completion_date\" INTEGER NOT NULL);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "riverpod",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"riverpod\" (\"key\" TEXT PRIMARY KEY NOT NULL, \"json\" TEXT NOT NULL, \"expireAt\" INTEGER, \"destroyKey\" TEXT) WITHOUT ROWID;"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "toolbar_button_configs",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"toolbar_button_configs\" (\"button_id\" TEXT NOT NULL PRIMARY KEY, \"order_key\" TEXT NOT NULL, \"is_visible\" INTEGER NOT NULL DEFAULT TRUE, \"fallback_id\" TEXT REFERENCES toolbar_button_configs(button_id)ON DELETE SET NULL);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_toolbar_order_key",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "quick_switcher_button_configs",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"quick_switcher_button_configs\" (\"button_id\" TEXT NOT NULL PRIMARY KEY, \"order_key\" TEXT NOT NULL, \"is_visible\" INTEGER NOT NULL DEFAULT FALSE, \"fallback_id\" TEXT REFERENCES quick_switcher_button_configs(button_id)ON DELETE SET NULL);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_quick_switcher_order_key",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE INDEX idx_quick_switcher_order_key ON quick_switcher_button_configs (order_key)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "search_tokens",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE TABLE IF NOT EXISTS \"search_tokens\" (\"id\" INTEGER PRIMARY KEY AUTOINCREMENT, \"token\" BLOB NOT NULL, \"inserted_at\" INTEGER NOT NULL, \"issuer_key_version\" TEXT NOT NULL, \"reserved_at\" INTEGER);"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_search_tokens_inserted_at",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE INDEX idx_search_tokens_inserted_at ON search_tokens (inserted_at)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "idx_search_tokens_reserved_at",
|
||||||
|
"sql": [
|
||||||
|
{
|
||||||
|
"dialect": "sqlite",
|
||||||
|
"sql": "CREATE INDEX idx_search_tokens_reserved_at ON search_tokens (reserved_at)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@ import 'package:weblibre/features/geckoview/features/bookmarks/domain/entities/b
|
|||||||
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/screens/bookmark_entry_edit.dart';
|
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/screens/bookmark_entry_edit.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/screens/bookmark_folder_edit.dart';
|
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/screens/bookmark_folder_edit.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart';
|
import 'package:weblibre/features/geckoview/features/bookmarks/presentation/screens/bookmark_list.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/dialogs/tab_tree.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/dialogs/tab_tree.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/screens/browser.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/screens/browser.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/screens/tab_view.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/screens/tab_view.dart';
|
||||||
|
|||||||
@@ -1674,6 +1674,11 @@ RouteBase get $settingsRoute => GoRouteData.$route(
|
|||||||
name: 'ContextualToolbarSettingsRoute',
|
name: 'ContextualToolbarSettingsRoute',
|
||||||
factory: $ContextualToolbarSettingsRoute._fromState,
|
factory: $ContextualToolbarSettingsRoute._fromState,
|
||||||
),
|
),
|
||||||
|
GoRouteData.$route(
|
||||||
|
path: 'quick_switcher_toolbar',
|
||||||
|
name: 'QuickSwitcherToolbarSettingsRoute',
|
||||||
|
factory: $QuickSwitcherToolbarSettingsRoute._fromState,
|
||||||
|
),
|
||||||
GoRouteData.$route(
|
GoRouteData.$route(
|
||||||
path: 'desktop_mode_sites',
|
path: 'desktop_mode_sites',
|
||||||
name: 'DesktopModeSitesRoute',
|
name: 'DesktopModeSitesRoute',
|
||||||
@@ -2285,6 +2290,28 @@ mixin $ContextualToolbarSettingsRoute on GoRouteData {
|
|||||||
void replace(BuildContext context) => context.replace(location);
|
void replace(BuildContext context) => context.replace(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mixin $QuickSwitcherToolbarSettingsRoute on GoRouteData {
|
||||||
|
static QuickSwitcherToolbarSettingsRoute _fromState(GoRouterState state) =>
|
||||||
|
const QuickSwitcherToolbarSettingsRoute();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get location =>
|
||||||
|
GoRouteData.$location('/settings/quick_switcher_toolbar');
|
||||||
|
|
||||||
|
@override
|
||||||
|
void go(BuildContext context) => context.go(location);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<T?> push<T>(BuildContext context) => context.push<T>(location);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void pushReplacement(BuildContext context) =>
|
||||||
|
context.pushReplacement(location);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void replace(BuildContext context) => context.replace(location);
|
||||||
|
}
|
||||||
|
|
||||||
mixin $DesktopModeSitesRoute on GoRouteData {
|
mixin $DesktopModeSitesRoute on GoRouteData {
|
||||||
static DesktopModeSitesRoute _fromState(GoRouterState state) =>
|
static DesktopModeSitesRoute _fromState(GoRouterState state) =>
|
||||||
const DesktopModeSitesRoute();
|
const DesktopModeSitesRoute();
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ part of 'routes.dart';
|
|||||||
name: 'ContextualToolbarSettingsRoute',
|
name: 'ContextualToolbarSettingsRoute',
|
||||||
path: 'contextual_toolbar',
|
path: 'contextual_toolbar',
|
||||||
),
|
),
|
||||||
|
TypedGoRoute<QuickSwitcherToolbarSettingsRoute>(
|
||||||
|
name: 'QuickSwitcherToolbarSettingsRoute',
|
||||||
|
path: 'quick_switcher_toolbar',
|
||||||
|
),
|
||||||
TypedGoRoute<DesktopModeSitesRoute>(
|
TypedGoRoute<DesktopModeSitesRoute>(
|
||||||
name: 'DesktopModeSitesRoute',
|
name: 'DesktopModeSitesRoute',
|
||||||
path: 'desktop_mode_sites',
|
path: 'desktop_mode_sites',
|
||||||
@@ -354,6 +358,19 @@ class ContextualToolbarSettingsRoute extends GoRouteData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QuickSwitcherToolbarSettingsRoute extends GoRouteData
|
||||||
|
with $QuickSwitcherToolbarSettingsRoute {
|
||||||
|
const QuickSwitcherToolbarSettingsRoute();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, GoRouterState state) {
|
||||||
|
return const ContextualToolbarSettingsScreen(
|
||||||
|
location: ToolbarConfigLocation.quickSwitcher,
|
||||||
|
title: 'Customize Switcher Buttons',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class DesktopModeSitesRoute extends GoRouteData with $DesktopModeSitesRoute {
|
class DesktopModeSitesRoute extends GoRouteData with $DesktopModeSitesRoute {
|
||||||
const DesktopModeSitesRoute();
|
const DesktopModeSitesRoute();
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ final class TabRepositoryProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$tabRepositoryHash() => r'dd2f9c776be1d5437141e94dbd0b7ef382093b63';
|
String _$tabRepositoryHash() => r'749b131347685933ac36a3afcdd49f7def7155a9';
|
||||||
|
|
||||||
abstract class _$TabRepository extends $Notifier<void> {
|
abstract class _$TabRepository extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
+35
-12
@@ -21,14 +21,17 @@
|
|||||||
import 'package:fast_equatable/fast_equatable.dart';
|
import 'package:fast_equatable/fast_equatable.dart';
|
||||||
import 'package:lexo_rank/lexo_rank.dart';
|
import 'package:lexo_rank/lexo_rank.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/contextual_toolbar_config_repository.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/toolbar_button_config_repository.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
||||||
show ToolbarButtonConfig;
|
show ToolbarButtonConfig;
|
||||||
|
|
||||||
part 'toolbar_button_configs.g.dart';
|
part 'toolbar_button_configs.g.dart';
|
||||||
|
|
||||||
List<ToolbarButtonConfig> _buildDefaultToolbarButtonConfigs() {
|
List<ToolbarButtonConfig> _buildDefaultToolbarButtonConfigs({
|
||||||
|
required bool allHidden,
|
||||||
|
}) {
|
||||||
String? lastKey;
|
String? lastKey;
|
||||||
|
|
||||||
return toolbarButtonSpecs.map((spec) {
|
return toolbarButtonSpecs.map((spec) {
|
||||||
@@ -41,19 +44,38 @@ List<ToolbarButtonConfig> _buildDefaultToolbarButtonConfigs() {
|
|||||||
return ToolbarButtonConfig(
|
return ToolbarButtonConfig(
|
||||||
buttonId: spec.id.name,
|
buttonId: spec.id.name,
|
||||||
orderKey: key,
|
orderKey: key,
|
||||||
isVisible: spec.defaultVisible,
|
isVisible: allHidden ? false : spec.defaultVisible,
|
||||||
fallbackId: spec.defaultFallback?.name,
|
fallbackId: allHidden ? null : spec.defaultFallback?.name,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
final defaultToolbarButtonConfigs = EquatableValue(
|
final _contextualDefaultConfigs = EquatableValue(
|
||||||
_buildDefaultToolbarButtonConfigs(),
|
_buildDefaultToolbarButtonConfigs(allHidden: false),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final _quickSwitcherDefaultConfigs = EquatableValue(
|
||||||
|
_buildDefaultToolbarButtonConfigs(allHidden: true),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Default configuration set for [location], used as the reset target and as the
|
||||||
|
/// fallback while the persisted set is still loading. The quick switcher starts
|
||||||
|
/// with every button hidden.
|
||||||
|
EquatableValue<List<ToolbarButtonConfig>> defaultToolbarButtonConfigsFor(
|
||||||
|
ToolbarConfigLocation location,
|
||||||
|
) {
|
||||||
|
return switch (location) {
|
||||||
|
ToolbarConfigLocation.contextual => _contextualDefaultConfigs,
|
||||||
|
ToolbarConfigLocation.quickSwitcher => _quickSwitcherDefaultConfigs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
Stream<List<ToolbarButtonConfig>> toolbarButtonConfigs(Ref ref) async* {
|
Stream<List<ToolbarButtonConfig>> toolbarButtonConfigs(
|
||||||
final repository = ref.watch(contextualToolbarConfigRepositoryProvider);
|
Ref ref,
|
||||||
|
ToolbarConfigLocation location,
|
||||||
|
) async* {
|
||||||
|
final repository = ref.watch(toolbarConfigRepositoryProvider(location));
|
||||||
await repository.seedMissingDefaults();
|
await repository.seedMissingDefaults();
|
||||||
yield* repository.watchAll();
|
yield* repository.watchAll();
|
||||||
}
|
}
|
||||||
@@ -61,8 +83,9 @@ Stream<List<ToolbarButtonConfig>> toolbarButtonConfigs(Ref ref) async* {
|
|||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
EquatableValue<List<ToolbarButtonConfig>> effectiveToolbarButtonConfigs(
|
EquatableValue<List<ToolbarButtonConfig>> effectiveToolbarButtonConfigs(
|
||||||
Ref ref,
|
Ref ref,
|
||||||
|
ToolbarConfigLocation location,
|
||||||
) {
|
) {
|
||||||
final configsAsync = ref.watch(toolbarButtonConfigsProvider);
|
final configsAsync = ref.watch(toolbarButtonConfigsProvider(location));
|
||||||
|
|
||||||
return configsAsync.when(
|
return configsAsync.when(
|
||||||
data: (configs) {
|
data: (configs) {
|
||||||
@@ -71,12 +94,12 @@ EquatableValue<List<ToolbarButtonConfig>> effectiveToolbarButtonConfigs(
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (filtered.isEmpty) {
|
if (filtered.isEmpty) {
|
||||||
return defaultToolbarButtonConfigs;
|
return defaultToolbarButtonConfigsFor(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EquatableValue(filtered);
|
return EquatableValue(filtered);
|
||||||
},
|
},
|
||||||
loading: () => defaultToolbarButtonConfigs,
|
loading: () => defaultToolbarButtonConfigsFor(location),
|
||||||
error: (_, _) => defaultToolbarButtonConfigs,
|
error: (_, _) => defaultToolbarButtonConfigsFor(location),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+107
-26
@@ -10,7 +10,7 @@ part of 'toolbar_button_configs.dart';
|
|||||||
// ignore_for_file: type=lint, type=warning
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
@ProviderFor(toolbarButtonConfigs)
|
@ProviderFor(toolbarButtonConfigs)
|
||||||
final toolbarButtonConfigsProvider = ToolbarButtonConfigsProvider._();
|
final toolbarButtonConfigsProvider = ToolbarButtonConfigsFamily._();
|
||||||
|
|
||||||
final class ToolbarButtonConfigsProvider
|
final class ToolbarButtonConfigsProvider
|
||||||
extends
|
extends
|
||||||
@@ -22,20 +22,27 @@ final class ToolbarButtonConfigsProvider
|
|||||||
with
|
with
|
||||||
$FutureModifier<List<ToolbarButtonConfig>>,
|
$FutureModifier<List<ToolbarButtonConfig>>,
|
||||||
$StreamProvider<List<ToolbarButtonConfig>> {
|
$StreamProvider<List<ToolbarButtonConfig>> {
|
||||||
ToolbarButtonConfigsProvider._()
|
ToolbarButtonConfigsProvider._({
|
||||||
: super(
|
required ToolbarButtonConfigsFamily super.from,
|
||||||
from: null,
|
required ToolbarConfigLocation super.argument,
|
||||||
argument: null,
|
}) : super(
|
||||||
retry: null,
|
retry: null,
|
||||||
name: r'toolbarButtonConfigsProvider',
|
name: r'toolbarButtonConfigsProvider',
|
||||||
isAutoDispose: false,
|
isAutoDispose: false,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
$allTransitiveDependencies: null,
|
$allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String debugGetCreateSourceHash() => _$toolbarButtonConfigsHash();
|
String debugGetCreateSourceHash() => _$toolbarButtonConfigsHash();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return r'toolbarButtonConfigsProvider'
|
||||||
|
''
|
||||||
|
'($argument)';
|
||||||
|
}
|
||||||
|
|
||||||
@$internal
|
@$internal
|
||||||
@override
|
@override
|
||||||
$StreamProviderElement<List<ToolbarButtonConfig>> $createElement(
|
$StreamProviderElement<List<ToolbarButtonConfig>> $createElement(
|
||||||
@@ -44,16 +51,49 @@ final class ToolbarButtonConfigsProvider
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<List<ToolbarButtonConfig>> create(Ref ref) {
|
Stream<List<ToolbarButtonConfig>> create(Ref ref) {
|
||||||
return toolbarButtonConfigs(ref);
|
final argument = this.argument as ToolbarConfigLocation;
|
||||||
|
return toolbarButtonConfigs(ref, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is ToolbarButtonConfigsProvider && other.argument == argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return argument.hashCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$toolbarButtonConfigsHash() =>
|
String _$toolbarButtonConfigsHash() =>
|
||||||
r'02f79c2087a3a5413fe879405c05f4a4d1eaffeb';
|
r'913d2c8ca3b8b3f39f2247cafac068dc26abc566';
|
||||||
|
|
||||||
|
final class ToolbarButtonConfigsFamily extends $Family
|
||||||
|
with
|
||||||
|
$FunctionalFamilyOverride<
|
||||||
|
Stream<List<ToolbarButtonConfig>>,
|
||||||
|
ToolbarConfigLocation
|
||||||
|
> {
|
||||||
|
ToolbarButtonConfigsFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'toolbarButtonConfigsProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
ToolbarButtonConfigsProvider call(ToolbarConfigLocation location) =>
|
||||||
|
ToolbarButtonConfigsProvider._(argument: location, from: this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => r'toolbarButtonConfigsProvider';
|
||||||
|
}
|
||||||
|
|
||||||
@ProviderFor(effectiveToolbarButtonConfigs)
|
@ProviderFor(effectiveToolbarButtonConfigs)
|
||||||
final effectiveToolbarButtonConfigsProvider =
|
final effectiveToolbarButtonConfigsProvider =
|
||||||
EffectiveToolbarButtonConfigsProvider._();
|
EffectiveToolbarButtonConfigsFamily._();
|
||||||
|
|
||||||
final class EffectiveToolbarButtonConfigsProvider
|
final class EffectiveToolbarButtonConfigsProvider
|
||||||
extends
|
extends
|
||||||
@@ -63,20 +103,27 @@ final class EffectiveToolbarButtonConfigsProvider
|
|||||||
EquatableValue<List<ToolbarButtonConfig>>
|
EquatableValue<List<ToolbarButtonConfig>>
|
||||||
>
|
>
|
||||||
with $Provider<EquatableValue<List<ToolbarButtonConfig>>> {
|
with $Provider<EquatableValue<List<ToolbarButtonConfig>>> {
|
||||||
EffectiveToolbarButtonConfigsProvider._()
|
EffectiveToolbarButtonConfigsProvider._({
|
||||||
: super(
|
required EffectiveToolbarButtonConfigsFamily super.from,
|
||||||
from: null,
|
required ToolbarConfigLocation super.argument,
|
||||||
argument: null,
|
}) : super(
|
||||||
retry: null,
|
retry: null,
|
||||||
name: r'effectiveToolbarButtonConfigsProvider',
|
name: r'effectiveToolbarButtonConfigsProvider',
|
||||||
isAutoDispose: false,
|
isAutoDispose: false,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
$allTransitiveDependencies: null,
|
$allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String debugGetCreateSourceHash() => _$effectiveToolbarButtonConfigsHash();
|
String debugGetCreateSourceHash() => _$effectiveToolbarButtonConfigsHash();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return r'effectiveToolbarButtonConfigsProvider'
|
||||||
|
''
|
||||||
|
'($argument)';
|
||||||
|
}
|
||||||
|
|
||||||
@$internal
|
@$internal
|
||||||
@override
|
@override
|
||||||
$ProviderElement<EquatableValue<List<ToolbarButtonConfig>>> $createElement(
|
$ProviderElement<EquatableValue<List<ToolbarButtonConfig>>> $createElement(
|
||||||
@@ -85,7 +132,8 @@ final class EffectiveToolbarButtonConfigsProvider
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
EquatableValue<List<ToolbarButtonConfig>> create(Ref ref) {
|
EquatableValue<List<ToolbarButtonConfig>> create(Ref ref) {
|
||||||
return effectiveToolbarButtonConfigs(ref);
|
final argument = this.argument as ToolbarConfigLocation;
|
||||||
|
return effectiveToolbarButtonConfigs(ref, argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// {@macro riverpod.override_with_value}
|
/// {@macro riverpod.override_with_value}
|
||||||
@@ -96,7 +144,40 @@ final class EffectiveToolbarButtonConfigsProvider
|
|||||||
$SyncValueProvider<EquatableValue<List<ToolbarButtonConfig>>>(value),
|
$SyncValueProvider<EquatableValue<List<ToolbarButtonConfig>>>(value),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is EffectiveToolbarButtonConfigsProvider &&
|
||||||
|
other.argument == argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return argument.hashCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$effectiveToolbarButtonConfigsHash() =>
|
String _$effectiveToolbarButtonConfigsHash() =>
|
||||||
r'dd876160f586c64237a42a29eb63cb119f962b02';
|
r'6cd77c8af6df8943db6778b5222bb6ae9fb40025';
|
||||||
|
|
||||||
|
final class EffectiveToolbarButtonConfigsFamily extends $Family
|
||||||
|
with
|
||||||
|
$FunctionalFamilyOverride<
|
||||||
|
EquatableValue<List<ToolbarButtonConfig>>,
|
||||||
|
ToolbarConfigLocation
|
||||||
|
> {
|
||||||
|
EffectiveToolbarButtonConfigsFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'effectiveToolbarButtonConfigsProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
EffectiveToolbarButtonConfigsProvider call(ToolbarConfigLocation location) =>
|
||||||
|
EffectiveToolbarButtonConfigsProvider._(argument: location, from: this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => r'effectiveToolbarButtonConfigsProvider';
|
||||||
|
}
|
||||||
|
|||||||
+13
-1
@@ -19,6 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/toolbar_button_config_repository.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart';
|
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart';
|
||||||
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
||||||
@@ -27,37 +28,46 @@ import 'package:weblibre/features/user/data/providers.dart';
|
|||||||
|
|
||||||
part 'contextual_toolbar_config_repository.g.dart';
|
part 'contextual_toolbar_config_repository.g.dart';
|
||||||
|
|
||||||
class ContextualToolbarConfigRepository {
|
class ContextualToolbarConfigRepository
|
||||||
|
implements ToolbarButtonConfigRepository {
|
||||||
ContextualToolbarConfigRepository(this._dao);
|
ContextualToolbarConfigRepository(this._dao);
|
||||||
|
|
||||||
final ToolbarButtonConfigDao _dao;
|
final ToolbarButtonConfigDao _dao;
|
||||||
|
|
||||||
|
@override
|
||||||
Stream<List<ToolbarButtonConfig>> watchAll() => _dao.watchAll();
|
Stream<List<ToolbarButtonConfig>> watchAll() => _dao.watchAll();
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> replaceAll(List<ToolbarButtonConfig> configs) {
|
Future<void> replaceAll(List<ToolbarButtonConfig> configs) {
|
||||||
return _dao.replaceAll(configs);
|
return _dao.replaceAll(configs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> assignOrderKey(String buttonId, {required String orderKey}) {
|
Future<void> assignOrderKey(String buttonId, {required String orderKey}) {
|
||||||
return _dao.assignOrderKey(buttonId, orderKey: orderKey);
|
return _dao.assignOrderKey(buttonId, orderKey: orderKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> assignVisibility(String buttonId, {required bool visible}) {
|
Future<void> assignVisibility(String buttonId, {required bool visible}) {
|
||||||
return _dao.assignVisibility(buttonId, visible: visible);
|
return _dao.assignVisibility(buttonId, visible: visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> assignFallback(String buttonId, String? fallbackId) {
|
Future<void> assignFallback(String buttonId, String? fallbackId) {
|
||||||
return _dao.assignFallback(buttonId, fallbackId);
|
return _dao.assignFallback(buttonId, fallbackId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<String> generateLeadingOrderKey({required bool isVisible}) {
|
Future<String> generateLeadingOrderKey({required bool isVisible}) {
|
||||||
return _dao.generateLeadingOrderKey(isVisible: isVisible).getSingle();
|
return _dao.generateLeadingOrderKey(isVisible: isVisible).getSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<String> generateTrailingOrderKey({required bool isVisible}) {
|
Future<String> generateTrailingOrderKey({required bool isVisible}) {
|
||||||
return _dao.generateTrailingOrderKey(isVisible: isVisible).getSingle();
|
return _dao.generateTrailingOrderKey(isVisible: isVisible).getSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<String?> generateOrderKeyAfterButtonId(
|
Future<String?> generateOrderKeyAfterButtonId(
|
||||||
String buttonId, {
|
String buttonId, {
|
||||||
required bool isVisible,
|
required bool isVisible,
|
||||||
@@ -67,6 +77,7 @@ class ContextualToolbarConfigRepository {
|
|||||||
.getSingleOrNull();
|
.getSingleOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<String> generateOrderKeyBeforeButtonId(
|
Future<String> generateOrderKeyBeforeButtonId(
|
||||||
String buttonId, {
|
String buttonId, {
|
||||||
required bool isVisible,
|
required bool isVisible,
|
||||||
@@ -76,6 +87,7 @@ class ContextualToolbarConfigRepository {
|
|||||||
.getSingle();
|
.getSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
Future<void> seedMissingDefaults() {
|
Future<void> seedMissingDefaults() {
|
||||||
return _dao.seedMissing(
|
return _dao.seedMissing(
|
||||||
toolbarButtonSpecs
|
toolbarButtonSpecs
|
||||||
|
|||||||
+135
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 Fabian Freund.
|
||||||
|
*
|
||||||
|
* This file is part of WebLibre
|
||||||
|
* (see https://weblibre.eu).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/toolbar_button_config_repository.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/daos/quick_switcher_button_config.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
||||||
|
show QuickSwitcherButtonConfig, ToolbarButtonConfig;
|
||||||
|
import 'package:weblibre/features/user/data/providers.dart';
|
||||||
|
|
||||||
|
part 'quick_switcher_toolbar_config_repository.g.dart';
|
||||||
|
|
||||||
|
/// Quick tab switcher counterpart to [ContextualToolbarConfigRepository]. Backed
|
||||||
|
/// by the separate `quick_switcher_button_configs` table and mapping its row
|
||||||
|
/// type to the shared [ToolbarButtonConfig] transport type.
|
||||||
|
class QuickSwitcherToolbarConfigRepository
|
||||||
|
implements ToolbarButtonConfigRepository {
|
||||||
|
QuickSwitcherToolbarConfigRepository(this._dao);
|
||||||
|
|
||||||
|
final QuickSwitcherButtonConfigDao _dao;
|
||||||
|
|
||||||
|
ToolbarButtonConfig _toShared(QuickSwitcherButtonConfig config) =>
|
||||||
|
ToolbarButtonConfig(
|
||||||
|
buttonId: config.buttonId,
|
||||||
|
orderKey: config.orderKey,
|
||||||
|
isVisible: config.isVisible,
|
||||||
|
fallbackId: config.fallbackId,
|
||||||
|
);
|
||||||
|
|
||||||
|
QuickSwitcherButtonConfig _fromShared(ToolbarButtonConfig config) =>
|
||||||
|
QuickSwitcherButtonConfig(
|
||||||
|
buttonId: config.buttonId,
|
||||||
|
orderKey: config.orderKey,
|
||||||
|
isVisible: config.isVisible,
|
||||||
|
fallbackId: config.fallbackId,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<List<ToolbarButtonConfig>> watchAll() =>
|
||||||
|
_dao.watchAll().map((rows) => rows.map(_toShared).toList());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> replaceAll(List<ToolbarButtonConfig> configs) {
|
||||||
|
return _dao.replaceAll(configs.map(_fromShared).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> assignOrderKey(String buttonId, {required String orderKey}) {
|
||||||
|
return _dao.assignOrderKey(buttonId, orderKey: orderKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> assignVisibility(String buttonId, {required bool visible}) {
|
||||||
|
return _dao.assignVisibility(buttonId, visible: visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> assignFallback(String buttonId, String? fallbackId) {
|
||||||
|
return _dao.assignFallback(buttonId, fallbackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> generateLeadingOrderKey({required bool isVisible}) {
|
||||||
|
return _dao.generateLeadingOrderKey(isVisible: isVisible).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> generateTrailingOrderKey({required bool isVisible}) {
|
||||||
|
return _dao.generateTrailingOrderKey(isVisible: isVisible).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> generateOrderKeyAfterButtonId(
|
||||||
|
String buttonId, {
|
||||||
|
required bool isVisible,
|
||||||
|
}) {
|
||||||
|
return _dao
|
||||||
|
.generateOrderKeyAfterButtonId(buttonId, isVisible: isVisible)
|
||||||
|
.getSingleOrNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> generateOrderKeyBeforeButtonId(
|
||||||
|
String buttonId, {
|
||||||
|
required bool isVisible,
|
||||||
|
}) {
|
||||||
|
return _dao
|
||||||
|
.generateOrderKeyBeforeButtonId(buttonId, isVisible: isVisible)
|
||||||
|
.getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> seedMissingDefaults() {
|
||||||
|
// The quick switcher cluster starts empty: every known button is seeded
|
||||||
|
// hidden with no fallback, so nothing renders until the user enables it.
|
||||||
|
return _dao.seedMissing(
|
||||||
|
toolbarButtonSpecs
|
||||||
|
.map(
|
||||||
|
(spec) => (
|
||||||
|
buttonId: spec.id.name,
|
||||||
|
defaultVisible: false,
|
||||||
|
defaultFallback: null,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
QuickSwitcherToolbarConfigRepository quickSwitcherToolbarConfigRepository(
|
||||||
|
Ref ref,
|
||||||
|
) {
|
||||||
|
return QuickSwitcherToolbarConfigRepository(
|
||||||
|
ref.watch(userDatabaseProvider).quickSwitcherButtonConfigDao,
|
||||||
|
);
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'quick_switcher_toolbar_config_repository.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(quickSwitcherToolbarConfigRepository)
|
||||||
|
final quickSwitcherToolbarConfigRepositoryProvider =
|
||||||
|
QuickSwitcherToolbarConfigRepositoryProvider._();
|
||||||
|
|
||||||
|
final class QuickSwitcherToolbarConfigRepositoryProvider
|
||||||
|
extends
|
||||||
|
$FunctionalProvider<
|
||||||
|
QuickSwitcherToolbarConfigRepository,
|
||||||
|
QuickSwitcherToolbarConfigRepository,
|
||||||
|
QuickSwitcherToolbarConfigRepository
|
||||||
|
>
|
||||||
|
with $Provider<QuickSwitcherToolbarConfigRepository> {
|
||||||
|
QuickSwitcherToolbarConfigRepositoryProvider._()
|
||||||
|
: super(
|
||||||
|
from: null,
|
||||||
|
argument: null,
|
||||||
|
retry: null,
|
||||||
|
name: r'quickSwitcherToolbarConfigRepositoryProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() =>
|
||||||
|
_$quickSwitcherToolbarConfigRepositoryHash();
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<QuickSwitcherToolbarConfigRepository> $createElement(
|
||||||
|
$ProviderPointer pointer,
|
||||||
|
) => $ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
QuickSwitcherToolbarConfigRepository create(Ref ref) {
|
||||||
|
return quickSwitcherToolbarConfigRepository(ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(QuickSwitcherToolbarConfigRepository value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride:
|
||||||
|
$SyncValueProvider<QuickSwitcherToolbarConfigRepository>(value),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$quickSwitcherToolbarConfigRepositoryHash() =>
|
||||||
|
r'5459350ebde214186e882d8316e66d438c6913d8';
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 Fabian Freund.
|
||||||
|
*
|
||||||
|
* This file is part of WebLibre
|
||||||
|
* (see https://weblibre.eu).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/contextual_toolbar_config_repository.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/quick_switcher_toolbar_config_repository.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/definitions.drift.dart'
|
||||||
|
show ToolbarButtonConfig;
|
||||||
|
|
||||||
|
part 'toolbar_button_config_repository.g.dart';
|
||||||
|
|
||||||
|
/// Shared contract for a single toolbar button configuration set. Both the
|
||||||
|
/// contextual toolbar and the quick tab switcher cluster persist to their own
|
||||||
|
/// table but expose this same interface, so the resolution logic, providers and
|
||||||
|
/// customization UI are location-agnostic. [ToolbarButtonConfig] (the contextual
|
||||||
|
/// drift row) is used as the shared transport type; the quick switcher
|
||||||
|
/// repository maps its own row type at the boundary.
|
||||||
|
abstract interface class ToolbarButtonConfigRepository {
|
||||||
|
Stream<List<ToolbarButtonConfig>> watchAll();
|
||||||
|
|
||||||
|
Future<void> replaceAll(List<ToolbarButtonConfig> configs);
|
||||||
|
|
||||||
|
Future<void> assignOrderKey(String buttonId, {required String orderKey});
|
||||||
|
|
||||||
|
Future<void> assignVisibility(String buttonId, {required bool visible});
|
||||||
|
|
||||||
|
Future<void> assignFallback(String buttonId, String? fallbackId);
|
||||||
|
|
||||||
|
Future<String> generateLeadingOrderKey({required bool isVisible});
|
||||||
|
|
||||||
|
Future<String> generateTrailingOrderKey({required bool isVisible});
|
||||||
|
|
||||||
|
Future<String?> generateOrderKeyAfterButtonId(
|
||||||
|
String buttonId, {
|
||||||
|
required bool isVisible,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<String> generateOrderKeyBeforeButtonId(
|
||||||
|
String buttonId, {
|
||||||
|
required bool isVisible,
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> seedMissingDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
ToolbarButtonConfigRepository toolbarConfigRepository(
|
||||||
|
Ref ref,
|
||||||
|
ToolbarConfigLocation location,
|
||||||
|
) {
|
||||||
|
return switch (location) {
|
||||||
|
ToolbarConfigLocation.contextual => ref.watch(
|
||||||
|
contextualToolbarConfigRepositoryProvider,
|
||||||
|
),
|
||||||
|
ToolbarConfigLocation.quickSwitcher => ref.watch(
|
||||||
|
quickSwitcherToolbarConfigRepositoryProvider,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'toolbar_button_config_repository.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint, type=warning
|
||||||
|
|
||||||
|
@ProviderFor(toolbarConfigRepository)
|
||||||
|
final toolbarConfigRepositoryProvider = ToolbarConfigRepositoryFamily._();
|
||||||
|
|
||||||
|
final class ToolbarConfigRepositoryProvider
|
||||||
|
extends
|
||||||
|
$FunctionalProvider<
|
||||||
|
ToolbarButtonConfigRepository,
|
||||||
|
ToolbarButtonConfigRepository,
|
||||||
|
ToolbarButtonConfigRepository
|
||||||
|
>
|
||||||
|
with $Provider<ToolbarButtonConfigRepository> {
|
||||||
|
ToolbarConfigRepositoryProvider._({
|
||||||
|
required ToolbarConfigRepositoryFamily super.from,
|
||||||
|
required ToolbarConfigLocation super.argument,
|
||||||
|
}) : super(
|
||||||
|
retry: null,
|
||||||
|
name: r'toolbarConfigRepositoryProvider',
|
||||||
|
isAutoDispose: false,
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String debugGetCreateSourceHash() => _$toolbarConfigRepositoryHash();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return r'toolbarConfigRepositoryProvider'
|
||||||
|
''
|
||||||
|
'($argument)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@$internal
|
||||||
|
@override
|
||||||
|
$ProviderElement<ToolbarButtonConfigRepository> $createElement(
|
||||||
|
$ProviderPointer pointer,
|
||||||
|
) => $ProviderElement(pointer);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ToolbarButtonConfigRepository create(Ref ref) {
|
||||||
|
final argument = this.argument as ToolbarConfigLocation;
|
||||||
|
return toolbarConfigRepository(ref, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// {@macro riverpod.override_with_value}
|
||||||
|
Override overrideWithValue(ToolbarButtonConfigRepository value) {
|
||||||
|
return $ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
providerOverride: $SyncValueProvider<ToolbarButtonConfigRepository>(
|
||||||
|
value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is ToolbarConfigRepositoryProvider &&
|
||||||
|
other.argument == argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return argument.hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$toolbarConfigRepositoryHash() =>
|
||||||
|
r'47129b30f01db6ea73d553a8fd1b4f6e8a7b4a3c';
|
||||||
|
|
||||||
|
final class ToolbarConfigRepositoryFamily extends $Family
|
||||||
|
with
|
||||||
|
$FunctionalFamilyOverride<
|
||||||
|
ToolbarButtonConfigRepository,
|
||||||
|
ToolbarConfigLocation
|
||||||
|
> {
|
||||||
|
ToolbarConfigRepositoryFamily._()
|
||||||
|
: super(
|
||||||
|
retry: null,
|
||||||
|
name: r'toolbarConfigRepositoryProvider',
|
||||||
|
dependencies: null,
|
||||||
|
$allTransitiveDependencies: null,
|
||||||
|
isAutoDispose: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
ToolbarConfigRepositoryProvider call(ToolbarConfigLocation location) =>
|
||||||
|
ToolbarConfigRepositoryProvider._(argument: location, from: this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => r'toolbarConfigRepositoryProvider';
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 Fabian Freund.
|
||||||
|
*
|
||||||
|
* This file is part of WebLibre
|
||||||
|
* (see https://weblibre.eu).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// Identifies which independently-configured toolbar a button configuration
|
||||||
|
/// belongs to. Each location persists its own enabled set, ordering and
|
||||||
|
/// fallbacks (backed by a separate drift table) while sharing the button
|
||||||
|
/// registry, resolution logic and customization UI.
|
||||||
|
enum ToolbarConfigLocation {
|
||||||
|
/// The contextual toolbar row that sits below the URL bar.
|
||||||
|
contextual,
|
||||||
|
|
||||||
|
/// The trailing fixed button cluster on the quick tab switcher bar.
|
||||||
|
quickSwitcher,
|
||||||
|
}
|
||||||
+8
@@ -20,6 +20,7 @@
|
|||||||
import 'package:fast_equatable/fast_equatable.dart';
|
import 'package:fast_equatable/fast_equatable.dart';
|
||||||
import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart';
|
import 'package:weblibre/features/geckoview/domain/entities/states/tab.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/domain/entities/sheet.dart';
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
|
|
||||||
class ContextualToolbarScope with FastEquatable {
|
class ContextualToolbarScope with FastEquatable {
|
||||||
final String? selectedTabId;
|
final String? selectedTabId;
|
||||||
@@ -27,11 +28,17 @@ class ContextualToolbarScope with FastEquatable {
|
|||||||
final TabState? tabState;
|
final TabState? tabState;
|
||||||
final bool isPreview;
|
final bool isPreview;
|
||||||
|
|
||||||
|
/// Which configuration set this scope renders for, so shared registry
|
||||||
|
/// builders that read sibling button config (e.g. the back button's
|
||||||
|
/// stop-loading fallback) consult the correct location.
|
||||||
|
final ToolbarConfigLocation location;
|
||||||
|
|
||||||
ContextualToolbarScope({
|
ContextualToolbarScope({
|
||||||
required this.selectedTabId,
|
required this.selectedTabId,
|
||||||
required this.displayedSheet,
|
required this.displayedSheet,
|
||||||
required this.tabState,
|
required this.tabState,
|
||||||
required this.isPreview,
|
required this.isPreview,
|
||||||
|
this.location = ToolbarConfigLocation.contextual,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -40,5 +47,6 @@ class ContextualToolbarScope with FastEquatable {
|
|||||||
displayedSheet,
|
displayedSheet,
|
||||||
tabState,
|
tabState,
|
||||||
isPreview,
|
isPreview,
|
||||||
|
location,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -37,6 +37,7 @@ import 'package:weblibre/features/geckoview/features/browser/domain/entities/fon
|
|||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/utils/tab_close_confirmation.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/utils/tab_close_confirmation.dart';
|
||||||
@@ -85,12 +86,12 @@ class ToolbarButtonDefinition {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a reload button is currently configured visible in the contextual
|
/// Whether a reload button is currently configured visible in [location]'s
|
||||||
/// toolbar. Used to decide whether the back button should fall back to acting
|
/// toolbar. Used to decide whether the back button should fall back to acting
|
||||||
/// as a stop-loading control (see issue #351).
|
/// as a stop-loading control (see issue #351).
|
||||||
bool _isReloadButtonVisible(WidgetRef ref) {
|
bool _isReloadButtonVisible(WidgetRef ref, ToolbarConfigLocation location) {
|
||||||
return ref
|
return ref
|
||||||
.read(effectiveToolbarButtonConfigsProvider)
|
.read(effectiveToolbarButtonConfigsProvider(location))
|
||||||
.value
|
.value
|
||||||
.any(
|
.any(
|
||||||
(config) =>
|
(config) =>
|
||||||
@@ -108,7 +109,8 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
|||||||
final isLoading = scope.tabState?.isLoading == true;
|
final isLoading = scope.tabState?.isLoading == true;
|
||||||
// The back button only doubles as a stop-loading control when no
|
// The back button only doubles as a stop-loading control when no
|
||||||
// dedicated reload button is present to take over that role.
|
// dedicated reload button is present to take over that role.
|
||||||
return canGoBack || (isLoading && !_isReloadButtonVisible(ref));
|
return canGoBack ||
|
||||||
|
(isLoading && !_isReloadButtonVisible(ref, scope.location));
|
||||||
},
|
},
|
||||||
longPressActions: ['History Menu (Previous pages)'],
|
longPressActions: ['History Menu (Previous pages)'],
|
||||||
builder: (scope, context, ref) {
|
builder: (scope, context, ref) {
|
||||||
@@ -123,7 +125,7 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
|||||||
return NavigateBackButton(
|
return NavigateBackButton(
|
||||||
selectedTabId: scope.selectedTabId,
|
selectedTabId: scope.selectedTabId,
|
||||||
isLoading: scope.tabState?.isLoading ?? false,
|
isLoading: scope.tabState?.isLoading ?? false,
|
||||||
stopLoadingFallback: !_isReloadButtonVisible(ref),
|
stopLoadingFallback: !_isReloadButtonVisible(ref, scope.location),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
+5
-5
@@ -25,6 +25,7 @@ import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart';
|
|||||||
import 'package:weblibre/features/geckoview/features/browser/domain/entities/sheet.dart';
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/services/toolbar_button_resolution.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/services/toolbar_button_resolution.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart';
|
||||||
@@ -47,7 +48,9 @@ class ContextualToolbar extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final tabState = ref.watch(tabStateProvider(selectedTabId));
|
final tabState = ref.watch(tabStateProvider(selectedTabId));
|
||||||
final configs = ref.watch(effectiveToolbarButtonConfigsProvider);
|
final configs = ref.watch(
|
||||||
|
effectiveToolbarButtonConfigsProvider(ToolbarConfigLocation.contextual),
|
||||||
|
);
|
||||||
|
|
||||||
final scope = ContextualToolbarScope(
|
final scope = ContextualToolbarScope(
|
||||||
selectedTabId: selectedTabId,
|
selectedTabId: selectedTabId,
|
||||||
@@ -143,10 +146,7 @@ class ContextualToolbarView extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
for (final button in buttons)
|
for (final button in buttons)
|
||||||
UnconstrainedBox(
|
UnconstrainedBox(constrainedAxis: Axis.vertical, child: button),
|
||||||
constrainedAxis: Axis.vertical,
|
|
||||||
child: button,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
+143
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 Fabian Freund.
|
||||||
|
*
|
||||||
|
* This file is part of WebLibre
|
||||||
|
* (see https://weblibre.eu).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/domain/providers/tab_state.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/sheet.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/services/toolbar_button_resolution.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart';
|
||||||
|
|
||||||
|
/// The switcher bar's cross-axis extent (height when horizontal, width on the
|
||||||
|
/// side rail). Mirrors `BrowserTabBar.quickTabSwitcherHeight`; kept as a local
|
||||||
|
/// const to avoid a circular import with the bar widget that hosts this row.
|
||||||
|
const double _switcherExtent = 48.0;
|
||||||
|
|
||||||
|
/// Trailing fixed button cluster for the quick tab switcher bar. Reuses the
|
||||||
|
/// contextual toolbar's button registry and resolution logic against the
|
||||||
|
/// independently-persisted [ToolbarConfigLocation.quickSwitcher] configuration.
|
||||||
|
///
|
||||||
|
/// Pins to the trailing end of the bar while the tab chips keep the remaining
|
||||||
|
/// scrollable space. Each button is scaled to fit the bar's cross-axis extent
|
||||||
|
/// (reused [ToolbarButton]s are taller than the 48px bar), and the cluster
|
||||||
|
/// scrolls along the bar axis so enabling many buttons can never overflow — the
|
||||||
|
/// hosting bar additionally caps how much room the cluster may claim. Renders
|
||||||
|
/// nothing when no buttons are enabled.
|
||||||
|
class QuickSwitcherButtonRow extends HookConsumerWidget {
|
||||||
|
const QuickSwitcherButtonRow({
|
||||||
|
super.key,
|
||||||
|
required this.selectedTabId,
|
||||||
|
required this.displayedSheet,
|
||||||
|
this.axis = Axis.horizontal,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? selectedTabId;
|
||||||
|
final Sheet? displayedSheet;
|
||||||
|
|
||||||
|
/// Layout direction of the switcher bar; vertical for the side rail.
|
||||||
|
final Axis axis;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final tabState = ref.watch(tabStateProvider(selectedTabId));
|
||||||
|
final configs = ref.watch(
|
||||||
|
effectiveToolbarButtonConfigsProvider(
|
||||||
|
ToolbarConfigLocation.quickSwitcher,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final scope = ContextualToolbarScope(
|
||||||
|
selectedTabId: selectedTabId,
|
||||||
|
displayedSheet: displayedSheet,
|
||||||
|
tabState: tabState,
|
||||||
|
isPreview: false,
|
||||||
|
location: ToolbarConfigLocation.quickSwitcher,
|
||||||
|
);
|
||||||
|
|
||||||
|
final resolvedButtons = useMemoized(
|
||||||
|
() => resolveVisibleContextualToolbarButtons(
|
||||||
|
configs: configs.value,
|
||||||
|
knownButtonIds: knownToolbarButtonIds,
|
||||||
|
isPrimaryAvailable: (buttonId) {
|
||||||
|
final def = toolbarButtonRegistryById[buttonId];
|
||||||
|
return def?.isPrimaryAvailable?.call(scope, ref) ?? true;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[configs, scope],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (resolvedButtons.isEmpty) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
|
||||||
|
final isVertical = axis == Axis.vertical;
|
||||||
|
|
||||||
|
final buttons = resolvedButtons
|
||||||
|
.map((button) => _buildButton(scope, context, ref, button))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// Bound each button to the bar's cross-axis extent and scale down (never
|
||||||
|
// clip) so a taller [ToolbarButton] can't overflow the switcher bar.
|
||||||
|
final fittedButtons = [
|
||||||
|
for (final button in buttons)
|
||||||
|
SizedBox(
|
||||||
|
height: isVertical ? null : _switcherExtent,
|
||||||
|
width: isVertical ? _switcherExtent : null,
|
||||||
|
child: FittedBox(fit: BoxFit.scaleDown, child: button),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Scroll along the bar axis: the host caps the cluster's main-axis extent,
|
||||||
|
// and anything beyond that scrolls instead of stealing the chips' space.
|
||||||
|
return SizedBox(
|
||||||
|
height: isVertical ? null : _switcherExtent,
|
||||||
|
width: isVertical ? _switcherExtent : null,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: axis,
|
||||||
|
child: isVertical
|
||||||
|
? Column(mainAxisSize: MainAxisSize.min, children: fittedButtons)
|
||||||
|
: Row(mainAxisSize: MainAxisSize.min, children: fittedButtons),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildButton(
|
||||||
|
ContextualToolbarScope scope,
|
||||||
|
BuildContext context,
|
||||||
|
WidgetRef ref,
|
||||||
|
ContextualToolbarButtonResolution button,
|
||||||
|
) {
|
||||||
|
final def = toolbarButtonRegistryById[button.buttonId];
|
||||||
|
if (def == null) return const SizedBox.shrink();
|
||||||
|
|
||||||
|
final child = def.builder(scope, context, ref);
|
||||||
|
|
||||||
|
if (button.isEnabled) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Opacity(opacity: 0.38, child: IgnorePointer(child: child));
|
||||||
|
}
|
||||||
|
}
|
||||||
+121
-46
@@ -36,8 +36,10 @@ import 'package:weblibre/features/geckoview/features/browser/domain/entities/she
|
|||||||
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
|
import 'package:weblibre/features/geckoview/features/browser/domain/providers.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_toolbar.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_toolbar.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/quick_switcher_button_row.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/controllers/tab_view_controllers.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/controllers/tab_view_controllers.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/controllers/toolbar_visibility.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/controllers/toolbar_visibility.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/presentation/utils/close_tab_helper.dart';
|
import 'package:weblibre/features/geckoview/features/browser/presentation/utils/close_tab_helper.dart';
|
||||||
@@ -188,7 +190,8 @@ class BrowserSideRail extends ConsumerWidget {
|
|||||||
quickTabSwitcherRowCount: quickTabSwitcherRowCount,
|
quickTabSwitcherRowCount: quickTabSwitcherRowCount,
|
||||||
isSmallWebMode: isSmallWebMode,
|
isSmallWebMode: isSmallWebMode,
|
||||||
enableGestures: true,
|
enableGestures: true,
|
||||||
hideMainToolbarButtonsDuplicatedInContextualToolbar: showContextualToolbar,
|
hideMainToolbarButtonsDuplicatedInContextualToolbar:
|
||||||
|
showContextualToolbar,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +306,11 @@ class BrowserTabBar extends HookConsumerWidget {
|
|||||||
// Determine which buttons are actually visible in the contextual toolbar
|
// Determine which buttons are actually visible in the contextual toolbar
|
||||||
// so we only hide them from the main toolbar when they're genuinely present there.
|
// so we only hide them from the main toolbar when they're genuinely present there.
|
||||||
final contextualConfigs = ref
|
final contextualConfigs = ref
|
||||||
.watch(effectiveToolbarButtonConfigsProvider)
|
.watch(
|
||||||
|
effectiveToolbarButtonConfigsProvider(
|
||||||
|
ToolbarConfigLocation.contextual,
|
||||||
|
),
|
||||||
|
)
|
||||||
.value;
|
.value;
|
||||||
|
|
||||||
final tabsCountInContextual =
|
final tabsCountInContextual =
|
||||||
@@ -449,55 +456,69 @@ class BrowserTabBar extends HookConsumerWidget {
|
|||||||
if (showMainToolbarNavigationButton)
|
if (showMainToolbarNavigationButton)
|
||||||
NavigationMenuButton(selectedTabId: selectedTabId),
|
NavigationMenuButton(selectedTabId: selectedTabId),
|
||||||
],
|
],
|
||||||
quickTabSwitcher: switch (stackingMode) {
|
quickTabSwitcher: _wrapQuickTabSwitcherWithButtonRow(
|
||||||
TabBarStackingMode.disabled => const SizedBox.shrink(),
|
axis: switcherAxis,
|
||||||
TabBarStackingMode.lastUsedTabs => QuickTabSwitcher(
|
// The button row lives on the switcher bar; when stacking is disabled
|
||||||
quickTabSwitcherMode: QuickTabSwitcherMode.lastUsedTabs,
|
// the whole bar is hidden anyway, but skip building it for clarity.
|
||||||
axis: switcherAxis,
|
buttonRow: stackingMode == TabBarStackingMode.disabled
|
||||||
),
|
? null
|
||||||
TabBarStackingMode.containerTabs => QuickTabSwitcher(
|
: QuickSwitcherButtonRow(
|
||||||
quickTabSwitcherMode: QuickTabSwitcherMode.containerTabs,
|
selectedTabId: selectedTabId,
|
||||||
axis: switcherAxis,
|
displayedSheet: displayedSheet,
|
||||||
),
|
axis: switcherAxis,
|
||||||
TabBarStackingMode.accordion => AccordionQuickTabSwitcher(
|
),
|
||||||
axis: switcherAxis,
|
child: switch (stackingMode) {
|
||||||
),
|
TabBarStackingMode.disabled => const SizedBox.shrink(),
|
||||||
// History fallback only on the MRU row, so empty-state history
|
TabBarStackingMode.lastUsedTabs => QuickTabSwitcher(
|
||||||
// chips don't show twice. On the rail the two rows stack as two
|
quickTabSwitcherMode: QuickTabSwitcherMode.lastUsedTabs,
|
||||||
// equal-height vertical lists.
|
axis: switcherAxis,
|
||||||
TabBarStackingMode.twoLevel =>
|
),
|
||||||
isVertical
|
TabBarStackingMode.containerTabs => QuickTabSwitcher(
|
||||||
? Column(
|
quickTabSwitcherMode: QuickTabSwitcherMode.containerTabs,
|
||||||
children: [
|
axis: switcherAxis,
|
||||||
Expanded(
|
),
|
||||||
child: QuickTabSwitcher(
|
TabBarStackingMode.accordion => AccordionQuickTabSwitcher(
|
||||||
|
axis: switcherAxis,
|
||||||
|
),
|
||||||
|
// History fallback only on the MRU row, so empty-state history
|
||||||
|
// chips don't show twice. On the rail the two rows stack as two
|
||||||
|
// equal-height vertical lists.
|
||||||
|
TabBarStackingMode.twoLevel =>
|
||||||
|
isVertical
|
||||||
|
? Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: QuickTabSwitcher(
|
||||||
|
quickTabSwitcherMode:
|
||||||
|
QuickTabSwitcherMode.containerTabs,
|
||||||
|
enableHistoryFallback: false,
|
||||||
|
axis: switcherAxis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: QuickTabSwitcher(
|
||||||
|
quickTabSwitcherMode:
|
||||||
|
QuickTabSwitcherMode.lastUsedTabs,
|
||||||
|
axis: switcherAxis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: const Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
QuickTabSwitcher(
|
||||||
quickTabSwitcherMode:
|
quickTabSwitcherMode:
|
||||||
QuickTabSwitcherMode.containerTabs,
|
QuickTabSwitcherMode.containerTabs,
|
||||||
enableHistoryFallback: false,
|
enableHistoryFallback: false,
|
||||||
axis: switcherAxis,
|
|
||||||
),
|
),
|
||||||
),
|
QuickTabSwitcher(
|
||||||
Expanded(
|
|
||||||
child: QuickTabSwitcher(
|
|
||||||
quickTabSwitcherMode: QuickTabSwitcherMode.lastUsedTabs,
|
quickTabSwitcherMode: QuickTabSwitcherMode.lastUsedTabs,
|
||||||
axis: switcherAxis,
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
)
|
},
|
||||||
: const Column(
|
),
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
QuickTabSwitcher(
|
|
||||||
quickTabSwitcherMode: QuickTabSwitcherMode.containerTabs,
|
|
||||||
enableHistoryFallback: false,
|
|
||||||
),
|
|
||||||
QuickTabSwitcher(
|
|
||||||
quickTabSwitcherMode: QuickTabSwitcherMode.lastUsedTabs,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
},
|
|
||||||
contextualToolbar: ContextualToolbar(
|
contextualToolbar: ContextualToolbar(
|
||||||
selectedTabId: selectedTabId,
|
selectedTabId: selectedTabId,
|
||||||
displayedSheet: displayedSheet,
|
displayedSheet: displayedSheet,
|
||||||
@@ -707,6 +728,58 @@ class BrowserTabBarView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pins [buttonRow] to the trailing end of the quick tab switcher bar (right of
|
||||||
|
/// the horizontal bar / bottom of the side rail) while [child] (the scrollable
|
||||||
|
/// chips) fills the remaining space. The cluster is capped to a fraction of the
|
||||||
|
/// bar so it can never starve the chips; [QuickSwitcherButtonRow] scrolls any
|
||||||
|
/// overflow beyond that cap. [buttonRow] collapses to nothing when no buttons
|
||||||
|
/// are enabled, so the default state is unchanged.
|
||||||
|
Widget _wrapQuickTabSwitcherWithButtonRow({
|
||||||
|
required Axis axis,
|
||||||
|
required Widget? buttonRow,
|
||||||
|
required Widget child,
|
||||||
|
}) {
|
||||||
|
if (buttonRow == null) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never let the button cluster take more than this share of the bar; the tab
|
||||||
|
// chips keep the rest.
|
||||||
|
const maxClusterFraction = 0.6;
|
||||||
|
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
if (axis == Axis.vertical) {
|
||||||
|
final maxExtent = constraints.maxHeight.isFinite
|
||||||
|
? constraints.maxHeight * maxClusterFraction
|
||||||
|
: double.infinity;
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(child: child),
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxHeight: maxExtent),
|
||||||
|
child: buttonRow,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final maxExtent = constraints.maxWidth.isFinite
|
||||||
|
? constraints.maxWidth * maxClusterFraction
|
||||||
|
: double.infinity;
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(child: child),
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: maxExtent),
|
||||||
|
child: buttonRow,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
class QuickTabSwitcher extends HookConsumerWidget {
|
class QuickTabSwitcher extends HookConsumerWidget {
|
||||||
final QuickTabSwitcherMode quickTabSwitcherMode;
|
final QuickTabSwitcherMode quickTabSwitcherMode;
|
||||||
|
|
||||||
@@ -1043,7 +1116,9 @@ class QuickTabSwitcherView extends StatelessWidget {
|
|||||||
// collapse, since the toolbar height already accounts for both rows.
|
// collapse, since the toolbar height already accounts for both rows.
|
||||||
// On the rail the cross-axis width is fixed and the (vertical) list
|
// On the rail the cross-axis width is fixed and the (vertical) list
|
||||||
// fills the available height.
|
// fills the available height.
|
||||||
return _isVertical ? const SizedBox(width: 48) : const SizedBox(height: 48);
|
return _isVertical
|
||||||
|
? const SizedBox(width: 48)
|
||||||
|
: const SizedBox(height: 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ final class TabDataRepositoryProvider
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$tabDataRepositoryHash() => r'5192e4bb2a373bdef4474fb781eaacc64cc35609';
|
String _$tabDataRepositoryHash() => r'cb923fb0723271cd64d66a720dc3e1aed2d86c71';
|
||||||
|
|
||||||
abstract class _$TabDataRepository extends $Notifier<void> {
|
abstract class _$TabDataRepository extends $Notifier<void> {
|
||||||
void build();
|
void build();
|
||||||
|
|||||||
+41
-17
@@ -23,7 +23,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/contextual_toolbar_config_repository.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/repositories/toolbar_button_config_repository.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_config_location.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_fallback_choice.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_fallback_choice.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/toolbar_button_registry.dart';
|
||||||
@@ -33,12 +34,22 @@ import 'package:weblibre/features/settings/presentation/widgets/settings_detail.
|
|||||||
import 'package:weblibre/features/user/data/database/definitions.drift.dart';
|
import 'package:weblibre/features/user/data/database/definitions.drift.dart';
|
||||||
|
|
||||||
class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
||||||
const ContextualToolbarSettingsScreen({super.key});
|
const ContextualToolbarSettingsScreen({
|
||||||
|
super.key,
|
||||||
|
this.location = ToolbarConfigLocation.contextual,
|
||||||
|
this.title = 'Customize Toolbar',
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Which independently-configured toolbar this screen edits.
|
||||||
|
final ToolbarConfigLocation location;
|
||||||
|
|
||||||
|
/// App bar title, so the quick switcher variant reads distinctly.
|
||||||
|
final String title;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final configs = ref.watch(effectiveToolbarButtonConfigsProvider);
|
final configs = ref.watch(effectiveToolbarButtonConfigsProvider(location));
|
||||||
final repository = ref.watch(contextualToolbarConfigRepositoryProvider);
|
final repository = ref.watch(toolbarConfigRepositoryProvider(location));
|
||||||
final search = useSettingsSearch();
|
final search = useSettingsSearch();
|
||||||
final query = search.normalizedQuery;
|
final query = search.normalizedQuery;
|
||||||
|
|
||||||
@@ -69,7 +80,7 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return SettingsCustomScrollScaffold(
|
return SettingsCustomScrollScaffold(
|
||||||
title: 'Customize Toolbar',
|
title: title,
|
||||||
searchController: search.controller,
|
searchController: search.controller,
|
||||||
searchHintText: 'Search toolbar buttons',
|
searchHintText: 'Search toolbar buttons',
|
||||||
actions: [
|
actions: [
|
||||||
@@ -87,7 +98,7 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
|||||||
menuChildren: [
|
menuChildren: [
|
||||||
MenuItemButton(
|
MenuItemButton(
|
||||||
leadingIcon: const Icon(Icons.restore),
|
leadingIcon: const Icon(Icons.restore),
|
||||||
onPressed: () => _resetToDefaults(ref),
|
onPressed: () => _resetToDefaults(ref, location),
|
||||||
child: const Text('Reset to Defaults'),
|
child: const Text('Reset to Defaults'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -97,7 +108,10 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
|||||||
const SliverToBoxAdapter(child: SizedBox(height: 16)),
|
const SliverToBoxAdapter(child: SizedBox(height: 16)),
|
||||||
SliverPersistentHeader(
|
SliverPersistentHeader(
|
||||||
pinned: true,
|
pinned: true,
|
||||||
delegate: _ToolbarPreviewDelegate(configs: configs.value),
|
delegate: _ToolbarPreviewDelegate(
|
||||||
|
configs: configs.value,
|
||||||
|
location: location,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SliverPadding(
|
const SliverPadding(
|
||||||
padding: EdgeInsets.fromLTRB(16, 20, 16, 0),
|
padding: EdgeInsets.fromLTRB(16, 20, 16, 0),
|
||||||
@@ -193,7 +207,7 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
|||||||
List<ToolbarButtonConfig> configs,
|
List<ToolbarButtonConfig> configs,
|
||||||
int oldIndex,
|
int oldIndex,
|
||||||
int newIndex,
|
int newIndex,
|
||||||
ContextualToolbarConfigRepository repository, {
|
ToolbarButtonConfigRepository repository, {
|
||||||
required bool isVisible,
|
required bool isVisible,
|
||||||
}) {
|
}) {
|
||||||
if (oldIndex == newIndex) return;
|
if (oldIndex == newIndex) return;
|
||||||
@@ -212,7 +226,7 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _reorderViaDb(
|
Future<void> _reorderViaDb(
|
||||||
ContextualToolbarConfigRepository repository,
|
ToolbarButtonConfigRepository repository,
|
||||||
List<ToolbarButtonConfig> configs,
|
List<ToolbarButtonConfig> configs,
|
||||||
int oldIndex,
|
int oldIndex,
|
||||||
int targetIndex,
|
int targetIndex,
|
||||||
@@ -248,9 +262,12 @@ class ContextualToolbarSettingsScreen extends HookConsumerWidget {
|
|||||||
await repository.assignOrderKey(movedId, orderKey: orderKey);
|
await repository.assignOrderKey(movedId, orderKey: orderKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resetToDefaults(WidgetRef ref) async {
|
Future<void> _resetToDefaults(
|
||||||
final repository = ref.read(contextualToolbarConfigRepositoryProvider);
|
WidgetRef ref,
|
||||||
await repository.replaceAll(defaultToolbarButtonConfigs.value);
|
ToolbarConfigLocation location,
|
||||||
|
) async {
|
||||||
|
final repository = ref.read(toolbarConfigRepositoryProvider(location));
|
||||||
|
await repository.replaceAll(defaultToolbarButtonConfigsFor(location).value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +301,7 @@ class _ToolbarButtonConfigTile extends HookConsumerWidget {
|
|||||||
|
|
||||||
final int index;
|
final int index;
|
||||||
final ToolbarButtonConfig config;
|
final ToolbarButtonConfig config;
|
||||||
final ContextualToolbarConfigRepository repository;
|
final ToolbarButtonConfigRepository repository;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -511,9 +528,13 @@ class _FallbackPicker extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ToolbarPreviewDelegate extends SliverPersistentHeaderDelegate {
|
class _ToolbarPreviewDelegate extends SliverPersistentHeaderDelegate {
|
||||||
const _ToolbarPreviewDelegate({required this.configs});
|
const _ToolbarPreviewDelegate({
|
||||||
|
required this.configs,
|
||||||
|
required this.location,
|
||||||
|
});
|
||||||
|
|
||||||
final List<ToolbarButtonConfig> configs;
|
final List<ToolbarButtonConfig> configs;
|
||||||
|
final ToolbarConfigLocation location;
|
||||||
|
|
||||||
static const _previewHeight = BrowserTabBar.contextualToolabarHeight;
|
static const _previewHeight = BrowserTabBar.contextualToolabarHeight;
|
||||||
|
|
||||||
@@ -532,19 +553,21 @@ class _ToolbarPreviewDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
height: maxExtent,
|
height: maxExtent,
|
||||||
child: ColoredBox(
|
child: ColoredBox(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
child: _ToolbarPreview(configs: configs),
|
child: _ToolbarPreview(configs: configs, location: location),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldRebuild(_ToolbarPreviewDelegate old) => old.configs != configs;
|
bool shouldRebuild(_ToolbarPreviewDelegate old) =>
|
||||||
|
old.configs != configs || old.location != location;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ToolbarPreview extends ConsumerWidget {
|
class _ToolbarPreview extends ConsumerWidget {
|
||||||
const _ToolbarPreview({required this.configs});
|
const _ToolbarPreview({required this.configs, required this.location});
|
||||||
|
|
||||||
final List<ToolbarButtonConfig> configs;
|
final List<ToolbarButtonConfig> configs;
|
||||||
|
final ToolbarConfigLocation location;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -555,6 +578,7 @@ class _ToolbarPreview extends ConsumerWidget {
|
|||||||
displayedSheet: null,
|
displayedSheet: null,
|
||||||
tabState: null,
|
tabState: null,
|
||||||
isPreview: true,
|
isPreview: true,
|
||||||
|
location: location,
|
||||||
);
|
);
|
||||||
|
|
||||||
final buttons = visibleConfigs.map((config) {
|
final buttons = visibleConfigs.map((config) {
|
||||||
|
|||||||
@@ -92,6 +92,12 @@ const List<SettingsSectionDefinition> toolbarLayoutSettingsSections = [
|
|||||||
],
|
],
|
||||||
child: _TabBarStackingModeSection(),
|
child: _TabBarStackingModeSection(),
|
||||||
),
|
),
|
||||||
|
SettingsEntryDefinition(
|
||||||
|
title: 'Customize Switcher Buttons',
|
||||||
|
subtitle: 'Choose which action buttons appear at the end of the bar',
|
||||||
|
keywords: ['buttons', 'new tab', 'actions', 'trailing'],
|
||||||
|
child: _CustomizeQuickSwitcherButtonsTile(),
|
||||||
|
),
|
||||||
SettingsEntryDefinition(
|
SettingsEntryDefinition(
|
||||||
title: 'Close Buttons on All Tabs',
|
title: 'Close Buttons on All Tabs',
|
||||||
subtitle: 'Show a close button on every switcher chip',
|
subtitle: 'Show a close button on every switcher chip',
|
||||||
@@ -328,6 +334,33 @@ class _CustomizeToolbarButtonsTile extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _CustomizeQuickSwitcherButtonsTile extends HookConsumerWidget {
|
||||||
|
const _CustomizeQuickSwitcherButtonsTile();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final switcherEnabled = ref.watch(
|
||||||
|
generalSettingsWithDefaultsProvider.select(
|
||||||
|
(s) => s.effectiveTabBarStackingMode() != TabBarStackingMode.disabled,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
leading: const Icon(Icons.tune),
|
||||||
|
title: const Text('Customize Switcher Buttons'),
|
||||||
|
subtitle: const Text(
|
||||||
|
'Action buttons pinned at the end of the switcher bar (independent of '
|
||||||
|
'the contextual toolbar)',
|
||||||
|
),
|
||||||
|
trailing: const Icon(Icons.chevron_right),
|
||||||
|
enabled: switcherEnabled,
|
||||||
|
onTap: () async {
|
||||||
|
await const QuickSwitcherToolbarSettingsRoute().push(context);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _TabBarStackingModeSection extends HookConsumerWidget {
|
class _TabBarStackingModeSection extends HookConsumerWidget {
|
||||||
const _TabBarStackingModeSection();
|
const _TabBarStackingModeSection();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024-2026 Fabian Freund.
|
||||||
|
*
|
||||||
|
* This file is part of WebLibre
|
||||||
|
* (see https://weblibre.eu).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/daos/quick_switcher_button_config.drift.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/database.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/definitions.drift.dart';
|
||||||
|
|
||||||
|
/// Mirror of [ToolbarButtonConfigDao] against the separate
|
||||||
|
/// `quick_switcher_button_configs` table. See that DAO for the rationale behind
|
||||||
|
/// each visibility-partitioned order-key operation.
|
||||||
|
@DriftAccessor()
|
||||||
|
class QuickSwitcherButtonConfigDao extends DatabaseAccessor<UserDatabase>
|
||||||
|
with $QuickSwitcherButtonConfigDaoMixin {
|
||||||
|
QuickSwitcherButtonConfigDao(super.attachedDatabase);
|
||||||
|
|
||||||
|
Selectable<QuickSwitcherButtonConfig> selectAll() =>
|
||||||
|
db.quickSwitcherButtonConfigs.select()
|
||||||
|
..orderBy([(t) => OrderingTerm.asc(t.orderKey)]);
|
||||||
|
|
||||||
|
Stream<List<QuickSwitcherButtonConfig>> watchAll() => selectAll().watch();
|
||||||
|
|
||||||
|
Future<List<QuickSwitcherButtonConfig>> getAll() => selectAll().get();
|
||||||
|
|
||||||
|
Future<void> upsert(QuickSwitcherButtonConfig config) =>
|
||||||
|
into(db.quickSwitcherButtonConfigs).insertOnConflictUpdate(config);
|
||||||
|
|
||||||
|
Future<void> assignOrderKey(String buttonId, {required String orderKey}) =>
|
||||||
|
(update(
|
||||||
|
db.quickSwitcherButtonConfigs,
|
||||||
|
)..where((t) => t.buttonId.equals(buttonId))).write(
|
||||||
|
QuickSwitcherButtonConfigsCompanion(orderKey: Value(orderKey)),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> assignVisibility(String buttonId, {required bool visible}) =>
|
||||||
|
transaction(() async {
|
||||||
|
// Land the toggled button at the trailing edge of its *new* section so
|
||||||
|
// its order_key always stays inside the visibility partition.
|
||||||
|
final orderKey = await generateTrailingOrderKey(
|
||||||
|
isVisible: visible,
|
||||||
|
).getSingle();
|
||||||
|
|
||||||
|
await (update(
|
||||||
|
db.quickSwitcherButtonConfigs,
|
||||||
|
)..where((t) => t.buttonId.equals(buttonId))).write(
|
||||||
|
QuickSwitcherButtonConfigsCompanion(
|
||||||
|
isVisible: Value(visible),
|
||||||
|
orderKey: Value(orderKey),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> assignFallback(String buttonId, String? fallbackId) =>
|
||||||
|
(update(
|
||||||
|
db.quickSwitcherButtonConfigs,
|
||||||
|
)..where((t) => t.buttonId.equals(buttonId))).write(
|
||||||
|
QuickSwitcherButtonConfigsCompanion(fallbackId: Value(fallbackId)),
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> replaceAll(List<QuickSwitcherButtonConfig> configs) =>
|
||||||
|
transaction(() async {
|
||||||
|
await delete(db.quickSwitcherButtonConfigs).go();
|
||||||
|
await _insertWithDeferredFallbacks(configs);
|
||||||
|
});
|
||||||
|
|
||||||
|
Future<void> seedMissing(
|
||||||
|
List<({String buttonId, bool defaultVisible, String? defaultFallback})>
|
||||||
|
defaults,
|
||||||
|
) async {
|
||||||
|
final existing = await getAll();
|
||||||
|
final existingIds = {for (final r in existing) r.buttonId};
|
||||||
|
|
||||||
|
final missing = defaults
|
||||||
|
.where((d) => !existingIds.contains(d.buttonId))
|
||||||
|
.toList();
|
||||||
|
if (missing.isEmpty) return;
|
||||||
|
|
||||||
|
await transaction(() async {
|
||||||
|
final inserted = <QuickSwitcherButtonConfig>[];
|
||||||
|
for (final def in missing) {
|
||||||
|
final orderKey = await generateTrailingOrderKey(
|
||||||
|
isVisible: def.defaultVisible,
|
||||||
|
).getSingle();
|
||||||
|
inserted.add(
|
||||||
|
QuickSwitcherButtonConfig(
|
||||||
|
buttonId: def.buttonId,
|
||||||
|
orderKey: orderKey,
|
||||||
|
isVisible: def.defaultVisible,
|
||||||
|
fallbackId: def.defaultFallback,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await into(db.quickSwitcherButtonConfigs).insert(
|
||||||
|
QuickSwitcherButtonConfig(
|
||||||
|
buttonId: def.buttonId,
|
||||||
|
orderKey: orderKey,
|
||||||
|
isVisible: def.defaultVisible,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _assignFallbacks(inserted);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleSelectable<String> generateLeadingOrderKey({
|
||||||
|
int bucket = 0,
|
||||||
|
required bool isVisible,
|
||||||
|
}) => db.definitionsDrift.quickSwitcherLeadingOrderKey(
|
||||||
|
bucket: bucket,
|
||||||
|
isVisible: isVisible,
|
||||||
|
);
|
||||||
|
|
||||||
|
SingleSelectable<String> generateTrailingOrderKey({
|
||||||
|
int bucket = 0,
|
||||||
|
required bool isVisible,
|
||||||
|
}) => db.definitionsDrift.quickSwitcherTrailingOrderKey(
|
||||||
|
bucket: bucket,
|
||||||
|
isVisible: isVisible,
|
||||||
|
);
|
||||||
|
|
||||||
|
SingleOrNullSelectable<String> generateOrderKeyAfterButtonId(
|
||||||
|
String buttonId, {
|
||||||
|
required bool isVisible,
|
||||||
|
}) => db.definitionsDrift.quickSwitcherOrderKeyAfterButton(
|
||||||
|
buttonId: buttonId,
|
||||||
|
isVisible: isVisible,
|
||||||
|
);
|
||||||
|
|
||||||
|
SingleSelectable<String> generateOrderKeyBeforeButtonId(
|
||||||
|
String buttonId, {
|
||||||
|
required bool isVisible,
|
||||||
|
}) => db.definitionsDrift.quickSwitcherOrderKeyBeforeButton(
|
||||||
|
buttonId: buttonId,
|
||||||
|
isVisible: isVisible,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> _insertWithDeferredFallbacks(
|
||||||
|
List<QuickSwitcherButtonConfig> configs,
|
||||||
|
) async {
|
||||||
|
for (final config in configs) {
|
||||||
|
await into(db.quickSwitcherButtonConfigs).insert(
|
||||||
|
QuickSwitcherButtonConfig(
|
||||||
|
buttonId: config.buttonId,
|
||||||
|
orderKey: config.orderKey,
|
||||||
|
isVisible: config.isVisible,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _assignFallbacks(configs);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _assignFallbacks(List<QuickSwitcherButtonConfig> configs) async {
|
||||||
|
for (final config in configs) {
|
||||||
|
if (config.fallbackId == null) continue;
|
||||||
|
await assignFallback(config.buttonId, config.fallbackId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
import 'package:drift/drift.dart' as i0;
|
||||||
|
import 'package:weblibre/features/user/data/database/database.dart' as i1;
|
||||||
|
|
||||||
|
mixin $QuickSwitcherButtonConfigDaoMixin
|
||||||
|
on i0.DatabaseAccessor<i1.UserDatabase> {
|
||||||
|
QuickSwitcherButtonConfigDaoManager get managers =>
|
||||||
|
QuickSwitcherButtonConfigDaoManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
class QuickSwitcherButtonConfigDaoManager {
|
||||||
|
final $QuickSwitcherButtonConfigDaoMixin _db;
|
||||||
|
QuickSwitcherButtonConfigDaoManager(this._db);
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:weblibre/features/user/data/database/daos/cache.dart';
|
import 'package:weblibre/features/user/data/database/daos/cache.dart';
|
||||||
import 'package:weblibre/features/user/data/database/daos/onboarding.dart';
|
import 'package:weblibre/features/user/data/database/daos/onboarding.dart';
|
||||||
import 'package:weblibre/features/user/data/database/daos/proxy_profile.dart';
|
import 'package:weblibre/features/user/data/database/daos/proxy_profile.dart';
|
||||||
|
import 'package:weblibre/features/user/data/database/daos/quick_switcher_button_config.dart';
|
||||||
import 'package:weblibre/features/user/data/database/daos/search_tokens.dart';
|
import 'package:weblibre/features/user/data/database/daos/search_tokens.dart';
|
||||||
import 'package:weblibre/features/user/data/database/daos/setting.dart';
|
import 'package:weblibre/features/user/data/database/daos/setting.dart';
|
||||||
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart';
|
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart';
|
||||||
@@ -37,13 +38,14 @@ import 'package:weblibre/features/user/data/database/database.steps.dart';
|
|||||||
CacheDao,
|
CacheDao,
|
||||||
OnboardingDao,
|
OnboardingDao,
|
||||||
ToolbarButtonConfigDao,
|
ToolbarButtonConfigDao,
|
||||||
|
QuickSwitcherButtonConfigDao,
|
||||||
SearchTokensDao,
|
SearchTokensDao,
|
||||||
ProxyProfileDao,
|
ProxyProfileDao,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class UserDatabase extends $UserDatabase {
|
class UserDatabase extends $UserDatabase {
|
||||||
@override
|
@override
|
||||||
final int schemaVersion = 8;
|
final int schemaVersion = 9;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
@@ -121,5 +123,9 @@ class UserDatabase extends $UserDatabase {
|
|||||||
'DROP TABLE IF EXISTS proxy_routing_setting',
|
'DROP TABLE IF EXISTS proxy_routing_setting',
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
from8To9: (m, schema) async {
|
||||||
|
await m.createTable(schema.quickSwitcherButtonConfigs);
|
||||||
|
await m.createIndex(schema.idxQuickSwitcherOrderKey);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ import 'package:weblibre/features/user/data/database/daos/onboarding.dart'
|
|||||||
as i5;
|
as i5;
|
||||||
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart'
|
import 'package:weblibre/features/user/data/database/daos/toolbar_button_config.dart'
|
||||||
as i6;
|
as i6;
|
||||||
import 'package:weblibre/features/user/data/database/daos/search_tokens.dart'
|
import 'package:weblibre/features/user/data/database/daos/quick_switcher_button_config.dart'
|
||||||
as i7;
|
as i7;
|
||||||
import 'package:weblibre/features/user/data/database/daos/proxy_profile.dart'
|
import 'package:weblibre/features/user/data/database/daos/search_tokens.dart'
|
||||||
as i8;
|
as i8;
|
||||||
import 'package:drift/internal/modular.dart' as i9;
|
import 'package:weblibre/features/user/data/database/daos/proxy_profile.dart'
|
||||||
import 'package:sqlite3/common.dart' as i10;
|
as i9;
|
||||||
|
import 'package:drift/internal/modular.dart' as i10;
|
||||||
|
import 'package:sqlite3/common.dart' as i11;
|
||||||
|
|
||||||
abstract class $UserDatabase extends i0.GeneratedDatabase {
|
abstract class $UserDatabase extends i0.GeneratedDatabase {
|
||||||
$UserDatabase(i0.QueryExecutor e) : super(e);
|
$UserDatabase(i0.QueryExecutor e) : super(e);
|
||||||
@@ -27,6 +29,8 @@ abstract class $UserDatabase extends i0.GeneratedDatabase {
|
|||||||
late final i1.Riverpod riverpod = i1.Riverpod(this);
|
late final i1.Riverpod riverpod = i1.Riverpod(this);
|
||||||
late final i1.ToolbarButtonConfigs toolbarButtonConfigs =
|
late final i1.ToolbarButtonConfigs toolbarButtonConfigs =
|
||||||
i1.ToolbarButtonConfigs(this);
|
i1.ToolbarButtonConfigs(this);
|
||||||
|
late final i1.QuickSwitcherButtonConfigs quickSwitcherButtonConfigs =
|
||||||
|
i1.QuickSwitcherButtonConfigs(this);
|
||||||
late final i1.SearchTokens searchTokens = i1.SearchTokens(this);
|
late final i1.SearchTokens searchTokens = i1.SearchTokens(this);
|
||||||
late final i2.SettingDao settingDao = i2.SettingDao(this as i3.UserDatabase);
|
late final i2.SettingDao settingDao = i2.SettingDao(this as i3.UserDatabase);
|
||||||
late final i4.CacheDao cacheDao = i4.CacheDao(this as i3.UserDatabase);
|
late final i4.CacheDao cacheDao = i4.CacheDao(this as i3.UserDatabase);
|
||||||
@@ -35,13 +39,15 @@ abstract class $UserDatabase extends i0.GeneratedDatabase {
|
|||||||
);
|
);
|
||||||
late final i6.ToolbarButtonConfigDao toolbarButtonConfigDao =
|
late final i6.ToolbarButtonConfigDao toolbarButtonConfigDao =
|
||||||
i6.ToolbarButtonConfigDao(this as i3.UserDatabase);
|
i6.ToolbarButtonConfigDao(this as i3.UserDatabase);
|
||||||
late final i7.SearchTokensDao searchTokensDao = i7.SearchTokensDao(
|
late final i7.QuickSwitcherButtonConfigDao quickSwitcherButtonConfigDao =
|
||||||
|
i7.QuickSwitcherButtonConfigDao(this as i3.UserDatabase);
|
||||||
|
late final i8.SearchTokensDao searchTokensDao = i8.SearchTokensDao(
|
||||||
this as i3.UserDatabase,
|
this as i3.UserDatabase,
|
||||||
);
|
);
|
||||||
late final i8.ProxyProfileDao proxyProfileDao = i8.ProxyProfileDao(
|
late final i9.ProxyProfileDao proxyProfileDao = i9.ProxyProfileDao(
|
||||||
this as i3.UserDatabase,
|
this as i3.UserDatabase,
|
||||||
);
|
);
|
||||||
i1.DefinitionsDrift get definitionsDrift => i9.ReadDatabaseContainer(
|
i1.DefinitionsDrift get definitionsDrift => i10.ReadDatabaseContainer(
|
||||||
this,
|
this,
|
||||||
).accessor<i1.DefinitionsDrift>(i1.DefinitionsDrift.new);
|
).accessor<i1.DefinitionsDrift>(i1.DefinitionsDrift.new);
|
||||||
@override
|
@override
|
||||||
@@ -57,6 +63,8 @@ abstract class $UserDatabase extends i0.GeneratedDatabase {
|
|||||||
riverpod,
|
riverpod,
|
||||||
toolbarButtonConfigs,
|
toolbarButtonConfigs,
|
||||||
i1.idxToolbarOrderKey,
|
i1.idxToolbarOrderKey,
|
||||||
|
quickSwitcherButtonConfigs,
|
||||||
|
i1.idxQuickSwitcherOrderKey,
|
||||||
searchTokens,
|
searchTokens,
|
||||||
i1.idxSearchTokensInsertedAt,
|
i1.idxSearchTokensInsertedAt,
|
||||||
i1.idxSearchTokensReservedAt,
|
i1.idxSearchTokensReservedAt,
|
||||||
@@ -78,11 +86,16 @@ class $UserDatabaseManager {
|
|||||||
i1.$RiverpodTableManager(_db, _db.riverpod);
|
i1.$RiverpodTableManager(_db, _db.riverpod);
|
||||||
i1.$ToolbarButtonConfigsTableManager get toolbarButtonConfigs =>
|
i1.$ToolbarButtonConfigsTableManager get toolbarButtonConfigs =>
|
||||||
i1.$ToolbarButtonConfigsTableManager(_db, _db.toolbarButtonConfigs);
|
i1.$ToolbarButtonConfigsTableManager(_db, _db.toolbarButtonConfigs);
|
||||||
|
i1.$QuickSwitcherButtonConfigsTableManager get quickSwitcherButtonConfigs =>
|
||||||
|
i1.$QuickSwitcherButtonConfigsTableManager(
|
||||||
|
_db,
|
||||||
|
_db.quickSwitcherButtonConfigs,
|
||||||
|
);
|
||||||
i1.$SearchTokensTableManager get searchTokens =>
|
i1.$SearchTokensTableManager get searchTokens =>
|
||||||
i1.$SearchTokensTableManager(_db, _db.searchTokens);
|
i1.$SearchTokensTableManager(_db, _db.searchTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DefineFunctions on i10.CommonDatabase {
|
extension DefineFunctions on i11.CommonDatabase {
|
||||||
void defineFunctions({
|
void defineFunctions({
|
||||||
required String Function(int, String?) lexoRankNext,
|
required String Function(int, String?) lexoRankNext,
|
||||||
required String Function(int, String?) lexoRankPrevious,
|
required String Function(int, String?) lexoRankPrevious,
|
||||||
@@ -96,7 +109,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
}) {
|
}) {
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'lexo_rank_next',
|
functionName: 'lexo_rank_next',
|
||||||
argumentCount: const i10.AllowedArgumentCount(2),
|
argumentCount: const i11.AllowedArgumentCount(2),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as int;
|
final arg0 = args[0] as int;
|
||||||
final arg1 = args[1] as String?;
|
final arg1 = args[1] as String?;
|
||||||
@@ -105,7 +118,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'lexo_rank_previous',
|
functionName: 'lexo_rank_previous',
|
||||||
argumentCount: const i10.AllowedArgumentCount(2),
|
argumentCount: const i11.AllowedArgumentCount(2),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as int;
|
final arg0 = args[0] as int;
|
||||||
final arg1 = args[1] as String?;
|
final arg1 = args[1] as String?;
|
||||||
@@ -114,7 +127,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'lexo_rank_reorder_after',
|
functionName: 'lexo_rank_reorder_after',
|
||||||
argumentCount: const i10.AllowedArgumentCount(2),
|
argumentCount: const i11.AllowedArgumentCount(2),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as String?;
|
final arg0 = args[0] as String?;
|
||||||
final arg1 = args[1] as String?;
|
final arg1 = args[1] as String?;
|
||||||
@@ -123,7 +136,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'lexo_rank_reorder_before',
|
functionName: 'lexo_rank_reorder_before',
|
||||||
argumentCount: const i10.AllowedArgumentCount(2),
|
argumentCount: const i11.AllowedArgumentCount(2),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as String?;
|
final arg0 = args[0] as String?;
|
||||||
final arg1 = args[1] as String?;
|
final arg1 = args[1] as String?;
|
||||||
@@ -132,14 +145,14 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'generate_content_hash',
|
functionName: 'generate_content_hash',
|
||||||
argumentCount: const i10.AllowedArgumentCount(0),
|
argumentCount: const i11.AllowedArgumentCount(0),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
return generateContentHash();
|
return generateContentHash();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'url_indexable',
|
functionName: 'url_indexable',
|
||||||
argumentCount: const i10.AllowedArgumentCount(1),
|
argumentCount: const i11.AllowedArgumentCount(1),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as String?;
|
final arg0 = args[0] as String?;
|
||||||
return urlIndexable(arg0);
|
return urlIndexable(arg0);
|
||||||
@@ -147,7 +160,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'url_canonical',
|
functionName: 'url_canonical',
|
||||||
argumentCount: const i10.AllowedArgumentCount(1),
|
argumentCount: const i11.AllowedArgumentCount(1),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as String?;
|
final arg0 = args[0] as String?;
|
||||||
return urlCanonical(arg0);
|
return urlCanonical(arg0);
|
||||||
@@ -155,7 +168,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'url_host',
|
functionName: 'url_host',
|
||||||
argumentCount: const i10.AllowedArgumentCount(1),
|
argumentCount: const i11.AllowedArgumentCount(1),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as String?;
|
final arg0 = args[0] as String?;
|
||||||
return urlHost(arg0);
|
return urlHost(arg0);
|
||||||
@@ -163,7 +176,7 @@ extension DefineFunctions on i10.CommonDatabase {
|
|||||||
);
|
);
|
||||||
createFunction(
|
createFunction(
|
||||||
functionName: 'url_path',
|
functionName: 'url_path',
|
||||||
argumentCount: const i10.AllowedArgumentCount(1),
|
argumentCount: const i11.AllowedArgumentCount(1),
|
||||||
function: (args) {
|
function: (args) {
|
||||||
final arg0 = args[0] as String?;
|
final arg0 = args[0] as String?;
|
||||||
return urlPath(arg0);
|
return urlPath(arg0);
|
||||||
|
|||||||
@@ -1085,6 +1085,161 @@ final class Schema8 extends i0.VersionedSchema {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class Schema9 extends i0.VersionedSchema {
|
||||||
|
Schema9({required super.database}) : super(version: 9);
|
||||||
|
@override
|
||||||
|
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||||
|
setting,
|
||||||
|
proxyProfile,
|
||||||
|
idxProxyProfileUpdatedAt,
|
||||||
|
iconCache,
|
||||||
|
onboarding,
|
||||||
|
riverpod,
|
||||||
|
toolbarButtonConfigs,
|
||||||
|
idxToolbarOrderKey,
|
||||||
|
quickSwitcherButtonConfigs,
|
||||||
|
idxQuickSwitcherOrderKey,
|
||||||
|
searchTokens,
|
||||||
|
idxSearchTokensInsertedAt,
|
||||||
|
idxSearchTokensReservedAt,
|
||||||
|
];
|
||||||
|
late final Shape0 setting = Shape0(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'setting',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: true,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_0, _column_1, _column_2],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape9 proxyProfile = Shape9(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'proxy_profile',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [
|
||||||
|
_column_20,
|
||||||
|
_column_21,
|
||||||
|
_column_22,
|
||||||
|
_column_23,
|
||||||
|
_column_30,
|
||||||
|
_column_24,
|
||||||
|
_column_25,
|
||||||
|
],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxProxyProfileUpdatedAt = i1.Index(
|
||||||
|
'idx_proxy_profile_updated_at',
|
||||||
|
'CREATE INDEX idx_proxy_profile_updated_at ON proxy_profile (updated_at)',
|
||||||
|
);
|
||||||
|
late final Shape1 iconCache = Shape1(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'icon_cache',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_3, _column_4, _column_5],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape2 onboarding = Shape2(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'onboarding',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_6, _column_7],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape3 riverpod = Shape3(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'riverpod',
|
||||||
|
withoutRowId: true,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_0, _column_8, _column_9, _column_10],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
late final Shape4 toolbarButtonConfigs = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'toolbar_button_configs',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_11, _column_12, _column_13, _column_14],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxToolbarOrderKey = i1.Index(
|
||||||
|
'idx_toolbar_order_key',
|
||||||
|
'CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)',
|
||||||
|
);
|
||||||
|
late final Shape4 quickSwitcherButtonConfigs = Shape4(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'quick_switcher_button_configs',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_11, _column_12, _column_31, _column_32],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxQuickSwitcherOrderKey = i1.Index(
|
||||||
|
'idx_quick_switcher_order_key',
|
||||||
|
'CREATE INDEX idx_quick_switcher_order_key ON quick_switcher_button_configs (order_key)',
|
||||||
|
);
|
||||||
|
late final Shape6 searchTokens = Shape6(
|
||||||
|
source: i0.VersionedTable(
|
||||||
|
entityName: 'search_tokens',
|
||||||
|
withoutRowId: false,
|
||||||
|
isStrict: false,
|
||||||
|
tableConstraints: [],
|
||||||
|
columns: [_column_15, _column_16, _column_17, _column_18, _column_19],
|
||||||
|
attachedDatabase: database,
|
||||||
|
),
|
||||||
|
alias: null,
|
||||||
|
);
|
||||||
|
final i1.Index idxSearchTokensInsertedAt = i1.Index(
|
||||||
|
'idx_search_tokens_inserted_at',
|
||||||
|
'CREATE INDEX idx_search_tokens_inserted_at ON search_tokens (inserted_at)',
|
||||||
|
);
|
||||||
|
final i1.Index idxSearchTokensReservedAt = i1.Index(
|
||||||
|
'idx_search_tokens_reserved_at',
|
||||||
|
'CREATE INDEX idx_search_tokens_reserved_at ON search_tokens (reserved_at)',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.GeneratedColumn<int> _column_31(String aliasedName) =>
|
||||||
|
i1.GeneratedColumn<int>(
|
||||||
|
'is_visible',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i1.DriftSqlType.int,
|
||||||
|
$customConstraints: 'NOT NULL DEFAULT FALSE',
|
||||||
|
defaultValue: const i1.CustomExpression('FALSE'),
|
||||||
|
);
|
||||||
|
i1.GeneratedColumn<String> _column_32(
|
||||||
|
String aliasedName,
|
||||||
|
) => i1.GeneratedColumn<String>(
|
||||||
|
'fallback_id',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i1.DriftSqlType.string,
|
||||||
|
$customConstraints:
|
||||||
|
'REFERENCES quick_switcher_button_configs(button_id)ON DELETE SET NULL',
|
||||||
|
);
|
||||||
i0.MigrationStepWithVersion migrationSteps({
|
i0.MigrationStepWithVersion migrationSteps({
|
||||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||||
@@ -1093,6 +1248,7 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||||
}) {
|
}) {
|
||||||
return (currentVersion, database) async {
|
return (currentVersion, database) async {
|
||||||
switch (currentVersion) {
|
switch (currentVersion) {
|
||||||
@@ -1131,6 +1287,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||||||
final migrator = i1.Migrator(database, schema);
|
final migrator = i1.Migrator(database, schema);
|
||||||
await from7To8(migrator, schema);
|
await from7To8(migrator, schema);
|
||||||
return 8;
|
return 8;
|
||||||
|
case 8:
|
||||||
|
final schema = Schema9(database: database);
|
||||||
|
final migrator = i1.Migrator(database, schema);
|
||||||
|
await from8To9(migrator, schema);
|
||||||
|
return 9;
|
||||||
default:
|
default:
|
||||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||||
}
|
}
|
||||||
@@ -1145,6 +1306,7 @@ i1.OnUpgrade stepByStep({
|
|||||||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||||
|
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||||
}) => i0.VersionedSchema.stepByStepHelper(
|
}) => i0.VersionedSchema.stepByStepHelper(
|
||||||
step: migrationSteps(
|
step: migrationSteps(
|
||||||
from1To2: from1To2,
|
from1To2: from1To2,
|
||||||
@@ -1154,5 +1316,6 @@ i1.OnUpgrade stepByStep({
|
|||||||
from5To6: from5To6,
|
from5To6: from5To6,
|
||||||
from6To7: from6To7,
|
from6To7: from6To7,
|
||||||
from7To8: from7To8,
|
from7To8: from7To8,
|
||||||
|
from8To9: from8To9,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -45,6 +45,18 @@ CREATE TABLE toolbar_button_configs (
|
|||||||
|
|
||||||
CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs(order_key);
|
CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs(order_key);
|
||||||
|
|
||||||
|
-- Independently-configured button set for the quick tab switcher's trailing
|
||||||
|
-- cluster. Same shape as toolbar_button_configs but a separate table so the two
|
||||||
|
-- toolbars keep fully isolated ordering/visibility/fallbacks.
|
||||||
|
CREATE TABLE quick_switcher_button_configs (
|
||||||
|
button_id TEXT NOT NULL PRIMARY KEY,
|
||||||
|
order_key TEXT NOT NULL,
|
||||||
|
is_visible BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
fallback_id TEXT REFERENCES quick_switcher_button_configs(button_id) ON DELETE SET NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_quick_switcher_order_key ON quick_switcher_button_configs(order_key);
|
||||||
|
|
||||||
CREATE TABLE search_tokens (
|
CREATE TABLE search_tokens (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
token BLOB NOT NULL,
|
token BLOB NOT NULL,
|
||||||
@@ -111,6 +123,58 @@ toolbarOrderKeyBeforeButton(:button_id AS TEXT, :is_visible AS BOOL):
|
|||||||
FROM ordered_table
|
FROM ordered_table
|
||||||
WHERE button_id = :button_id;
|
WHERE button_id = :button_id;
|
||||||
|
|
||||||
|
-- Quick-switcher variants of the order-key helpers above, scoped to the
|
||||||
|
-- quick_switcher_button_configs table (see the toolbar* queries for rationale).
|
||||||
|
quickSwitcherLeadingOrderKey(:bucket AS INTEGER, :is_visible AS BOOL):
|
||||||
|
SELECT lexo_rank_previous(
|
||||||
|
:bucket,
|
||||||
|
(
|
||||||
|
SELECT order_key
|
||||||
|
FROM quick_switcher_button_configs
|
||||||
|
WHERE is_visible = :is_visible
|
||||||
|
ORDER BY order_key
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
quickSwitcherTrailingOrderKey(:bucket AS INTEGER, :is_visible AS BOOL):
|
||||||
|
SELECT lexo_rank_next(
|
||||||
|
:bucket,
|
||||||
|
(
|
||||||
|
SELECT order_key
|
||||||
|
FROM quick_switcher_button_configs
|
||||||
|
WHERE is_visible = :is_visible
|
||||||
|
ORDER BY order_key DESC
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
quickSwitcherOrderKeyAfterButton(:button_id AS TEXT, :is_visible AS BOOL):
|
||||||
|
WITH ordered_table AS (
|
||||||
|
SELECT
|
||||||
|
button_id,
|
||||||
|
order_key,
|
||||||
|
LEAD(order_key) OVER (ORDER BY order_key) AS next_order_key
|
||||||
|
FROM quick_switcher_button_configs
|
||||||
|
WHERE is_visible = :is_visible
|
||||||
|
)
|
||||||
|
SELECT lexo_rank_reorder_after(order_key, next_order_key)
|
||||||
|
FROM ordered_table
|
||||||
|
WHERE button_id = :button_id;
|
||||||
|
|
||||||
|
quickSwitcherOrderKeyBeforeButton(:button_id AS TEXT, :is_visible AS BOOL):
|
||||||
|
WITH ordered_table AS (
|
||||||
|
SELECT
|
||||||
|
button_id,
|
||||||
|
order_key,
|
||||||
|
LAG(order_key) OVER (ORDER BY order_key) AS prev_order_key
|
||||||
|
FROM quick_switcher_button_configs
|
||||||
|
WHERE is_visible = :is_visible
|
||||||
|
)
|
||||||
|
SELECT lexo_rank_reorder_before(order_key, prev_order_key)
|
||||||
|
FROM ordered_table
|
||||||
|
WHERE button_id = :button_id;
|
||||||
|
|
||||||
evictCacheEntries:
|
evictCacheEntries:
|
||||||
DELETE FROM icon_cache
|
DELETE FROM icon_cache
|
||||||
WHERE rowid IN (
|
WHERE rowid IN (
|
||||||
|
|||||||
@@ -1123,6 +1123,208 @@ typedef $ToolbarButtonConfigsProcessedTableManager =
|
|||||||
i1.ToolbarButtonConfig,
|
i1.ToolbarButtonConfig,
|
||||||
i0.PrefetchHooks Function()
|
i0.PrefetchHooks Function()
|
||||||
>;
|
>;
|
||||||
|
typedef $QuickSwitcherButtonConfigsCreateCompanionBuilder =
|
||||||
|
i1.QuickSwitcherButtonConfigsCompanion Function({
|
||||||
|
required String buttonId,
|
||||||
|
required String orderKey,
|
||||||
|
i0.Value<bool> isVisible,
|
||||||
|
i0.Value<String?> fallbackId,
|
||||||
|
i0.Value<int> rowid,
|
||||||
|
});
|
||||||
|
typedef $QuickSwitcherButtonConfigsUpdateCompanionBuilder =
|
||||||
|
i1.QuickSwitcherButtonConfigsCompanion Function({
|
||||||
|
i0.Value<String> buttonId,
|
||||||
|
i0.Value<String> orderKey,
|
||||||
|
i0.Value<bool> isVisible,
|
||||||
|
i0.Value<String?> fallbackId,
|
||||||
|
i0.Value<int> rowid,
|
||||||
|
});
|
||||||
|
|
||||||
|
class $QuickSwitcherButtonConfigsFilterComposer
|
||||||
|
extends i0.Composer<i0.GeneratedDatabase, i1.QuickSwitcherButtonConfigs> {
|
||||||
|
$QuickSwitcherButtonConfigsFilterComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.ColumnFilters<String> get buttonId => $composableBuilder(
|
||||||
|
column: $table.buttonId,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get orderKey => $composableBuilder(
|
||||||
|
column: $table.orderKey,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<bool> get isVisible => $composableBuilder(
|
||||||
|
column: $table.isVisible,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnFilters<String> get fallbackId => $composableBuilder(
|
||||||
|
column: $table.fallbackId,
|
||||||
|
builder: (column) => i0.ColumnFilters(column),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $QuickSwitcherButtonConfigsOrderingComposer
|
||||||
|
extends i0.Composer<i0.GeneratedDatabase, i1.QuickSwitcherButtonConfigs> {
|
||||||
|
$QuickSwitcherButtonConfigsOrderingComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.ColumnOrderings<String> get buttonId => $composableBuilder(
|
||||||
|
column: $table.buttonId,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get orderKey => $composableBuilder(
|
||||||
|
column: $table.orderKey,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<bool> get isVisible => $composableBuilder(
|
||||||
|
column: $table.isVisible,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
|
i0.ColumnOrderings<String> get fallbackId => $composableBuilder(
|
||||||
|
column: $table.fallbackId,
|
||||||
|
builder: (column) => i0.ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $QuickSwitcherButtonConfigsAnnotationComposer
|
||||||
|
extends i0.Composer<i0.GeneratedDatabase, i1.QuickSwitcherButtonConfigs> {
|
||||||
|
$QuickSwitcherButtonConfigsAnnotationComposer({
|
||||||
|
required super.$db,
|
||||||
|
required super.$table,
|
||||||
|
super.joinBuilder,
|
||||||
|
super.$addJoinBuilderToRootComposer,
|
||||||
|
super.$removeJoinBuilderFromRootComposer,
|
||||||
|
});
|
||||||
|
i0.GeneratedColumn<String> get buttonId =>
|
||||||
|
$composableBuilder(column: $table.buttonId, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get orderKey =>
|
||||||
|
$composableBuilder(column: $table.orderKey, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<bool> get isVisible =>
|
||||||
|
$composableBuilder(column: $table.isVisible, builder: (column) => column);
|
||||||
|
|
||||||
|
i0.GeneratedColumn<String> get fallbackId => $composableBuilder(
|
||||||
|
column: $table.fallbackId,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class $QuickSwitcherButtonConfigsTableManager
|
||||||
|
extends
|
||||||
|
i0.RootTableManager<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.QuickSwitcherButtonConfigs,
|
||||||
|
i1.QuickSwitcherButtonConfig,
|
||||||
|
i1.$QuickSwitcherButtonConfigsFilterComposer,
|
||||||
|
i1.$QuickSwitcherButtonConfigsOrderingComposer,
|
||||||
|
i1.$QuickSwitcherButtonConfigsAnnotationComposer,
|
||||||
|
$QuickSwitcherButtonConfigsCreateCompanionBuilder,
|
||||||
|
$QuickSwitcherButtonConfigsUpdateCompanionBuilder,
|
||||||
|
(
|
||||||
|
i1.QuickSwitcherButtonConfig,
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.QuickSwitcherButtonConfigs,
|
||||||
|
i1.QuickSwitcherButtonConfig
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
i1.QuickSwitcherButtonConfig,
|
||||||
|
i0.PrefetchHooks Function()
|
||||||
|
> {
|
||||||
|
$QuickSwitcherButtonConfigsTableManager(
|
||||||
|
i0.GeneratedDatabase db,
|
||||||
|
i1.QuickSwitcherButtonConfigs table,
|
||||||
|
) : super(
|
||||||
|
i0.TableManagerState(
|
||||||
|
db: db,
|
||||||
|
table: table,
|
||||||
|
createFilteringComposer: () =>
|
||||||
|
i1.$QuickSwitcherButtonConfigsFilterComposer(
|
||||||
|
$db: db,
|
||||||
|
$table: table,
|
||||||
|
),
|
||||||
|
createOrderingComposer: () =>
|
||||||
|
i1.$QuickSwitcherButtonConfigsOrderingComposer(
|
||||||
|
$db: db,
|
||||||
|
$table: table,
|
||||||
|
),
|
||||||
|
createComputedFieldComposer: () =>
|
||||||
|
i1.$QuickSwitcherButtonConfigsAnnotationComposer(
|
||||||
|
$db: db,
|
||||||
|
$table: table,
|
||||||
|
),
|
||||||
|
updateCompanionCallback:
|
||||||
|
({
|
||||||
|
i0.Value<String> buttonId = const i0.Value.absent(),
|
||||||
|
i0.Value<String> orderKey = const i0.Value.absent(),
|
||||||
|
i0.Value<bool> isVisible = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> fallbackId = const i0.Value.absent(),
|
||||||
|
i0.Value<int> rowid = const i0.Value.absent(),
|
||||||
|
}) => i1.QuickSwitcherButtonConfigsCompanion(
|
||||||
|
buttonId: buttonId,
|
||||||
|
orderKey: orderKey,
|
||||||
|
isVisible: isVisible,
|
||||||
|
fallbackId: fallbackId,
|
||||||
|
rowid: rowid,
|
||||||
|
),
|
||||||
|
createCompanionCallback:
|
||||||
|
({
|
||||||
|
required String buttonId,
|
||||||
|
required String orderKey,
|
||||||
|
i0.Value<bool> isVisible = const i0.Value.absent(),
|
||||||
|
i0.Value<String?> fallbackId = const i0.Value.absent(),
|
||||||
|
i0.Value<int> rowid = const i0.Value.absent(),
|
||||||
|
}) => i1.QuickSwitcherButtonConfigsCompanion.insert(
|
||||||
|
buttonId: buttonId,
|
||||||
|
orderKey: orderKey,
|
||||||
|
isVisible: isVisible,
|
||||||
|
fallbackId: fallbackId,
|
||||||
|
rowid: rowid,
|
||||||
|
),
|
||||||
|
withReferenceMapper: (p0) => p0
|
||||||
|
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
||||||
|
.toList(),
|
||||||
|
prefetchHooksCallback: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef $QuickSwitcherButtonConfigsProcessedTableManager =
|
||||||
|
i0.ProcessedTableManager<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.QuickSwitcherButtonConfigs,
|
||||||
|
i1.QuickSwitcherButtonConfig,
|
||||||
|
i1.$QuickSwitcherButtonConfigsFilterComposer,
|
||||||
|
i1.$QuickSwitcherButtonConfigsOrderingComposer,
|
||||||
|
i1.$QuickSwitcherButtonConfigsAnnotationComposer,
|
||||||
|
$QuickSwitcherButtonConfigsCreateCompanionBuilder,
|
||||||
|
$QuickSwitcherButtonConfigsUpdateCompanionBuilder,
|
||||||
|
(
|
||||||
|
i1.QuickSwitcherButtonConfig,
|
||||||
|
i0.BaseReferences<
|
||||||
|
i0.GeneratedDatabase,
|
||||||
|
i1.QuickSwitcherButtonConfigs,
|
||||||
|
i1.QuickSwitcherButtonConfig
|
||||||
|
>,
|
||||||
|
),
|
||||||
|
i1.QuickSwitcherButtonConfig,
|
||||||
|
i0.PrefetchHooks Function()
|
||||||
|
>;
|
||||||
typedef $SearchTokensCreateCompanionBuilder =
|
typedef $SearchTokensCreateCompanionBuilder =
|
||||||
i1.SearchTokensCompanion Function({
|
i1.SearchTokensCompanion Function({
|
||||||
i0.Value<int> id,
|
i0.Value<int> id,
|
||||||
@@ -2902,6 +3104,283 @@ i0.Index get idxToolbarOrderKey => i0.Index(
|
|||||||
'CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)',
|
'CREATE INDEX idx_toolbar_order_key ON toolbar_button_configs (order_key)',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
class QuickSwitcherButtonConfigs extends i0.Table
|
||||||
|
with
|
||||||
|
i0.TableInfo<QuickSwitcherButtonConfigs, i1.QuickSwitcherButtonConfig> {
|
||||||
|
@override
|
||||||
|
final i0.GeneratedDatabase attachedDatabase;
|
||||||
|
final String? _alias;
|
||||||
|
QuickSwitcherButtonConfigs(this.attachedDatabase, [this._alias]);
|
||||||
|
late final i0.GeneratedColumn<String> buttonId = i0.GeneratedColumn<String>(
|
||||||
|
'button_id',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
$customConstraints: 'NOT NULL PRIMARY KEY',
|
||||||
|
);
|
||||||
|
late final i0.GeneratedColumn<String> orderKey = i0.GeneratedColumn<String>(
|
||||||
|
'order_key',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
$customConstraints: 'NOT NULL',
|
||||||
|
);
|
||||||
|
late final i0.GeneratedColumn<bool> isVisible = i0.GeneratedColumn<bool>(
|
||||||
|
'is_visible',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: i0.DriftSqlType.bool,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
$customConstraints: 'NOT NULL DEFAULT FALSE',
|
||||||
|
defaultValue: const i0.CustomExpression('FALSE'),
|
||||||
|
);
|
||||||
|
late final i0.GeneratedColumn<String> fallbackId = i0.GeneratedColumn<String>(
|
||||||
|
'fallback_id',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: i0.DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
$customConstraints:
|
||||||
|
'REFERENCES quick_switcher_button_configs(button_id)ON DELETE SET NULL',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
List<i0.GeneratedColumn> get $columns => [
|
||||||
|
buttonId,
|
||||||
|
orderKey,
|
||||||
|
isVisible,
|
||||||
|
fallbackId,
|
||||||
|
];
|
||||||
|
@override
|
||||||
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
|
@override
|
||||||
|
String get actualTableName => $name;
|
||||||
|
static const String $name = 'quick_switcher_button_configs';
|
||||||
|
@override
|
||||||
|
Set<i0.GeneratedColumn> get $primaryKey => {buttonId};
|
||||||
|
@override
|
||||||
|
i1.QuickSwitcherButtonConfig map(
|
||||||
|
Map<String, dynamic> data, {
|
||||||
|
String? tablePrefix,
|
||||||
|
}) {
|
||||||
|
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||||
|
return i1.QuickSwitcherButtonConfig(
|
||||||
|
buttonId: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}button_id'],
|
||||||
|
)!,
|
||||||
|
orderKey: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}order_key'],
|
||||||
|
)!,
|
||||||
|
isVisible: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.bool,
|
||||||
|
data['${effectivePrefix}is_visible'],
|
||||||
|
)!,
|
||||||
|
fallbackId: attachedDatabase.typeMapping.read(
|
||||||
|
i0.DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}fallback_id'],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
QuickSwitcherButtonConfigs createAlias(String alias) {
|
||||||
|
return QuickSwitcherButtonConfigs(attachedDatabase, alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get dontWriteConstraints => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class QuickSwitcherButtonConfig extends i0.DataClass
|
||||||
|
implements i0.Insertable<i1.QuickSwitcherButtonConfig> {
|
||||||
|
final String buttonId;
|
||||||
|
final String orderKey;
|
||||||
|
final bool isVisible;
|
||||||
|
final String? fallbackId;
|
||||||
|
const QuickSwitcherButtonConfig({
|
||||||
|
required this.buttonId,
|
||||||
|
required this.orderKey,
|
||||||
|
required this.isVisible,
|
||||||
|
this.fallbackId,
|
||||||
|
});
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
map['button_id'] = i0.Variable<String>(buttonId);
|
||||||
|
map['order_key'] = i0.Variable<String>(orderKey);
|
||||||
|
map['is_visible'] = i0.Variable<bool>(isVisible);
|
||||||
|
if (!nullToAbsent || fallbackId != null) {
|
||||||
|
map['fallback_id'] = i0.Variable<String>(fallbackId);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory QuickSwitcherButtonConfig.fromJson(
|
||||||
|
Map<String, dynamic> json, {
|
||||||
|
i0.ValueSerializer? serializer,
|
||||||
|
}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return QuickSwitcherButtonConfig(
|
||||||
|
buttonId: serializer.fromJson<String>(json['button_id']),
|
||||||
|
orderKey: serializer.fromJson<String>(json['order_key']),
|
||||||
|
isVisible: serializer.fromJson<bool>(json['is_visible']),
|
||||||
|
fallbackId: serializer.fromJson<String?>(json['fallback_id']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||||
|
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'button_id': serializer.toJson<String>(buttonId),
|
||||||
|
'order_key': serializer.toJson<String>(orderKey),
|
||||||
|
'is_visible': serializer.toJson<bool>(isVisible),
|
||||||
|
'fallback_id': serializer.toJson<String?>(fallbackId),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.QuickSwitcherButtonConfig copyWith({
|
||||||
|
String? buttonId,
|
||||||
|
String? orderKey,
|
||||||
|
bool? isVisible,
|
||||||
|
i0.Value<String?> fallbackId = const i0.Value.absent(),
|
||||||
|
}) => i1.QuickSwitcherButtonConfig(
|
||||||
|
buttonId: buttonId ?? this.buttonId,
|
||||||
|
orderKey: orderKey ?? this.orderKey,
|
||||||
|
isVisible: isVisible ?? this.isVisible,
|
||||||
|
fallbackId: fallbackId.present ? fallbackId.value : this.fallbackId,
|
||||||
|
);
|
||||||
|
QuickSwitcherButtonConfig copyWithCompanion(
|
||||||
|
i1.QuickSwitcherButtonConfigsCompanion data,
|
||||||
|
) {
|
||||||
|
return QuickSwitcherButtonConfig(
|
||||||
|
buttonId: data.buttonId.present ? data.buttonId.value : this.buttonId,
|
||||||
|
orderKey: data.orderKey.present ? data.orderKey.value : this.orderKey,
|
||||||
|
isVisible: data.isVisible.present ? data.isVisible.value : this.isVisible,
|
||||||
|
fallbackId: data.fallbackId.present
|
||||||
|
? data.fallbackId.value
|
||||||
|
: this.fallbackId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('QuickSwitcherButtonConfig(')
|
||||||
|
..write('buttonId: $buttonId, ')
|
||||||
|
..write('orderKey: $orderKey, ')
|
||||||
|
..write('isVisible: $isVisible, ')
|
||||||
|
..write('fallbackId: $fallbackId')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(buttonId, orderKey, isVisible, fallbackId);
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is i1.QuickSwitcherButtonConfig &&
|
||||||
|
other.buttonId == this.buttonId &&
|
||||||
|
other.orderKey == this.orderKey &&
|
||||||
|
other.isVisible == this.isVisible &&
|
||||||
|
other.fallbackId == this.fallbackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
class QuickSwitcherButtonConfigsCompanion
|
||||||
|
extends i0.UpdateCompanion<i1.QuickSwitcherButtonConfig> {
|
||||||
|
final i0.Value<String> buttonId;
|
||||||
|
final i0.Value<String> orderKey;
|
||||||
|
final i0.Value<bool> isVisible;
|
||||||
|
final i0.Value<String?> fallbackId;
|
||||||
|
final i0.Value<int> rowid;
|
||||||
|
const QuickSwitcherButtonConfigsCompanion({
|
||||||
|
this.buttonId = const i0.Value.absent(),
|
||||||
|
this.orderKey = const i0.Value.absent(),
|
||||||
|
this.isVisible = const i0.Value.absent(),
|
||||||
|
this.fallbackId = const i0.Value.absent(),
|
||||||
|
this.rowid = const i0.Value.absent(),
|
||||||
|
});
|
||||||
|
QuickSwitcherButtonConfigsCompanion.insert({
|
||||||
|
required String buttonId,
|
||||||
|
required String orderKey,
|
||||||
|
this.isVisible = const i0.Value.absent(),
|
||||||
|
this.fallbackId = const i0.Value.absent(),
|
||||||
|
this.rowid = const i0.Value.absent(),
|
||||||
|
}) : buttonId = i0.Value(buttonId),
|
||||||
|
orderKey = i0.Value(orderKey);
|
||||||
|
static i0.Insertable<i1.QuickSwitcherButtonConfig> custom({
|
||||||
|
i0.Expression<String>? buttonId,
|
||||||
|
i0.Expression<String>? orderKey,
|
||||||
|
i0.Expression<bool>? isVisible,
|
||||||
|
i0.Expression<String>? fallbackId,
|
||||||
|
i0.Expression<int>? rowid,
|
||||||
|
}) {
|
||||||
|
return i0.RawValuesInsertable({
|
||||||
|
if (buttonId != null) 'button_id': buttonId,
|
||||||
|
if (orderKey != null) 'order_key': orderKey,
|
||||||
|
if (isVisible != null) 'is_visible': isVisible,
|
||||||
|
if (fallbackId != null) 'fallback_id': fallbackId,
|
||||||
|
if (rowid != null) 'rowid': rowid,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
i1.QuickSwitcherButtonConfigsCompanion copyWith({
|
||||||
|
i0.Value<String>? buttonId,
|
||||||
|
i0.Value<String>? orderKey,
|
||||||
|
i0.Value<bool>? isVisible,
|
||||||
|
i0.Value<String?>? fallbackId,
|
||||||
|
i0.Value<int>? rowid,
|
||||||
|
}) {
|
||||||
|
return i1.QuickSwitcherButtonConfigsCompanion(
|
||||||
|
buttonId: buttonId ?? this.buttonId,
|
||||||
|
orderKey: orderKey ?? this.orderKey,
|
||||||
|
isVisible: isVisible ?? this.isVisible,
|
||||||
|
fallbackId: fallbackId ?? this.fallbackId,
|
||||||
|
rowid: rowid ?? this.rowid,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, i0.Expression>{};
|
||||||
|
if (buttonId.present) {
|
||||||
|
map['button_id'] = i0.Variable<String>(buttonId.value);
|
||||||
|
}
|
||||||
|
if (orderKey.present) {
|
||||||
|
map['order_key'] = i0.Variable<String>(orderKey.value);
|
||||||
|
}
|
||||||
|
if (isVisible.present) {
|
||||||
|
map['is_visible'] = i0.Variable<bool>(isVisible.value);
|
||||||
|
}
|
||||||
|
if (fallbackId.present) {
|
||||||
|
map['fallback_id'] = i0.Variable<String>(fallbackId.value);
|
||||||
|
}
|
||||||
|
if (rowid.present) {
|
||||||
|
map['rowid'] = i0.Variable<int>(rowid.value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('QuickSwitcherButtonConfigsCompanion(')
|
||||||
|
..write('buttonId: $buttonId, ')
|
||||||
|
..write('orderKey: $orderKey, ')
|
||||||
|
..write('isVisible: $isVisible, ')
|
||||||
|
..write('fallbackId: $fallbackId, ')
|
||||||
|
..write('rowid: $rowid')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.Index get idxQuickSwitcherOrderKey => i0.Index(
|
||||||
|
'idx_quick_switcher_order_key',
|
||||||
|
'CREATE INDEX idx_quick_switcher_order_key ON quick_switcher_button_configs (order_key)',
|
||||||
|
);
|
||||||
|
|
||||||
class SearchTokens extends i0.Table
|
class SearchTokens extends i0.Table
|
||||||
with i0.TableInfo<SearchTokens, i1.SearchToken> {
|
with i0.TableInfo<SearchTokens, i1.SearchToken> {
|
||||||
@override
|
@override
|
||||||
@@ -3259,6 +3738,50 @@ class DefinitionsDrift extends i4.ModularAccessor {
|
|||||||
).map((i0.QueryRow row) => row.read<String>('_c0'));
|
).map((i0.QueryRow row) => row.read<String>('_c0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i0.Selectable<String> quickSwitcherLeadingOrderKey({
|
||||||
|
required int bucket,
|
||||||
|
required bool isVisible,
|
||||||
|
}) {
|
||||||
|
return customSelect(
|
||||||
|
'SELECT lexo_rank_previous(?1, (SELECT order_key FROM quick_switcher_button_configs WHERE is_visible = ?2 ORDER BY order_key LIMIT 1)) AS _c0',
|
||||||
|
variables: [i0.Variable<int>(bucket), i0.Variable<bool>(isVisible)],
|
||||||
|
readsFrom: {quickSwitcherButtonConfigs},
|
||||||
|
).map((i0.QueryRow row) => row.read<String>('_c0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.Selectable<String> quickSwitcherTrailingOrderKey({
|
||||||
|
required int bucket,
|
||||||
|
required bool isVisible,
|
||||||
|
}) {
|
||||||
|
return customSelect(
|
||||||
|
'SELECT lexo_rank_next(?1, (SELECT order_key FROM quick_switcher_button_configs WHERE is_visible = ?2 ORDER BY order_key DESC LIMIT 1)) AS _c0',
|
||||||
|
variables: [i0.Variable<int>(bucket), i0.Variable<bool>(isVisible)],
|
||||||
|
readsFrom: {quickSwitcherButtonConfigs},
|
||||||
|
).map((i0.QueryRow row) => row.read<String>('_c0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.Selectable<String> quickSwitcherOrderKeyAfterButton({
|
||||||
|
required bool isVisible,
|
||||||
|
required String buttonId,
|
||||||
|
}) {
|
||||||
|
return customSelect(
|
||||||
|
'WITH ordered_table AS (SELECT button_id, order_key, LEAD(order_key)OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS next_order_key FROM quick_switcher_button_configs WHERE is_visible = ?1) SELECT lexo_rank_reorder_after(order_key, next_order_key) AS _c0 FROM ordered_table WHERE button_id = ?2',
|
||||||
|
variables: [i0.Variable<bool>(isVisible), i0.Variable<String>(buttonId)],
|
||||||
|
readsFrom: {quickSwitcherButtonConfigs},
|
||||||
|
).map((i0.QueryRow row) => row.read<String>('_c0'));
|
||||||
|
}
|
||||||
|
|
||||||
|
i0.Selectable<String> quickSwitcherOrderKeyBeforeButton({
|
||||||
|
required bool isVisible,
|
||||||
|
required String buttonId,
|
||||||
|
}) {
|
||||||
|
return customSelect(
|
||||||
|
'WITH ordered_table AS (SELECT button_id, order_key, LAG(order_key)OVER (ORDER BY order_key RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW EXCLUDE NO OTHERS) AS prev_order_key FROM quick_switcher_button_configs WHERE is_visible = ?1) SELECT lexo_rank_reorder_before(order_key, prev_order_key) AS _c0 FROM ordered_table WHERE button_id = ?2',
|
||||||
|
variables: [i0.Variable<bool>(isVisible), i0.Variable<String>(buttonId)],
|
||||||
|
readsFrom: {quickSwitcherButtonConfigs},
|
||||||
|
).map((i0.QueryRow row) => row.read<String>('_c0'));
|
||||||
|
}
|
||||||
|
|
||||||
Future<int> evictCacheEntries({required int limit}) {
|
Future<int> evictCacheEntries({required int limit}) {
|
||||||
return customUpdate(
|
return customUpdate(
|
||||||
'DELETE FROM icon_cache WHERE "rowid" IN (SELECT "rowid" FROM icon_cache ORDER BY fetch_date DESC LIMIT -1 OFFSET ?1)',
|
'DELETE FROM icon_cache WHERE "rowid" IN (SELECT "rowid" FROM icon_cache ORDER BY fetch_date DESC LIMIT -1 OFFSET ?1)',
|
||||||
@@ -3271,6 +3794,12 @@ class DefinitionsDrift extends i4.ModularAccessor {
|
|||||||
i1.ToolbarButtonConfigs get toolbarButtonConfigs => i4.ReadDatabaseContainer(
|
i1.ToolbarButtonConfigs get toolbarButtonConfigs => i4.ReadDatabaseContainer(
|
||||||
attachedDatabase,
|
attachedDatabase,
|
||||||
).resultSet<i1.ToolbarButtonConfigs>('toolbar_button_configs');
|
).resultSet<i1.ToolbarButtonConfigs>('toolbar_button_configs');
|
||||||
|
i1.QuickSwitcherButtonConfigs get quickSwitcherButtonConfigs =>
|
||||||
|
i4.ReadDatabaseContainer(
|
||||||
|
attachedDatabase,
|
||||||
|
).resultSet<i1.QuickSwitcherButtonConfigs>(
|
||||||
|
'quick_switcher_button_configs',
|
||||||
|
);
|
||||||
i1.IconCache get iconCache => i4.ReadDatabaseContainer(
|
i1.IconCache get iconCache => i4.ReadDatabaseContainer(
|
||||||
attachedDatabase,
|
attachedDatabase,
|
||||||
).resultSet<i1.IconCache>('icon_cache');
|
).resultSet<i1.IconCache>('icon_cache');
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import 'schema_v5.dart' as v5;
|
|||||||
import 'schema_v6.dart' as v6;
|
import 'schema_v6.dart' as v6;
|
||||||
import 'schema_v7.dart' as v7;
|
import 'schema_v7.dart' as v7;
|
||||||
import 'schema_v8.dart' as v8;
|
import 'schema_v8.dart' as v8;
|
||||||
|
import 'schema_v9.dart' as v9;
|
||||||
|
|
||||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||||
@override
|
@override
|
||||||
@@ -33,10 +34,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||||||
return v7.DatabaseAtV7(db);
|
return v7.DatabaseAtV7(db);
|
||||||
case 8:
|
case 8:
|
||||||
return v8.DatabaseAtV8(db);
|
return v8.DatabaseAtV8(db);
|
||||||
|
case 9:
|
||||||
|
return v9.DatabaseAtV9(db);
|
||||||
default:
|
default:
|
||||||
throw MissingSchemaException(version, versions);
|
throw MissingSchemaException(version, versions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8];
|
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user