diff --git a/bun.lock b/bun.lock index e443115..00f5bd8 100644 --- a/bun.lock +++ b/bun.lock @@ -11,6 +11,7 @@ "@codemirror/legacy-modes": "^6.5.3", "@codemirror/lint": "^6.9.7", "@codemirror/lsp-client": "^6.2.5", + "@codemirror/merge": "^6.12.2", "@codemirror/state": "^6.7.1", "@codemirror/view": "^6.43.6", "@iconify/svelte": "^5.2.2", @@ -21,6 +22,9 @@ "@tauri-apps/plugin-opener": "^2.5.4", "codemirror": "^6.0.2", "codemirror-lang-typst": "^0.4.0", + "y-codemirror.next": "^0.3.5", + "y-websocket": "^3.0.0", + "yjs": "^13.6.31", }, "devDependencies": { "@sveltejs/adapter-static": "^3.0.10", @@ -51,6 +55,8 @@ "@codemirror/lsp-client": ["@codemirror/lsp-client@6.2.5", "", { "dependencies": { "@codemirror/autocomplete": "^6.20.0", "@codemirror/language": "^6.11.0", "@codemirror/lint": "^6.8.5", "@codemirror/state": "^6.5.2", "@codemirror/view": "^6.37.0", "@lezer/highlight": "^1.2.1", "marked": "^15.0.12", "vscode-languageserver-protocol": "^3.17.5" } }, "sha512-1EqhGRmCZOV7Me+rRuwwkTuvkNoD4Nz6UcE1yx5gdwTVTLD4D9xIy48MJc0LeBQGFLn/HNRW/pHmet4EAEkJFQ=="], + "@codemirror/merge": ["@codemirror/merge@6.12.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/highlight": "^1.0.0", "style-mod": "^4.1.0" } }, "sha512-V8JvyAPjHbPupqP7BeMcsdsYCbyPij74jxIbaIJDORI+VZzW44zFmon8bF+oxGWvOKhcRmkiUMXd8MxHr3YA2w=="], + "@codemirror/search": ["@codemirror/search@6.7.1", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA=="], "@codemirror/state": ["@codemirror/state@6.7.1", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A=="], @@ -341,10 +347,14 @@ "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + "isomorphic.js": ["isomorphic.js@0.2.5", "", {}, "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw=="], + "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + "lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0serve": "bin/0serve.js", "0gentesthtml": "bin/gentesthtml.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="], + "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], @@ -435,6 +445,14 @@ "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], + "y-codemirror.next": ["y-codemirror.next@0.3.5", "", { "dependencies": { "lib0": "^0.2.42" }, "peerDependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "yjs": "^13.5.6" } }, "sha512-VluNu3e5HfEXybnypnsGwKAj+fKLd4iAnR7JuX1Sfyydmn1jCBS5wwEL/uS04Ch2ib0DnMAOF6ZRR/8kK3wyGw=="], + + "y-protocols": ["y-protocols@1.0.7", "", { "dependencies": { "lib0": "^0.2.85" }, "peerDependencies": { "yjs": "^13.0.0" } }, "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw=="], + + "y-websocket": ["y-websocket@3.0.0", "", { "dependencies": { "lib0": "^0.2.102", "y-protocols": "^1.0.5" }, "peerDependencies": { "yjs": "^13.5.6" } }, "sha512-mUHy7AzkOZ834T/7piqtlA8Yk6AchqKqcrCXjKW8J1w2lPtRDjz8W5/CvXz9higKAHgKRKqpI3T33YkRFLkPtg=="], + + "yjs": ["yjs@13.6.31", "", { "dependencies": { "lib0": "^0.2.99" } }, "sha512-Eq+5BRfbeGyqGVrTJL3bEcr8gKkxPuyuoHmAwpk52fDb8kOVMrfVSTRPd6yiGgX5Fskb96qCRjzjbRjrL4YEnw=="], + "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="], diff --git a/package.json b/package.json index 12b73d5..62ae2db 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@codemirror/legacy-modes": "^6.5.3", "@codemirror/lint": "^6.9.7", "@codemirror/lsp-client": "^6.2.5", + "@codemirror/merge": "^6.12.2", "@codemirror/state": "^6.7.1", "@codemirror/view": "^6.43.6", "@iconify/svelte": "^5.2.2", @@ -29,7 +30,10 @@ "@tauri-apps/plugin-dialog": "^2.7.2", "@tauri-apps/plugin-opener": "^2.5.4", "codemirror": "^6.0.2", - "codemirror-lang-typst": "^0.4.0" + "codemirror-lang-typst": "^0.4.0", + "y-codemirror.next": "^0.3.5", + "y-websocket": "^3.0.0", + "yjs": "^13.6.31" }, "devDependencies": { "@sveltejs/adapter-static": "^3.0.10", diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 1ae1119..0ece8c5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1062,6 +1062,32 @@ fn cloud_sync_document( sync::sync_document(&server_url, &token, &app, &store, &path) } +#[tauri::command] +fn cloud_room_id( + app: AppHandle, + store: State<'_, Store>, + path: String, + file: String, +) -> Result, String> { + if let Some(link) = store.document_link(&path)? { + return Ok(Some(link.document_id)); + } + + let meta = store.meta(&path)?; + let Some(cloud_project_id) = meta.cloud_project_id else { + return Ok(None); + }; + + let (server_url, token) = cloud_credentials(&app, &store)?; + let manifest = sync::get_manifest(&server_url, &token, &cloud_project_id)?; + + Ok(manifest + .files + .into_iter() + .find(|entry| entry.path == file) + .map(|entry| format!("project:{}:{}", cloud_project_id, entry.id))) +} + #[tauri::command] fn cloud_resolve_document( app: AppHandle, @@ -1425,6 +1451,7 @@ pub fn run() { cloud_download_document, cloud_delete_document, cloud_sync_document, + cloud_room_id, cloud_resolve_document, cloud_document_link, cloud_linked_documents, diff --git a/src-tauri/src/sync.rs b/src-tauri/src/sync.rs index 0c0731b..6d4b64e 100644 --- a/src-tauri/src/sync.rs +++ b/src-tauri/src/sync.rs @@ -241,6 +241,7 @@ pub fn move_cloud_project( #[derive(Deserialize)] pub struct ManifestEntry { + pub id: String, pub path: String, pub hash: String, } diff --git a/src/lib/components/ConflictModal.svelte b/src/lib/components/ConflictModal.svelte index bbb90cc..04e73e0 100644 --- a/src/lib/components/ConflictModal.svelte +++ b/src/lib/components/ConflictModal.svelte @@ -1,5 +1,9 @@