diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart index 595c013904..6a41e2f173 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart @@ -64,7 +64,7 @@ class DatabaseViewListener { (error) => _rowsVisibility?.value = FlowyResult.failure(error), ); break; - case DatabaseNotification.DidUpdateViewRows: + case DatabaseNotification.DidUpdateRow: result.fold( (payload) => _rowsNotifier?.value = FlowyResult.success(RowsChangePB.fromBuffer(payload)), diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart index 41e85d86dd..66502b44cf 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart @@ -175,10 +175,10 @@ class AppFlowyGridCellTest { context.makeSelectOptionCellController(fieldType, rowIndex); } -Future gridResponseFuture({int milliseconds = 200}) { +Future gridResponseFuture({int milliseconds = 400}) { return Future.delayed(gridResponseDuration(milliseconds: milliseconds)); } -Duration gridResponseDuration({int milliseconds = 200}) { +Duration gridResponseDuration({int milliseconds = 400}) { return Duration(milliseconds: milliseconds); } diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 2309399cde..7fb0797ccb 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -860,7 +860,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -884,7 +884,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -914,7 +914,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -933,7 +933,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "bytes", @@ -948,7 +948,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "chrono", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-stream", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -1293,7 +1293,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1384,12 +1384,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.12.3", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core 0.9.8", @@ -2103,12 +2103,15 @@ name = "flowy-notification" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-codegen", "flowy-derive", "lazy_static", "lib-dispatch", "protobuf", "serde", + "tokio", + "tokio-util", "tracing", ] @@ -4722,7 +4725,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4743,7 +4746,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.11.0", "proc-macro2", "quote", "syn 2.0.47", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 192ac22184..caeccf20b3 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -97,10 +97,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "af7 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 16b2deebcf..fd0e21c358 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -632,7 +632,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -656,7 +656,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -675,7 +675,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "bytes", @@ -690,7 +690,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "chrono", @@ -728,7 +728,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-stream", @@ -805,7 +805,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -1417,12 +1417,15 @@ name = "flowy-notification" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-codegen", "flowy-derive", "lazy_static", "lib-dispatch", "protobuf", "serde", + "tokio", + "tokio-util", "tracing", ] @@ -4981,4 +4984,4 @@ dependencies = [ [[patch.unused]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 1b49c32a80..c862da05f2 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -65,10 +65,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "af7 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 8c376dd5c3..1efe1ebece 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -843,7 +843,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -897,7 +897,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "bytes", @@ -931,7 +931,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "chrono", @@ -969,7 +969,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-stream", @@ -1047,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -2140,12 +2140,15 @@ name = "flowy-notification" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-codegen", "flowy-derive", "lazy_static", "lib-dispatch", "protobuf", "serde", + "tokio", + "tokio-util", "tracing", ] diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 93d02a1f6c..4b79460edd 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -96,10 +96,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "af7 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index e80237c6f7..e6fa2283d2 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -809,7 +809,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-trait", @@ -839,7 +839,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -858,7 +858,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "bytes", @@ -873,7 +873,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "chrono", @@ -911,7 +911,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "async-stream", @@ -989,7 +989,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=542ab275eae087f7be7207ada311c769ed1808b4#542ab275eae087f7be7207ada311c769ed1808b4" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff#29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" dependencies = [ "anyhow", "collab", @@ -2077,12 +2077,15 @@ name = "flowy-notification" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-codegen", "flowy-derive", "lazy_static", "lib-dispatch", "protobuf", "serde", + "tokio", + "tokio-util", "tracing", ] diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index d88b3cef19..f4542347eb 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -125,10 +125,10 @@ client-api = { git = " https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "af # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } -collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "542ab275eae087f7be7207ada311c769ed1808b4" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "29475f0ec00dc06b42da68bc54efa5b7c1bcd0ff" } diff --git a/frontend/rust-lib/flowy-database2/src/notification.rs b/frontend/rust-lib/flowy-database2/src/notification.rs index f4ed4c6acd..eadaa7e031 100644 --- a/frontend/rust-lib/flowy-database2/src/notification.rs +++ b/frontend/rust-lib/flowy-database2/src/notification.rs @@ -1,7 +1,7 @@ use flowy_derive::ProtoBuf_Enum; use flowy_notification::NotificationBuilder; -const DATABASE_OBSERVABLE_SOURCE: &str = "Database"; +pub(crate) const DATABASE_OBSERVABLE_SOURCE: &str = "Database"; #[derive(ProtoBuf_Enum, Debug, Default)] pub enum DatabaseNotification { @@ -11,7 +11,7 @@ pub enum DatabaseNotification { /// storage. DidFetchRow = 19, /// Trigger after inserting/deleting/updating a row - DidUpdateViewRows = 20, + DidUpdateRow = 20, /// Trigger when the visibility of the row was changed. For example, updating the filter will trigger the notification DidUpdateViewRowsVisibility = 21, /// Trigger after inserting/deleting/updating a field @@ -64,7 +64,7 @@ impl std::convert::From for DatabaseNotification { fn from(notification: i32) -> Self { match notification { 19 => DatabaseNotification::DidFetchRow, - 20 => DatabaseNotification::DidUpdateViewRows, + 20 => DatabaseNotification::DidUpdateRow, 21 => DatabaseNotification::DidUpdateViewRowsVisibility, 22 => DatabaseNotification::DidUpdateFields, 40 => DatabaseNotification::DidUpdateCell, diff --git a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs index c770c2b5fc..9067ebfe95 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/database_editor.rs @@ -4,7 +4,6 @@ use crate::services::calculations::Calculation; use crate::services::cell::{apply_cell_changeset, get_cell_protobuf, CellCache}; use crate::services::database::database_observe::*; use crate::services::database::util::database_view_setting_pb_from_view; -use crate::services::database::UpdatedRow; use crate::services::database_view::{ DatabaseViewChanged, DatabaseViewEditor, DatabaseViewOperation, DatabaseViews, EditorByViewId, }; @@ -27,6 +26,7 @@ use collab_database::views::{ DatabaseLayout, DatabaseView, FilterMap, LayoutSetting, OrderObjectPosition, }; use flowy_error::{internal_error, ErrorCode, FlowyError, FlowyResult}; +use flowy_notification::DebounceNotificationSender; use lib_infra::box_any::BoxAny; use lib_infra::future::{to_fut, Fut, FutureResult}; use lib_infra::priority_task::TaskDispatcher; @@ -41,6 +41,9 @@ pub struct DatabaseEditor { database: Arc, pub cell_cache: CellCache, database_views: Arc, + #[allow(dead_code)] + /// Used to send notification to the frontend. + notification_sender: Arc, } impl DatabaseEditor { @@ -48,6 +51,7 @@ impl DatabaseEditor { database: Arc, task_scheduler: Arc>, ) -> FlowyResult { + let notification_sender = Arc::new(DebounceNotificationSender::new(200)); let cell_cache = AnyTypeCache::::new(); let database_id = database.lock().get_database_id(); @@ -55,7 +59,7 @@ impl DatabaseEditor { observe_sync_state(&database_id, &database).await; // observe_view_change(&database_id, &database).await; // observe_field_change(&database_id, &database).await; - // observe_rows_change(&database_id, &database).await; + observe_rows_change(&database_id, &database, ¬ification_sender).await; // observe_block_event(&database_id, &database).await; // Used to cache the view of the database for fast access. @@ -81,6 +85,7 @@ impl DatabaseEditor { database, cell_cache, database_views, + notification_sender, }) } @@ -154,7 +159,7 @@ impl DatabaseEditor { if !changes.is_empty() { for view in self.database_views.editors().await { - send_notification(&view.view_id, DatabaseNotification::DidUpdateViewRows) + send_notification(&view.view_id, DatabaseNotification::DidUpdateRow) .payload(changes.clone()) .send(); } @@ -497,7 +502,7 @@ impl DatabaseEditor { let insert_row = InsertedRowPB::new(RowMetaPB::from(row_detail)).with_index(index as i32); let changes = RowsChangePB::from_move(vec![delete_row_id], vec![insert_row]); - send_notification(view_id, DatabaseNotification::DidUpdateViewRows) + send_notification(view_id, DatabaseNotification::DidUpdateRow) .payload(changes) .send(); } @@ -788,10 +793,6 @@ impl DatabaseEditor { .v_did_update_row(&Some(row_detail.clone()), &row_detail, None) .await; } - - self - .notify_update_row(view_id, row_detail.row.id, vec![]) - .await; } /// Update a cell in the database. @@ -851,15 +852,6 @@ impl DatabaseEditor { .await; } } - - let changeset = CellChangesetNotifyPB { - view_id: view_id.to_string(), - row_id: row_id.clone().into_inner(), - field_id: field_id.to_string(), - }; - self - .notify_update_row(view_id, row_id, vec![changeset]) - .await; } pub fn get_auto_updated_fields_changesets( @@ -1082,13 +1074,6 @@ impl DatabaseEditor { self.database.lock().update_row(&row_detail.row.id, |row| { row.set_cells(Cells::from(row_changeset.cell_by_field_id.clone())); }); - - let changesets = cell_changesets_from_cell_by_field_id( - view_id, - row_changeset.row_id, - row_changeset.cell_by_field_id, - ); - self.notify_update_row(view_id, from_row, changesets).await; }, } @@ -1337,58 +1322,6 @@ impl DatabaseEditor { pub fn get_mutex_database(&self) -> &MutexDatabase { &self.database } - - async fn notify_update_row( - &self, - view_id: &str, - row: RowId, - extra_changesets: Vec, - ) { - let mut changesets = self.get_auto_updated_fields_changesets(view_id, row); - changesets.extend(extra_changesets); - - notify_did_update_cell(changesets.clone()).await; - notify_did_update_row(changesets).await; - } -} - -pub(crate) async fn notify_did_update_cell(changesets: Vec) { - for changeset in changesets { - let id = format!("{}:{}", changeset.row_id, changeset.field_id); - send_notification(&id, DatabaseNotification::DidUpdateCell).send(); - } -} - -async fn notify_did_update_row(changesets: Vec) { - let row_id = changesets[0].row_id.clone(); - let view_id = changesets[0].view_id.clone(); - - let field_ids = changesets - .iter() - .map(|changeset| changeset.field_id.to_string()) - .collect(); - let update_row = UpdatedRow::new(&row_id).with_field_ids(field_ids); - let update_changeset = RowsChangePB::from_update(update_row.into()); - - send_notification(&view_id, DatabaseNotification::DidUpdateViewRows) - .payload(update_changeset) - .send(); -} - -fn cell_changesets_from_cell_by_field_id( - view_id: &str, - row_id: RowId, - cell_by_field_id: HashMap, -) -> Vec { - let row_id = row_id.into_inner(); - cell_by_field_id - .into_keys() - .map(|field_id| CellChangesetNotifyPB { - view_id: view_id.to_string(), - row_id: row_id.clone(), - field_id, - }) - .collect() } struct DatabaseViewOperationImpl { diff --git a/frontend/rust-lib/flowy-database2/src/services/database/database_observe.rs b/frontend/rust-lib/flowy-database2/src/services/database/database_observe.rs index 45194d8f4e..fbf4194571 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database/database_observe.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database/database_observe.rs @@ -1,14 +1,16 @@ -use crate::entities::{DatabaseSyncStatePB, DidFetchRowPB}; -use crate::notification::{send_notification, DatabaseNotification}; +use crate::entities::{DatabaseSyncStatePB, DidFetchRowPB, RowsChangePB}; +use crate::notification::{send_notification, DatabaseNotification, DATABASE_OBSERVABLE_SOURCE}; +use crate::services::database::UpdatedRow; use collab_database::blocks::BlockEvent; use collab_database::database::MutexDatabase; use collab_database::fields::FieldChange; -use collab_database::rows::RowChange; +use collab_database::rows::{RowChange, RowId}; use collab_database::views::DatabaseViewChange; +use flowy_notification::{DebounceNotificationSender, NotificationBuilder}; use futures::StreamExt; use lib_dispatch::prelude::af_spawn; use std::sync::Arc; -use tracing::trace; +use tracing::{trace, warn}; pub(crate) async fn observe_sync_state(database_id: &str, database: &Arc) { let weak_database = Arc::downgrade(database); @@ -31,7 +33,12 @@ pub(crate) async fn observe_sync_state(database_id: &str, database: &Arc) { +pub(crate) async fn observe_rows_change( + database_id: &str, + database: &Arc, + notification_sender: &Arc, +) { + let notification_sender = notification_sender.clone(); let database_id = database_id.to_string(); let weak_database = Arc::downgrade(database); let mut row_change = database.lock().subscribe_row_change(); @@ -47,15 +54,24 @@ pub(crate) async fn observe_rows_change(database_id: &str, database: &Arc {}, - RowChange::DidUpdateHeight { .. } => {}, - RowChange::DidUpdateCell { .. } => {}, - RowChange::DidUpdateRowComment { .. } => {}, + RowChange::DidUpdateCell { + field_id, + row_id, + value: _, + } => { + let cell_id = format!("{}:{}", row_id, field_id); + notify_cell(¬ification_sender, &cell_id); + // In the old logic, it will notify the row when the cell is updated. But in the new logic, + // it will notify the cell only. Enable the following code if needed. + // notify_row(¬ification_sender, &database_id, field_id, &row_id); + }, + _ => { + warn!("unhandled row change: {:?}", row_change); + }, } } }); } - #[allow(dead_code)] pub(crate) async fn observe_field_change(database_id: &str, database: &Arc) { let database_id = database_id.to_string(); @@ -148,3 +164,32 @@ pub(crate) async fn observe_block_event(database_id: &str, database: &Arc, + _database_id: &str, + field_id: String, + row_id: &RowId, +) { + let update_row = UpdatedRow::new(row_id).with_field_ids(vec![field_id]); + let update_changeset = RowsChangePB::from_update(update_row.into()); + let subject = NotificationBuilder::new( + row_id, + DatabaseNotification::DidUpdateRow, + DATABASE_OBSERVABLE_SOURCE, + ) + .payload(update_changeset) + .build(); + notification_sender.send_subject(subject); +} + +fn notify_cell(notification_sender: &Arc, cell_id: &str) { + let subject = NotificationBuilder::new( + cell_id, + DatabaseNotification::DidUpdateCell, + DATABASE_OBSERVABLE_SOURCE, + ) + .build(); + notification_sender.send_subject(subject); +} diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs index 478aa2c5a4..99c3efa45d 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/notifier.rs @@ -86,7 +86,7 @@ impl DatabaseViewChangedReceiverRunner { is_new: true, }; let changes = RowsChangePB::from_insert(inserted_row); - send_notification(&result.view_id, DatabaseNotification::DidUpdateViewRows) + send_notification(&result.view_id, DatabaseNotification::DidUpdateRow) .payload(changes) .send(); }, diff --git a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs index e08faaac8d..0e2d886655 100644 --- a/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs +++ b/frontend/rust-lib/flowy-database2/src/services/database_view/view_editor.rs @@ -173,7 +173,7 @@ impl DatabaseViewEditor { pub async fn v_did_update_row_meta(&self, row_id: &RowId, row_detail: &RowDetail) { let update_row = UpdatedRow::new(row_id.as_str()).with_row_meta(row_detail.clone()); let changeset = RowsChangePB::from_update(update_row.into()); - send_notification(&self.view_id, DatabaseNotification::DidUpdateViewRows) + send_notification(&self.view_id, DatabaseNotification::DidUpdateRow) .payload(changeset) .send(); } @@ -223,7 +223,7 @@ impl DatabaseViewEditor { } let changes = RowsChangePB::from_delete(row.id.clone().into_inner()); - send_notification(&self.view_id, DatabaseNotification::DidUpdateViewRows) + send_notification(&self.view_id, DatabaseNotification::DidUpdateRow) .payload(changes) .send(); @@ -1031,7 +1031,7 @@ impl DatabaseViewEditor { } => RowsChangePB::from_move(vec![deleted_row_id.into_inner()], vec![inserted_row.into()]), }; - send_notification(&self.view_id, DatabaseNotification::DidUpdateViewRows) + send_notification(&self.view_id, DatabaseNotification::DidUpdateRow) .payload(changeset) .send(); } diff --git a/frontend/rust-lib/flowy-notification/Cargo.toml b/frontend/rust-lib/flowy-notification/Cargo.toml index 3853914866..b459c9afbf 100644 --- a/frontend/rust-lib/flowy-notification/Cargo.toml +++ b/frontend/rust-lib/flowy-notification/Cargo.toml @@ -13,6 +13,9 @@ protobuf.workspace = true tracing.workspace = true bytes.workspace = true serde = { workspace = true, features = ["derive"] } +dashmap = "5.5" +tokio-util = "0.7" +tokio = { workspace = true, features = ["time"] } flowy-derive.workspace = true lib-dispatch = { workspace = true } diff --git a/frontend/rust-lib/flowy-notification/src/builder.rs b/frontend/rust-lib/flowy-notification/src/builder.rs new file mode 100644 index 0000000000..ef0d37a207 --- /dev/null +++ b/frontend/rust-lib/flowy-notification/src/builder.rs @@ -0,0 +1,94 @@ +use crate::entities::SubscribeObject; +use crate::NOTIFICATION_SENDER; +use bytes::Bytes; +use lib_dispatch::prelude::ToBytes; + +pub struct NotificationBuilder { + /// This identifier is used to uniquely distinguish each notification. For instance, if the + /// notification relates to a folder's view, the identifier could be the view's ID. The frontend + /// uses this ID to link the notification with the relevant observable entity. + id: String, + payload: Option, + error: Option, + source: String, + ty: i32, +} + +impl NotificationBuilder { + pub fn new>(id: &str, ty: T, source: &str) -> Self { + Self { + id: id.to_owned(), + ty: ty.into(), + payload: None, + error: None, + source: source.to_owned(), + } + } + + pub fn payload(mut self, payload: T) -> Self + where + T: ToBytes, + { + match payload.into_bytes() { + Ok(bytes) => self.payload = Some(bytes), + Err(e) => { + tracing::error!("Set observable payload failed: {:?}", e); + }, + } + + self + } + + pub fn error(mut self, error: T) -> Self + where + T: ToBytes, + { + match error.into_bytes() { + Ok(bytes) => self.error = Some(bytes), + Err(e) => { + tracing::error!("Set observable error failed: {:?}", e); + }, + } + self + } + + pub fn build(self) -> SubscribeObject { + let payload = self.payload.map(|bytes| bytes.to_vec()); + let error = self.error.map(|bytes| bytes.to_vec()); + SubscribeObject { + source: self.source, + ty: self.ty, + id: self.id, + payload, + error, + } + } + + pub fn send(self) { + let payload = self.payload.map(|bytes| bytes.to_vec()); + let error = self.error.map(|bytes| bytes.to_vec()); + let subject = SubscribeObject { + source: self.source, + ty: self.ty, + id: self.id, + payload, + error, + }; + + send_subject(subject); + } +} + +#[inline] +pub fn send_subject(subject: SubscribeObject) { + match NOTIFICATION_SENDER.read() { + Ok(read_guard) => read_guard.iter().for_each(|sender| { + if let Err(e) = sender.send_subject(subject.clone()) { + tracing::error!("Post notification failed: {}", e); + } + }), + Err(err) => { + tracing::error!("Read notification sender failed: {}", err); + }, + } +} diff --git a/frontend/rust-lib/flowy-notification/src/debounce.rs b/frontend/rust-lib/flowy-notification/src/debounce.rs new file mode 100644 index 0000000000..dc32e74889 --- /dev/null +++ b/frontend/rust-lib/flowy-notification/src/debounce.rs @@ -0,0 +1,54 @@ +use crate::entities::SubscribeObject; +use crate::{send_subject, NotificationBuilder}; +use dashmap::mapref::entry::Entry; +use dashmap::DashMap; +use lib_dispatch::prelude::ToBytes; +use tokio_util::sync::CancellationToken; + +pub struct DebounceNotificationSender { + debounce_in_millis: u64, + cancel_token_by_subject: DashMap, +} + +impl DebounceNotificationSender { + pub fn new(debounce_in_millis: u64) -> Self { + Self { + debounce_in_millis, + cancel_token_by_subject: DashMap::new(), + } + } + + pub fn send, P: ToBytes>(&self, id: &str, ty: T, source: &str, payload: P) { + let subject = NotificationBuilder::new(id, ty, source) + .payload(payload) + .build(); + self.send_subject(subject); + } + + pub fn send_subject(&self, subject: SubscribeObject) { + let subject_key = format!("{}-{}-{}", subject.source, subject.id, subject.ty); + // remove the old cancel token and call cancel to stop the old task + if let Entry::Occupied(entry) = self.cancel_token_by_subject.entry(subject_key.clone()) { + let cancel_token = entry.get(); + cancel_token.cancel(); + entry.remove(); + } + + // insert a new cancel token + let cancel_token = CancellationToken::new(); + self + .cancel_token_by_subject + .insert(subject_key.clone(), cancel_token.clone()); + let debounce_in_millis = self.debounce_in_millis; + tokio::spawn(async move { + if debounce_in_millis > 0 { + tokio::time::sleep(std::time::Duration::from_millis(debounce_in_millis)).await; + } + + if cancel_token.is_cancelled() { + return; + } + send_subject(subject); + }); + } +} diff --git a/frontend/rust-lib/flowy-notification/src/lib.rs b/frontend/rust-lib/flowy-notification/src/lib.rs index 9d425f968c..873dd948ad 100644 --- a/frontend/rust-lib/flowy-notification/src/lib.rs +++ b/frontend/rust-lib/flowy-notification/src/lib.rs @@ -1,11 +1,12 @@ use std::sync::RwLock; -use bytes::Bytes; -use lazy_static::lazy_static; - -use lib_dispatch::prelude::ToBytes; - use crate::entities::SubscribeObject; +use lazy_static::lazy_static; +mod builder; +pub use builder::*; + +mod debounce; +pub use debounce::*; pub mod entities; mod protobuf; @@ -36,73 +37,3 @@ pub fn unregister_all_notification_sender() { pub trait NotificationSender: Send + Sync + 'static { fn send_subject(&self, subject: SubscribeObject) -> Result<(), String>; } - -pub struct NotificationBuilder { - id: String, - payload: Option, - error: Option, - source: String, - ty: i32, -} - -impl NotificationBuilder { - pub fn new>(id: &str, ty: T, source: &str) -> Self { - Self { - id: id.to_owned(), - ty: ty.into(), - payload: None, - error: None, - source: source.to_owned(), - } - } - - pub fn payload(mut self, payload: T) -> Self - where - T: ToBytes, - { - match payload.into_bytes() { - Ok(bytes) => self.payload = Some(bytes), - Err(e) => { - tracing::error!("Set observable payload failed: {:?}", e); - }, - } - - self - } - - pub fn error(mut self, error: T) -> Self - where - T: ToBytes, - { - match error.into_bytes() { - Ok(bytes) => self.error = Some(bytes), - Err(e) => { - tracing::error!("Set observable error failed: {:?}", e); - }, - } - self - } - - pub fn send(self) { - let payload = self.payload.map(|bytes| bytes.to_vec()); - let error = self.error.map(|bytes| bytes.to_vec()); - let subject = SubscribeObject { - source: self.source, - ty: self.ty, - id: self.id, - payload, - error, - }; - - match NOTIFICATION_SENDER.read() { - Ok(read_guard) => read_guard.iter().for_each(|sender| { - if let Err(e) = sender.send_subject(subject.clone()) { - tracing::error!("Post notification failed: {}", e); - } - }), - Err(err) => { - tracing::error!("Read notification sender failed: {}", err); - }, - } - } -}