refactored design

This commit is contained in:
2025-10-28 14:16:17 +01:00
parent 16b71d9ea8
commit ef225b281f
34 changed files with 2574 additions and 819 deletions

View File

@ -16,6 +16,9 @@ export default defineNuxtConfig({
},
app: {
head: {
viewport: 'width=device-width, initial-scale=1.0, viewport-fit=cover',
},
pageTransition: {
name: 'fade',
},
@ -108,8 +111,7 @@ export default defineNuxtConfig({
runtimeConfig: {
public: {
haexVault: {
lastVaultFileName: 'lastVaults.json',
instanceFileName: 'instance.json',
deviceFileName: 'device.json',
defaultVaultName: 'HaexHub',
},
},

View File

@ -21,19 +21,19 @@
"@nuxt/eslint": "1.9.0",
"@nuxt/fonts": "0.11.4",
"@nuxt/icon": "2.0.0",
"@nuxt/ui": "4.0.0",
"@nuxt/ui": "4.1.0",
"@nuxtjs/i18n": "10.0.6",
"@pinia/nuxt": "^0.11.2",
"@tailwindcss/vite": "^4.1.16",
"@tauri-apps/api": "^2.9.0",
"@tauri-apps/plugin-dialog": "^2.4.0",
"@tauri-apps/plugin-fs": "^2.4.2",
"@tauri-apps/plugin-dialog": "^2.4.2",
"@tauri-apps/plugin-fs": "^2.4.4",
"@tauri-apps/plugin-http": "2.5.2",
"@tauri-apps/plugin-notification": "2.3.1",
"@tauri-apps/plugin-opener": "^2.5.0",
"@tauri-apps/plugin-os": "^2.3.1",
"@tauri-apps/plugin-opener": "^2.5.2",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-sql": "2.3.0",
"@tauri-apps/plugin-store": "^2.4.0",
"@tauri-apps/plugin-store": "^2.4.1",
"@vueuse/components": "^13.9.0",
"@vueuse/core": "^13.9.0",
"@vueuse/gesture": "^2.0.0",
@ -41,7 +41,6 @@
"drizzle-orm": "^0.44.7",
"eslint": "^9.38.0",
"fuse.js": "^7.1.0",
"nuxt": "^4.1.3",
"nuxt-zod-i18n": "^1.12.1",
"swiper": "^12.0.3",
"tailwindcss": "^4.1.16",
@ -51,8 +50,8 @@
},
"devDependencies": {
"@iconify-json/hugeicons": "^1.2.17",
"@iconify-json/lucide": "^1.2.70",
"@iconify/json": "^2.2.399",
"@iconify-json/lucide": "^1.2.71",
"@iconify/json": "^2.2.401",
"@iconify/tailwind4": "^1.0.6",
"@libsql/client": "^0.15.15",
"@tauri-apps/cli": "^2.9.1",
@ -61,6 +60,7 @@
"@vue/compiler-sfc": "^3.5.22",
"drizzle-kit": "^0.31.5",
"globals": "^16.4.0",
"nuxt": "^4.2.0",
"prettier": "3.6.2",
"tsx": "^4.20.6",
"tw-animate-css": "^1.4.0",

837
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

69
src-tauri/Cargo.lock generated
View File

@ -4399,9 +4399,9 @@ dependencies = [
[[package]]
name = "tao"
version = "0.34.3"
version = "0.34.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7"
checksum = "f3a753bdc39c07b192151523a3f77cd0394aa75413802c883a0f6f6a0e5ee2e7"
dependencies = [
"bitflags 2.9.0",
"block2 0.6.0",
@ -4456,9 +4456,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "tauri"
version = "2.8.5"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d1d3b3dc4c101ac989fd7db77e045cc6d91a25349cd410455cb5c57d510c1c"
checksum = "c9871670c6711f50fddd4e20350be6b9dd6e6c2b5d77d8ee8900eb0d58cd837a"
dependencies = [
"anyhow",
"bytes",
@ -4500,7 +4500,6 @@ dependencies = [
"tokio",
"tray-icon",
"url",
"urlpattern",
"webkit2gtk",
"webview2-com",
"window-vibrancy",
@ -4509,9 +4508,9 @@ dependencies = [
[[package]]
name = "tauri-build"
version = "2.4.1"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c432ccc9ff661803dab74c6cd78de11026a578a9307610bbc39d3c55be7943f"
checksum = "a924b6c50fe83193f0f8b14072afa7c25b7a72752a2a73d9549b463f5fe91a38"
dependencies = [
"anyhow",
"cargo_toml",
@ -4531,9 +4530,9 @@ dependencies = [
[[package]]
name = "tauri-codegen"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab3a62cf2e6253936a8b267c2e95839674e7439f104fa96ad0025e149d54d8a"
checksum = "6c1fe64c74cc40f90848281a90058a6db931eb400b60205840e09801ee30f190"
dependencies = [
"base64 0.22.1",
"brotli",
@ -4558,9 +4557,9 @@ dependencies = [
[[package]]
name = "tauri-macros"
version = "2.4.0"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4368ea8094e7045217edb690f493b55b30caf9f3e61f79b4c24b6db91f07995e"
checksum = "260c5d2eb036b76206b9fca20b7be3614cfd21046c5396f7959e0e64a4b07f2f"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@ -4589,9 +4588,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
version = "2.4.0"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0beee42a4002bc695550599b011728d9dfabf82f767f134754ed6655e434824e"
checksum = "313f8138692ddc4a2127c4c9607d616a46f5c042e77b3722450866da0aad2f19"
dependencies = [
"log",
"raw-window-handle",
@ -4607,9 +4606,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs"
version = "2.4.2"
version = "2.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "315784ec4be45e90a987687bae7235e6be3d6e9e350d2b75c16b8a4bf22c1db7"
checksum = "47df422695255ecbe7bac7012440eddaeefd026656171eac9559f5243d3230d9"
dependencies = [
"anyhow",
"dunce",
@ -4629,9 +4628,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-http"
version = "2.5.2"
version = "2.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "938a3d7051c9a82b431e3a0f3468f85715b3442b3c3a3913095e9fa509e2652c"
checksum = "c00685aceab12643cf024f712ab0448ba8fcadf86f2391d49d2e5aa732aacc70"
dependencies = [
"bytes",
"cookie_store",
@ -4653,9 +4652,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-notification"
version = "2.3.1"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fbc86b929b5376ab84b25c060f966d146b2fbd59b6af8264027b343c82c219"
checksum = "01fc2c5ff41105bd1f7242d8201fdf3efd70749b82fa013a17f2126357d194cc"
dependencies = [
"log",
"notify-rust",
@ -4672,9 +4671,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-opener"
version = "2.5.0"
version = "2.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "786156aa8e89e03d271fbd3fe642207da8e65f3c961baa9e2930f332bf80a1f5"
checksum = "c26b72571d25dee25667940027114e60f569fc3974f8cefbe50c2cbc5fd65e3b"
dependencies = [
"dunce",
"glob",
@ -4694,9 +4693,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-os"
version = "2.3.1"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a1c77ebf6f20417ab2a74e8c310820ba52151406d0c80fbcea7df232e3f6ba"
checksum = "d8f08346c8deb39e96f86973da0e2d76cbb933d7ac9b750f6dc4daf955a6f997"
dependencies = [
"gethostname",
"log",
@ -4712,9 +4711,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-persisted-scope"
version = "2.3.2"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41f1fed7dc3c24a4bdb183ce7c18490466985e5b3aaef05825bd62588c507ae2"
checksum = "65e4639faf38e4527a4549cbc68b788c0d29b03b65e65f1590f5ec582df5d028"
dependencies = [
"aho-corasick",
"bincode",
@ -4728,9 +4727,9 @@ dependencies = [
[[package]]
name = "tauri-plugin-store"
version = "2.4.0"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d85dd80d60a76ee2c2fdce09e9ef30877b239c2a6bb76e6d7d03708aa5f13a19"
checksum = "59a77036340a97eb5bbe1b3209c31e5f27f75e6f92a52fd9dd4b211ef08bf310"
dependencies = [
"dunce",
"serde",
@ -4744,9 +4743,9 @@ dependencies = [
[[package]]
name = "tauri-runtime"
version = "2.8.0"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4cfc9ad45b487d3fded5a4731a567872a4812e9552e3964161b08edabf93846"
checksum = "9368f09358496f2229313fccb37682ad116b7f46fa76981efe116994a0628926"
dependencies = [
"cookie",
"dpi",
@ -4769,9 +4768,9 @@ dependencies = [
[[package]]
name = "tauri-runtime-wry"
version = "2.8.1"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fe9d48bd122ff002064e88cfcd7027090d789c4302714e68fcccba0f4b7807"
checksum = "929f5df216f5c02a9e894554401bcdab6eec3e39ec6a4a7731c7067fc8688a93"
dependencies = [
"gtk",
"http",
@ -4796,9 +4795,9 @@ dependencies = [
[[package]]
name = "tauri-utils"
version = "2.7.0"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41a3852fdf9a4f8fbeaa63dc3e9a85284dd6ef7200751f0bd66ceee30c93f212"
checksum = "f6b8bbe426abdbf52d050e52ed693130dbd68375b9ad82a3fb17efb4c8d85673"
dependencies = [
"anyhow",
"brotli",
@ -6190,9 +6189,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "wry"
version = "0.53.3"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f0e9642a0d061f6236c54ccae64c2722a7879ad4ec7dff59bd376d446d8e90"
checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2"
dependencies = [
"base64 0.22.1",
"block2 0.6.0",

View File

@ -39,18 +39,18 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1.0.143"
sha2 = "0.10.9"
sqlparser = { version = "0.59.0", features = ["visitor"] }
tauri = { version = "2.8.5", features = ["protocol-asset", "devtools"] }
tauri-plugin-dialog = "2.4.0"
tauri = { version = "2.9.1", features = ["protocol-asset", "devtools"] }
tauri-plugin-dialog = "2.4.2"
tauri-plugin-fs = "2.4.0"
tauri-plugin-http = "2.5.2"
tauri-plugin-notification = "2.3.1"
tauri-plugin-opener = "2.5.0"
tauri-plugin-os = "2.3"
tauri-plugin-persisted-scope = "2.3.2"
tauri-plugin-store = "2.4.0"
tauri-plugin-http = "2.5.4"
tauri-plugin-notification = "2.3.3"
tauri-plugin-opener = "2.5.2"
tauri-plugin-os = "2.3.2"
tauri-plugin-persisted-scope = "2.3.4"
tauri-plugin-store = "2.4.1"
thiserror = "2.0.17"
ts-rs = { version = "11.1.0", features = ["serde-compat"] }
uhlc = "0.8.2"
url = "2.5.7"
uuid = { version = "1.18.1", features = ["v4"] }
zip = "6.0.0"
url = "2.5.7"

View File

@ -19,5 +19,3 @@ const dummyExecutor = async (
// Erstelle die Drizzle-Instanz für den SQLite-Dialekt
// Übergib den dummyExecutor und das importierte Schema
export const db = drizzle(dummyExecutor, { schema })
// Exportiere auch alle Schema-Definitionen weiter, damit man alles aus einer Datei importieren kann

View File

@ -0,0 +1 @@
ALTER TABLE `haex_workspaces` ADD `device_id` text NOT NULL;

View File

@ -0,0 +1,677 @@
{
"version": "6",
"dialect": "sqlite",
"id": "27735348-b9c5-4bc6-9cc5-dd707ad689b9",
"prevId": "bcdd9ad3-a87a-4a43-9eba-673f94b10287",
"tables": {
"haex_crdt_configs": {
"name": "haex_crdt_configs",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_crdt_logs": {
"name": "haex_crdt_logs",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"table_name": {
"name": "table_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"row_pks": {
"name": "row_pks",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"op_type": {
"name": "op_type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"column_name": {
"name": "column_name",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"new_value": {
"name": "new_value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"old_value": {
"name": "old_value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"idx_haex_timestamp": {
"name": "idx_haex_timestamp",
"columns": [
"haex_timestamp"
],
"isUnique": false
},
"idx_table_row": {
"name": "idx_table_row",
"columns": [
"table_name",
"row_pks"
],
"isUnique": false
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_crdt_snapshots": {
"name": "haex_crdt_snapshots",
"columns": {
"snapshot_id": {
"name": "snapshot_id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"created": {
"name": "created",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"epoch_hlc": {
"name": "epoch_hlc",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"location_url": {
"name": "location_url",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"file_size_bytes": {
"name": "file_size_bytes",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_desktop_items": {
"name": "haex_desktop_items",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"workspace_id": {
"name": "workspace_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"item_type": {
"name": "item_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"extension_id": {
"name": "extension_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"system_window_id": {
"name": "system_window_id",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"position_x": {
"name": "position_x",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"position_y": {
"name": "position_y",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"haex_desktop_items_workspace_id_haex_workspaces_id_fk": {
"name": "haex_desktop_items_workspace_id_haex_workspaces_id_fk",
"tableFrom": "haex_desktop_items",
"tableTo": "haex_workspaces",
"columnsFrom": [
"workspace_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"haex_desktop_items_extension_id_haex_extensions_id_fk": {
"name": "haex_desktop_items_extension_id_haex_extensions_id_fk",
"tableFrom": "haex_desktop_items",
"tableTo": "haex_extensions",
"columnsFrom": [
"extension_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {
"item_reference": {
"name": "item_reference",
"value": "(\"haex_desktop_items\".\"item_type\" = 'extension' AND \"haex_desktop_items\".\"extension_id\" IS NOT NULL AND \"haex_desktop_items\".\"system_window_id\" IS NULL) OR (\"haex_desktop_items\".\"item_type\" = 'system' AND \"haex_desktop_items\".\"system_window_id\" IS NOT NULL AND \"haex_desktop_items\".\"extension_id\" IS NULL) OR (\"haex_desktop_items\".\"item_type\" = 'file' AND \"haex_desktop_items\".\"system_window_id\" IS NOT NULL AND \"haex_desktop_items\".\"extension_id\" IS NULL) OR (\"haex_desktop_items\".\"item_type\" = 'folder' AND \"haex_desktop_items\".\"system_window_id\" IS NOT NULL AND \"haex_desktop_items\".\"extension_id\" IS NULL)"
}
}
},
"haex_extension_permissions": {
"name": "haex_extension_permissions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"extension_id": {
"name": "extension_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"resource_type": {
"name": "resource_type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"action": {
"name": "action",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"target": {
"name": "target",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"constraints": {
"name": "constraints",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'denied'"
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_extension_permissions_extension_id_resource_type_action_target_unique": {
"name": "haex_extension_permissions_extension_id_resource_type_action_target_unique",
"columns": [
"extension_id",
"resource_type",
"action",
"target"
],
"isUnique": true
}
},
"foreignKeys": {
"haex_extension_permissions_extension_id_haex_extensions_id_fk": {
"name": "haex_extension_permissions_extension_id_haex_extensions_id_fk",
"tableFrom": "haex_extension_permissions",
"tableTo": "haex_extensions",
"columnsFrom": [
"extension_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_extensions": {
"name": "haex_extensions",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"public_key": {
"name": "public_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"author": {
"name": "author",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"entry": {
"name": "entry",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'index.html'"
},
"homepage": {
"name": "homepage",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"enabled": {
"name": "enabled",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": true
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"signature": {
"name": "signature",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_extensions_public_key_name_unique": {
"name": "haex_extensions_public_key_name_unique",
"columns": [
"public_key",
"name"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_notifications": {
"name": "haex_notifications",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"alt": {
"name": "alt",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"date": {
"name": "date",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"icon": {
"name": "icon",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"read": {
"name": "read",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"text": {
"name": "text",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"title": {
"name": "title",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_settings": {
"name": "haex_settings",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_settings_key_type_value_unique": {
"name": "haex_settings_key_type_value_unique",
"columns": [
"key",
"type",
"value"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"haex_workspaces": {
"name": "haex_workspaces",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"device_id": {
"name": "device_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"position": {
"name": "position",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": 0
},
"haex_timestamp": {
"name": "haex_timestamp",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"haex_workspaces_position_unique": {
"name": "haex_workspaces_position_unique",
"columns": [
"position"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}

View File

@ -8,6 +8,13 @@
"when": 1761430560028,
"tag": "0000_secret_ender_wiggin",
"breakpoints": true
},
{
"idx": 1,
"version": "6",
"when": 1761581351395,
"tag": "0001_late_the_renegades",
"breakpoints": true
}
]
}

View File

@ -9,30 +9,28 @@ import {
type SQLiteColumnBuilderBase,
} from 'drizzle-orm/sqlite-core'
import tableNames from '../tableNames.json'
import { crdtColumnNames } from '.'
// Helper function to add common CRDT columns ( haexTimestamp)
export const withCrdtColumns = <
T extends Record<string, SQLiteColumnBuilderBase>,
>(
columns: T,
columnNames: { haexTimestamp: string },
) => ({
...columns,
haexTimestamp: text(columnNames.haexTimestamp),
haexTimestamp: text(crdtColumnNames.haexTimestamp),
})
export const haexSettings = sqliteTable(
tableNames.haex.settings.name,
{
withCrdtColumns({
id: text()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
key: text(),
type: text(),
value: text(),
haexTimestamp: text(tableNames.haex.settings.columns.haexTimestamp),
},
}),
(table) => [unique().on(table.key, table.type, table.value)],
)
export type InsertHaexSettings = typeof haexSettings.$inferInsert
@ -40,7 +38,7 @@ export type SelectHaexSettings = typeof haexSettings.$inferSelect
export const haexExtensions = sqliteTable(
tableNames.haex.extensions.name,
{
withCrdtColumns({
id: text()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
@ -54,8 +52,7 @@ export const haexExtensions = sqliteTable(
enabled: integer({ mode: 'boolean' }).default(true),
icon: text(),
signature: text().notNull(),
haexTimestamp: text(tableNames.haex.extensions.columns.haexTimestamp),
},
}),
(table) => [
// UNIQUE constraint: Pro Developer (public_key) kann nur eine Extension mit diesem Namen existieren
unique().on(table.public_key, table.name),
@ -66,7 +63,7 @@ export type SelectHaexExtensions = typeof haexExtensions.$inferSelect
export const haexExtensionPermissions = sqliteTable(
tableNames.haex.extension_permissions.name,
{
withCrdtColumns({
id: text()
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
@ -88,10 +85,7 @@ export const haexExtensionPermissions = sqliteTable(
updateAt: integer('updated_at', { mode: 'timestamp' }).$onUpdate(
() => new Date(),
),
haexTimestamp: text(
tableNames.haex.extension_permissions.columns.haexTimestamp,
),
},
}),
(table) => [
unique().on(
table.extensionId,
@ -108,7 +102,7 @@ export type SelecthaexExtensionPermissions =
export const haexNotifications = sqliteTable(
tableNames.haex.notifications.name,
{
withCrdtColumns({
id: text().primaryKey(),
alt: text(),
date: text(),
@ -121,26 +115,23 @@ export const haexNotifications = sqliteTable(
type: text({
enum: ['error', 'success', 'warning', 'info', 'log'],
}).notNull(),
haexTimestamp: text(tableNames.haex.notifications.columns.haexTimestamp),
},
}),
)
export type InsertHaexNotifications = typeof haexNotifications.$inferInsert
export type SelectHaexNotifications = typeof haexNotifications.$inferSelect
export const haexWorkspaces = sqliteTable(
tableNames.haex.workspaces.name,
withCrdtColumns(
{
withCrdtColumns({
id: text(tableNames.haex.workspaces.columns.id)
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
deviceId: text(tableNames.haex.workspaces.columns.deviceId).notNull(),
name: text(tableNames.haex.workspaces.columns.name).notNull(),
position: integer(tableNames.haex.workspaces.columns.position)
.notNull()
.default(0),
},
tableNames.haex.workspaces.columns,
),
}),
(table) => [unique().on(table.position)],
)
export type InsertHaexWorkspaces = typeof haexWorkspaces.$inferInsert
@ -148,8 +139,7 @@ export type SelectHaexWorkspaces = typeof haexWorkspaces.$inferSelect
export const haexDesktopItems = sqliteTable(
tableNames.haex.desktop_items.name,
withCrdtColumns(
{
withCrdtColumns({
id: text(tableNames.haex.desktop_items.columns.id)
.primaryKey()
.$defaultFn(() => crypto.randomUUID()),
@ -160,8 +150,9 @@ export const haexDesktopItems = sqliteTable(
enum: ['system', 'extension', 'file', 'folder'],
}).notNull(),
// Für Extensions (wenn itemType = 'extension')
extensionId: text(tableNames.haex.desktop_items.columns.extensionId)
.references((): AnySQLiteColumn => haexExtensions.id, {
extensionId: text(
tableNames.haex.desktop_items.columns.extensionId,
).references((): AnySQLiteColumn => haexExtensions.id, {
onDelete: 'cascade',
}),
// Für System Windows (wenn itemType = 'system')
@ -172,9 +163,7 @@ export const haexDesktopItems = sqliteTable(
positionY: integer(tableNames.haex.desktop_items.columns.positionY)
.notNull()
.default(0),
},
tableNames.haex.desktop_items.columns,
),
}),
(table) => [
check(
'item_reference',

View File

@ -1,2 +1,5 @@
export const crdtColumnNames = {
haexTimestamp: 'haex_timestamp',
}
export * from './crdt'
export * from './haex'

View File

@ -67,6 +67,7 @@
"name": "haex_workspaces",
"columns": {
"id": "id",
"deviceId": "device_id",
"name": "name",
"position": "position",
"createdAt": "created_at",

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -1400,10 +1400,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",
@ -2277,10 +2277,10 @@
"markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`"
},
{
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`",
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`",
"type": "string",
"const": "core:app:default",
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`"
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`"
},
{
"description": "Enables the app_hide command without any pre-configured scope.",
@ -2324,12 +2324,24 @@
"const": "core:app:allow-name",
"markdownDescription": "Enables the name command without any pre-configured scope."
},
{
"description": "Enables the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-register-listener",
"markdownDescription": "Enables the register_listener command without any pre-configured scope."
},
{
"description": "Enables the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-data-store",
"markdownDescription": "Enables the remove_data_store command without any pre-configured scope."
},
{
"description": "Enables the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-listener",
"markdownDescription": "Enables the remove_listener command without any pre-configured scope."
},
{
"description": "Enables the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -2396,12 +2408,24 @@
"const": "core:app:deny-name",
"markdownDescription": "Denies the name command without any pre-configured scope."
},
{
"description": "Denies the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-register-listener",
"markdownDescription": "Denies the register_listener command without any pre-configured scope."
},
{
"description": "Denies the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-data-store",
"markdownDescription": "Denies the remove_data_store command without any pre-configured scope."
},
{
"description": "Denies the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-listener",
"markdownDescription": "Denies the remove_listener command without any pre-configured scope."
},
{
"description": "Denies the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -5541,10 +5565,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",

View File

@ -1400,10 +1400,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",
@ -2277,10 +2277,10 @@
"markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`"
},
{
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`",
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`",
"type": "string",
"const": "core:app:default",
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`"
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`"
},
{
"description": "Enables the app_hide command without any pre-configured scope.",
@ -2324,12 +2324,24 @@
"const": "core:app:allow-name",
"markdownDescription": "Enables the name command without any pre-configured scope."
},
{
"description": "Enables the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-register-listener",
"markdownDescription": "Enables the register_listener command without any pre-configured scope."
},
{
"description": "Enables the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-data-store",
"markdownDescription": "Enables the remove_data_store command without any pre-configured scope."
},
{
"description": "Enables the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-listener",
"markdownDescription": "Enables the remove_listener command without any pre-configured scope."
},
{
"description": "Enables the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -2396,12 +2408,24 @@
"const": "core:app:deny-name",
"markdownDescription": "Denies the name command without any pre-configured scope."
},
{
"description": "Denies the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-register-listener",
"markdownDescription": "Denies the register_listener command without any pre-configured scope."
},
{
"description": "Denies the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-data-store",
"markdownDescription": "Denies the remove_data_store command without any pre-configured scope."
},
{
"description": "Denies the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-listener",
"markdownDescription": "Denies the remove_listener command without any pre-configured scope."
},
{
"description": "Denies the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -5541,10 +5565,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",

View File

@ -1400,10 +1400,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",
@ -2277,10 +2277,10 @@
"markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`"
},
{
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`",
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`",
"type": "string",
"const": "core:app:default",
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`"
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`"
},
{
"description": "Enables the app_hide command without any pre-configured scope.",
@ -2324,12 +2324,24 @@
"const": "core:app:allow-name",
"markdownDescription": "Enables the name command without any pre-configured scope."
},
{
"description": "Enables the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-register-listener",
"markdownDescription": "Enables the register_listener command without any pre-configured scope."
},
{
"description": "Enables the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-data-store",
"markdownDescription": "Enables the remove_data_store command without any pre-configured scope."
},
{
"description": "Enables the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-listener",
"markdownDescription": "Enables the remove_listener command without any pre-configured scope."
},
{
"description": "Enables the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -2396,12 +2408,24 @@
"const": "core:app:deny-name",
"markdownDescription": "Denies the name command without any pre-configured scope."
},
{
"description": "Denies the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-register-listener",
"markdownDescription": "Denies the register_listener command without any pre-configured scope."
},
{
"description": "Denies the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-data-store",
"markdownDescription": "Denies the remove_data_store command without any pre-configured scope."
},
{
"description": "Denies the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-listener",
"markdownDescription": "Denies the remove_listener command without any pre-configured scope."
},
{
"description": "Denies the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -5541,10 +5565,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",

View File

@ -1400,10 +1400,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",
@ -2277,10 +2277,10 @@
"markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`"
},
{
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`",
"description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`",
"type": "string",
"const": "core:app:default",
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`"
"markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`"
},
{
"description": "Enables the app_hide command without any pre-configured scope.",
@ -2324,12 +2324,24 @@
"const": "core:app:allow-name",
"markdownDescription": "Enables the name command without any pre-configured scope."
},
{
"description": "Enables the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-register-listener",
"markdownDescription": "Enables the register_listener command without any pre-configured scope."
},
{
"description": "Enables the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-data-store",
"markdownDescription": "Enables the remove_data_store command without any pre-configured scope."
},
{
"description": "Enables the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:allow-remove-listener",
"markdownDescription": "Enables the remove_listener command without any pre-configured scope."
},
{
"description": "Enables the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -2396,12 +2408,24 @@
"const": "core:app:deny-name",
"markdownDescription": "Denies the name command without any pre-configured scope."
},
{
"description": "Denies the register_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-register-listener",
"markdownDescription": "Denies the register_listener command without any pre-configured scope."
},
{
"description": "Denies the remove_data_store command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-data-store",
"markdownDescription": "Denies the remove_data_store command without any pre-configured scope."
},
{
"description": "Denies the remove_listener command without any pre-configured scope.",
"type": "string",
"const": "core:app:deny-remove-listener",
"markdownDescription": "Denies the remove_listener command without any pre-configured scope."
},
{
"description": "Denies the set_app_theme command without any pre-configured scope.",
"type": "string",
@ -5541,10 +5565,10 @@
"markdownDescription": "This enables all index or metadata related commands without any pre-configured accessible paths."
},
{
"description": "An empty permission you can use to modify the global scope.",
"description": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n",
"type": "string",
"const": "fs:scope",
"markdownDescription": "An empty permission you can use to modify the global scope."
"markdownDescription": "An empty permission you can use to modify the global scope.\n\n## Example\n\n```json\n{\n \"identifier\": \"read-documents\",\n \"windows\": [\"main\"],\n \"permissions\": [\n \"fs:allow-read\",\n {\n \"identifier\": \"fs:scope\",\n \"allow\": [\n \"$APPDATA/documents/**/*\"\n ],\n \"deny\": [\n \"$APPDATA/documents/secret.txt\"\n ]\n }\n ]\n}\n```\n"
},
{
"description": "This scope permits access to all files and list content of top level directories in the application folders.",

View File

@ -1,9 +1,7 @@
<template>
<UApp :locale="locales[locale]">
<div data-vaul-drawer-wrapper>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</UApp>
</template>

View File

@ -13,6 +13,20 @@
[disabled] {
@apply cursor-not-allowed;
}
#__nuxt {
/* Stellt sicher, dass die App immer die volle Höhe hat */
min-height: 100vh;
/* Sorgt dafür, dass Padding die Höhe nicht sprengt */
@apply box-border;
/* Die Safe-Area Paddings */
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
}
@theme {

View File

@ -1,7 +1,7 @@
<template>
<div
ref="desktopEl"
class="w-full h-full relative overflow-hidden isolate"
class="w-full h-full relative overflow-hidden"
>
<Swiper
:modules="[SwiperNavigation]"
@ -24,7 +24,7 @@
class="w-full h-full"
>
<div
class="w-full h-full relative isolate"
class="w-full h-full relative"
@click.self.stop="handleDesktopClick"
@mousedown.left.self="handleAreaSelectStart"
@dragover.prevent="handleDragOver"
@ -51,7 +51,6 @@
class="absolute right-0 top-0 bottom-0 border-blue-500 pointer-events-none backdrop-blur-sm z-50 transition-all duration-500 ease-in-out"
:class="showRightSnapZone ? 'w-1/2 bg-blue-500/20 border-2' : 'w-0'"
/>
<!-- </Transition> -->
<!-- Area Selection Box -->
<div
@ -199,52 +198,6 @@
<!-- Window Overview Modal -->
<HaexWindowOverview />
<!-- Workspace Drawer -->
<UDrawer
v-model:open="isOverviewMode"
direction="left"
:dismissible="false"
:overlay="false"
:modal="false"
title="Workspaces"
description="Workspaces"
>
<template #content>
<div class="p-6 h-full overflow-y-auto">
<UButton
block
trailing-icon="mdi-close"
class="text-2xl font-bold ext-gray-900 dark:text-white mb-4"
@click="isOverviewMode = false"
>
Workspaces
</UButton>
<!-- Workspace Cards -->
<div class="flex flex-col gap-3">
<HaexWorkspaceCard
v-for="workspace in workspaces"
:key="workspace.id"
:workspace
/>
</div>
<!-- Add New Workspace Button -->
<UButton
block
variant="outline"
class="mt-6"
@click="handleAddWorkspace"
>
<template #leading>
<UIcon name="i-heroicons-plus" />
</template>
New Workspace
</UButton>
</div>
</template>
</UDrawer>
</div>
</template>
@ -600,17 +553,6 @@ const onSlideChange = (swiper: SwiperType) => {
)
}
// Workspace control handlers
const handleAddWorkspace = async () => {
await workspaceStore.addWorkspaceAsync()
// Swiper will auto-slide to new workspace because we switch in addWorkspaceAsync
nextTick(() => {
if (swiperInstance.value) {
swiperInstance.value.slideTo(workspaces.value.length - 1)
}
})
}
/* const handleRemoveWorkspace = async () => {
if (!currentWorkspace.value || workspaces.value.length <= 1) return

View File

@ -5,7 +5,7 @@
:description="vault.path || path"
@confirm="onOpenDatabase"
>
<!-- <UiButton
<UiButton
:label="t('vault.open')"
:ui="{
base: 'px-3 py-2',
@ -14,8 +14,7 @@
size="xl"
variant="outline"
block
@click.stop="onLoadDatabase"
/> -->
/>
<template #title>
<i18n-t

View File

@ -0,0 +1,83 @@
<template>
<UTooltip :text="tooltip">
<button
class="size-8 shrink-0 rounded-lg flex justify-center transition-colors group"
:class="variantClasses.buttonClass"
@click="(e) => $emit('click', e)"
>
<UIcon
:name="icon"
class="size-4 text-gray-600 dark:text-gray-400"
:class="variantClasses.iconClass"
/>
</button>
</UTooltip>
</template>
<script setup lang="ts">
const props = defineProps<{
variant: 'close' | 'maximize' | 'minimize'
isMaximized?: boolean
}>()
defineEmits(['click'])
const icon = computed(() => {
switch (props.variant) {
case 'close':
return 'i-heroicons-x-mark'
case 'maximize':
return props.isMaximized
? 'i-heroicons-arrows-pointing-in'
: 'i-heroicons-arrows-pointing-out'
default:
return 'i-heroicons-minus'
}
})
const variantClasses = computed(() => {
if (props.variant === 'close') {
return {
iconClass: 'group-hover:text-error',
buttonClass: 'hover:bg-error/30 items-center',
}
} else if (props.variant === 'maximize') {
return {
iconClass: 'group-hover:text-warning',
buttonClass: 'hover:bg-warning/30 items-center',
}
} else {
return {
iconClass: 'group-hover:text-success',
buttonClass: 'hover:bg-success/30 items-end pb-1',
}
}
})
const { t } = useI18n()
const tooltip = computed(() => {
switch (props.variant) {
case 'close':
return t('close')
case 'maximize':
return props.isMaximized ? t('shrink') : t('maximize')
default:
return t('minimize')
}
})
</script>
<i18n lang="yaml">
de:
close: Schließen
maximize: Maximieren
shrink: Verkleinern
minimize: Minimieren
en:
close: Close
maximize: Maximize
shrink: Shrink
minimize: Minimize
</i18n>

View File

@ -38,37 +38,21 @@
<!-- Right: Window Controls -->
<div class="flex items-center gap-1 justify-end">
<button
class="w-8 h-8 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 flex items-center justify-center transition-colors"
<HaexWindowButton
variant="minimize"
@click.stop="handleMinimize"
>
<UIcon
name="i-heroicons-minus"
class="w-4 h-4 text-gray-600 dark:text-gray-400"
/>
</button>
<button
class="w-8 h-8 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 flex items-center justify-center transition-colors"
<HaexWindowButton
:is-maximized
variant="maximize"
@click.stop="handleMaximize"
>
<UIcon
:name="
isMaximized
? 'i-heroicons-arrows-pointing-in'
: 'i-heroicons-arrows-pointing-out'
"
class="w-4 h-4 text-gray-600 dark:text-gray-400"
/>
</button>
<button
class="w-8 h-8 rounded-lg hover:bg-red-100 dark:hover:bg-red-900/30 flex items-center justify-center transition-colors group"
<HaexWindowButton
variant="close"
@click.stop="handleClose"
>
<UIcon
name="i-heroicons-x-mark"
class="w-4 h-4 text-gray-600 dark:text-gray-400 group-hover:text-red-600 dark:group-hover:text-red-400"
/>
</button>
</div>
</div>

View File

@ -1,98 +0,0 @@
<template>
<div class="flex flex-col w-full h-full overflow-hidden">
<div ref="headerRef">
<UPageHeader
as="header"
:ui="{
root: [
'bg-default border-b border-accented sticky top-0 z-50 pt-2 px-8 h-header',
],
wrapper: [
'flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4',
],
}"
>
<template #title>
<div class="flex items-center">
<UiLogoHaexhub class="size-12 shrink-0" />
<NuxtLinkLocale
class="link text-base-content link-neutral text-xl font-semibold no-underline flex items-center"
:to="{ name: 'desktop' }"
>
<UiTextGradient class="text-nowrap">
{{ currentVaultName }}
</UiTextGradient>
</NuxtLinkLocale>
</div>
</template>
<template #links>
<UButton
color="neutral"
variant="outline"
:block="isSmallScreen"
icon="i-bi-person-workspace"
size="lg"
@click="isOverviewMode = !isOverviewMode"
/>
<UButton
color="neutral"
variant="outline"
:block="isSmallScreen"
icon="i-heroicons-squares-2x2"
size="lg"
@click="showWindowOverview = !showWindowOverview"
>
<template v-if="openWindowsCount > 0" #trailing>
<UBadge
:label="openWindowsCount.toString()"
color="primary"
size="xs"
/>
</template>
</UButton>
<HaexExtensionLauncher :block="isSmallScreen" />
</template>
</UPageHeader>
</div>
<main class="flex-1 overflow-hidden bg-elevated">
<NuxtPage />
</main>
</div>
</template>
<script setup lang="ts">
const { currentVaultName } = storeToRefs(useVaultStore())
const { isSmallScreen } = storeToRefs(useUiStore())
const { isOverviewMode } = storeToRefs(useWorkspaceStore())
const { showWindowOverview, openWindowsCount } = storeToRefs(
useWindowManagerStore(),
)
</script>
<i18n lang="yaml">
de:
vault:
close: Vault schließen
sidebar:
close: Sidebar ausblenden
show: Sidebar anzeigen
search:
label: Suche
en:
vault:
close: Close vault
sidebar:
close: close sidebar
show: show sidebar
search:
label: Search
</i18n>

View File

@ -1,5 +1,145 @@
<template>
<div class="bg-default isolate w-dvw h-dvh flex flex-col">
<slot />
<div class="w-dvw h-dvh flex flex-col">
<UPageHeader
as="header"
:ui="{
root: ['px-8 py-0'],
wrapper: ['flex flex-row items-center justify-between gap-4'],
}"
>
<template #default>
<div class="flex justify-between items-center py-1">
<div>
<!-- <NuxtLinkLocale
class="link text-base-content link-neutral text-xl font-semibold no-underline flex items-center"
:to="{ name: 'desktop' }"
>
<UiTextGradient class="text-nowrap">
{{ currentVaultName }}
</UiTextGradient>
</NuxtLinkLocale> -->
<UiButton
v-if="currentVaultId"
color="neutral"
variant="outline"
icon="i-bi-person-workspace"
size="lg"
:tooltip="t('header.workspaces')"
@click="isOverviewMode = !isOverviewMode"
/>
</div>
<div>
<div v-if="!currentVaultId">
<UiDropdownLocale @select="onSelectLocale" />
</div>
<div
v-else
class="flex flex-row gap-2"
>
<UButton
v-if="openWindowsCount > 0"
color="primary"
variant="outline"
size="lg"
@click="showWindowOverview = !showWindowOverview"
>
{{ openWindowsCount }}
</UButton>
<HaexExtensionLauncher />
</div>
</div>
</div>
</template>
</UPageHeader>
<main class="flex-1 overflow-hidden bg-elevated flex flex-col">
<slot />
</main>
<!-- Workspace Drawer -->
<UDrawer
v-model:open="isOverviewMode"
direction="left"
:dismissible="false"
:overlay="false"
:modal="false"
title="Workspaces"
description="Workspaces"
>
<template #content>
<div class="p-6 h-full overflow-y-auto">
<UButton
block
trailing-icon="mdi-close"
class="text-2xl font-bold ext-gray-900 dark:text-white mb-4"
@click="isOverviewMode = false"
>
Workspaces
</UButton>
<!-- Workspace Cards -->
<div class="flex flex-col gap-3">
<HaexWorkspaceCard
v-for="workspace in workspaces"
:key="workspace.id"
:workspace
/>
</div>
<!-- Add New Workspace Button -->
<UButton
block
variant="outline"
class="mt-6"
@click="handleAddWorkspace"
>
<template #leading>
<UIcon name="i-heroicons-plus" />
</template>
New Workspace
</UButton>
</div>
</template>
</UDrawer>
</div>
</template>
<script setup lang="ts">
import type { Locale } from 'vue-i18n'
const { t, setLocale } = useI18n()
const onSelectLocale = async (locale: Locale) => {
await setLocale(locale)
}
const { currentVaultId } = storeToRefs(useVaultStore())
const { showWindowOverview, openWindowsCount } = storeToRefs(
useWindowManagerStore(),
)
const workspaceStore = useWorkspaceStore()
const { workspaces, isOverviewMode } = storeToRefs(workspaceStore)
const handleAddWorkspace = async () => {
const workspace = await workspaceStore.addWorkspaceAsync()
nextTick(() => {
workspaceStore.slideToWorkspace(workspace?.id)
})
}
</script>
<i18n lang="yaml">
de:
search:
label: Suche
header:
workspaces: Workspaces
en:
search:
label: Search
header:
workspaces: Workspaces
</i18n>

View File

@ -1,11 +1,23 @@
<template>
<div class="items-center justify-center flex w-full h-full relative">
<div class="absolute top-8 right-8 sm:top-4 sm:right-4">
<div>
<NuxtLayout>
<UDashboardPanel
id="inbox-1"
resizable
class=""
>
<template #body>
<div class="items-center justify-center flex relative flex-1">
<!-- <div class="absolute top-0 right-0">
<UiDropdownLocale @select="onSelectLocale" />
</div>
</div> -->
<div class="flex flex-col justify-center items-center gap-5 max-w-3xl">
<UiLogoHaexhub class="bg-primary p-3 size-16 rounded-full shrink-0" />
<div
class="flex flex-col justify-center items-center gap-5 max-w-3xl"
>
<UiLogoHaexhub
class="bg-primary p-3 size-16 rounded-full shrink-0"
/>
<span
class="flex flex-wrap font-bold text-pretty text-xl gap-2 justify-center"
>
@ -15,7 +27,9 @@
<UiTextGradient>Haex Hub</UiTextGradient>
</span>
<div class="flex flex-col md:flex-row gap-4 w-full h-24 md:h-auto">
<div
class="flex flex-col md:flex-row gap-4 w-full h-24 md:h-auto"
>
<HaexVaultCreate />
<HaexVaultOpen
@ -81,31 +95,38 @@
</div>
</div>
</div>
<UiDialogConfirm
v-model:open="showRemoveDialog"
:title="t('remove.title')"
:description="t('remove.description', { vaultName: vaultToBeRemoved })"
:description="
t('remove.description', { vaultName: vaultToBeRemoved })
"
@confirm="onConfirmRemoveAsync"
/>
</div>
</template>
</UDashboardPanel>
</NuxtLayout>
</div>
</template>
<script setup lang="ts">
import { openUrl } from '@tauri-apps/plugin-opener'
import type { Locale } from 'vue-i18n'
import type { VaultInfo } from '@bindings/VaultInfo'
definePageMeta({
name: 'vaultOpen',
})
const { t, setLocale } = useI18n()
const { t } = useI18n()
const passwordPromptOpen = ref(false)
const selectedVault = ref<VaultInfo>()
const showRemoveDialog = ref(false)
const { syncLastVaultsAsync, removeVaultAsync } = useLastVaultStore()
const { lastVaults } = storeToRefs(useLastVaultStore())
const vaultToBeRemoved = ref('')
@ -127,17 +148,18 @@ const onConfirmRemoveAsync = async () => {
})
}
}
const { syncLastVaultsAsync, removeVaultAsync } = useLastVaultStore()
const { syncDeviceIdAsync } = useDeviceStore()
onMounted(async () => {
try {
await syncLastVaultsAsync()
await syncDeviceIdAsync()
} catch (error) {
console.error('ERROR: ', error)
}
})
const onSelectLocale = async (locale: Locale) => {
await setLocale(locale)
}
</script>
<i18n lang="yaml">

View File

@ -1,6 +1,6 @@
<template>
<div class="w-full h-full overflow-y-auto">
<NuxtLayout name="app">
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
@ -48,7 +48,7 @@ const newDeviceName = ref<string>('unknown')
const { readNotificationsAsync } = useNotificationStore()
const { isKnownDeviceAsync } = useDeviceStore()
const { loadExtensionsAsync } = useExtensionsStore()
const { setDeviceIdIfNotExistsAsync, addDeviceNameAsync } = useDeviceStore()
const { addDeviceNameAsync } = useDeviceStore()
const { deviceId } = storeToRefs(useDeviceStore())
const { syncLocaleAsync, syncThemeAsync, syncVaultNameAsync } =
useVaultSettingsStore()
@ -56,11 +56,11 @@ const { syncLocaleAsync, syncThemeAsync, syncVaultNameAsync } =
onMounted(async () => {
try {
// Sync settings first before other initialization
await Promise.allSettled([
syncLocaleAsync(),
syncThemeAsync(),
syncVaultNameAsync(),
setDeviceIdIfNotExistsAsync(),
loadExtensionsAsync(),
readNotificationsAsync(),
])

View File

@ -10,6 +10,7 @@ export type IWorkspace = SelectHaexWorkspaces
export const useWorkspaceStore = defineStore('workspaceStore', () => {
const vaultStore = useVaultStore()
const windowStore = useWindowManagerStore()
const { deviceId } = storeToRefs(useDeviceStore())
const { currentVault } = storeToRefs(vaultStore)
@ -31,10 +32,16 @@ export const useWorkspaceStore = defineStore('workspaceStore', () => {
return
}
if (!deviceId.value) {
console.error('Keine DeviceId vergeben')
return
}
try {
const items = await currentVault.value.drizzle
.select()
.from(haexWorkspaces)
.where(eq(haexWorkspaces.deviceId, deviceId.value))
.orderBy(asc(haexWorkspaces.position))
workspaces.value = items
@ -58,11 +65,16 @@ export const useWorkspaceStore = defineStore('workspaceStore', () => {
throw new Error('Kein Vault geöffnet')
}
if (!deviceId.value) {
return
}
try {
const newIndex = workspaces.value.length + 1
const newWorkspace = {
name: name || `Workspace ${newIndex}`,
position: workspaces.value.length,
deviceId: deviceId.value,
}
const result = await currentVault.value.drizzle

View File

@ -4,8 +4,18 @@ import {
platform as tauriPlatform,
} from '@tauri-apps/plugin-os'
export const useDeviceStore = defineStore('vaultInstanceStore', () => {
const deviceId = ref<string>()
const deviceIdKey = 'deviceId'
const defaultDeviceFileName = 'device.json'
export const useDeviceStore = defineStore('vaultDeviceStore', () => {
const deviceId = ref<string | undefined>('')
const syncDeviceIdAsync = async () => {
deviceId.value = await getDeviceIdAsync()
if (deviceId.value) return deviceId.value
deviceId.value = await setDeviceIdAsync()
}
const platform = computedAsync(() => tauriPlatform())
@ -15,7 +25,7 @@ export const useDeviceStore = defineStore('vaultInstanceStore', () => {
const getDeviceIdAsync = async () => {
const store = await getStoreAsync()
return store.get<string>('id')
return await store.get<string>(deviceIdKey)
}
const getStoreAsync = async () => {
@ -23,30 +33,19 @@ export const useDeviceStore = defineStore('vaultInstanceStore', () => {
public: { haexVault },
} = useRuntimeConfig()
return await load(haexVault.instanceFileName || 'instance.json')
return await load(haexVault.deviceFileName || defaultDeviceFileName)
}
const setDeviceIdAsync = async (id?: string) => {
const store = await getStoreAsync()
const _id = id || crypto.randomUUID()
await store.set('id', _id)
deviceId.value = _id
await store.set(deviceIdKey, _id)
return _id
}
const setDeviceIdIfNotExistsAsync = async () => {
const _deviceId = await getDeviceIdAsync()
if (_deviceId) {
deviceId.value = _deviceId
return deviceId.value
}
return await setDeviceIdAsync()
}
const isKnownDeviceAsync = async () => {
const { readDeviceNameAsync } = useVaultSettingsStore()
const deviceId = await getDeviceIdAsync()
return deviceId ? (await readDeviceNameAsync(deviceId)) || false : false
return !!(await readDeviceNameAsync(deviceId.value))
}
const readDeviceNameAsync = async (id?: string) => {
@ -99,12 +98,13 @@ export const useDeviceStore = defineStore('vaultInstanceStore', () => {
addDeviceNameAsync,
deviceId,
deviceName,
getDeviceIdAsync,
hostname,
isKnownDeviceAsync,
platform,
readDeviceNameAsync,
setDeviceIdAsync,
setDeviceIdIfNotExistsAsync,
syncDeviceIdAsync,
updateDeviceNameAsync,
}
})

View File

@ -118,9 +118,11 @@ export const useVaultSettingsStore = defineStore('vaultSettingsStore', () => {
.where(eq(schema.haexSettings.key, 'vaultName'))
}
const readDeviceNameAsync = async (id: string) => {
const readDeviceNameAsync = async (id?: string) => {
const { currentVault } = useVaultStore()
if (!id) return undefined
const deviceName =
await currentVault?.drizzle?.query.haexSettings.findFirst({
where: and(

View File

@ -0,0 +1,14 @@
Blocking waiting for file lock on build directory
23.313630402s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: stale: missing "/home/haex/Projekte/haex-hub/src-tauri/src/database/schemas/crdt.ts"
23.319711685s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: false }/TargetInner { ..: lib_target("haex_hub_lib", ["staticlib", "cdylib", "rlib"], "/home/haex/Projekte/haex-hub/src-tauri/src/lib.rs", Edition2021) }
23.319734303s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "build_script_build" })
23.322781234s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="build-script-build"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/RunCustomBuild/TargetInner { ..: custom_build_target("build-script-build", "/home/haex/Projekte/haex-hub/src-tauri/build.rs", Edition2021) }
23.322837026s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="build-script-build"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleItem(MissingFile("/home/haex/Projekte/haex-hub/src-tauri/src/database/schemas/crdt.ts")))
23.335082427s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: true }/TargetInner { ..: lib_target("haex_hub_lib", ["staticlib", "cdylib", "rlib"], "/home/haex/Projekte/haex-hub/src-tauri/src/lib.rs", Edition2021) }
23.335103454s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "build_script_build" })
23.336844253s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: false }/TargetInner { name: "haex-hub", doc: true, ..: with_path("/home/haex/Projekte/haex-hub/src-tauri/src/main.rs", Edition2021) }
23.336854407s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "haex_hub_lib" })
23.338162602s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: true }/TargetInner { name: "haex-hub", doc: true, ..: with_path("/home/haex/Projekte/haex-hub/src-tauri/src/main.rs", Edition2021) }
23.338170106s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "haex_hub_lib" })
Compiling haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 25.44s

File diff suppressed because one or more lines are too long