From c59508dccb0537f0d9bc2e14f15d3dc3fa386320 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 9 May 2024 15:08:26 +0800 Subject: [PATCH 01/41] chore: ai type --- .../lib/plugins/ai_chat/ai_chat.dart | 81 +++++++++ .../lib/plugins/blank/blank.dart | 4 + .../lib/plugins/database/board/board.dart | 2 +- .../plugins/database/calendar/calendar.dart | 2 +- .../lib/plugins/database/grid/grid.dart | 2 +- .../database_document_plugin.dart | 3 + .../lib/plugins/document/document.dart | 2 +- .../lib/plugins/trash/trash.dart | 4 + .../lib/startup/plugin/plugin.dart | 3 +- .../lib/startup/tasks/load_plugin.dart | 9 + .../test/bloc_test/board_test/util.dart | 2 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 157 ++++++++++------- frontend/appflowy_tauri/src-tauri/Cargo.toml | 16 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 161 +++++++++++------ frontend/appflowy_web/wasm-libs/Cargo.toml | 16 +- .../appflowy_web_app/src-tauri/Cargo.lock | 163 +++++++++++------- .../appflowy_web_app/src-tauri/Cargo.toml | 16 +- frontend/rust-lib/Cargo.lock | 34 ++-- frontend/rust-lib/Cargo.toml | 42 +++-- .../src/deps_resolve/folder_deps.rs | 26 +-- .../flowy-core/src/integrate/trait_impls.rs | 10 +- .../flowy-folder/src/entities/view.rs | 2 + .../flowy-folder/src/view_operation.rs | 1 + .../src/af_cloud/impls/database.rs | 10 +- .../src/af_cloud/impls/document.rs | 10 +- .../flowy-server/src/af_cloud/impls/folder.rs | 20 +-- .../af_cloud/impls/user/cloud_service_impl.rs | 27 ++- .../anon_user/sync_supabase_user_collab.rs | 2 + 28 files changed, 532 insertions(+), 295 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart new file mode 100644 index 0000000000000..45d4feb462c6b --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart @@ -0,0 +1,81 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/startup/plugin/plugin.dart'; +import 'package:appflowy/workspace/presentation/home/home_stack.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; + +class AIChatPluginBuilder extends PluginBuilder { + @override + Plugin build(dynamic data) { + return AIChatPagePlugin(); + } + + @override + String get menuName => "AIChat"; + + @override + FlowySvgData get icon => FlowySvgs.ai_summary_s; + + @override + PluginType get pluginType => PluginType.aiChat; + + @override + ViewLayoutPB get layoutType => ViewLayoutPB.Document; +} + +class AIChatPluginConfig implements PluginConfig { + @override + bool get creatable => true; +} + +class AIChatPagePlugin extends Plugin { + @override + PluginWidgetBuilder get widgetBuilder => AIChatPagePluginWidgetBuilder(); + + @override + PluginId get id => "AIChatStack"; + + @override + PluginType get pluginType => PluginType.aiChat; +} + +class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder + with NavigationItem { + @override + Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr()); + + @override + Widget tabBarItem(String pluginId) => leftBarItem; + + @override + Widget buildWidget({PluginContext? context, required bool shrinkWrap}) => + const AIChatPage(); + + @override + List get navigationItems => [this]; +} + +class AIChatPage extends StatefulWidget { + const AIChatPage({super.key}); + + @override + State createState() => _AIChatPageState(); +} + +class _AIChatPageState extends State { + @override + Widget build(BuildContext context) { + return SizedBox.expand( + child: Container( + color: Theme.of(context).colorScheme.surface, + child: const Padding( + padding: EdgeInsets.all(10), + child: SizedBox.shrink(), + ), + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/blank/blank.dart b/frontend/appflowy_flutter/lib/plugins/blank/blank.dart index 9e4a6ba3735c9..61864b4b7f300 100644 --- a/frontend/appflowy_flutter/lib/plugins/blank/blank.dart +++ b/frontend/appflowy_flutter/lib/plugins/blank/blank.dart @@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pbenum.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; @@ -20,6 +21,9 @@ class BlankPluginBuilder extends PluginBuilder { @override PluginType get pluginType => PluginType.blank; + + @override + ViewLayoutPB get layoutType => ViewLayoutPB.Document; } class BlankPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/board.dart b/frontend/appflowy_flutter/lib/plugins/database/board/board.dart index fb267220beebf..86851c4bbbb7f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/board.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/board.dart @@ -25,7 +25,7 @@ class BoardPluginBuilder implements PluginBuilder { PluginType get pluginType => PluginType.board; @override - ViewLayoutPB? get layoutType => ViewLayoutPB.Board; + ViewLayoutPB get layoutType => ViewLayoutPB.Board; } class BoardPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/calendar.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/calendar.dart index 099714c3046a6..861d9f43039d0 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/calendar.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/calendar.dart @@ -25,7 +25,7 @@ class CalendarPluginBuilder extends PluginBuilder { PluginType get pluginType => PluginType.calendar; @override - ViewLayoutPB? get layoutType => ViewLayoutPB.Calendar; + ViewLayoutPB get layoutType => ViewLayoutPB.Calendar; } class CalendarPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/grid.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/grid.dart index 3a10835489f28..1f8816d92b329 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/grid.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/grid.dart @@ -25,7 +25,7 @@ class GridPluginBuilder implements PluginBuilder { PluginType get pluginType => PluginType.grid; @override - ViewLayoutPB? get layoutType => ViewLayoutPB.Grid; + ViewLayoutPB get layoutType => ViewLayoutPB.Grid; } class GridPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart b/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart index ce3668b43d084..c0385ec479463 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart @@ -48,6 +48,9 @@ class DatabaseDocumentPluginBuilder extends PluginBuilder { @override PluginType get pluginType => PluginType.databaseDocument; + + @override + ViewLayoutPB get layoutType => ViewLayoutPB.Document; } class DatabaseDocumentPlugin extends Plugin { diff --git a/frontend/appflowy_flutter/lib/plugins/document/document.dart b/frontend/appflowy_flutter/lib/plugins/document/document.dart index 13242bbe0a9e8..43122daced472 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/document.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/document.dart @@ -44,7 +44,7 @@ class DocumentPluginBuilder extends PluginBuilder { PluginType get pluginType => PluginType.document; @override - ViewLayoutPB? get layoutType => ViewLayoutPB.Document; + ViewLayoutPB get layoutType => ViewLayoutPB.Document; } class DocumentPlugin extends Plugin { diff --git a/frontend/appflowy_flutter/lib/plugins/trash/trash.dart b/frontend/appflowy_flutter/lib/plugins/trash/trash.dart index a25609edd3573..aa6445a65f62b 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/trash.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/trash.dart @@ -5,6 +5,7 @@ export "./src/trash_header.dart"; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pbenum.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; @@ -26,6 +27,9 @@ class TrashPluginBuilder extends PluginBuilder { @override PluginType get pluginType => PluginType.trash; + + @override + ViewLayoutPB get layoutType => ViewLayoutPB.Document; } class TrashPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart index e675cf1459e65..516136d02a9ab 100644 --- a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart @@ -18,6 +18,7 @@ enum PluginType { board, calendar, databaseDocument, + aiChat, } typedef PluginId = String; @@ -57,7 +58,7 @@ abstract class PluginBuilder { /// The layoutType is used in the backend to determine the layout of the view. /// Currently, AppFlowy supports 4 layout types: Document, Grid, Board, Calendar. - ViewLayoutPB? get layoutType => ViewLayoutPB.Document; + ViewLayoutPB? get layoutType; } abstract class PluginConfig { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart b/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart index 3899959b027d7..bb1b769fdbc97 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart @@ -1,3 +1,4 @@ +import 'package:appflowy/plugins/ai_chat/ai_chat.dart'; import 'package:appflowy/plugins/database/calendar/calendar.dart'; import 'package:appflowy/plugins/database/board/board.dart'; import 'package:appflowy/plugins/database/grid/grid.dart'; @@ -29,6 +30,14 @@ class PluginLoadTask extends LaunchTask { builder: DatabaseDocumentPluginBuilder(), config: DatabaseDocumentPluginConfig(), ); + registerPlugin( + builder: DatabaseDocumentPluginBuilder(), + config: DatabaseDocumentPluginConfig(), + ); + registerPlugin( + builder: AIChatPluginBuilder(), + config: AIChatPluginConfig(), + ); } @override diff --git a/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart b/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart index abff7256b2fed..e29c6a4a7345e 100644 --- a/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart @@ -29,7 +29,7 @@ class AppFlowyBoardTest { return ViewBackendService.createView( parentViewId: app.id, name: "Test Board", - layoutType: builder.layoutType!, + layoutType: builder.layoutType, openAfterCreate: true, ).then((result) { return result.fold( diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 1da9cd7027014..38006b87d5903 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "bincode", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "again", "anyhow", @@ -751,8 +751,8 @@ dependencies = [ "bytes", "chrono", "client-websocket", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "collab-rt-entity", "collab-rt-protocol", "database-entity", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "futures-channel", "futures-util", @@ -860,7 +860,31 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978#108a79782f47d7636313979f99bc7a964498d878" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bytes", + "chrono", + "js-sys", + "parking_lot 0.12.1", + "serde", + "serde_json", + "serde_repr", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "unicode-segmentation", + "web-sys", + "yrs", +] + +[[package]] +name = "collab" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -884,13 +908,13 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-plugins", "dashmap", "getrandom 0.2.10", @@ -914,11 +938,11 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.10", "nanoid", "parking_lot 0.12.1", @@ -933,11 +957,26 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978#108a79782f47d7636313979f99bc7a964498d878" +dependencies = [ + "anyhow", + "bytes", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "getrandom 0.2.10", + "serde", + "serde_json", + "serde_repr", + "uuid", +] + +[[package]] +name = "collab-entity" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.10", "serde", "serde_json", @@ -948,12 +987,12 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.10", "parking_lot 0.12.1", "serde", @@ -971,8 +1010,8 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-plugins", "futures", "lib-infra", @@ -986,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -994,8 +1033,8 @@ dependencies = [ "bincode", "bytes", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "futures", "futures-util", "getrandom 0.2.10", @@ -1025,15 +1064,15 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "bincode", "bytes", "chrono", "client-websocket", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "collab-rt-protocol", "database-entity", "prost", @@ -1050,13 +1089,13 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "async-trait", "bincode", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "serde", "thiserror", "tokio", @@ -1067,11 +1106,11 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.10", "parking_lot 0.12.1", "serde", @@ -1407,13 +1446,13 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", "bincode", "chrono", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "serde", "serde_json", "serde_repr", @@ -1840,8 +1879,8 @@ dependencies = [ "base64 0.21.5", "bytes", "client-api", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "diesel", @@ -1884,8 +1923,8 @@ name = "flowy-database-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "lib-infra", ] @@ -1899,9 +1938,9 @@ dependencies = [ "bytes", "chrono", "chrono-tz 0.8.2", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-database", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "csv", @@ -1972,9 +2011,9 @@ version = "0.1.0" dependencies = [ "anyhow", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "dashmap", @@ -2008,7 +2047,7 @@ name = "flowy-document-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", "flowy-error", "lib-infra", @@ -2064,9 +2103,9 @@ dependencies = [ "async-trait", "bytes", "chrono", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-integrate", "collab-plugins", @@ -2097,8 +2136,8 @@ name = "flowy-folder-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "lib-infra", "uuid", @@ -2127,7 +2166,7 @@ version = "0.1.0" dependencies = [ "async-stream", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "diesel", "diesel_derives", @@ -2157,7 +2196,7 @@ dependencies = [ name = "flowy-search-pub" version = "0.1.0" dependencies = [ - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "flowy-error", ] @@ -2170,9 +2209,9 @@ dependencies = [ "bytes", "chrono", "client-api", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-plugins", "flowy-database-pub", @@ -2262,10 +2301,10 @@ dependencies = [ "base64 0.21.5", "bytes", "chrono", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-database", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-integrate", "collab-plugins", @@ -2309,8 +2348,8 @@ dependencies = [ "anyhow", "base64 0.21.5", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "flowy-error", "flowy-folder-pub", "lib-infra", @@ -2777,7 +2816,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "futures-util", @@ -2794,7 +2833,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", @@ -3226,7 +3265,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "reqwest", @@ -5714,12 +5753,12 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", "chrono", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "database-entity", "gotrue-entity", "reqwest", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index a46ae6084e68c..cb2ef9bafd8e6 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -39,20 +39,20 @@ yrs = "0.18.7" # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } # Please using the following command to update the revision id # Current directory: frontend # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "da1f1293e7a423464381925bcd6c39430d0f9e26" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index c85cb2ae63f69..d50d370d9ce4f 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -89,8 +89,8 @@ dependencies = [ "af-persistence", "anyhow", "bytes", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-user", "flowy-codegen", @@ -113,7 +113,7 @@ dependencies = [ "af-persistence", "af-user", "anyhow", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "console_error_panic_hook", "flowy-document", @@ -216,7 +216,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "bincode", @@ -548,7 +548,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "again", "anyhow", @@ -559,8 +559,8 @@ dependencies = [ "bytes", "chrono", "client-websocket", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "collab-rt-entity", "collab-rt-protocol", "database-entity", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "futures-channel", "futures-util", @@ -638,7 +638,31 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978#108a79782f47d7636313979f99bc7a964498d878" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bytes", + "chrono", + "js-sys", + "parking_lot 0.12.1", + "serde", + "serde_json", + "serde_repr", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "unicode-segmentation", + "web-sys", + "yrs", +] + +[[package]] +name = "collab" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -662,11 +686,11 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "nanoid", "parking_lot 0.12.1", @@ -681,11 +705,26 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978#108a79782f47d7636313979f99bc7a964498d878" +dependencies = [ + "anyhow", + "bytes", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "getrandom 0.2.12", + "serde", + "serde_json", + "serde_repr", + "uuid", +] + +[[package]] +name = "collab-entity" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "serde", "serde_json", @@ -696,12 +735,12 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "parking_lot 0.12.1", "serde", @@ -719,8 +758,8 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-plugins", "futures", "lib-infra", @@ -734,7 +773,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -742,8 +781,8 @@ dependencies = [ "bincode", "bytes", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "futures", "futures-util", "getrandom 0.2.12", @@ -772,15 +811,15 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "bincode", "bytes", "chrono", "client-websocket", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "collab-rt-protocol", "database-entity", "prost", @@ -797,13 +836,13 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "async-trait", "bincode", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "serde", "thiserror", "tokio", @@ -814,11 +853,11 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "parking_lot 0.12.1", "serde", @@ -966,7 +1005,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1011,13 +1050,13 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", "bincode", "chrono", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "serde", "serde_json", "serde_repr", @@ -1270,8 +1309,8 @@ name = "flowy-database-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "lib-infra", ] @@ -1296,9 +1335,9 @@ version = "0.1.0" dependencies = [ "anyhow", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "dashmap", @@ -1332,7 +1371,7 @@ name = "flowy-document-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", "flowy-error", "lib-infra", @@ -1384,9 +1423,9 @@ dependencies = [ "async-trait", "bytes", "chrono", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-integrate", "collab-plugins", @@ -1417,8 +1456,8 @@ name = "flowy-folder-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "lib-infra", "uuid", @@ -1445,7 +1484,7 @@ dependencies = [ name = "flowy-search-pub" version = "0.1.0" dependencies = [ - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "flowy-error", ] @@ -1458,9 +1497,9 @@ dependencies = [ "bytes", "chrono", "client-api", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-plugins", "flowy-database-pub", @@ -1531,8 +1570,8 @@ dependencies = [ "anyhow", "base64 0.21.7", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "flowy-error", "flowy-folder-pub", "lib-infra", @@ -1788,7 +1827,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "futures-util", @@ -1805,7 +1844,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", @@ -2106,7 +2145,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "reqwest", @@ -2790,7 +2829,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2810,6 +2849,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2877,6 +2917,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3732,12 +3785,12 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", "chrono", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "database-entity", "gotrue-entity", "reqwest", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index bd2427c83d74a..33651582483b5 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -41,13 +41,13 @@ serde-wasm-bindgen = "0.4" # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } yrs = "0.18.7" # Please using the following command to update the revision id @@ -55,7 +55,7 @@ yrs = "0.18.7" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "da1f1293e7a423464381925bcd6c39430d0f9e26" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index f669732bdc97b..b699ed1496dee 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "bincode", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "again", "anyhow", @@ -725,8 +725,8 @@ dependencies = [ "bytes", "chrono", "client-websocket", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "collab-rt-entity", "collab-rt-protocol", "database-entity", @@ -760,7 +760,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "futures-channel", "futures-util", @@ -843,7 +843,31 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978#108a79782f47d7636313979f99bc7a964498d878" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bytes", + "chrono", + "js-sys", + "parking_lot 0.12.1", + "serde", + "serde_json", + "serde_repr", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "unicode-segmentation", + "web-sys", + "yrs", +] + +[[package]] +name = "collab" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -867,13 +891,13 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-plugins", "dashmap", "getrandom 0.2.12", @@ -897,11 +921,11 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "nanoid", "parking_lot 0.12.1", @@ -916,11 +940,26 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "getrandom 0.2.12", + "serde", + "serde_json", + "serde_repr", + "uuid", +] + +[[package]] +name = "collab-entity" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" +dependencies = [ + "anyhow", + "bytes", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "serde", "serde_json", @@ -931,12 +970,12 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "parking_lot 0.12.1", "serde", @@ -954,8 +993,8 @@ version = "0.1.0" dependencies = [ "anyhow", "async-trait", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-plugins", "futures", "lib-infra", @@ -969,7 +1008,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -977,8 +1016,8 @@ dependencies = [ "bincode", "bytes", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "futures", "futures-util", "getrandom 0.2.12", @@ -1008,15 +1047,15 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "bincode", "bytes", "chrono", "client-websocket", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "collab-rt-protocol", "database-entity", "prost", @@ -1033,13 +1072,13 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "async-trait", "bincode", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "serde", "thiserror", "tokio", @@ -1050,11 +1089,11 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "getrandom 0.2.12", "parking_lot 0.12.1", "serde", @@ -1283,7 +1322,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1394,13 +1433,13 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", "bincode", "chrono", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "serde", "serde_json", "serde_repr", @@ -1877,8 +1916,8 @@ dependencies = [ "base64 0.21.7", "bytes", "client-api", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "diesel", @@ -1921,8 +1960,8 @@ name = "flowy-database-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "lib-infra", ] @@ -1936,9 +1975,9 @@ dependencies = [ "bytes", "chrono", "chrono-tz", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-database", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "csv", @@ -2009,9 +2048,9 @@ version = "0.1.0" dependencies = [ "anyhow", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-integrate", "collab-plugins", "dashmap", @@ -2045,7 +2084,7 @@ name = "flowy-document-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", "flowy-error", "lib-infra", @@ -2101,9 +2140,9 @@ dependencies = [ "async-trait", "bytes", "chrono", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-integrate", "collab-plugins", @@ -2134,8 +2173,8 @@ name = "flowy-folder-pub" version = "0.1.0" dependencies = [ "anyhow", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "lib-infra", "uuid", @@ -2164,7 +2203,7 @@ version = "0.1.0" dependencies = [ "async-stream", "bytes", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "diesel", "diesel_derives", @@ -2194,7 +2233,7 @@ dependencies = [ name = "flowy-search-pub" version = "0.1.0" dependencies = [ - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "flowy-error", ] @@ -2207,9 +2246,9 @@ dependencies = [ "bytes", "chrono", "client-api", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-plugins", "flowy-database-pub", @@ -2299,10 +2338,10 @@ dependencies = [ "base64 0.21.7", "bytes", "chrono", - "collab", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-database", "collab-document", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "collab-folder", "collab-integrate", "collab-plugins", @@ -2346,8 +2385,8 @@ dependencies = [ "anyhow", "base64 0.21.7", "chrono", - "collab", - "collab-entity", + "collab 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878)", "flowy-error", "flowy-folder-pub", "lib-infra", @@ -2851,7 +2890,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "futures-util", @@ -2868,7 +2907,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", @@ -3305,7 +3344,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "reqwest", @@ -4810,7 +4849,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4831,7 +4870,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.55", @@ -5809,12 +5848,12 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d708d0562954f90c33adb68e13df890c974b7db3#d708d0562954f90c33adb68e13df890c974b7db3" dependencies = [ "anyhow", "app-error", "chrono", - "collab-entity", + "collab-entity 0.2.0 (git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a7978)", "database-entity", "gotrue-entity", "reqwest", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 7c85ebbed6cb2..150977a12af70 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -39,20 +39,20 @@ yrs = "0.18.7" # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } # Please using the following command to update the revision id # Current directory: frontend # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "da1f1293e7a423464381925bcd6c39430d0f9e26" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 046c52c854d55..44d33ea32193e 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "bincode", @@ -650,7 +650,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "again", "anyhow", @@ -696,7 +696,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "futures-channel", "futures-util", @@ -739,7 +739,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -763,7 +763,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -793,7 +793,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", @@ -827,7 +827,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", @@ -865,7 +865,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -904,7 +904,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "bincode", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "async-trait", @@ -946,7 +946,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -1248,7 +1248,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "app-error", @@ -2461,7 +2461,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "futures-util", @@ -2478,7 +2478,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "app-error", @@ -2843,7 +2843,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "reqwest", @@ -4940,7 +4940,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=da1f1293e7a423464381925bcd6c39430d0f9e26#da1f1293e7a423464381925bcd6c39430d0f9e26" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 26de92e4cec2b..2cfac3f2fa71b 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -76,22 +76,13 @@ tokio = "1.34.0" tokio-stream = "0.1.14" async-trait = "0.1.74" chrono = { version = "0.4.31", default-features = false, features = ["clock"] } -# Please use the following script to update collab. -# Working directory: frontend -# -# To update the commit ID, run: -# scripts/tool/update_collab_rev.sh new_rev_id -# -# To switch to the local path, run: -# scripts/tool/update_collab_source.sh -# ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { version = "0.2.0" } +collab-entity = { version = "0.2.0" } +collab-folder = { version = "0.2.0" } +collab-document = { version = "0.2.0" } +collab-database = { version = "0.2.0" } +collab-plugins = { version = "0.2.0" } +collab-user = { version = "0.2.0" } yrs = "0.18.7" # Please using the following command to update the revision id @@ -99,7 +90,7 @@ yrs = "0.18.7" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "da1f1293e7a423464381925bcd6c39430d0f9e26" } [profile.dev] opt-level = 1 @@ -129,3 +120,20 @@ incremental = false # TODO(Lucas.Xu) Upgrade to the latest version of RocksDB once PR(https://github.com/rust-rocksdb/rust-rocksdb/pull/869) is merged. # Currently, using the following revision id. This commit is patched to fix the 32-bit build issue and it's checked out from 0.21.0, not 0.22.0. rocksdb = { git = "https://github.com/LucasXu0/rust-rocksdb", rev = "21cf4a23ec131b9d82dc94e178fe8efc0c147b09" } + +# Please use the following script to update collab. +# Working directory: frontend +# +# To update the commit ID, run: +# scripts/tool/update_collab_rev.sh new_rev_id +# +# To switch to the local path, run: +# scripts/tool/update_collab_source.sh +# ⚠️⚠️⚠️️ +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs index 1a9fd4160ec64..43a8478eb0480 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs @@ -9,7 +9,6 @@ use flowy_document::entities::DocumentDataPB; use flowy_document::manager::DocumentManager; use flowy_document::parser::json::parser::JsonToDocumentParser; use flowy_error::FlowyError; -use flowy_folder::entities::ViewLayoutPB; use flowy_folder::manager::{FolderManager, FolderUser}; use flowy_folder::share::ImportType; use flowy_folder::view_operation::{FolderOperationHandler, FolderOperationHandlers, View}; @@ -315,7 +314,15 @@ impl FolderOperationHandler for DatabaseFolderOperation { }, Some(params) => { let database_manager = self.0.clone(); - let layout = layout_type_from_view_layout(layout.into()); + + let layout = match layout { + ViewLayout::Board => DatabaseLayoutPB::Board, + ViewLayout::Calendar => DatabaseLayoutPB::Calendar, + ViewLayout::Grid => DatabaseLayoutPB::Grid, + ViewLayout::Document | ViewLayout::Chat => { + return FutureResult::new(async move { Err(FlowyError::not_support()) }); + }, + }; let name = name.to_string(); let database_view_id = view_id.to_string(); @@ -351,6 +358,10 @@ impl FolderOperationHandler for DatabaseFolderOperation { Err(FlowyError::internal().with_context(format!("Can't handle {:?} layout type", layout))) }); }, + ViewLayout::Chat => { + // TODO(nathan): AI + todo!("AI") + }, }; FutureResult::new(async move { let result = database_manager.create_database_with_params(data).await; @@ -413,7 +424,7 @@ impl FolderOperationHandler for DatabaseFolderOperation { fn did_update_view(&self, old: &View, new: &View) -> FutureResult<(), FlowyError> { let database_layout = match new.layout { - ViewLayout::Document => { + ViewLayout::Document | ViewLayout::Chat => { return FutureResult::new(async { Err(FlowyError::internal().with_context("Can't handle document layout type")) }); @@ -449,12 +460,3 @@ impl CreateDatabaseExtParams { serde_json::from_value::(value).ok() } } - -pub fn layout_type_from_view_layout(layout: ViewLayoutPB) -> DatabaseLayoutPB { - match layout { - ViewLayoutPB::Grid => DatabaseLayoutPB::Grid, - ViewLayoutPB::Board => DatabaseLayoutPB::Board, - ViewLayoutPB::Calendar => DatabaseLayoutPB::Calendar, - ViewLayoutPB::Document => DatabaseLayoutPB::Grid, - } -} diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index a4c3638d4155a..95f7b25c72d0e 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -3,8 +3,9 @@ use std::sync::Arc; use anyhow::Error; use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin}; - use collab::core::origin::{CollabClient, CollabOrigin}; + +// use collab::core::origin::{CollabClient, CollabOrigin}; use collab::preclude::CollabPlugin; use collab_entity::CollabType; use collab_plugins::cloud_storage::postgres::SupabaseDBPlugin; @@ -372,7 +373,12 @@ impl CollabCloudPluginProvider for ServerProvider { collab_object.uid, collab_object.device_id.clone(), )); - let sync_object = SyncObject::from(collab_object); + let sync_object = SyncObject::new( + &collab_object.object_id, + &collab_object.workspace_id, + collab_object.collab_type.into(), + &collab_object.device_id, + ); let (sink, stream) = (channel.sink(), channel.stream()); let sink_config = SinkConfig::new().send_timeout(8); let sync_plugin = SyncPlugin::new( diff --git a/frontend/rust-lib/flowy-folder/src/entities/view.rs b/frontend/rust-lib/flowy-folder/src/entities/view.rs index 004f793e11b69..27fde3b7a2d59 100644 --- a/frontend/rust-lib/flowy-folder/src/entities/view.rs +++ b/frontend/rust-lib/flowy-folder/src/entities/view.rs @@ -115,6 +115,7 @@ pub enum ViewLayoutPB { Grid = 1, Board = 2, Calendar = 3, + Chat = 4, } impl ViewLayoutPB { @@ -133,6 +134,7 @@ impl std::convert::From for ViewLayoutPB { ViewLayout::Board => ViewLayoutPB::Board, ViewLayout::Document => ViewLayoutPB::Document, ViewLayout::Calendar => ViewLayoutPB::Calendar, + ViewLayout::Chat => ViewLayoutPB::Chat, } } } diff --git a/frontend/rust-lib/flowy-folder/src/view_operation.rs b/frontend/rust-lib/flowy-folder/src/view_operation.rs index c5dfcf6007be8..10d173394c0a4 100644 --- a/frontend/rust-lib/flowy-folder/src/view_operation.rs +++ b/frontend/rust-lib/flowy-folder/src/view_operation.rs @@ -115,6 +115,7 @@ impl From for ViewLayout { ViewLayoutPB::Grid => ViewLayout::Grid, ViewLayoutPB::Board => ViewLayout::Board, ViewLayoutPB::Calendar => ViewLayout::Calendar, + ViewLayoutPB::Chat => ViewLayout::Chat, } } } diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs index 6b2a67c67b224..80c143d9426f2 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs @@ -42,10 +42,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab { - object_id: object_id.clone(), - collab_type: collab_type.clone(), - }, + inner: QueryCollab::new(object_id.clone(), collab_type.clone().into()), }; match try_get_client?.get_collab(params).await { Ok(data) => { @@ -81,10 +78,7 @@ where let client = try_get_client?; let params = object_ids .into_iter() - .map(|object_id| QueryCollab { - object_id, - collab_type: object_ty.clone(), - }) + .map(|object_id| QueryCollab::new(object_id, object_ty.clone().into())) .collect(); let results = client.batch_get_collab(&workspace_id, params).await?; check_request_workspace_id_is_match( diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs index c5d88ba15c02a..73c001e60b995 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs @@ -37,10 +37,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab { - object_id: document_id.to_string(), - collab_type: CollabType::Document, - }, + inner: QueryCollab::new(document_id.to_string(), CollabType::Document.into()), }; let doc_state = try_get_client? .get_collab(params) @@ -82,10 +79,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab { - object_id: document_id.clone(), - collab_type: CollabType::Document, - }, + inner: QueryCollab::new(document_id.clone(), CollabType::Document.into()), }; let doc_state = try_get_client? .get_collab(params) diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs index c33569aea8c03..63b0b69cc418d 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs @@ -93,10 +93,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab { - object_id: workspace_id.clone(), - collab_type: CollabType::Folder, - }, + inner: QueryCollab::new(workspace_id.clone(), CollabType::Folder.into()), }; let doc_state = try_get_client? .get_collab(params) @@ -140,10 +137,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab { - object_id, - collab_type, - }, + inner: QueryCollab::new(object_id, collab_type.into()), }; let doc_state = try_get_client? .get_collab(params) @@ -167,10 +161,12 @@ where FutureResult::new(async move { let params = objects .into_iter() - .map(|object| CollabParams { - object_id: object.object_id, - encoded_collab_v1: object.encoded_collab_v1, - collab_type: object.collab_type, + .map(|object| { + CollabParams::new( + object.object_id, + object.collab_type.into(), + object.encoded_collab_v1, + ) }) .collect::>(); try_get_client? diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs index f602b404f8c65..7e897bb66e155 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs @@ -348,10 +348,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab { - object_id, - collab_type: CollabType::UserAwareness, - }, + inner: QueryCollab::new(object_id, CollabType::UserAwareness.into()), }; let resp = try_get_client?.get_collab(params).await?; check_request_workspace_id_is_match( @@ -380,12 +377,12 @@ where let collab_object = collab_object.clone(); FutureResult::new(async move { let client = try_get_client?; - let params = CreateCollabParams { - workspace_id: collab_object.workspace_id.clone(), - object_id: collab_object.object_id.clone(), - encoded_collab_v1: data, - collab_type: collab_object.collab_type.clone(), - }; + let params = CreateCollabParams::new( + collab_object.workspace_id, + collab_object.object_id, + collab_object.collab_type.into(), + data, + ); client.create_collab(params).await?; Ok(()) }) @@ -401,10 +398,12 @@ where FutureResult::new(async move { let params = objects .into_iter() - .map(|object| CollabParams { - object_id: object.object_id, - encoded_collab_v1: object.encoded_collab, - collab_type: object.collab_type, + .map(|object| { + CollabParams::new( + object.object_id, + u8::from(object.collab_type).into(), + object.encoded_collab, + ) }) .collect::>(); try_get_client? diff --git a/frontend/rust-lib/flowy-user/src/anon_user/sync_supabase_user_collab.rs b/frontend/rust-lib/flowy-user/src/anon_user/sync_supabase_user_collab.rs index c6435531f329e..cee388e77b712 100644 --- a/frontend/rust-lib/flowy-user/src/anon_user/sync_supabase_user_collab.rs +++ b/frontend/rust-lib/flowy-user/src/anon_user/sync_supabase_user_collab.rs @@ -170,6 +170,7 @@ fn sync_view( } } }, + ViewLayout::Chat => {}, } tokio::task::yield_now().await; @@ -357,6 +358,7 @@ fn collab_type_from_view_layout(view_layout: &ViewLayout) -> CollabType { match view_layout { ViewLayout::Document => CollabType::Document, ViewLayout::Grid | ViewLayout::Board | ViewLayout::Calendar => CollabType::Database, + ViewLayout::Chat => CollabType::Unknown, } } From 25e0a4e23ec838c22d7ffb93043bc7df90ef066a Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 9 May 2024 15:20:49 +0800 Subject: [PATCH 02/41] chore: use patch to fix version issue --- frontend/appflowy_tauri/src-tauri/Cargo.lock | 20 ++++----- frontend/appflowy_tauri/src-tauri/Cargo.toml | 25 +++++++---- frontend/appflowy_web/wasm-libs/Cargo.lock | 25 ++++++----- frontend/appflowy_web/wasm-libs/Cargo.toml | 25 +++++++---- .../appflowy_web_app/src-tauri/Cargo.lock | 26 ++++++------ .../appflowy_web_app/src-tauri/Cargo.toml | 24 +++++++---- frontend/rust-lib/Cargo.lock | 20 ++++----- frontend/rust-lib/Cargo.toml | 41 +++++++++++-------- 8 files changed, 122 insertions(+), 84 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 1da9cd7027014..3eea9e18aeac3 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "again", "anyhow", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "futures-channel", "futures-util", @@ -1025,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "async-trait", @@ -1407,7 +1407,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "futures-util", @@ -2794,7 +2794,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -3226,7 +3226,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "reqwest", @@ -5714,7 +5714,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index a46ae6084e68c..66db6b15a9312 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -39,20 +39,20 @@ yrs = "0.18.7" # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { version = "0.2" } +collab-entity = { version = "0.2" } +collab-folder = { version = "0.2" } +collab-document = { version = "0.2" } +collab-database = { version = "0.2" } +collab-plugins = { version = "0.2" } +collab-user = { version = "0.2" } # Please using the following command to update the revision id # Current directory: frontend # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } [dependencies] serde_json.workspace = true @@ -102,3 +102,12 @@ default = ["custom-protocol"] # this feature is used used for production builds where `devPath` points to the filesystem # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] + +[patch.crates-io] +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index c85cb2ae63f69..a7d441c1fc62c 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -548,7 +548,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "again", "anyhow", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "futures-channel", "futures-util", @@ -772,7 +772,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -797,7 +797,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "async-trait", @@ -1011,7 +1011,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -1788,7 +1788,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "futures-util", @@ -1805,7 +1805,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -2106,7 +2106,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "reqwest", @@ -3732,7 +3732,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -4991,3 +4991,8 @@ dependencies = [ "cc", "pkg-config", ] + +[[patch.unused]] +name = "collab-database" +version = "0.2.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index bd2427c83d74a..32b93cf6ab906 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -41,13 +41,13 @@ serde-wasm-bindgen = "0.4" # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { version = "0.2" } +collab-entity = { version = "0.2" } +collab-folder = { version = "0.2" } +collab-document = { version = "0.2" } +collab-database = { version = "0.2" } +collab-plugins = { version = "0.2" } +collab-user = { version = "0.2" } yrs = "0.18.7" # Please using the following command to update the revision id @@ -55,7 +55,7 @@ yrs = "0.18.7" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } @@ -68,3 +68,12 @@ codegen-units = 16 lto = true opt-level = 3 codegen-units = 1 + +[patch.crates-io] +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index f669732bdc97b..2fcd8de4d431d 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "again", "anyhow", @@ -760,7 +760,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "futures-channel", "futures-util", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -1033,7 +1033,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "async-trait", @@ -1283,7 +1283,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1394,7 +1394,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -2851,7 +2851,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "futures-util", @@ -2868,7 +2868,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -3305,7 +3305,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "reqwest", @@ -4810,7 +4810,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4831,7 +4831,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.55", @@ -5809,7 +5809,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 7c85ebbed6cb2..19bff2cd60d43 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -39,20 +39,20 @@ yrs = "0.18.7" # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { version = "0.2" } +collab-entity = { version = "0.2" } +collab-folder = { version = "0.2" } +collab-document = { version = "0.2" } +collab-database = { version = "0.2" } +collab-plugins = { version = "0.2" } +collab-user = { version = "0.2" } # Please using the following command to update the revision id # Current directory: frontend # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } [dependencies] serde_json.workspace = true @@ -102,3 +102,11 @@ default = ["custom-protocol"] # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] +[patch.crates-io] +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 046c52c854d55..72c052a00e79b 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -650,7 +650,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "again", "anyhow", @@ -696,7 +696,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "futures-channel", "futures-util", @@ -904,7 +904,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "bincode", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "async-trait", @@ -1248,7 +1248,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -2461,7 +2461,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "futures-util", @@ -2478,7 +2478,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", @@ -2843,7 +2843,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "reqwest", @@ -4940,7 +4940,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef8e6f3#ef8e6f360f9c1d4daf2283e8475894d2ca5ef2fc" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 26de92e4cec2b..29ff927103385 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -76,22 +76,13 @@ tokio = "1.34.0" tokio-stream = "0.1.14" async-trait = "0.1.74" chrono = { version = "0.4.31", default-features = false, features = ["clock"] } -# Please use the following script to update collab. -# Working directory: frontend -# -# To update the commit ID, run: -# scripts/tool/update_collab_rev.sh new_rev_id -# -# To switch to the local path, run: -# scripts/tool/update_collab_source.sh -# ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab = { version = "0.2" } +collab-entity = { version = "0.2" } +collab-folder = { version = "0.2" } +collab-document = { version = "0.2" } +collab-database = { version = "0.2" } +collab-plugins = { version = "0.2" } +collab-user = { version = "0.2" } yrs = "0.18.7" # Please using the following command to update the revision id @@ -99,7 +90,7 @@ yrs = "0.18.7" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef8e6f3" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } [profile.dev] opt-level = 1 @@ -129,3 +120,19 @@ incremental = false # TODO(Lucas.Xu) Upgrade to the latest version of RocksDB once PR(https://github.com/rust-rocksdb/rust-rocksdb/pull/869) is merged. # Currently, using the following revision id. This commit is patched to fix the 32-bit build issue and it's checked out from 0.21.0, not 0.22.0. rocksdb = { git = "https://github.com/LucasXu0/rust-rocksdb", rev = "21cf4a23ec131b9d82dc94e178fe8efc0c147b09" } +# Please use the following script to update collab. +# Working directory: frontend +# +# To update the commit ID, run: +# scripts/tool/update_collab_rev.sh new_rev_id +# +# To switch to the local path, run: +# scripts/tool/update_collab_source.sh +# ⚠️⚠️⚠️️ +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file From 8bb4fd2a1e6aec4e087ce854a10264b53c47e33b Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 16 May 2024 17:36:43 +0800 Subject: [PATCH 03/41] chore: update --- .../widgets/field/field_type_list.dart | 2 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 34 +++++------ frontend/appflowy_tauri/src-tauri/Cargo.toml | 16 +++--- frontend/appflowy_web/wasm-libs/Cargo.lock | 52 ++++++++++------- frontend/appflowy_web/wasm-libs/Cargo.toml | 16 +++--- .../appflowy_web_app/src-tauri/Cargo.lock | 40 ++++++------- .../appflowy_web_app/src-tauri/Cargo.toml | 16 +++--- frontend/rust-lib/Cargo.lock | 56 +++++++------------ frontend/rust-lib/Cargo.toml | 16 +++--- 9 files changed, 124 insertions(+), 124 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_type_list.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_type_list.dart index bcb1867086b4a..02bc0700a41bd 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_type_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_type_list.dart @@ -20,7 +20,7 @@ const List _supportedFieldTypes = [ FieldType.LastEditedTime, FieldType.CreatedTime, FieldType.Relation, - // FieldType.Summary, + FieldType.Summary, ]; class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate { diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 3eea9e18aeac3..5c0b997bc5d2d 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "again", "anyhow", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "futures-channel", "futures-util", @@ -860,7 +860,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -884,7 +884,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -914,7 +914,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -933,7 +933,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", @@ -948,7 +948,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -1025,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "async-trait", @@ -1067,7 +1067,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -1407,7 +1407,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "futures-util", @@ -2794,7 +2794,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -3226,7 +3226,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "reqwest", @@ -5714,7 +5714,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 66db6b15a9312..3c37f963cfbd2 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "cc88a4c522799b6e37211ae5df71d67dbd39bbbf" } [dependencies] serde_json.workspace = true @@ -104,10 +104,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } \ No newline at end of file diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index a7d441c1fc62c..76062d5c3d26c 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -548,7 +548,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "again", "anyhow", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "futures-channel", "futures-util", @@ -638,7 +638,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -681,7 +681,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", @@ -696,7 +696,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -772,7 +772,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -797,7 +797,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "async-trait", @@ -814,7 +814,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -966,7 +966,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1011,7 +1011,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -1788,7 +1788,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "futures-util", @@ -1805,7 +1805,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -2106,7 +2106,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "reqwest", @@ -2790,7 +2790,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2810,6 +2810,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2877,6 +2878,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3732,7 +3746,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -4995,4 +5009,4 @@ dependencies = [ [[patch.unused]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 32b93cf6ab906..bd310953a998c 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.7" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "cc88a4c522799b6e37211ae5df71d67dbd39bbbf" } @@ -70,10 +70,10 @@ opt-level = 3 codegen-units = 1 [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } \ No newline at end of file diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 2fcd8de4d431d..520e05c8308a9 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "again", "anyhow", @@ -760,7 +760,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "futures-channel", "futures-util", @@ -843,7 +843,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -897,7 +897,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", @@ -931,7 +931,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", @@ -969,7 +969,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -1033,7 +1033,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "async-trait", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -1283,7 +1283,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1394,7 +1394,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -2851,7 +2851,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "futures-util", @@ -2868,7 +2868,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -3305,7 +3305,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "reqwest", @@ -4810,7 +4810,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4831,7 +4831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5809,7 +5809,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 19bff2cd60d43..63583e5168e93 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "cc88a4c522799b6e37211ae5df71d67dbd39bbbf" } [dependencies] serde_json.workspace = true @@ -103,10 +103,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 72c052a00e79b..09b950124714d 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -650,7 +650,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "again", "anyhow", @@ -696,7 +696,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "futures-channel", "futures-util", @@ -739,7 +739,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -763,7 +763,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-trait", @@ -793,7 +793,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "bytes", @@ -827,7 +827,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "chrono", @@ -865,7 +865,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "async-stream", @@ -904,7 +904,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "bincode", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "async-trait", @@ -946,7 +946,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=108a79782f47d7636313979f99bc7a964498d878#108a79782f47d7636313979f99bc7a964498d878" dependencies = [ "anyhow", "collab", @@ -1149,7 +1149,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1248,7 +1248,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -2461,7 +2461,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "futures-util", @@ -2478,7 +2478,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", @@ -2843,7 +2843,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "reqwest", @@ -3718,7 +3718,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3738,7 +3738,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3806,19 +3805,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4022,7 +4008,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4043,7 +4029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4940,7 +4926,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=cc88a4c522799b6e37211ae5df71d67dbd39bbbf#cc88a4c522799b6e37211ae5df71d67dbd39bbbf" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 29ff927103385..12b21d6530e7c 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -90,7 +90,7 @@ yrs = "0.18.7" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "cc88a4c522799b6e37211ae5df71d67dbd39bbbf" } [profile.dev] opt-level = 1 @@ -129,10 +129,10 @@ rocksdb = { git = "https://github.com/LucasXu0/rust-rocksdb", rev = "21cf4a23ec1 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "870cd70" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "108a79782f47d7636313979f99bc7a964498d878" } \ No newline at end of file From 7945acb1e65ce87dafd9b6a269a0c77a3a28dec4 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 16 May 2024 20:26:16 +0800 Subject: [PATCH 04/41] chore: update --- frontend/appflowy_tauri/src-tauri/Cargo.lock | 38 ++++++------- frontend/appflowy_tauri/src-tauri/Cargo.toml | 16 +++--- frontend/appflowy_web/wasm-libs/Cargo.lock | 38 ++++++------- frontend/appflowy_web/wasm-libs/Cargo.toml | 16 +++--- .../appflowy_web_app/src-tauri/Cargo.lock | 44 +++++++-------- .../appflowy_web_app/src-tauri/Cargo.toml | 16 +++--- frontend/rust-lib/Cargo.lock | 56 +++++++------------ frontend/rust-lib/Cargo.toml | 16 +++--- 8 files changed, 113 insertions(+), 127 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 3eea9e18aeac3..ee515af12ce4c 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -740,7 +740,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "again", "anyhow", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "futures-channel", "futures-util", @@ -860,7 +860,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -884,7 +884,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -914,7 +914,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -933,7 +933,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "bytes", @@ -948,7 +948,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "chrono", @@ -986,7 +986,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-stream", @@ -1025,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "async-trait", @@ -1067,7 +1067,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -1407,7 +1407,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "futures-util", @@ -2794,7 +2794,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -3226,7 +3226,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "reqwest", @@ -5714,7 +5714,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -7968,9 +7968,9 @@ dependencies = [ [[package]] name = "yrs" -version = "0.18.7" +version = "0.18.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58fbc807677598fedfab76f99f6e1aa5c644411255002b5438ea0ab14672398" +checksum = "da227d69095141c331d9b60c11496d0a3c6505cd9f8e200898b197219e8e394f" dependencies = [ "arc-swap", "atomic_refcell", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index f323062ffce58..d659b6a78a2d9 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c79267d42ae35020d14c25ed5716d7277cee8568" } [dependencies] serde_json.workspace = true @@ -104,10 +104,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } \ No newline at end of file diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index a7d441c1fc62c..e8c3a0badcd81 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -548,7 +548,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "again", "anyhow", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "futures-channel", "futures-util", @@ -638,7 +638,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -681,7 +681,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "bytes", @@ -696,7 +696,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "chrono", @@ -734,7 +734,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-stream", @@ -772,7 +772,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -797,7 +797,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "async-trait", @@ -814,7 +814,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -1011,7 +1011,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -1788,7 +1788,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "futures-util", @@ -1805,7 +1805,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -2106,7 +2106,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "reqwest", @@ -3732,7 +3732,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -4909,9 +4909,9 @@ dependencies = [ [[package]] name = "yrs" -version = "0.18.7" +version = "0.18.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58fbc807677598fedfab76f99f6e1aa5c644411255002b5438ea0ab14672398" +checksum = "da227d69095141c331d9b60c11496d0a3c6505cd9f8e200898b197219e8e394f" dependencies = [ "arc-swap", "atomic_refcell", @@ -4995,4 +4995,4 @@ dependencies = [ [[patch.unused]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 1b6cb52c67684..b7abd2e70e6f0 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c79267d42ae35020d14c25ed5716d7277cee8568" } @@ -70,10 +70,10 @@ opt-level = 3 codegen-units = 1 [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } \ No newline at end of file diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 2fcd8de4d431d..68cc05b0e3341 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -714,7 +714,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "again", "anyhow", @@ -760,7 +760,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "futures-channel", "futures-util", @@ -843,7 +843,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -897,7 +897,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -916,7 +916,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "bytes", @@ -931,7 +931,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "chrono", @@ -969,7 +969,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-stream", @@ -1008,7 +1008,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -1033,7 +1033,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "async-trait", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=870cd70#870cd70e31fa30bc6f94595ca040a91c685dfb4e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -1283,7 +1283,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1394,7 +1394,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -2851,7 +2851,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "futures-util", @@ -2868,7 +2868,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -3305,7 +3305,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "reqwest", @@ -4810,7 +4810,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4831,7 +4831,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5809,7 +5809,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -8272,9 +8272,9 @@ dependencies = [ [[package]] name = "yrs" -version = "0.18.7" +version = "0.18.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58fbc807677598fedfab76f99f6e1aa5c644411255002b5438ea0ab14672398" +checksum = "da227d69095141c331d9b60c11496d0a3c6505cd9f8e200898b197219e8e394f" dependencies = [ "arc-swap", "atomic_refcell", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 63bc2269e31fa..f560eab50372f 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c79267d42ae35020d14c25ed5716d7277cee8568" } [dependencies] serde_json.workspace = true @@ -103,10 +103,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index a33996614fb76..aef7054a1849d 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -650,7 +650,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "again", "anyhow", @@ -696,7 +696,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "futures-channel", "futures-util", @@ -739,7 +739,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -763,7 +763,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-trait", @@ -793,7 +793,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "bytes", @@ -827,7 +827,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "chrono", @@ -865,7 +865,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "async-stream", @@ -904,7 +904,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "bincode", @@ -929,7 +929,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "async-trait", @@ -946,7 +946,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2c430e0#2c430e05fff6ca541cfef9836dc72e66a7847b6e" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=abf6e5d348041c4f998aab340dcc0220c148d389#abf6e5d348041c4f998aab340dcc0220c148d389" dependencies = [ "anyhow", "collab", @@ -1149,7 +1149,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1248,7 +1248,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -2461,7 +2461,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "futures-util", @@ -2478,7 +2478,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", @@ -2843,7 +2843,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "reqwest", @@ -3718,7 +3718,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3738,7 +3738,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3806,19 +3805,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4022,7 +4008,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4043,7 +4029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4940,7 +4926,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=c79267d42ae35020d14c25ed5716d7277cee8568#c79267d42ae35020d14c25ed5716d7277cee8568" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index b650644ec54af..b6256708b9f74 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -90,7 +90,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c79267d42ae35020d14c25ed5716d7277cee8568" } [profile.dev] opt-level = 1 @@ -129,10 +129,10 @@ rocksdb = { git = "https://github.com/LucasXu0/rust-rocksdb", rev = "21cf4a23ec1 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "2c430e0" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "abf6e5d348041c4f998aab340dcc0220c148d389" } \ No newline at end of file From 5f7d6aba493fc15de534eb89483d323dabd3e135 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 21 May 2024 23:31:56 +0800 Subject: [PATCH 05/41] chore: integrate client api --- .../lib/plugins/ai_chat/ai_chat.dart | 2 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 105 ++++++++++----- frontend/appflowy_tauri/src-tauri/Cargo.toml | 17 +-- frontend/appflowy_web/wasm-libs/Cargo.lock | 96 +++++++------- frontend/appflowy_web/wasm-libs/Cargo.toml | 16 +-- .../appflowy_web_app/src-tauri/Cargo.lock | 91 +++++++++---- .../appflowy_web_app/src-tauri/Cargo.toml | 19 +-- frontend/rust-lib/Cargo.lock | 120 +++++++++++------- frontend/rust-lib/Cargo.toml | 19 +-- frontend/rust-lib/flowy-chat-pub/Cargo.toml | 11 ++ frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 27 ++++ frontend/rust-lib/flowy-chat-pub/src/lib.rs | 1 + frontend/rust-lib/flowy-chat/Cargo.toml | 31 +++++ frontend/rust-lib/flowy-chat/Flowy.toml | 3 + frontend/rust-lib/flowy-chat/build.rs | 40 ++++++ frontend/rust-lib/flowy-chat/src/entities.rs | 14 ++ .../rust-lib/flowy-chat/src/event_handler.rs | 25 ++++ frontend/rust-lib/flowy-chat/src/event_map.rs | 23 ++++ frontend/rust-lib/flowy-chat/src/lib.rs | 7 + frontend/rust-lib/flowy-chat/src/manager.rs | 29 +++++ .../rust-lib/flowy-chat/src/notification.rs | 30 +++++ frontend/rust-lib/flowy-core/Cargo.toml | 3 + .../flowy-core/src/deps_resolve/chat_deps.rs | 10 ++ .../src/deps_resolve/folder_deps.rs | 96 +++++++++++++- .../flowy-core/src/deps_resolve/mod.rs | 2 + frontend/rust-lib/flowy-core/src/lib.rs | 2 + frontend/rust-lib/flowy-server/Cargo.toml | 1 + .../flowy-server/src/af_cloud/impls/chat.rs | 84 ++++++++++++ .../flowy-server/src/af_cloud/impls/mod.rs | 2 + .../af_cloud/impls/user/cloud_service_impl.rs | 12 +- .../flowy-server/src/af_cloud/server.rs | 13 +- .../rust-lib/flowy-server/src/default_impl.rs | 42 ++++++ frontend/rust-lib/flowy-server/src/lib.rs | 1 + frontend/rust-lib/flowy-server/src/server.rs | 6 + 34 files changed, 815 insertions(+), 185 deletions(-) create mode 100644 frontend/rust-lib/flowy-chat-pub/Cargo.toml create mode 100644 frontend/rust-lib/flowy-chat-pub/src/cloud.rs create mode 100644 frontend/rust-lib/flowy-chat-pub/src/lib.rs create mode 100644 frontend/rust-lib/flowy-chat/Cargo.toml create mode 100644 frontend/rust-lib/flowy-chat/Flowy.toml create mode 100644 frontend/rust-lib/flowy-chat/build.rs create mode 100644 frontend/rust-lib/flowy-chat/src/entities.rs create mode 100644 frontend/rust-lib/flowy-chat/src/event_handler.rs create mode 100644 frontend/rust-lib/flowy-chat/src/event_map.rs create mode 100644 frontend/rust-lib/flowy-chat/src/lib.rs create mode 100644 frontend/rust-lib/flowy-chat/src/manager.rs create mode 100644 frontend/rust-lib/flowy-chat/src/notification.rs create mode 100644 frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs create mode 100644 frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs create mode 100644 frontend/rust-lib/flowy-server/src/default_impl.rs diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart index 45d4feb462c6b..1f42363e0f20f 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart @@ -23,7 +23,7 @@ class AIChatPluginBuilder extends PluginBuilder { PluginType get pluginType => PluginType.aiChat; @override - ViewLayoutPB get layoutType => ViewLayoutPB.Document; + ViewLayoutPB get layoutType => ViewLayoutPB.Chat; } class AIChatPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 2a1c42eaa10c1..6205f6624ac6c 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -155,14 +155,14 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -179,12 +179,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "appflowy-ai-client" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "serde_repr", + "thiserror", +] + [[package]] name = "appflowy_tauri" version = "0.0.0" dependencies = [ "bytes", "dotenv", + "flowy-chat", "flowy-config", "flowy-core", "flowy-date", @@ -740,7 +753,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "again", "anyhow", @@ -770,6 +783,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serde_urlencoded", "shared-entity", "thiserror", "tokio", @@ -786,7 +800,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "futures-channel", "futures-util", @@ -860,7 +874,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -884,7 +898,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -914,7 +928,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -933,7 +947,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "bytes", @@ -948,7 +962,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "chrono", @@ -986,7 +1000,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-stream", @@ -1025,7 +1039,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -1050,7 +1064,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "async-trait", @@ -1067,7 +1081,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -1296,7 +1310,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1407,7 +1421,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -1794,6 +1808,34 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "flowy-chat" +version = "0.1.0" +dependencies = [ + "bytes", + "flowy-chat-pub", + "flowy-codegen", + "flowy-derive", + "flowy-error", + "flowy-notification", + "lib-dispatch", + "lib-infra", + "protobuf", + "strum_macros 0.21.1", + "tracing", + "uuid", + "validator", +] + +[[package]] +name = "flowy-chat-pub" +version = "0.1.0" +dependencies = [ + "client-api", + "flowy-error", + "lib-infra", +] + [[package]] name = "flowy-codegen" version = "0.1.0" @@ -1845,6 +1887,7 @@ dependencies = [ "collab-integrate", "collab-plugins", "diesel", + "flowy-chat", "flowy-config", "flowy-database-pub", "flowy-database2", @@ -2175,6 +2218,7 @@ dependencies = [ "collab-entity", "collab-folder", "collab-plugins", + "flowy-chat-pub", "flowy-database-pub", "flowy-document-pub", "flowy-encrypt", @@ -2777,7 +2821,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "futures-util", @@ -2794,7 +2838,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -3226,7 +3270,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "reqwest", @@ -4729,7 +4773,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4750,7 +4794,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -5533,18 +5577,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.195" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -5714,10 +5758,11 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", + "appflowy-ai-client", "chrono", "collab-entity", "database-entity", @@ -6566,18 +6611,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 9206c93d27a23..e0153b672fb18 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } [dependencies] serde_json.workspace = true @@ -75,6 +75,7 @@ flowy-core = { path = "../../rust-lib/flowy-core", features = [ flowy-user = { path = "../../rust-lib/flowy-user", features = ["tauri_ts"] } flowy-config = { path = "../../rust-lib/flowy-config", features = ["tauri_ts"] } flowy-date = { path = "../../rust-lib/flowy-date", features = ["tauri_ts"] } +flowy-chat = { path = "../../rust-lib/flowy-chat", features = ["tauri_ts"] } flowy-error = { path = "../../rust-lib/flowy-error", features = [ "impl_from_sqlite", "impl_from_dispatch_error", @@ -104,10 +105,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } \ No newline at end of file diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 1c6f692f498ba..89484d4681053 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -209,14 +209,14 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -233,6 +233,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "appflowy-ai-client" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "serde_repr", + "thiserror", +] + [[package]] name = "arc-swap" version = "1.7.1" @@ -548,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "again", "anyhow", @@ -578,6 +590,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serde_urlencoded", "shared-entity", "thiserror", "tokio", @@ -594,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "futures-channel", "futures-util", @@ -638,7 +651,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -662,7 +675,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -681,7 +694,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "bytes", @@ -696,7 +709,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "chrono", @@ -734,7 +747,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-stream", @@ -772,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -797,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "async-trait", @@ -814,7 +827,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -966,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1011,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -1241,6 +1254,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "flowy-chat-pub" +version = "0.1.0" +dependencies = [ + "client-api", + "flowy-error", + "lib-infra", +] + [[package]] name = "flowy-codegen" version = "0.1.0" @@ -1463,6 +1485,7 @@ dependencies = [ "collab-entity", "collab-folder", "collab-plugins", + "flowy-chat-pub", "flowy-database-pub", "flowy-document-pub", "flowy-encrypt", @@ -1788,7 +1811,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "futures-util", @@ -1805,7 +1828,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -2106,7 +2129,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "reqwest", @@ -2790,7 +2813,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2810,7 +2833,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2878,19 +2900,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -3623,9 +3632,9 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -3643,9 +3652,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -3746,10 +3755,11 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", + "appflowy-ai-client", "chrono", "collab-entity", "database-entity", @@ -4033,18 +4043,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -5009,4 +5019,4 @@ dependencies = [ [[patch.unused]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index e6637b4d31a33..965262069eb97 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } @@ -70,10 +70,10 @@ opt-level = 3 codegen-units = 1 [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } \ No newline at end of file diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 2bb44433edf77..d4a2c6df5a45e 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -170,6 +170,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "appflowy-ai-client" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "serde_repr", + "thiserror", +] + [[package]] name = "appflowy_tauri" version = "0.0.0" @@ -714,7 +726,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "again", "anyhow", @@ -744,6 +756,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serde_urlencoded", "shared-entity", "thiserror", "tokio", @@ -760,7 +773,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "futures-channel", "futures-util", @@ -843,7 +856,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -867,7 +880,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -897,7 +910,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -916,7 +929,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "bytes", @@ -931,7 +944,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "chrono", @@ -969,7 +982,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-stream", @@ -1008,7 +1021,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -1033,7 +1046,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "async-trait", @@ -1050,7 +1063,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -1283,7 +1296,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1394,7 +1407,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -1831,6 +1844,34 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "flowy-chat" +version = "0.1.0" +dependencies = [ + "bytes", + "flowy-chat-pub", + "flowy-codegen", + "flowy-derive", + "flowy-error", + "flowy-notification", + "lib-dispatch", + "lib-infra", + "protobuf", + "strum_macros 0.21.1", + "tracing", + "uuid", + "validator", +] + +[[package]] +name = "flowy-chat-pub" +version = "0.1.0" +dependencies = [ + "client-api", + "flowy-error", + "lib-infra", +] + [[package]] name = "flowy-codegen" version = "0.1.0" @@ -1882,6 +1923,7 @@ dependencies = [ "collab-integrate", "collab-plugins", "diesel", + "flowy-chat", "flowy-config", "flowy-database-pub", "flowy-database2", @@ -2851,7 +2893,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "futures-util", @@ -2868,7 +2910,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -3305,7 +3347,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "reqwest", @@ -4810,7 +4852,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4831,7 +4873,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5625,18 +5667,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -5809,10 +5851,11 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", + "appflowy-ai-client", "chrono", "collab-entity", "database-entity", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 45d822b46ed08..11b2c4de50d20 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } [dependencies] serde_json.workspace = true @@ -89,6 +89,9 @@ flowy-document = { path = "../../rust-lib/flowy-document", features = [ flowy-notification = { path = "../../rust-lib/flowy-notification", features = [ "tauri_ts", ] } +flowy-chat = { path = "../../rust-lib/flowy-chat", features = [ + "tauri_ts", +] } uuid = "1.5.0" tauri-plugin-deep-link = "0.1.2" @@ -103,10 +106,10 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 0560f222de22e..d35275c0ac480 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -156,14 +156,14 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -180,6 +180,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "appflowy-ai-client" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +dependencies = [ + "anyhow", + "serde", + "serde_json", + "serde_repr", + "thiserror", +] + [[package]] name = "arc-swap" version = "1.7.1" @@ -650,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "again", "anyhow", @@ -680,6 +692,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serde_urlencoded", "shared-entity", "thiserror", "tokio", @@ -696,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "futures-channel", "futures-util", @@ -739,7 +752,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -763,7 +776,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -793,7 +806,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -812,7 +825,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "bytes", @@ -827,7 +840,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "chrono", @@ -865,7 +878,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-stream", @@ -904,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "bincode", @@ -929,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "async-trait", @@ -946,7 +959,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -1149,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1248,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -1627,6 +1640,34 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "flowy-chat" +version = "0.1.0" +dependencies = [ + "bytes", + "flowy-chat-pub", + "flowy-codegen", + "flowy-derive", + "flowy-error", + "flowy-notification", + "lib-dispatch", + "lib-infra", + "protobuf", + "strum_macros 0.21.1", + "tracing", + "uuid", + "validator", +] + +[[package]] +name = "flowy-chat-pub" +version = "0.1.0" +dependencies = [ + "client-api", + "flowy-error", + "lib-infra", +] + [[package]] name = "flowy-codegen" version = "0.1.0" @@ -1679,6 +1720,7 @@ dependencies = [ "collab-plugins", "console-subscriber", "diesel", + "flowy-chat", "flowy-config", "flowy-database-pub", "flowy-database2", @@ -2015,6 +2057,7 @@ dependencies = [ "collab-folder", "collab-plugins", "dotenv", + "flowy-chat-pub", "flowy-database-pub", "flowy-document-pub", "flowy-encrypt", @@ -2461,7 +2504,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "futures-util", @@ -2478,7 +2521,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", @@ -2843,7 +2886,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "reqwest", @@ -3718,7 +3761,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3738,7 +3781,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3806,19 +3848,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4022,7 +4051,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4043,7 +4072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4806,18 +4835,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -4940,10 +4969,11 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" dependencies = [ "anyhow", "app-error", + "appflowy-ai-client", "chrono", "collab-entity", "database-entity", @@ -5451,18 +5481,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index bb728e820b102..643795a14b742 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -29,6 +29,7 @@ members = [ "build-tool/flowy-codegen", "build-tool/flowy-derive", "flowy-search-pub", + "flowy-chat", "flowy-chat-pub", ] resolver = "2" @@ -61,6 +62,8 @@ flowy-search = { workspace = true, path = "flowy-search" } flowy-search-pub = { workspace = true, path = "flowy-search-pub" } collab-integrate = { workspace = true, path = "collab-integrate" } flowy-date = { workspace = true, path = "flowy-date" } +flowy-chat = { workspace = true, path = "flowy-chat" } +flowy-chat-pub = { workspace = true, path = "flowy-chat-pub" } anyhow = "1.0" tracing = "0.1.40" bytes = "1.5.0" @@ -90,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ef96b42e43c7b929a928f6c334967c7edffc1319" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } [profile.dev] opt-level = 1 @@ -129,10 +132,10 @@ rocksdb = { git = "https://github.com/LucasXu0/rust-rocksdb", rev = "21cf4a23ec1 # To switch to the local path, run: # scripts/tool/update_collab_source.sh # ⚠️⚠️⚠️️ -collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } -collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "0b52164" } \ No newline at end of file +collab = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-entity = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-folder = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-document = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-database = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-plugins = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } +collab-user = { version = "0.2", git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "cca5135f0010fa5de22a298cbed939e21575538c" } diff --git a/frontend/rust-lib/flowy-chat-pub/Cargo.toml b/frontend/rust-lib/flowy-chat-pub/Cargo.toml new file mode 100644 index 0000000000000..9ec2b18b1b64c --- /dev/null +++ b/frontend/rust-lib/flowy-chat-pub/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "flowy-chat-pub" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lib-infra = { workspace = true } +flowy-error = { workspace = true } +client-api = { workspace = true } \ No newline at end of file diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs new file mode 100644 index 0000000000000..3ea39aeaab407 --- /dev/null +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -0,0 +1,27 @@ +use client_api::entity::{MessageOffset, RepeatedChatMessage}; +use flowy_error::FlowyError; +use lib_infra::future::FutureResult; + +pub trait ChatCloudService: Send + Sync + 'static { + fn create_chat( + &self, + uid: &i64, + workspace_id: &str, + chat_id: &str, + ) -> FutureResult<(), FlowyError>; + + fn send_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult<(), FlowyError>; + + fn get_chat_messages( + &self, + workspace_id: &str, + chat_id: &str, + offset: MessageOffset, + limit: u64, + ) -> FutureResult; +} diff --git a/frontend/rust-lib/flowy-chat-pub/src/lib.rs b/frontend/rust-lib/flowy-chat-pub/src/lib.rs new file mode 100644 index 0000000000000..1ede32218e76e --- /dev/null +++ b/frontend/rust-lib/flowy-chat-pub/src/lib.rs @@ -0,0 +1 @@ +pub mod cloud; diff --git a/frontend/rust-lib/flowy-chat/Cargo.toml b/frontend/rust-lib/flowy-chat/Cargo.toml new file mode 100644 index 0000000000000..3611f0a8ef441 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "flowy-chat" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +flowy-derive.workspace = true +flowy-notification = { workspace = true } +flowy-error = { path = "../flowy-error", features = [ + "impl_from_dispatch_error", + "impl_from_collab_folder", +] } +lib-dispatch = { workspace = true } +tracing.workspace = true +uuid.workspace = true +strum_macros = "0.21" +protobuf.workspace = true +bytes.workspace = true +validator = { version = "0.16.0", features = ["derive"] } +lib-infra = { workspace = true } +flowy-chat-pub.workspace = true + +[build-dependencies] +flowy-codegen.workspace = true + +[features] +dart = ["flowy-codegen/dart", "flowy-notification/dart"] +tauri_ts = ["flowy-codegen/ts", "flowy-notification/tauri_ts"] +web_ts = ["flowy-codegen/ts", "flowy-notification/web_ts"] diff --git a/frontend/rust-lib/flowy-chat/Flowy.toml b/frontend/rust-lib/flowy-chat/Flowy.toml new file mode 100644 index 0000000000000..1410c5951e861 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/Flowy.toml @@ -0,0 +1,3 @@ +# Check out the FlowyConfig (located in flowy_toml.rs) for more details. +proto_input = ["src/entities.rs", "src/event_map.rs", "src/notification.rs"] +event_files = ["src/event_map.rs"] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-chat/build.rs b/frontend/rust-lib/flowy-chat/build.rs new file mode 100644 index 0000000000000..fac4cc65ae836 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/build.rs @@ -0,0 +1,40 @@ +fn main() { + #[cfg(feature = "dart")] + { + flowy_codegen::protobuf_file::dart_gen(env!("CARGO_PKG_NAME")); + flowy_codegen::dart_event::gen(env!("CARGO_PKG_NAME")); + } + + #[cfg(feature = "tauri_ts")] + { + flowy_codegen::ts_event::gen(env!("CARGO_PKG_NAME"), flowy_codegen::Project::Tauri); + flowy_codegen::protobuf_file::ts_gen( + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_NAME"), + flowy_codegen::Project::Tauri, + ); + flowy_codegen::ts_event::gen(env!("CARGO_PKG_NAME"), flowy_codegen::Project::Tauri); + flowy_codegen::protobuf_file::ts_gen( + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_NAME"), + flowy_codegen::Project::TauriApp, + ); + } + + #[cfg(feature = "web_ts")] + { + flowy_codegen::ts_event::gen( + "folder", + flowy_codegen::Project::Web { + relative_path: "../../".to_string(), + }, + ); + flowy_codegen::protobuf_file::ts_gen( + env!("CARGO_PKG_NAME"), + "folder", + flowy_codegen::Project::Web { + relative_path: "../../".to_string(), + }, + ); + } +} diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs new file mode 100644 index 0000000000000..8a9468efef465 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -0,0 +1,14 @@ +use flowy_derive::ProtoBuf; +use lib_infra::validator_fn::{required_not_empty_str, required_valid_path}; +use validator::Validate; + +#[derive(Default, ProtoBuf, Validate, Clone, Debug)] +pub struct SendChatPayloadPB { + #[pb(index = 1)] + #[validate(custom = "required_not_empty_str")] + pub chat_id: String, + + #[pb(index = 2)] + #[validate(custom = "required_not_empty_str")] + pub message: String, +} diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs new file mode 100644 index 0000000000000..2354fb7ad215a --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -0,0 +1,25 @@ +use std::sync::{Arc, Weak}; +use tracing::instrument; + +use flowy_error::{FlowyError, FlowyResult}; +use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult}; + +use crate::entities::*; +use crate::manager::ChatManager; + +fn upgrade_chat_manager( + chat_manager: AFPluginState>, +) -> FlowyResult> { + let chat_manager = chat_manager + .upgrade() + .ok_or(FlowyError::internal().with_context("The chat manager is already dropped"))?; + Ok(chat_manager) +} + +#[tracing::instrument(level = "debug", skip(data, folder), err)] +pub(crate) async fn send_chat_message_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + Ok(()) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs new file mode 100644 index 0000000000000..7a4b21a424696 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -0,0 +1,23 @@ +use std::sync::Weak; + +use strum_macros::Display; + +use flowy_derive::{Flowy_Event, ProtoBuf_Enum}; +use lib_dispatch::prelude::*; + +use crate::event_handler::*; +use crate::manager::ChatManager; + +pub fn init(chat_manager: Weak) -> AFPlugin { + AFPlugin::new().name("Flowy-Chat").state(chat_manager) + // Workspace + .event(ChatEvent::SendMessage, send_chat_message_handler) +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] +#[event_err = "FlowyError"] +pub enum ChatEvent { + /// Create a new workspace + #[event(input = "SendChatPayloadPB")] + SendMessage = 0, +} diff --git a/frontend/rust-lib/flowy-chat/src/lib.rs b/frontend/rust-lib/flowy-chat/src/lib.rs new file mode 100644 index 0000000000000..713b957ffa111 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/lib.rs @@ -0,0 +1,7 @@ +mod event_handler; +mod event_map; + +mod entities; +pub mod manager; +mod notification; +pub mod protobuf; diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs new file mode 100644 index 0000000000000..c878c55bd24eb --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -0,0 +1,29 @@ +use flowy_chat_pub::cloud::ChatCloudService; +use flowy_error::FlowyError; +use std::sync::Arc; + +pub struct ChatManager { + cloud_service: Arc, +} + +impl ChatManager { + pub fn new() -> ChatManager { + todo!() + } + + pub async fn open_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + todo!() + } + + pub async fn close_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + todo!() + } + + pub async fn delete_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + todo!() + } + + pub async fn create_chat(&self, uid: &i64, chat_id: &str) -> Result<(), FlowyError> { + todo!() + } +} diff --git a/frontend/rust-lib/flowy-chat/src/notification.rs b/frontend/rust-lib/flowy-chat/src/notification.rs new file mode 100644 index 0000000000000..6dc02e18c566e --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/notification.rs @@ -0,0 +1,30 @@ +use flowy_derive::ProtoBuf_Enum; +use flowy_notification::NotificationBuilder; + +const CHAT_OBSERVABLE_SOURCE: &str = "Chat"; + +#[derive(ProtoBuf_Enum, Debug, Default)] +pub enum ChatNotification { + #[default] + Unknown = 0, + DidReceiveResponse = 1, +} + +impl std::convert::From for i32 { + fn from(notification: ChatNotification) -> Self { + notification as i32 + } +} +impl std::convert::From for ChatNotification { + fn from(notification: i32) -> Self { + match notification { + 1 => ChatNotification::DidReceiveResponse, + _ => ChatNotification::Unknown, + } + } +} + +#[tracing::instrument(level = "trace")] +pub(crate) fn send_notification(id: &str, ty: ChatNotification) -> NotificationBuilder { + NotificationBuilder::new(id, ty, CHAT_OBSERVABLE_SOURCE) +} diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 289b4751b02a8..53429065e395e 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -31,6 +31,7 @@ diesel.workspace = true uuid.workspace = true flowy-storage = { workspace = true } client-api.workspace = true +flowy-chat = { workspace = true } tracing.workspace = true futures-core = { version = "0.3", default-features = false } @@ -61,6 +62,7 @@ dart = [ "flowy-search/dart", "flowy-folder/dart", "flowy-database2/dart", + "flowy-chat/dart", ] ts = [ "flowy-user/tauri_ts", @@ -68,6 +70,7 @@ ts = [ "flowy-search/tauri_ts", "flowy-database2/ts", "flowy-config/tauri_ts", + "flowy-chat/tauri_ts", ] openssl_vendored = ["flowy-sqlite/openssl_vendored"] diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs new file mode 100644 index 0000000000000..8288579a98f0c --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs @@ -0,0 +1,10 @@ +use flowy_chat::manager::ChatManager; +use std::sync::Arc; + +pub struct ChatDepsResolver; + +impl ChatDepsResolver { + pub fn resolve() -> Arc { + Arc::new(ChatManager::new()) + } +} diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs index 43a8478eb0480..e8cbb21006cd2 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs @@ -1,6 +1,7 @@ use bytes::Bytes; use collab_integrate::collab_builder::AppFlowyCollabBuilder; use collab_integrate::CollabKVDB; +use flowy_chat::manager::ChatManager; use flowy_database2::entities::DatabaseLayoutPB; use flowy_database2::services::share::csv::CSVFormat; use flowy_database2::template::{make_default_board, make_default_calendar, make_default_grid}; @@ -11,7 +12,9 @@ use flowy_document::parser::json::parser::JsonToDocumentParser; use flowy_error::FlowyError; use flowy_folder::manager::{FolderManager, FolderUser}; use flowy_folder::share::ImportType; -use flowy_folder::view_operation::{FolderOperationHandler, FolderOperationHandlers, View}; +use flowy_folder::view_operation::{ + FolderOperationHandler, FolderOperationHandlers, View, ViewData, +}; use flowy_folder::ViewLayout; use flowy_folder_pub::folder_builder::NestedViewBuilder; use flowy_search::folder::indexer::FolderIndexManagerImpl; @@ -34,12 +37,17 @@ impl FolderDepsResolver { collab_builder: Arc, server_provider: Arc, folder_indexer: Arc, + chat_manager: &Arc, ) -> Arc { let user: Arc = Arc::new(FolderUserImpl { authenticate_user: authenticate_user.clone(), }); - let handlers = folder_operation_handlers(document_manager.clone(), database_manager.clone()); + let handlers = folder_operation_handlers( + document_manager.clone(), + database_manager.clone(), + chat_manager.clone(), + ); Arc::new( FolderManager::new( user.clone(), @@ -57,6 +65,7 @@ impl FolderDepsResolver { fn folder_operation_handlers( document_manager: Arc, database_manager: Arc, + chat_manager: Arc, ) -> FolderOperationHandlers { let mut map: HashMap> = HashMap::new(); @@ -64,9 +73,11 @@ fn folder_operation_handlers( map.insert(ViewLayout::Document, document_folder_operation); let database_folder_operation = Arc::new(DatabaseFolderOperation(database_manager)); + let chat_folder_operation = Arc::new(ChatFolderOperation(chat_manager)); map.insert(ViewLayout::Board, database_folder_operation.clone()); map.insert(ViewLayout::Grid, database_folder_operation.clone()); map.insert(ViewLayout::Calendar, database_folder_operation); + map.insert(ViewLayout::Chat, chat_folder_operation); Arc::new(map) } @@ -460,3 +471,84 @@ impl CreateDatabaseExtParams { serde_json::from_value::(value).ok() } } + +struct ChatFolderOperation(Arc); +impl FolderOperationHandler for ChatFolderOperation { + fn open_view(&self, view_id: &str) -> FutureResult<(), FlowyError> { + let manager = self.0.clone(); + let view_id = view_id.to_string(); + FutureResult::new(async move { + manager.open_chat(&view_id).await?; + Ok(()) + }) + } + + fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> { + let manager = self.0.clone(); + let view_id = view_id.to_string(); + FutureResult::new(async move { + manager.close_chat(&view_id).await?; + Ok(()) + }) + } + + fn delete_view(&self, view_id: &str) -> FutureResult<(), FlowyError> { + let manager = self.0.clone(); + let view_id = view_id.to_string(); + FutureResult::new(async move { + manager.delete_chat(&view_id).await?; + Ok(()) + }) + } + + fn duplicate_view(&self, view_id: &str) -> FutureResult { + FutureResult::new(async move { Err(FlowyError::not_support()) }) + } + + fn create_view_with_view_data( + &self, + user_id: i64, + view_id: &str, + name: &str, + data: Vec, + layout: ViewLayout, + meta: HashMap, + ) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { Err(FlowyError::not_support()) }) + } + + fn create_built_in_view( + &self, + user_id: i64, + view_id: &str, + name: &str, + layout: ViewLayout, + ) -> FutureResult<(), FlowyError> { + let manager = self.0.clone(); + let view_id = view_id.to_string(); + FutureResult::new(async move { + manager.create_chat(&user_id, &view_id).await?; + Ok(()) + }) + } + + fn import_from_bytes( + &self, + uid: i64, + view_id: &str, + name: &str, + import_type: ImportType, + bytes: Vec, + ) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { Err(FlowyError::not_support()) }) + } + + fn import_from_file_path( + &self, + view_id: &str, + name: &str, + path: String, + ) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { Err(FlowyError::not_support()) }) + } +} diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs index a93530e519cda..a75589e89e23e 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs @@ -1,3 +1,4 @@ +pub use chat_deps::*; pub use collab_deps::*; pub use database_deps::*; pub use document_deps::*; @@ -9,6 +10,7 @@ mod collab_deps; mod document_deps; mod folder_deps; +mod chat_deps; mod database_deps; mod search_deps; mod user_deps; diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index 36addf0fe72f8..08e6e5564bc0d 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -166,6 +166,7 @@ impl AppFlowyCore { Arc::downgrade(&(server_provider.clone() as Arc)), ); + let chat_manager = ChatDepsResolver::resolve(); let folder_indexer = Arc::new(FolderIndexManagerImpl::new(None)); let folder_manager = FolderDepsResolver::resolve( Arc::downgrade(&authenticate_user), @@ -174,6 +175,7 @@ impl AppFlowyCore { collab_builder.clone(), server_provider.clone(), folder_indexer.clone(), + &chat_manager, ) .await; diff --git a/frontend/rust-lib/flowy-server/Cargo.toml b/frontend/rust-lib/flowy-server/Cargo.toml index b64b30fa496df..1e8e4e44fe4eb 100644 --- a/frontend/rust-lib/flowy-server/Cargo.toml +++ b/frontend/rust-lib/flowy-server/Cargo.toml @@ -41,6 +41,7 @@ flowy-error = { workspace = true, features = ["impl_from_serde", "impl_from_reqw flowy-server-pub = { workspace = true } flowy-encrypt = { workspace = true } flowy-storage = { workspace = true } +flowy-chat-pub = { workspace = true } mime_guess = "2.0" url = "2.4" tokio-util = "0.7" diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs new file mode 100644 index 0000000000000..538370216255d --- /dev/null +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -0,0 +1,84 @@ +use crate::af_cloud::AFServer; +use client_api::entity::{ + CreateChatMessageParams, CreateChatParams, MessageOffset, RepeatedChatMessage, +}; +use flowy_chat_pub::cloud::ChatCloudService; +use flowy_error::FlowyError; +use lib_infra::future::FutureResult; + +pub(crate) struct AFCloudChatCloudServiceImpl { + pub inner: T, +} + +impl ChatCloudService for AFCloudChatCloudServiceImpl +where + T: AFServer, +{ + fn create_chat( + &self, + _uid: &i64, + workspace_id: &str, + chat_id: &str, + ) -> FutureResult<(), FlowyError> { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let try_get_client = self.inner.try_get_client(); + + FutureResult::new(async move { + let params = CreateChatParams { + chat_id, + name: "".to_string(), + rag_ids: vec![], + }; + try_get_client? + .create_chat(&workspace_id, params) + .await + .map_err(FlowyError::from)?; + + Ok(()) + }) + } + + fn send_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult<(), FlowyError> { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let message = message.to_string(); + let try_get_client = self.inner.try_get_client(); + + FutureResult::new(async move { + let params = CreateChatMessageParams { content: message }; + try_get_client? + .create_chat_message(&workspace_id, &chat_id, params) + .await + .map_err(FlowyError::from)?; + + Ok(()) + }) + } + + fn get_chat_messages( + &self, + workspace_id: &str, + chat_id: &str, + offset: MessageOffset, + limit: u64, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let try_get_client = self.inner.try_get_client(); + + FutureResult::new(async move { + let resp = try_get_client? + .get_chat_messages(&workspace_id, &chat_id, offset, limit) + .await + .map_err(FlowyError::from)?; + + Ok(resp) + }) + } +} diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/mod.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/mod.rs index 3ecd8391095bf..37ad00781c61a 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/mod.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/mod.rs @@ -1,9 +1,11 @@ +pub(crate) use chat::*; pub(crate) use database::*; pub(crate) use document::*; pub(crate) use file_storage::*; pub(crate) use folder::*; pub(crate) use user::*; +mod chat; mod database; mod document; mod file_storage; diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs index 7e897bb66e155..7b3827561f19e 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs @@ -377,12 +377,12 @@ where let collab_object = collab_object.clone(); FutureResult::new(async move { let client = try_get_client?; - let params = CreateCollabParams::new( - collab_object.workspace_id, - collab_object.object_id, - collab_object.collab_type.into(), - data, - ); + let params = CreateCollabParams { + workspace_id: collab_object.workspace_id, + object_id: collab_object.object_id, + collab_type: collab_object.collab_type.into(), + encoded_collab_v1: data, + }; client.create_collab(params).await?; Ok(()) }) diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/server.rs b/frontend/rust-lib/flowy-server/src/af_cloud/server.rs index 1fd6a5b03fe31..b8a636fe7d18f 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/server.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/server.rs @@ -10,6 +10,7 @@ use client_api::ws::{ ConnectState, WSClient, WSClientConfig, WSConnectStateReceiver, WebSocketChannel, }; use client_api::{Client, ClientConfiguration}; +use flowy_chat_pub::cloud::ChatCloudService; use flowy_storage::ObjectStorageService; use rand::Rng; use tokio::select; @@ -30,9 +31,10 @@ use flowy_user_pub::entities::UserTokenState; use lib_dispatch::prelude::af_spawn; use crate::af_cloud::impls::{ - AFCloudDatabaseCloudServiceImpl, AFCloudDocumentCloudServiceImpl, AFCloudFileStorageServiceImpl, - AFCloudFolderCloudServiceImpl, AFCloudUserAuthServiceImpl, + AFCloudChatCloudServiceImpl, AFCloudDatabaseCloudServiceImpl, AFCloudDocumentCloudServiceImpl, + AFCloudFileStorageServiceImpl, AFCloudFolderCloudServiceImpl, AFCloudUserAuthServiceImpl, }; +use crate::default_impl::DefaultChatCloudServiceImpl; use crate::AppFlowyServer; pub(crate) type AFCloudClient = Client; @@ -213,6 +215,13 @@ impl AppFlowyServer for AppFlowyCloudServer { }) } + fn chat_service(&self) -> Arc { + let server = AFServerImpl { + client: self.get_client(), + }; + Arc::new(AFCloudChatCloudServiceImpl { inner: server }) + } + fn subscribe_ws_state(&self) -> Option { Some(self.ws_client.subscribe_connect_state()) } diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs new file mode 100644 index 0000000000000..b92a17da120c8 --- /dev/null +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -0,0 +1,42 @@ +use client_api::entity::{MessageOffset, RepeatedChatMessage}; +use flowy_chat_pub::cloud::ChatCloudService; +use flowy_error::FlowyError; +use lib_infra::future::FutureResult; + +pub(crate) struct DefaultChatCloudServiceImpl; + +impl ChatCloudService for DefaultChatCloudServiceImpl { + fn create_chat( + &self, + uid: &i64, + workspace_id: &str, + chat_id: &str, + ) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) + }) + } + + fn send_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult<(), FlowyError> { + FutureResult::new(async move { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) + }) + } + + fn get_chat_messages( + &self, + workspace_id: &str, + chat_id: &str, + offset: MessageOffset, + limit: u64, + ) -> FutureResult { + FutureResult::new(async move { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) + }) + } +} diff --git a/frontend/rust-lib/flowy-server/src/lib.rs b/frontend/rust-lib/flowy-server/src/lib.rs index 4e647f4210e29..704e9e0e49436 100644 --- a/frontend/rust-lib/flowy-server/src/lib.rs +++ b/frontend/rust-lib/flowy-server/src/lib.rs @@ -8,4 +8,5 @@ mod server; #[cfg(feature = "enable_supabase")] pub mod supabase; +mod default_impl; pub mod util; diff --git a/frontend/rust-lib/flowy-server/src/server.rs b/frontend/rust-lib/flowy-server/src/server.rs index 679771d162462..70a8e4b9a8a97 100644 --- a/frontend/rust-lib/flowy-server/src/server.rs +++ b/frontend/rust-lib/flowy-server/src/server.rs @@ -6,11 +6,13 @@ use std::sync::Arc; use anyhow::Error; use client_api::collab_sync::ServerCollabMessage; +use flowy_chat_pub::cloud::ChatCloudService; use parking_lot::RwLock; use tokio_stream::wrappers::WatchStream; #[cfg(feature = "enable_supabase")] use {collab_entity::CollabObject, collab_plugins::cloud_storage::RemoteCollabStorage}; +use crate::default_impl::DefaultChatCloudServiceImpl; use flowy_database_pub::cloud::DatabaseCloudService; use flowy_document_pub::cloud::DocumentCloudService; use flowy_folder_pub::cloud::FolderCloudService; @@ -94,6 +96,10 @@ pub trait AppFlowyServer: Send + Sync + 'static { /// An `Arc` wrapping the `DocumentCloudService` interface. fn document_service(&self) -> Arc; + fn chat_service(&self) -> Arc { + Arc::new(DefaultChatCloudServiceImpl) + } + /// Manages collaborative objects within a remote storage system. This includes operations such as /// checking storage status, retrieving updates and snapshots, and dispatching updates. The service /// also provides subscription capabilities for real-time updates. From d091002683c7aa461293c7cba4bc0cd15e51243c Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 23 May 2024 14:36:39 +0800 Subject: [PATCH 06/41] chore: add schema --- frontend/appflowy_flutter/pubspec.lock | 40 +++++++++ frontend/appflowy_flutter/pubspec.yaml | 1 + frontend/appflowy_tauri/src-tauri/Cargo.lock | 24 +++--- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 ++++++--- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 30 ++++--- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 47 ++++++---- frontend/rust-lib/Cargo.toml | 2 +- .../event-integration-test/Cargo.toml | 1 + frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 8 +- frontend/rust-lib/flowy-chat/Cargo.toml | 2 + frontend/rust-lib/flowy-chat/src/chat.rs | 16 ++++ frontend/rust-lib/flowy-chat/src/entities.rs | 62 +++++++++++++ .../rust-lib/flowy-chat/src/event_handler.rs | 32 ++++++- frontend/rust-lib/flowy-chat/src/event_map.rs | 11 ++- frontend/rust-lib/flowy-chat/src/lib.rs | 2 + frontend/rust-lib/flowy-chat/src/manager.rs | 50 ++++++++++- .../rust-lib/flowy-chat/src/persistence.rs | 86 +++++++++++++++++++ .../2024-05-23-061639_chat_message/down.sql | 3 + .../2024-05-23-061639_chat_message/up.sql | 20 +++++ frontend/rust-lib/flowy-sqlite/src/schema.rs | 29 ++++++- 23 files changed, 443 insertions(+), 69 deletions(-) create mode 100644 frontend/rust-lib/flowy-chat/src/chat.rs create mode 100644 frontend/rust-lib/flowy-chat/src/persistence.rs create mode 100644 frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/down.sql create mode 100644 frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index b46a113767248..3fa25daa467e9 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -385,6 +385,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.1" + diffutil_dart: + dependency: transitive + description: + name: diffutil_dart + sha256: "5e74883aedf87f3b703cb85e815bdc1ed9208b33501556e4a8a5572af9845c81" + url: "https://pub.dev" + source: hosted + version: "4.0.1" dotted_border: dependency: "direct main" description: @@ -594,6 +602,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.6.2" + flutter_chat_ui: + dependency: "direct main" + description: + name: flutter_chat_ui + sha256: "40fb37acc328dd179eadc3d67bf8bd2d950dc0da34464aa8d48e8707e0234c09" + url: "https://pub.dev" + source: hosted + version: "1.6.13" flutter_colorpicker: dependency: "direct main" description: @@ -653,6 +669,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" + flutter_parsed_text: + dependency: transitive + description: + name: flutter_parsed_text + sha256: "529cf5793b7acdf16ee0f97b158d0d4ba0bf06e7121ef180abe1a5b59e32c1e2" + url: "https://pub.dev" + source: hosted + version: "2.2.1" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -1385,6 +1409,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + photo_view: + dependency: transitive + description: + name: photo_view + sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" + url: "https://pub.dev" + source: hosted + version: "0.15.0" pixel_snap: dependency: transitive description: @@ -1537,6 +1569,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.9" + scroll_to_index: + dependency: transitive + description: + name: scroll_to_index + sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176 + url: "https://pub.dev" + source: hosted + version: "3.0.1" scrollable_positioned_list: dependency: "direct main" description: diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 8ad4bd55be041..8f88a10ac1f82 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -136,6 +136,7 @@ dependencies: flutter_animate: ^4.5.0 permission_handler: ^11.3.1 scaled_app: ^2.2.0 + flutter_chat_ui: ^1.6.13 dev_dependencies: flutter_lints: ^3.0.1 diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 6205f6624ac6c..c93cfcbeae398 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "serde", @@ -753,7 +753,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "again", "anyhow", @@ -800,7 +800,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "futures-channel", "futures-util", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "async-trait", @@ -1421,7 +1421,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -1813,11 +1813,13 @@ name = "flowy-chat" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-chat-pub", "flowy-codegen", "flowy-derive", "flowy-error", "flowy-notification", + "flowy-sqlite", "lib-dispatch", "lib-infra", "protobuf", @@ -2821,7 +2823,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "futures-util", @@ -2838,7 +2840,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -3270,7 +3272,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "reqwest", @@ -5758,7 +5760,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index e0153b672fb18..246fa091a2dac 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 89484d4681053..740d3fe82c64d 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "serde", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "again", "anyhow", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "async-trait", @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1024,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -1811,7 +1811,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "futures-util", @@ -1828,7 +1828,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -2129,7 +2129,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "reqwest", @@ -2813,7 +2813,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2833,6 +2833,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2900,6 +2901,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3755,7 +3769,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 965262069eb97..06d76e4e7bbf8 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index d4a2c6df5a45e..4e95633fc5414 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "serde", @@ -188,6 +188,7 @@ version = "0.0.0" dependencies = [ "bytes", "dotenv", + "flowy-chat", "flowy-config", "flowy-core", "flowy-date", @@ -726,7 +727,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "again", "anyhow", @@ -773,7 +774,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "futures-channel", "futures-util", @@ -1021,7 +1022,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -1046,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "async-trait", @@ -1296,7 +1297,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1407,7 +1408,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -2254,6 +2255,7 @@ dependencies = [ "collab-entity", "collab-folder", "collab-plugins", + "flowy-chat-pub", "flowy-database-pub", "flowy-document-pub", "flowy-encrypt", @@ -2893,7 +2895,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "futures-util", @@ -2910,7 +2912,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -3347,7 +3349,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "reqwest", @@ -4852,7 +4854,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4873,7 +4875,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.55", @@ -5851,7 +5853,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 11b2c4de50d20..d7dc779a56242 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index d35275c0ac480..caf90f3b85cfb 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "serde", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "again", "anyhow", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "bincode", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "async-trait", @@ -1162,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1261,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -1499,6 +1499,7 @@ dependencies = [ "collab-folder", "collab-plugins", "dotenv", + "flowy-chat", "flowy-core", "flowy-database-pub", "flowy-database2", @@ -1645,11 +1646,13 @@ name = "flowy-chat" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-chat-pub", "flowy-codegen", "flowy-derive", "flowy-error", "flowy-notification", + "flowy-sqlite", "lib-dispatch", "lib-infra", "protobuf", @@ -2504,7 +2507,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "futures-util", @@ -2521,7 +2524,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", @@ -2886,7 +2889,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "reqwest", @@ -3761,7 +3764,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3781,6 +3784,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3848,6 +3852,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.47", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -4051,7 +4068,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4072,7 +4089,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", @@ -4969,7 +4986,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=d0e06ce52a2e029405d63461de1a695227fa8b83#d0e06ce52a2e029405d63461de1a695227fa8b83" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 643795a14b742..8a8267ed38a33 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "d0e06ce52a2e029405d63461de1a695227fa8b83" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/event-integration-test/Cargo.toml b/frontend/rust-lib/event-integration-test/Cargo.toml index 26d561e993707..d579fee7a5525 100644 --- a/frontend/rust-lib/event-integration-test/Cargo.toml +++ b/frontend/rust-lib/event-integration-test/Cargo.toml @@ -16,6 +16,7 @@ flowy-database-pub = { workspace = true } flowy-document = { path = "../flowy-document" } flowy-document-pub = { workspace = true } flowy-encrypt = { workspace = true } +flowy-chat = { workspace = true } lib-dispatch = { workspace = true } lib-infra = { workspace = true } flowy-server = { path = "../flowy-server" } diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 3ea39aeaab407..53a2ff4ca98cb 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,4 +1,4 @@ -use client_api::entity::{MessageOffset, RepeatedChatMessage}; +pub use client_api::entity::{ChatMessage, MessageOffset, RepeatedChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -25,3 +25,9 @@ pub trait ChatCloudService: Send + Sync + 'static { limit: u64, ) -> FutureResult; } + +pub trait ChatUserService: Send + Sync + 'static { + fn user_id(&self) -> Result; + fn device_id(&self) -> Result; + fn workspace_id(&self) -> Result; +} diff --git a/frontend/rust-lib/flowy-chat/Cargo.toml b/frontend/rust-lib/flowy-chat/Cargo.toml index 3611f0a8ef441..e2c33c8b7719f 100644 --- a/frontend/rust-lib/flowy-chat/Cargo.toml +++ b/frontend/rust-lib/flowy-chat/Cargo.toml @@ -21,6 +21,8 @@ bytes.workspace = true validator = { version = "0.16.0", features = ["derive"] } lib-infra = { workspace = true } flowy-chat-pub.workspace = true +dashmap = "5.5" +flowy-sqlite = { workspace = true } [build-dependencies] flowy-codegen.workspace = true diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs new file mode 100644 index 0000000000000..eb5ec92c6fdef --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -0,0 +1,16 @@ +use flowy_chat_pub::cloud::ChatCloudService; +use std::sync::Arc; + +pub struct Chat { + chat_id: String, + cloud_service: Arc, +} + +impl Chat { + pub fn new(chat_id: String, cloud_service: Arc) -> Chat { + Chat { + chat_id, + cloud_service, + } + } +} diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index 8a9468efef465..aa5eb6e862833 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -1,3 +1,4 @@ +use flowy_chat_pub::cloud::{ChatMessage, RepeatedChatMessage}; use flowy_derive::ProtoBuf; use lib_infra::validator_fn::{required_not_empty_str, required_valid_path}; use validator::Validate; @@ -12,3 +13,64 @@ pub struct SendChatPayloadPB { #[validate(custom = "required_not_empty_str")] pub message: String, } + +#[derive(Default, ProtoBuf, Validate, Clone, Debug)] +pub struct LoadHistoryMessagePB { + #[pb(index = 1)] + #[validate(custom = "required_not_empty_str")] + pub chat_id: String, + + #[pb(index = 2)] + pub limit: i64, + + #[pb(index = 3, one_of)] + pub after_message_id: Option, + + #[pb(index = 4, one_of)] + pub before_message_id: Option, +} + +#[derive(Default, ProtoBuf, Validate, Clone, Debug)] +pub struct RepeatedChatMessagePB { + #[pb(index = 1)] + pub has_more: bool, + + #[pb(index = 2)] + pub messages: Vec, +} + +impl From for RepeatedChatMessagePB { + fn from(repeated_chat_message: RepeatedChatMessage) -> Self { + let messages = repeated_chat_message + .messages + .into_iter() + .map(ChatMessagePB::from) + .collect(); + RepeatedChatMessagePB { + has_more: repeated_chat_message.has_more, + messages, + } + } +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct ChatMessagePB { + #[pb(index = 1)] + pub message_id: i64, + + #[pb(index = 2)] + pub content: String, + + #[pb(index = 3)] + pub created_at: i64, +} + +impl From for ChatMessagePB { + fn from(chat_message: ChatMessage) -> Self { + ChatMessagePB { + message_id: chat_message.message_id, + content: chat_message.content, + created_at: chat_message.created_at.timestamp(), + } + } +} diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 2354fb7ad215a..2918c68e46fe5 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -1,5 +1,6 @@ use std::sync::{Arc, Weak}; use tracing::instrument; +use validator::Validate; use flowy_error::{FlowyError, FlowyResult}; use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult}; @@ -16,10 +17,37 @@ fn upgrade_chat_manager( Ok(chat_manager) } -#[tracing::instrument(level = "debug", skip(data, folder), err)] +#[tracing::instrument(level = "debug", skip_all, err)] pub(crate) async fn send_chat_message_handler( data: AFPluginData, - folder: AFPluginState>, + chat_manager: AFPluginState>, ) -> Result<(), FlowyError> { + let chat_manager = upgrade_chat_manager(chat_manager)?; + let data = data.into_inner(); + data.validate()?; + + chat_manager + .send_chat_message(&data.chat_id, &data.message) + .await?; Ok(()) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_history_message_handler( + data: AFPluginData, + chat_manager: AFPluginState>, +) -> DataResult { + let chat_manager = upgrade_chat_manager(chat_manager)?; + let data = data.into_inner(); + data.validate()?; + + let messages = chat_manager + .get_history_messages( + &data.chat_id, + data.limit, + data.after_message_id, + data.before_message_id, + ) + .await?; + data_result_ok(messages) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 7a4b21a424696..071cf5a0738b8 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -9,15 +9,20 @@ use crate::event_handler::*; use crate::manager::ChatManager; pub fn init(chat_manager: Weak) -> AFPlugin { - AFPlugin::new().name("Flowy-Chat").state(chat_manager) - // Workspace + AFPlugin::new() + .name("Flowy-Chat") + .state(chat_manager) .event(ChatEvent::SendMessage, send_chat_message_handler) + .event(ChatEvent::GetHistoryMessage, get_history_message_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] #[event_err = "FlowyError"] pub enum ChatEvent { /// Create a new workspace + #[event(input = "LoadHistoryMessagePB", output = "RepeatedChatMessage")] + GetHistoryMessage = 0, + #[event(input = "SendChatPayloadPB")] - SendMessage = 0, + SendMessage = 1, } diff --git a/frontend/rust-lib/flowy-chat/src/lib.rs b/frontend/rust-lib/flowy-chat/src/lib.rs index 713b957ffa111..720518ddb798d 100644 --- a/frontend/rust-lib/flowy-chat/src/lib.rs +++ b/frontend/rust-lib/flowy-chat/src/lib.rs @@ -1,7 +1,9 @@ mod event_handler; mod event_map; +mod chat; mod entities; pub mod manager; mod notification; +mod persistence; pub mod protobuf; diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index c878c55bd24eb..a425b5e6fab2b 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,9 +1,15 @@ -use flowy_chat_pub::cloud::ChatCloudService; +use crate::chat::Chat; +use crate::entities::RepeatedChatMessagePB; +use dashmap::DashMap; +use flowy_chat_pub::cloud::{ChatCloudService, ChatUserService, MessageOffset}; use flowy_error::FlowyError; use std::sync::Arc; +use tracing::warn; pub struct ChatManager { cloud_service: Arc, + user_service: Arc, + chats: DashMap>, } impl ChatManager { @@ -24,6 +30,46 @@ impl ChatManager { } pub async fn create_chat(&self, uid: &i64, chat_id: &str) -> Result<(), FlowyError> { - todo!() + let workspace_id = self.user_service.workspace_id()?; + self + .cloud_service + .create_chat(uid, &workspace_id, chat_id) + .await?; + Ok(()) + } + + pub async fn send_chat_message(&self, chat_id: &str, message: &str) -> Result<(), FlowyError> { + let workspace_id = self.user_service.workspace_id()?; + self + .cloud_service + .send_message(&workspace_id, chat_id, message) + .await?; + Ok(()) + } + + pub async fn get_history_messages( + &self, + chat_id: &str, + limit: i64, + after_message_id: Option, + before_message_id: Option, + ) -> Result { + if after_message_id.is_some() && before_message_id.is_some() { + warn!("Cannot specify both after_message_id and before_message_id"); + } + let workspace_id = self.user_service.workspace_id()?; + let offset = if after_message_id.is_some() { + MessageOffset::AfterMessageId(after_message_id.unwrap()) + } else if before_message_id.is_some() { + MessageOffset::BeforeMessageId(before_message_id.unwrap()) + } else { + MessageOffset::Offset(0) + }; + + let resp = self + .cloud_service + .get_chat_messages(&workspace_id, &chat_id, offset, limit as u64) + .await?; + Ok(RepeatedChatMessagePB::from(resp)) } } diff --git a/frontend/rust-lib/flowy-chat/src/persistence.rs b/frontend/rust-lib/flowy-chat/src/persistence.rs new file mode 100644 index 0000000000000..c0d9816e8cd43 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/persistence.rs @@ -0,0 +1,86 @@ +use flowy_sqlite::query_dsl::methods::OrderDsl; +use flowy_sqlite::schema::chat_message_table::dsl::chat_message_table; +use flowy_sqlite::schema::chat_message_table::{content, created_at, message_id}; +use flowy_sqlite::schema::chat_table::dsl::chat_table; +use flowy_sqlite::schema::chat_table::{chat_id, name}; +use flowy_sqlite::{ + diesel, ExpressionMethods, Insertable, QueryResult, Queryable, RunQueryDsl, SqliteConnection, +}; + +pub fn create_chat(conn: &mut SqliteConnection, new_chat: Chat) -> QueryResult { + diesel::insert_into(chat_table) + .values(&new_chat) + .execute(conn) +} + +pub fn read_chat(conn: &SqliteConnection, chat_id_val: &str) -> QueryResult { + chat_table.filter(chat_id.eq(chat_id_val)).first(conn) +} + +pub fn update_chat_name( + conn: &SqliteConnection, + chat_id_val: &str, + new_name: &str, +) -> QueryResult { + diesel::update(chat_table.filter(chat_id.eq(chat_id_val))) + .set(name.eq(new_name)) + .execute(conn) +} + +pub fn delete_chat(conn: &SqliteConnection, chat_id_val: &str) -> QueryResult { + diesel::delete(chat_table.filter(chat_id.eq(chat_id_val))).execute(conn) +} + +pub fn create_chat_message( + conn: &mut SqliteConnection, + new_message: ChatMessage, +) -> QueryResult { + diesel::insert_into(chat_message_table) + .values(&new_message) + .execute(conn) +} + +pub fn read_chat_message(conn: &SqliteConnection, message_id_val: i32) -> QueryResult { + chat_message_table + .filter(message_id.eq(message_id_val)) + .first(conn) +} + +pub fn update_chat_message_content( + conn: &SqliteConnection, + message_id_val: i32, + new_content: &str, +) -> QueryResult { + diesel::update(chat_message_table.filter(message_id.eq(message_id_val))) + .set(content.eq(new_content)) + .execute(conn) +} + +pub fn read_all_chat_messages( + conn: &SqliteConnection, + chat_id_val: &str, + limit_val: i64, +) -> QueryResult> { + chat_message_table + .filter(chat_id.eq(chat_id_val)) + .order(created_at.asc()) + .limit(limit_val) + .load::(conn) +} + +#[derive(Queryable, Insertable)] +#[table_name = "chat_table"] +pub struct Chat { + pub chat_id: String, + pub created_at: i64, + pub name: String, +} + +#[derive(Queryable, Insertable)] +#[table_name = "chat_message_table"] +pub struct ChatMessage { + pub message_id: i64, + pub chat_id: String, + pub content: String, + pub created_at: i64, +} diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/down.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/down.sql new file mode 100644 index 0000000000000..943e78adf2df8 --- /dev/null +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +drop table chat_table; +drop table chat_message_table; \ No newline at end of file diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql new file mode 100644 index 0000000000000..5fb7afbcd9857 --- /dev/null +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql @@ -0,0 +1,20 @@ +-- Your SQL goes here +-- Create table for chat documents +CREATE TABLE chat_table +( + chat_id TEXT PRIMARY KEY, + created_at INTEGER NOT NULL, + name TEXT NOT NULL DEFAULT '' +); + +-- Create table for chat messages +CREATE TABLE chat_message_table +( + message_id INTEGER PRIMARY KEY AUTOINCREMENT, + chat_id TEXT NOT NULL, + content TEXT NOT NULL, + created_at INTEGER NOT NULL, + FOREIGN KEY (chat_id) REFERENCES chat_table (chat_id) ON DELETE CASCADE +); + +CREATE INDEX idx_chat_messages_chat_id_created_at ON chat_message_table (message_id ASC, created_at ASC); diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index 37c2ff8bbd01a..941f640cdfcae 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -1,5 +1,22 @@ // @generated automatically by Diesel CLI. +diesel::table! { + chat_message_table (message_id) { + message_id -> Nullable, + chat_id -> Text, + content -> Text, + created_at -> Integer, + } +} + +diesel::table! { + chat_table (chat_id) { + chat_id -> Nullable, + created_at -> Integer, + name -> Text, + } +} + diesel::table! { collab_snapshot (id) { id -> Text, @@ -47,9 +64,13 @@ diesel::table! { } } +diesel::joinable!(chat_message_table -> chat_table (chat_id)); + diesel::allow_tables_to_appear_in_same_query!( - collab_snapshot, - user_data_migration_records, - user_table, - user_workspace_table, + chat_message_table, + chat_table, + collab_snapshot, + user_data_migration_records, + user_table, + user_workspace_table, ); From 06f0405b19feceedbb14e562be390f87820f3fb5 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 23 May 2024 19:29:11 +0800 Subject: [PATCH 07/41] chore: setup event --- frontend/appflowy_tauri/src-tauri/Cargo.lock | 2 + frontend/rust-lib/Cargo.lock | 2 + frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 8 +- frontend/rust-lib/flowy-chat/Cargo.toml | 1 + frontend/rust-lib/flowy-chat/src/entities.rs | 2 +- .../rust-lib/flowy-chat/src/event_handler.rs | 6 +- frontend/rust-lib/flowy-chat/src/event_map.rs | 6 +- frontend/rust-lib/flowy-chat/src/manager.rs | 219 +++++++++++++++--- .../rust-lib/flowy-chat/src/notification.rs | 4 +- .../rust-lib/flowy-chat/src/persistence.rs | 86 ------- .../src/persistence/chat_message_sql.rs | 72 ++++++ .../flowy-chat/src/persistence/chat_sql.rs | 42 ++++ .../flowy-chat/src/persistence/mod.rs | 5 + frontend/rust-lib/flowy-core/Cargo.toml | 1 + .../flowy-core/src/deps_resolve/chat_deps.rs | 45 +++- .../flowy-core/src/integrate/trait_impls.rs | 57 +++++ frontend/rust-lib/flowy-core/src/lib.rs | 3 +- .../flowy-server/src/af_cloud/impls/chat.rs | 8 +- .../rust-lib/flowy-server/src/default_impl.rs | 4 +- .../2024-05-23-061639_chat_message/up.sql | 14 +- frontend/rust-lib/flowy-sqlite/src/schema.rs | 8 +- 21 files changed, 444 insertions(+), 151 deletions(-) delete mode 100644 frontend/rust-lib/flowy-chat/src/persistence.rs create mode 100644 frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs create mode 100644 frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs create mode 100644 frontend/rust-lib/flowy-chat/src/persistence/mod.rs diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index c93cfcbeae398..ecab41ffebda0 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -1824,6 +1824,7 @@ dependencies = [ "lib-infra", "protobuf", "strum_macros 0.21.1", + "tokio", "tracing", "uuid", "validator", @@ -1890,6 +1891,7 @@ dependencies = [ "collab-plugins", "diesel", "flowy-chat", + "flowy-chat-pub", "flowy-config", "flowy-database-pub", "flowy-database2", diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index caf90f3b85cfb..183124c821dd4 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -1657,6 +1657,7 @@ dependencies = [ "lib-infra", "protobuf", "strum_macros 0.21.1", + "tokio", "tracing", "uuid", "validator", @@ -1724,6 +1725,7 @@ dependencies = [ "console-subscriber", "diesel", "flowy-chat", + "flowy-chat-pub", "flowy-config", "flowy-database-pub", "flowy-database2", diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 53a2ff4ca98cb..441a1e126f329 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -15,7 +15,7 @@ pub trait ChatCloudService: Send + Sync + 'static { workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult<(), FlowyError>; + ) -> FutureResult; fn get_chat_messages( &self, @@ -25,9 +25,3 @@ pub trait ChatCloudService: Send + Sync + 'static { limit: u64, ) -> FutureResult; } - -pub trait ChatUserService: Send + Sync + 'static { - fn user_id(&self) -> Result; - fn device_id(&self) -> Result; - fn workspace_id(&self) -> Result; -} diff --git a/frontend/rust-lib/flowy-chat/Cargo.toml b/frontend/rust-lib/flowy-chat/Cargo.toml index e2c33c8b7719f..331520c54c946 100644 --- a/frontend/rust-lib/flowy-chat/Cargo.toml +++ b/frontend/rust-lib/flowy-chat/Cargo.toml @@ -23,6 +23,7 @@ lib-infra = { workspace = true } flowy-chat-pub.workspace = true dashmap = "5.5" flowy-sqlite = { workspace = true } +tokio.workspace = true [build-dependencies] flowy-codegen.workspace = true diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index aa5eb6e862833..dd73dd6569a1b 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -15,7 +15,7 @@ pub struct SendChatPayloadPB { } #[derive(Default, ProtoBuf, Validate, Clone, Debug)] -pub struct LoadHistoryMessagePB { +pub struct LoadChatMessagePB { #[pb(index = 1)] #[validate(custom = "required_not_empty_str")] pub chat_id: String, diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 2918c68e46fe5..402ae0b0aba6a 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -33,8 +33,8 @@ pub(crate) async fn send_chat_message_handler( } #[tracing::instrument(level = "debug", skip_all, err)] -pub(crate) async fn get_history_message_handler( - data: AFPluginData, +pub(crate) async fn load_message_handler( + data: AFPluginData, chat_manager: AFPluginState>, ) -> DataResult { let chat_manager = upgrade_chat_manager(chat_manager)?; @@ -42,7 +42,7 @@ pub(crate) async fn get_history_message_handler( data.validate()?; let messages = chat_manager - .get_history_messages( + .load_chat_messages( &data.chat_id, data.limit, data.after_message_id, diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 071cf5a0738b8..618b1a6cc1d92 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -13,15 +13,15 @@ pub fn init(chat_manager: Weak) -> AFPlugin { .name("Flowy-Chat") .state(chat_manager) .event(ChatEvent::SendMessage, send_chat_message_handler) - .event(ChatEvent::GetHistoryMessage, get_history_message_handler) + .event(ChatEvent::LoadMessage, load_message_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] #[event_err = "FlowyError"] pub enum ChatEvent { /// Create a new workspace - #[event(input = "LoadHistoryMessagePB", output = "RepeatedChatMessage")] - GetHistoryMessage = 0, + #[event(input = "LoadChatMessagePB", output = "RepeatedChatMessage")] + LoadMessage = 0, #[event(input = "SendChatPayloadPB")] SendMessage = 1, diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index a425b5e6fab2b..3685232e4761c 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,10 +1,23 @@ use crate::chat::Chat; -use crate::entities::RepeatedChatMessagePB; +use crate::entities::{ChatMessagePB, RepeatedChatMessagePB}; +use crate::notification::{send_notification, ChatNotification}; +use crate::persistence::{ + insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, +}; use dashmap::DashMap; -use flowy_chat_pub::cloud::{ChatCloudService, ChatUserService, MessageOffset}; -use flowy_error::FlowyError; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageOffset, RepeatedChatMessage}; +use flowy_error::{FlowyError, FlowyResult}; +use flowy_sqlite::{DBConnection, QueryResult}; +use lib_infra::util::timestamp; use std::sync::Arc; -use tracing::warn; +use tracing::{error, warn}; + +pub trait ChatUserService: Send + Sync + 'static { + fn user_id(&self) -> Result; + fn device_id(&self) -> Result; + fn workspace_id(&self) -> Result; + fn sqlite_connection(&self, uid: i64) -> Result; +} pub struct ChatManager { cloud_service: Arc, @@ -13,20 +26,29 @@ pub struct ChatManager { } impl ChatManager { - pub fn new() -> ChatManager { - todo!() + pub fn new( + cloud_service: Arc, + user_service: impl ChatUserService, + ) -> ChatManager { + let user_service = Arc::new(user_service); + + Self { + cloud_service, + user_service, + chats: DashMap::new(), + } } pub async fn open_chat(&self, chat_id: &str) -> Result<(), FlowyError> { - todo!() + Ok(()) } pub async fn close_chat(&self, chat_id: &str) -> Result<(), FlowyError> { - todo!() + Ok(()) } pub async fn delete_chat(&self, chat_id: &str) -> Result<(), FlowyError> { - todo!() + Ok(()) } pub async fn create_chat(&self, uid: &i64, chat_id: &str) -> Result<(), FlowyError> { @@ -35,41 +57,184 @@ impl ChatManager { .cloud_service .create_chat(uid, &workspace_id, chat_id) .await?; + save_chat(self.user_service.sqlite_connection(*uid)?, chat_id)?; Ok(()) } pub async fn send_chat_message(&self, chat_id: &str, message: &str) -> Result<(), FlowyError> { + let uid = self.user_service.user_id()?; let workspace_id = self.user_service.workspace_id()?; - self + let message = self .cloud_service .send_message(&workspace_id, chat_id, message) .await?; + save_chat_message( + self.user_service.sqlite_connection(uid)?, + chat_id, + vec![message], + )?; Ok(()) } - pub async fn get_history_messages( + /// Load chat messages for a given `chat_id`. + /// + /// 1. When opening a chat: + /// - Loads local chat messages. + /// - `after_message_id` and `before_message_id` are `None`. + /// - Spawns a task to load messages from the remote server, notifying the user when the remote messages are loaded. + /// + /// 2. Loading more messages in an existing chat with `after_message_id`: + /// - `after_message_id` is the last message ID in the current chat messages. + /// + /// 3. Loading more messages in an existing chat with `before_message_id`: + /// - `before_message_id` is the first message ID in the current chat messages. + /// + /// 4. `after_message_id` and `before_message_id` cannot be specified at the same time. + + pub async fn load_chat_messages( &self, chat_id: &str, limit: i64, after_message_id: Option, before_message_id: Option, ) -> Result { - if after_message_id.is_some() && before_message_id.is_some() { - warn!("Cannot specify both after_message_id and before_message_id"); - } - let workspace_id = self.user_service.workspace_id()?; - let offset = if after_message_id.is_some() { - MessageOffset::AfterMessageId(after_message_id.unwrap()) - } else if before_message_id.is_some() { - MessageOffset::BeforeMessageId(before_message_id.unwrap()) - } else { - MessageOffset::Offset(0) - }; - - let resp = self - .cloud_service - .get_chat_messages(&workspace_id, &chat_id, offset, limit as u64) + let uid = self.user_service.user_id()?; + let messages = self + .load_local_chat_messages(uid, chat_id, limit, after_message_id, before_message_id) .await?; - Ok(RepeatedChatMessagePB::from(resp)) + + let after_message_id = after_message_id.or_else(|| messages.last().map(|m| m.message_id)); + let before_message_id = before_message_id.or_else(|| messages.first().map(|m| m.message_id)); + + if let Err(err) = self + .load_remote_chat_messages(chat_id, limit, after_message_id, before_message_id) + .await + { + error!("Failed to load remote chat messages: {}", err); + } + Ok(RepeatedChatMessagePB { + messages, + has_more: true, + }) } + + async fn load_local_chat_messages( + &self, + uid: i64, + chat_id: &str, + limit: i64, + after_message_id: Option, + before_message_id: Option, + ) -> Result, FlowyError> { + let conn = self.user_service.sqlite_connection(uid)?; + let records = select_chat_messages(conn, chat_id, limit, after_message_id, before_message_id)?; + let messages = records + .into_iter() + .map(|record| ChatMessagePB { + message_id: record.message_id, + content: record.content, + created_at: record.created_at, + }) + .collect::>(); + + Ok(messages) + } + + async fn load_remote_chat_messages( + &self, + chat_id: &str, + limit: i64, + after_message_id: Option, + before_message_id: Option, + ) -> Result<(), FlowyError> { + let chat_id = chat_id.to_string(); + let user_service = self.user_service.clone(); + let cloud_service = self.cloud_service.clone(); + tokio::spawn(async move { + let uid = user_service.user_id()?; + let workspace_id = user_service.workspace_id()?; + match _load_remote_chat_messages( + workspace_id, + chat_id.to_string(), + limit, + after_message_id, + before_message_id, + cloud_service, + ) + .await + { + Ok(resp) => { + // Save chat messages to local disk + save_chat_message( + user_service.sqlite_connection(uid)?, + &chat_id, + resp.messages.clone(), + )?; + let pb = RepeatedChatMessagePB::from(resp); + send_notification(&chat_id, ChatNotification::DidLoadChatMessage) + .payload(pb) + .send(); + }, + Err(err) => { + error!("Failed to load chat messages: {}", err); + }, + } + Ok::<(), FlowyError>(()) + }); + Ok(()) + } +} + +async fn _load_remote_chat_messages( + workspace_id: String, + chat_id: String, + limit: i64, + after_message_id: Option, + before_message_id: Option, + cloud_service: Arc, +) -> Result { + if after_message_id.is_some() && before_message_id.is_some() { + warn!("Cannot specify both after_message_id and before_message_id"); + } + let offset = if after_message_id.is_some() { + MessageOffset::AfterMessageId(after_message_id.unwrap()) + } else if before_message_id.is_some() { + MessageOffset::BeforeMessageId(before_message_id.unwrap()) + } else { + MessageOffset::Offset(0) + }; + + let resp = cloud_service + .get_chat_messages(&workspace_id, &chat_id, offset, limit as u64) + .await?; + Ok(resp) +} + +fn save_chat_message( + conn: DBConnection, + chat_id: &str, + messages: Vec, +) -> FlowyResult<()> { + let records = messages + .into_iter() + .map(|message| ChatMessageTable { + message_id: message.message_id, + chat_id: chat_id.to_string(), + content: message.content, + created_at: message.created_at.timestamp(), + }) + .collect::>(); + insert_chat_messages(conn, &records)?; + Ok(()) +} + +fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { + let row = ChatTable { + chat_id: chat_id.to_string(), + created_at: timestamp(), + name: "".to_string(), + }; + + insert_chat(conn, &row)?; + Ok(()) } diff --git a/frontend/rust-lib/flowy-chat/src/notification.rs b/frontend/rust-lib/flowy-chat/src/notification.rs index 6dc02e18c566e..3e02bcee8abca 100644 --- a/frontend/rust-lib/flowy-chat/src/notification.rs +++ b/frontend/rust-lib/flowy-chat/src/notification.rs @@ -7,7 +7,7 @@ const CHAT_OBSERVABLE_SOURCE: &str = "Chat"; pub enum ChatNotification { #[default] Unknown = 0, - DidReceiveResponse = 1, + DidLoadChatMessage = 1, } impl std::convert::From for i32 { @@ -18,7 +18,7 @@ impl std::convert::From for i32 { impl std::convert::From for ChatNotification { fn from(notification: i32) -> Self { match notification { - 1 => ChatNotification::DidReceiveResponse, + 1 => ChatNotification::DidLoadChatMessage, _ => ChatNotification::Unknown, } } diff --git a/frontend/rust-lib/flowy-chat/src/persistence.rs b/frontend/rust-lib/flowy-chat/src/persistence.rs deleted file mode 100644 index c0d9816e8cd43..0000000000000 --- a/frontend/rust-lib/flowy-chat/src/persistence.rs +++ /dev/null @@ -1,86 +0,0 @@ -use flowy_sqlite::query_dsl::methods::OrderDsl; -use flowy_sqlite::schema::chat_message_table::dsl::chat_message_table; -use flowy_sqlite::schema::chat_message_table::{content, created_at, message_id}; -use flowy_sqlite::schema::chat_table::dsl::chat_table; -use flowy_sqlite::schema::chat_table::{chat_id, name}; -use flowy_sqlite::{ - diesel, ExpressionMethods, Insertable, QueryResult, Queryable, RunQueryDsl, SqliteConnection, -}; - -pub fn create_chat(conn: &mut SqliteConnection, new_chat: Chat) -> QueryResult { - diesel::insert_into(chat_table) - .values(&new_chat) - .execute(conn) -} - -pub fn read_chat(conn: &SqliteConnection, chat_id_val: &str) -> QueryResult { - chat_table.filter(chat_id.eq(chat_id_val)).first(conn) -} - -pub fn update_chat_name( - conn: &SqliteConnection, - chat_id_val: &str, - new_name: &str, -) -> QueryResult { - diesel::update(chat_table.filter(chat_id.eq(chat_id_val))) - .set(name.eq(new_name)) - .execute(conn) -} - -pub fn delete_chat(conn: &SqliteConnection, chat_id_val: &str) -> QueryResult { - diesel::delete(chat_table.filter(chat_id.eq(chat_id_val))).execute(conn) -} - -pub fn create_chat_message( - conn: &mut SqliteConnection, - new_message: ChatMessage, -) -> QueryResult { - diesel::insert_into(chat_message_table) - .values(&new_message) - .execute(conn) -} - -pub fn read_chat_message(conn: &SqliteConnection, message_id_val: i32) -> QueryResult { - chat_message_table - .filter(message_id.eq(message_id_val)) - .first(conn) -} - -pub fn update_chat_message_content( - conn: &SqliteConnection, - message_id_val: i32, - new_content: &str, -) -> QueryResult { - diesel::update(chat_message_table.filter(message_id.eq(message_id_val))) - .set(content.eq(new_content)) - .execute(conn) -} - -pub fn read_all_chat_messages( - conn: &SqliteConnection, - chat_id_val: &str, - limit_val: i64, -) -> QueryResult> { - chat_message_table - .filter(chat_id.eq(chat_id_val)) - .order(created_at.asc()) - .limit(limit_val) - .load::(conn) -} - -#[derive(Queryable, Insertable)] -#[table_name = "chat_table"] -pub struct Chat { - pub chat_id: String, - pub created_at: i64, - pub name: String, -} - -#[derive(Queryable, Insertable)] -#[table_name = "chat_message_table"] -pub struct ChatMessage { - pub message_id: i64, - pub chat_id: String, - pub content: String, - pub created_at: i64, -} diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs new file mode 100644 index 0000000000000..9c1dbda172f12 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs @@ -0,0 +1,72 @@ +use flowy_chat_pub::cloud::ChatMessage; +use flowy_sqlite::{ + diesel, + query_dsl::*, + schema::{chat_message_table, chat_message_table::dsl}, + DBConnection, ExpressionMethods, Identifiable, Insertable, QueryResult, Queryable, +}; + +#[derive(Queryable, Insertable, Identifiable)] +#[diesel(table_name = chat_message_table)] +#[diesel(primary_key(message_id))] +pub struct ChatMessageTable { + pub message_id: i64, + pub chat_id: String, + pub content: String, + pub created_at: i64, +} + +pub fn insert_chat_messages( + mut conn: DBConnection, + new_messages: &[ChatMessageTable], +) -> QueryResult { + diesel::insert_into(chat_message_table::table) + .values(new_messages) + .execute(&mut *conn) +} + +pub fn read_chat_message( + mut conn: DBConnection, + message_id_val: i64, +) -> QueryResult { + dsl::chat_message_table + .filter(chat_message_table::message_id.eq(message_id_val)) + .first::(&mut *conn) +} + +// pub fn select_chat_messages( +// mut conn: DBConnection, +// chat_id_val: &str, +// limit_val: i64, +// ) -> QueryResult> { +// dsl::chat_message_table +// .filter(chat_message_table::chat_id.eq(chat_id_val)) +// .order(chat_message_table::created_at.asc()) +// .limit(limit_val) +// .load::(&mut *conn) +// } + +pub fn select_chat_messages( + mut conn: DBConnection, + chat_id_val: &str, + limit_val: i64, + after_message_id: Option, + before_message_id: Option, +) -> QueryResult> { + let mut query = dsl::chat_message_table + .filter(chat_message_table::chat_id.eq(chat_id_val)) + .into_boxed(); + if let Some(after_message_id) = after_message_id { + query = query.filter(chat_message_table::message_id.gt(after_message_id)); + } + + if let Some(before_message_id) = before_message_id { + query = query.filter(chat_message_table::message_id.lt(before_message_id)); + } + query = query + .order(chat_message_table::created_at.asc()) + .limit(limit_val); + + let messages: Vec = query.load::(&mut *conn)?; + Ok(messages) +} diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs new file mode 100644 index 0000000000000..480e57ca6e52b --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs @@ -0,0 +1,42 @@ +use flowy_sqlite::{ + diesel, + query_dsl::*, + schema::{chat_table, chat_table::dsl}, + DBConnection, ExpressionMethods, Identifiable, Insertable, QueryResult, Queryable, +}; + +#[derive(Clone, Default, Queryable, Insertable, Identifiable)] +#[diesel(table_name = chat_table)] +#[diesel(primary_key(chat_id))] +pub struct ChatTable { + pub chat_id: String, + pub created_at: i64, + pub name: String, +} + +pub fn insert_chat(mut conn: DBConnection, new_chat: &ChatTable) -> QueryResult { + diesel::insert_into(chat_table::table) + .values(new_chat) + .execute(&mut *conn) +} + +pub fn read_chat(mut conn: DBConnection, chat_id_val: &str) -> QueryResult { + let row = dsl::chat_table + .filter(chat_table::chat_id.eq(chat_id_val)) + .first::(&mut *conn)?; + Ok(row) +} + +pub fn update_chat_name( + mut conn: DBConnection, + chat_id_val: &str, + new_name: &str, +) -> QueryResult { + diesel::update(dsl::chat_table.filter(chat_table::chat_id.eq(chat_id_val))) + .set(chat_table::name.eq(new_name)) + .execute(&mut *conn) +} + +pub fn delete_chat(mut conn: DBConnection, chat_id_val: &str) -> QueryResult { + diesel::delete(dsl::chat_table.filter(chat_table::chat_id.eq(chat_id_val))).execute(&mut *conn) +} diff --git a/frontend/rust-lib/flowy-chat/src/persistence/mod.rs b/frontend/rust-lib/flowy-chat/src/persistence/mod.rs new file mode 100644 index 0000000000000..b21eb507ae0d3 --- /dev/null +++ b/frontend/rust-lib/flowy-chat/src/persistence/mod.rs @@ -0,0 +1,5 @@ +mod chat_message_sql; +mod chat_sql; + +pub use chat_message_sql::*; +pub use chat_sql::*; diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 53429065e395e..0e5687ce2e59b 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -32,6 +32,7 @@ uuid.workspace = true flowy-storage = { workspace = true } client-api.workspace = true flowy-chat = { workspace = true } +flowy-chat-pub = { workspace = true } tracing.workspace = true futures-core = { version = "0.3", default-features = false } diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs index 8288579a98f0c..9ba1604182549 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/chat_deps.rs @@ -1,10 +1,47 @@ -use flowy_chat::manager::ChatManager; -use std::sync::Arc; +use flowy_chat::manager::{ChatManager, ChatUserService}; +use flowy_chat_pub::cloud::ChatCloudService; +use flowy_error::FlowyError; +use flowy_sqlite::DBConnection; +use flowy_user::services::authenticate_user::AuthenticateUser; +use std::sync::{Arc, Weak}; pub struct ChatDepsResolver; impl ChatDepsResolver { - pub fn resolve() -> Arc { - Arc::new(ChatManager::new()) + pub fn resolve( + authenticate_user: Weak, + cloud_service: Arc, + ) -> Arc { + let user_service = ChatUserServiceImpl(authenticate_user); + Arc::new(ChatManager::new(cloud_service, user_service)) + } +} + +struct ChatUserServiceImpl(Weak); +impl ChatUserServiceImpl { + fn upgrade_user(&self) -> Result, FlowyError> { + let user = self + .0 + .upgrade() + .ok_or(FlowyError::internal().with_context("Unexpected error: UserSession is None"))?; + Ok(user) + } +} + +impl ChatUserService for ChatUserServiceImpl { + fn user_id(&self) -> Result { + self.upgrade_user()?.user_id() + } + + fn device_id(&self) -> Result { + self.upgrade_user()?.device_id() + } + + fn workspace_id(&self) -> Result { + self.upgrade_user()?.workspace_id() + } + + fn sqlite_connection(&self, uid: i64) -> Result { + self.upgrade_user()?.get_sqlite_connection(uid) } } diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 95f7b25c72d0e..de61ec4a9c94b 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -15,6 +15,7 @@ use tracing::debug; use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageOffset, RepeatedChatMessage}; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, }; @@ -433,3 +434,59 @@ impl CollabCloudPluginProvider for ServerProvider { *self.user_enable_sync.read() } } + +impl ChatCloudService for ServerProvider { + fn create_chat( + &self, + uid: &i64, + workspace_id: &str, + chat_id: &str, + ) -> FutureResult<(), FlowyError> { + let workspace_id = workspace_id.to_string(); + let server = self.get_server(); + let chat_id = chat_id.to_string(); + let uid = *uid; + FutureResult::new(async move { + server? + .chat_service() + .create_chat(&uid, &workspace_id, &chat_id) + .await + }) + } + + fn send_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let message = message.to_string(); + let server = self.get_server(); + FutureResult::new(async move { + server? + .chat_service() + .send_message(&workspace_id, &chat_id, &message) + .await + }) + } + + fn get_chat_messages( + &self, + workspace_id: &str, + chat_id: &str, + offset: MessageOffset, + limit: u64, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let server = self.get_server(); + FutureResult::new(async move { + server? + .chat_service() + .get_chat_messages(&workspace_id, &chat_id, offset, limit) + .await + }) + } +} diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index 08e6e5564bc0d..a39b555b94b3e 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -166,7 +166,8 @@ impl AppFlowyCore { Arc::downgrade(&(server_provider.clone() as Arc)), ); - let chat_manager = ChatDepsResolver::resolve(); + let chat_manager = + ChatDepsResolver::resolve(Arc::downgrade(&authenticate_user), server_provider.clone()); let folder_indexer = Arc::new(FolderIndexManagerImpl::new(None)); let folder_manager = FolderDepsResolver::resolve( Arc::downgrade(&authenticate_user), diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 538370216255d..744d791c3fa9e 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -2,7 +2,7 @@ use crate::af_cloud::AFServer; use client_api::entity::{ CreateChatMessageParams, CreateChatParams, MessageOffset, RepeatedChatMessage, }; -use flowy_chat_pub::cloud::ChatCloudService; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -44,7 +44,7 @@ where workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult<(), FlowyError> { + ) -> FutureResult { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); let message = message.to_string(); @@ -52,12 +52,12 @@ where FutureResult::new(async move { let params = CreateChatMessageParams { content: message }; - try_get_client? + let message = try_get_client? .create_chat_message(&workspace_id, &chat_id, params) .await .map_err(FlowyError::from)?; - Ok(()) + Ok(message) }) } diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index b92a17da120c8..ce4fb2f02b8a6 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,5 +1,5 @@ use client_api::entity::{MessageOffset, RepeatedChatMessage}; -use flowy_chat_pub::cloud::ChatCloudService; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -22,7 +22,7 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult<(), FlowyError> { + ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) }) diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql index 5fb7afbcd9857..c93a283179a66 100644 --- a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql @@ -2,18 +2,18 @@ -- Create table for chat documents CREATE TABLE chat_table ( - chat_id TEXT PRIMARY KEY, - created_at INTEGER NOT NULL, - name TEXT NOT NULL DEFAULT '' + chat_id TEXT PRIMARY KEY NOT NULL, + created_at BIGINT NOT NULL, + name TEXT NOT NULL DEFAULT '' ); -- Create table for chat messages CREATE TABLE chat_message_table ( - message_id INTEGER PRIMARY KEY AUTOINCREMENT, - chat_id TEXT NOT NULL, - content TEXT NOT NULL, - created_at INTEGER NOT NULL, + message_id BIGINT PRIMARY KEY NOT NULL, + chat_id TEXT NOT NULL, + content TEXT NOT NULL, + created_at BIGINT NOT NULL, FOREIGN KEY (chat_id) REFERENCES chat_table (chat_id) ON DELETE CASCADE ); diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index 941f640cdfcae..eee23311009e2 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -2,17 +2,17 @@ diesel::table! { chat_message_table (message_id) { - message_id -> Nullable, + message_id -> BigInt, chat_id -> Text, content -> Text, - created_at -> Integer, + created_at -> BigInt, } } diesel::table! { chat_table (chat_id) { - chat_id -> Nullable, - created_at -> Integer, + chat_id -> Text, + created_at -> BigInt, name -> Text, } } From e06ac3755fed06ce2bc4ed92a16805da0d47253b Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 23 May 2024 19:48:39 +0800 Subject: [PATCH 08/41] chore: add event test --- .../event-integration-test/src/chat_event.rs | 65 +++++++++++++++++++ .../event-integration-test/src/lib.rs | 1 + .../tests/chat/chat_message_test.rs | 37 +++++++++++ .../event-integration-test/tests/chat/mod.rs | 1 + .../event-integration-test/tests/main.rs | 2 + frontend/rust-lib/flowy-chat/src/entities.rs | 6 +- .../rust-lib/flowy-chat/src/event_handler.rs | 2 +- frontend/rust-lib/flowy-chat/src/event_map.rs | 2 +- frontend/rust-lib/flowy-chat/src/lib.rs | 6 +- frontend/rust-lib/flowy-chat/src/manager.rs | 36 ++++++++-- .../rust-lib/flowy-core/src/integrate/log.rs | 1 + frontend/rust-lib/flowy-core/src/lib.rs | 6 ++ frontend/rust-lib/flowy-core/src/module.rs | 4 ++ 13 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 frontend/rust-lib/event-integration-test/src/chat_event.rs create mode 100644 frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs create mode 100644 frontend/rust-lib/event-integration-test/tests/chat/mod.rs diff --git a/frontend/rust-lib/event-integration-test/src/chat_event.rs b/frontend/rust-lib/event-integration-test/src/chat_event.rs new file mode 100644 index 0000000000000..eac5f40af7a98 --- /dev/null +++ b/frontend/rust-lib/event-integration-test/src/chat_event.rs @@ -0,0 +1,65 @@ +use crate::event_builder::EventBuilder; +use crate::EventIntegrationTest; +use flowy_chat::entities::{ChatMessageListPB, LoadChatMessagePB, SendChatPayloadPB}; +use flowy_chat::event_map::ChatEvent; +use flowy_folder::entities::{CreateViewPayloadPB, ViewLayoutPB, ViewPB}; +use flowy_folder::event_map::FolderEvent; + +impl EventIntegrationTest { + pub async fn create_chat(&self, parent_id: &str) -> ViewPB { + let payload = CreateViewPayloadPB { + parent_view_id: parent_id.to_string(), + name: "chat".to_string(), + desc: "".to_string(), + thumbnail: None, + layout: ViewLayoutPB::Chat, + initial_data: vec![], + meta: Default::default(), + set_as_current: true, + index: None, + section: None, + }; + let view = EventBuilder::new(self.clone()) + .event(FolderEvent::CreateView) + .payload(payload) + .async_send() + .await + .parse::(); + + view + } + + pub async fn send_message(&self, chat_id: &str, message: impl ToString) { + let payload = SendChatPayloadPB { + chat_id: chat_id.to_string(), + message: message.to_string(), + }; + + EventBuilder::new(self.clone()) + .event(ChatEvent::SendMessage) + .payload(payload) + .async_send() + .await; + } + + pub async fn load_message( + &self, + chat_id: &str, + limit: i64, + after_message_id: Option, + before_message_id: Option, + ) -> ChatMessageListPB { + let payload = LoadChatMessagePB { + chat_id: chat_id.to_string(), + limit, + after_message_id, + before_message_id, + }; + EventBuilder::new(self.clone()) + .event(ChatEvent::LoadMessage) + .payload(payload) + .async_send() + .await + .parse::() + } +} diff --git a/frontend/rust-lib/event-integration-test/src/lib.rs b/frontend/rust-lib/event-integration-test/src/lib.rs index 180623d8d5b4b..9dfef36b3d776 100644 --- a/frontend/rust-lib/event-integration-test/src/lib.rs +++ b/frontend/rust-lib/event-integration-test/src/lib.rs @@ -23,6 +23,7 @@ use lib_dispatch::runtime::AFPluginRuntime; use crate::user_event::TestNotificationSender; +mod chat_event; pub mod database_event; pub mod document; pub mod document_event; diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs new file mode 100644 index 0000000000000..a7623412bd2bf --- /dev/null +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -0,0 +1,37 @@ +use event_integration_test::user_event::user_localhost_af_cloud; +use event_integration_test::EventIntegrationTest; + +#[tokio::test] +async fn af_cloud_create_chat_message_test() { + user_localhost_af_cloud().await; + let test = EventIntegrationTest::new().await; + test.af_cloud_sign_up().await; + + let current_workspace = test.get_current_workspace().await; + let view = test.create_chat(¤t_workspace.id).await; + let chat_id = view.id.clone(); + for i in 0..10 { + test + .send_message(&chat_id, format!("hello world {}", i)) + .await; + } + let all = test.load_message(&chat_id, 10, None, None).await; + assert_eq!(all.messages.len(), 10); + + let list = test + .load_message(&chat_id, 10, Some(all.messages[5].message_id), None) + .await; + assert_eq!(list.messages.len(), 4); + assert_eq!(list.messages[0].content, "hello world 6"); + assert_eq!(list.messages[1].content, "hello world 7"); + assert_eq!(list.messages[2].content, "hello world 8"); + assert_eq!(list.messages[3].content, "hello world 9"); + + let list = test + .load_message(&chat_id, 10, None, Some(all.messages[3].message_id)) + .await; + assert_eq!(list.messages.len(), 3); + assert_eq!(list.messages[0].content, "hello world 0"); + assert_eq!(list.messages[1].content, "hello world 1"); + assert_eq!(list.messages[2].content, "hello world 2"); +} diff --git a/frontend/rust-lib/event-integration-test/tests/chat/mod.rs b/frontend/rust-lib/event-integration-test/tests/chat/mod.rs new file mode 100644 index 0000000000000..773bdab81fef0 --- /dev/null +++ b/frontend/rust-lib/event-integration-test/tests/chat/mod.rs @@ -0,0 +1 @@ +mod chat_message_test; diff --git a/frontend/rust-lib/event-integration-test/tests/main.rs b/frontend/rust-lib/event-integration-test/tests/main.rs index 05d07974732b5..05f19e9b75a9d 100644 --- a/frontend/rust-lib/event-integration-test/tests/main.rs +++ b/frontend/rust-lib/event-integration-test/tests/main.rs @@ -6,3 +6,5 @@ mod folder; // mod search; mod user; pub mod util; + +mod chat; diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index dd73dd6569a1b..cd715684b61a2 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -31,7 +31,7 @@ pub struct LoadChatMessagePB { } #[derive(Default, ProtoBuf, Validate, Clone, Debug)] -pub struct RepeatedChatMessagePB { +pub struct ChatMessageListPB { #[pb(index = 1)] pub has_more: bool, @@ -39,14 +39,14 @@ pub struct RepeatedChatMessagePB { pub messages: Vec, } -impl From for RepeatedChatMessagePB { +impl From for ChatMessageListPB { fn from(repeated_chat_message: RepeatedChatMessage) -> Self { let messages = repeated_chat_message .messages .into_iter() .map(ChatMessagePB::from) .collect(); - RepeatedChatMessagePB { + ChatMessageListPB { has_more: repeated_chat_message.has_more, messages, } diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 402ae0b0aba6a..bbac20636a19d 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -36,7 +36,7 @@ pub(crate) async fn send_chat_message_handler( pub(crate) async fn load_message_handler( data: AFPluginData, chat_manager: AFPluginState>, -) -> DataResult { +) -> DataResult { let chat_manager = upgrade_chat_manager(chat_manager)?; let data = data.into_inner(); data.validate()?; diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 618b1a6cc1d92..80d3ec44705a6 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -20,7 +20,7 @@ pub fn init(chat_manager: Weak) -> AFPlugin { #[event_err = "FlowyError"] pub enum ChatEvent { /// Create a new workspace - #[event(input = "LoadChatMessagePB", output = "RepeatedChatMessage")] + #[event(input = "LoadChatMessagePB", output = "ChatMessageListPB")] LoadMessage = 0, #[event(input = "SendChatPayloadPB")] diff --git a/frontend/rust-lib/flowy-chat/src/lib.rs b/frontend/rust-lib/flowy-chat/src/lib.rs index 720518ddb798d..7a7f0951e9b8e 100644 --- a/frontend/rust-lib/flowy-chat/src/lib.rs +++ b/frontend/rust-lib/flowy-chat/src/lib.rs @@ -1,9 +1,9 @@ mod event_handler; -mod event_map; +pub mod event_map; mod chat; -mod entities; +pub mod entities; pub mod manager; mod notification; mod persistence; -pub mod protobuf; +mod protobuf; diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 3685232e4761c..4db72cfe83b4b 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,5 +1,5 @@ use crate::chat::Chat; -use crate::entities::{ChatMessagePB, RepeatedChatMessagePB}; +use crate::entities::{ChatMessageListPB, ChatMessagePB}; use crate::notification::{send_notification, ChatNotification}; use crate::persistence::{ insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, @@ -10,7 +10,7 @@ use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::{DBConnection, QueryResult}; use lib_infra::util::timestamp; use std::sync::Arc; -use tracing::{error, warn}; +use tracing::{error, instrument, trace, warn}; pub trait ChatUserService: Send + Sync + 'static { fn user_id(&self) -> Result; @@ -97,14 +97,27 @@ impl ChatManager { limit: i64, after_message_id: Option, before_message_id: Option, - ) -> Result { + ) -> Result { + trace!( + "Loading chat messages: chat_id={}, limit={}, after_message_id={:?}, before_message_id={:?}", + chat_id, + limit, + after_message_id, + before_message_id + ); + let uid = self.user_service.user_id()?; let messages = self .load_local_chat_messages(uid, chat_id, limit, after_message_id, before_message_id) .await?; - let after_message_id = after_message_id.or_else(|| messages.last().map(|m| m.message_id)); - let before_message_id = before_message_id.or_else(|| messages.first().map(|m| m.message_id)); + // If the number of messages equals the limit, then no need to load more messages from remote + if messages.len() == limit as usize { + return Ok(ChatMessageListPB { + messages, + has_more: true, + }); + } if let Err(err) = self .load_remote_chat_messages(chat_id, limit, after_message_id, before_message_id) @@ -112,7 +125,7 @@ impl ChatManager { { error!("Failed to load remote chat messages: {}", err); } - Ok(RepeatedChatMessagePB { + Ok(ChatMessageListPB { messages, has_more: true, }) @@ -140,6 +153,7 @@ impl ChatManager { Ok(messages) } + #[instrument(level = "info", skip_all, err)] async fn load_remote_chat_messages( &self, chat_id: &str, @@ -147,6 +161,14 @@ impl ChatManager { after_message_id: Option, before_message_id: Option, ) -> Result<(), FlowyError> { + trace!( + "Loading chat messages from remote: chat_id={}, limit={}, after_message_id={:?}, before_message_id={:?}", + chat_id, + limit, + after_message_id, + before_message_id + ); + let chat_id = chat_id.to_string(); let user_service = self.user_service.clone(); let cloud_service = self.cloud_service.clone(); @@ -170,7 +192,7 @@ impl ChatManager { &chat_id, resp.messages.clone(), )?; - let pb = RepeatedChatMessagePB::from(resp); + let pb = ChatMessageListPB::from(resp); send_notification(&chat_id, ChatNotification::DidLoadChatMessage) .payload(pb) .send(); diff --git a/frontend/rust-lib/flowy-core/src/integrate/log.rs b/frontend/rust-lib/flowy-core/src/integrate/log.rs index 66c37837d1e27..c855a557ac8cf 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/log.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/log.rs @@ -52,6 +52,7 @@ pub fn create_log_filter(level: String, with_crates: Vec, platform: Plat filters.push(format!("flowy_notification={}", "info")); filters.push(format!("lib_infra={}", level)); filters.push(format!("flowy_search={}", level)); + filters.push(format!("flowy_chat={}", level)); // Enable the frontend logs. DO NOT DISABLE. // These logs are essential for debugging and verifying frontend behavior. filters.push(format!("dart_ffi={}", level)); diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index a39b555b94b3e..d44c3bb573120 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -11,6 +11,7 @@ use tokio::sync::RwLock; use tracing::{debug, error, event, info, instrument}; use collab_integrate::collab_builder::{AppFlowyCollabBuilder, CollabPluginProviderType}; +use flowy_chat::manager::ChatManager; use flowy_database2::DatabaseManager; use flowy_document::manager::DocumentManager; use flowy_error::{FlowyError, FlowyResult}; @@ -58,6 +59,7 @@ pub struct AppFlowyCore { pub task_dispatcher: Arc>, pub store_preference: Arc, pub search_manager: Arc, + pub chat_manager: Arc, } impl AppFlowyCore { @@ -139,6 +141,7 @@ impl AppFlowyCore { document_manager, collab_builder, search_manager, + chat_manager, ) = async { /// The shared collab builder is used to build the [Collab] instance. The plugins will be loaded /// on demand based on the [CollabPluginConfig]. @@ -200,6 +203,7 @@ impl AppFlowyCore { document_manager, collab_builder, search_manager, + chat_manager, ) } .await; @@ -235,6 +239,7 @@ impl AppFlowyCore { Arc::downgrade(&user_manager), Arc::downgrade(&document_manager), Arc::downgrade(&search_manager), + Arc::downgrade(&chat_manager), ), )); @@ -249,6 +254,7 @@ impl AppFlowyCore { task_dispatcher, store_preference, search_manager, + chat_manager, } } diff --git a/frontend/rust-lib/flowy-core/src/module.rs b/frontend/rust-lib/flowy-core/src/module.rs index 8d021955efecc..7077007915f9c 100644 --- a/frontend/rust-lib/flowy-core/src/module.rs +++ b/frontend/rust-lib/flowy-core/src/module.rs @@ -1,3 +1,4 @@ +use flowy_chat::manager::ChatManager; use std::sync::Weak; use flowy_database2::DatabaseManager; @@ -13,6 +14,7 @@ pub fn make_plugins( user_session: Weak, document_manager2: Weak, search_manager: Weak, + chat_manager: Weak, ) -> Vec { let store_preferences = user_session .upgrade() @@ -25,6 +27,7 @@ pub fn make_plugins( let config_plugin = flowy_config::event_map::init(store_preferences); let date_plugin = flowy_date::event_map::init(); let search_plugin = flowy_search::event_map::init(search_manager); + let chat_plugin = flowy_chat::event_map::init(chat_manager); vec![ user_plugin, folder_plugin, @@ -33,5 +36,6 @@ pub fn make_plugins( config_plugin, date_plugin, search_plugin, + chat_plugin, ] } From 65438a0f4472961d053c9569b1c0d16ce7efb63d Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 23 May 2024 21:55:51 +0800 Subject: [PATCH 09/41] chore: add test --- .../desktop/sidebar/sidebar_test.dart | 2 + .../lib/plugins/ai_chat/ai_chat.dart | 18 ++++- .../lib/startup/plugin/plugin.dart | 2 +- .../workspace/application/view/view_ext.dart | 4 ++ .../home/menu/view/view_item.dart | 2 + .../lib/dispatch/dispatch.dart | 2 + frontend/appflowy_tauri/src-tauri/Cargo.lock | 28 ++++---- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 ++++------- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 32 +++++---- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/resources/translations/en.json | 3 +- frontend/rust-lib/Cargo.lock | 44 ++++-------- frontend/rust-lib/Cargo.toml | 2 +- .../tests/chat/chat_message_test.rs | 71 +++++++++++++++++++ frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 4 +- frontend/rust-lib/flowy-chat/src/entities.rs | 5 ++ .../rust-lib/flowy-chat/src/event_handler.rs | 1 - frontend/rust-lib/flowy-chat/src/lib.rs | 2 +- frontend/rust-lib/flowy-chat/src/manager.rs | 14 ++-- .../flowy-core/src/integrate/trait_impls.rs | 4 +- .../flowy-server/src/af_cloud/impls/chat.rs | 4 +- .../rust-lib/flowy-server/src/default_impl.rs | 4 +- 24 files changed, 185 insertions(+), 109 deletions(-) diff --git a/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart b/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart index 158a8db882129..7ac59c77a4854 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart @@ -66,6 +66,8 @@ void main() { case ViewLayoutPB.Calendar: expect(find.byType(CalendarPage), findsOneWidget); break; + case ViewLayoutPB.Chat: + break; } await tester.openPage(gettingStarted); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart index 1f42363e0f20f..4524918a5be86 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart @@ -1,5 +1,6 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/util.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; @@ -10,7 +11,11 @@ import 'package:flutter/material.dart'; class AIChatPluginBuilder extends PluginBuilder { @override Plugin build(dynamic data) { - return AIChatPagePlugin(); + if (data is ViewPB) { + return AIChatPagePlugin(view: data); + } + + throw FlowyPluginException.invalidData; } @override @@ -20,7 +25,7 @@ class AIChatPluginBuilder extends PluginBuilder { FlowySvgData get icon => FlowySvgs.ai_summary_s; @override - PluginType get pluginType => PluginType.aiChat; + PluginType get pluginType => PluginType.chat; @override ViewLayoutPB get layoutType => ViewLayoutPB.Chat; @@ -32,6 +37,13 @@ class AIChatPluginConfig implements PluginConfig { } class AIChatPagePlugin extends Plugin { + AIChatPagePlugin({ + required ViewPB view, + }) : notifier = ViewPluginNotifier(view: view); + + @override + final ViewPluginNotifier notifier; + @override PluginWidgetBuilder get widgetBuilder => AIChatPagePluginWidgetBuilder(); @@ -39,7 +51,7 @@ class AIChatPagePlugin extends Plugin { PluginId get id => "AIChatStack"; @override - PluginType get pluginType => PluginType.aiChat; + PluginType get pluginType => PluginType.chat; } class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder diff --git a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart index 516136d02a9ab..2fa8dbeaad08f 100644 --- a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart @@ -18,7 +18,7 @@ enum PluginType { board, calendar, databaseDocument, - aiChat, + chat, } typedef PluginId = String; diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart index ca3bb62fbb52f..b71bb44e69351 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart'; +import 'package:appflowy/plugins/ai_chat/ai_chat.dart'; import 'package:appflowy/plugins/database/board/presentation/board_page.dart'; import 'package:appflowy/plugins/database/calendar/presentation/calendar_page.dart'; import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart'; @@ -50,6 +51,7 @@ extension ViewExtension on ViewPB { ViewLayoutPB.Calendar => PluginType.calendar, ViewLayoutPB.Document => PluginType.document, ViewLayoutPB.Grid => PluginType.grid, + ViewLayoutPB.Chat => PluginType.chat, _ => throw UnimplementedError(), }; @@ -76,6 +78,8 @@ extension ViewExtension on ViewPB { pluginType: pluginType, initialSelection: initialSelection, ); + case ViewLayoutPB.Chat: + return AIChatPagePlugin(view: this); } throw UnimplementedError; } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart index 057b3d8f99188..8e7069415899a 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart @@ -602,6 +602,8 @@ class _SingleInnerViewItemState extends State { return LocaleKeys.newBoardText.tr(); case ViewLayoutPB.Calendar: return LocaleKeys.newCalendarText.tr(); + case ViewLayoutPB.Chat: + return LocaleKeys.newChatText.tr(); } return LocaleKeys.newPageText.tr(); } diff --git a/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart b/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart index 21ace45b28fa2..cd95941a15261 100644 --- a/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart +++ b/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart @@ -16,6 +16,7 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-search/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-chat/protobuf.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:ffi/ffi.dart'; import 'package:isolates/isolates.dart'; @@ -36,6 +37,7 @@ part 'dart_event/flowy-document/dart_event.dart'; part 'dart_event/flowy-config/dart_event.dart'; part 'dart_event/flowy-date/dart_event.dart'; part 'dart_event/flowy-search/dart_event.dart'; +part 'dart_event/flowy-chat/dart_event.dart'; enum FFIException { RequestIsEmpty, diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index ecab41ffebda0..fc385665d964e 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "serde", @@ -753,7 +753,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "again", "anyhow", @@ -800,7 +800,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "futures-channel", "futures-util", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "async-trait", @@ -1310,7 +1310,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1421,7 +1421,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -2825,7 +2825,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "futures-util", @@ -2842,7 +2842,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "reqwest", @@ -4777,7 +4777,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4798,7 +4798,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", @@ -5762,7 +5762,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 246fa091a2dac..88befd4827d2d 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 740d3fe82c64d..a2865ca4b9ff3 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "serde", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "again", "anyhow", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "async-trait", @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1024,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -1811,7 +1811,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "futures-util", @@ -1828,7 +1828,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -2129,7 +2129,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "reqwest", @@ -2813,7 +2813,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2833,7 +2833,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2901,19 +2900,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -3769,7 +3755,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 06d76e4e7bbf8..ddfb1c65dce13 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 4e95633fc5414..6c3d5fa5d48b2 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "serde", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "again", "anyhow", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "futures-channel", "futures-util", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -1047,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "async-trait", @@ -1297,7 +1297,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1408,7 +1408,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -1850,15 +1850,18 @@ name = "flowy-chat" version = "0.1.0" dependencies = [ "bytes", + "dashmap", "flowy-chat-pub", "flowy-codegen", "flowy-derive", "flowy-error", "flowy-notification", + "flowy-sqlite", "lib-dispatch", "lib-infra", "protobuf", "strum_macros 0.21.1", + "tokio", "tracing", "uuid", "validator", @@ -1925,6 +1928,7 @@ dependencies = [ "collab-plugins", "diesel", "flowy-chat", + "flowy-chat-pub", "flowy-config", "flowy-database-pub", "flowy-database2", @@ -2895,7 +2899,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "futures-util", @@ -2912,7 +2916,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -3349,7 +3353,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "reqwest", @@ -4854,7 +4858,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4875,7 +4879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5853,7 +5857,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index d7dc779a56242..4d7e8aba9bacd 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } [dependencies] serde_json.workspace = true diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 1b286e2498faa..838e30ca4ab40 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -144,6 +144,7 @@ "newGridText": "New grid", "newCalendarText": "New calendar", "newBoardText": "New board", + "newChatText": "New chat", "trash": { "text": "Trash", "restoreAll": "Restore All", @@ -1671,4 +1672,4 @@ "betaTooltip": "We currently only support searching for pages", "fromTrashHint": "From trash" } -} +} \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 183124c821dd4..5035d0ce45e57 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "serde", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "again", "anyhow", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "bincode", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "async-trait", @@ -1162,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1261,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -2509,7 +2509,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "futures-util", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", @@ -2891,7 +2891,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "reqwest", @@ -3766,7 +3766,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3786,7 +3786,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3854,19 +3853,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4070,7 +4056,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4091,7 +4077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4988,7 +4974,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=05e7f1cda7d3d7a159c01943cda7a2a82cbaf251#05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 8a8267ed38a33..f6c64a0545332 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "05e7f1cda7d3d7a159c01943cda7a2a82cbaf251" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index a7623412bd2bf..ec90ead3488f3 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -1,5 +1,11 @@ +use crate::util::receive_with_timeout; use event_integration_test::user_event::user_localhost_af_cloud; use event_integration_test::EventIntegrationTest; +use flowy_chat::entities::ChatMessageListPB; +use flowy_chat::notification::ChatNotification; +use flowy_folder::entities::ChildViewUpdatePB; +use flowy_folder::notification::FolderNotification; +use std::time::Duration; #[tokio::test] async fn af_cloud_create_chat_message_test() { @@ -35,3 +41,68 @@ async fn af_cloud_create_chat_message_test() { assert_eq!(list.messages[1].content, "hello world 1"); assert_eq!(list.messages[2].content, "hello world 2"); } + +#[tokio::test] +async fn af_cloud_load_remote_chat_message_test() { + user_localhost_af_cloud().await; + let test = EventIntegrationTest::new().await; + test.af_cloud_sign_up().await; + + let current_workspace = test.get_current_workspace().await; + let view = test.create_chat(¤t_workspace.id).await; + let chat_id = view.id.clone(); + + let chat_service = test.server_provider.get_server().unwrap().chat_service(); + for i in 0..10 { + chat_service + .send_message( + ¤t_workspace.id, + &chat_id, + &format!("hello server {}", i), + ) + .await + .unwrap(); + } + let rx = test + .notification_sender + .subscribe::(&chat_id, ChatNotification::DidLoadChatMessage); + + // Previous messages were created by the server, so there are no messages in the local cache. + // It will try to load messages in the background. + let all = test.load_message(&chat_id, 5, None, None).await; + assert!(all.messages.is_empty()); + + // Wait for the messages to be loaded. + let next_back_five = receive_with_timeout(rx, Duration::from_secs(30)) + .await + .unwrap(); + assert_eq!(next_back_five.messages.len(), 5); + assert_eq!(next_back_five.has_more, true); + assert_eq!(next_back_five.total, 10); + assert_eq!(next_back_five.messages[0].content, "hello server 5"); + assert_eq!(next_back_five.messages[1].content, "hello server 6"); + assert_eq!(next_back_five.messages[2].content, "hello server 7"); + assert_eq!(next_back_five.messages[3].content, "hello server 8"); + assert_eq!(next_back_five.messages[4].content, "hello server 9"); + + // Load first five messages + let rx = test + .notification_sender + .subscribe::(&chat_id, ChatNotification::DidLoadChatMessage); + test + .load_message( + &chat_id, + 5, + None, + Some(next_back_five.messages[0].message_id), + ) + .await; + let first_five_messages = receive_with_timeout(rx, Duration::from_secs(30)) + .await + .unwrap(); + assert_eq!(first_five_messages.messages[0].content, "hello server 0"); + assert_eq!(first_five_messages.messages[1].content, "hello server 1"); + assert_eq!(first_five_messages.messages[2].content, "hello server 2"); + assert_eq!(first_five_messages.messages[3].content, "hello server 3"); + assert_eq!(first_five_messages.messages[4].content, "hello server 4"); +} diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 441a1e126f329..811b3621c36c7 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,4 +1,4 @@ -pub use client_api::entity::{ChatMessage, MessageOffset, RepeatedChatMessage}; +pub use client_api::entity::{ChatMessage, MessageCursor, RepeatedChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -21,7 +21,7 @@ pub trait ChatCloudService: Send + Sync + 'static { &self, workspace_id: &str, chat_id: &str, - offset: MessageOffset, + offset: MessageCursor, limit: u64, ) -> FutureResult; } diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index cd715684b61a2..6ef5478460b3c 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -37,6 +37,10 @@ pub struct ChatMessageListPB { #[pb(index = 2)] pub messages: Vec, + + /// If the total number of messages is 0, then the total number of messages is unknown. + #[pb(index = 3)] + pub total: i64, } impl From for ChatMessageListPB { @@ -49,6 +53,7 @@ impl From for ChatMessageListPB { ChatMessageListPB { has_more: repeated_chat_message.has_more, messages, + total: repeated_chat_message.total, } } } diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index bbac20636a19d..06f9a2a327153 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -1,5 +1,4 @@ use std::sync::{Arc, Weak}; -use tracing::instrument; use validator::Validate; use flowy_error::{FlowyError, FlowyResult}; diff --git a/frontend/rust-lib/flowy-chat/src/lib.rs b/frontend/rust-lib/flowy-chat/src/lib.rs index 7a7f0951e9b8e..2244af580239f 100644 --- a/frontend/rust-lib/flowy-chat/src/lib.rs +++ b/frontend/rust-lib/flowy-chat/src/lib.rs @@ -4,6 +4,6 @@ pub mod event_map; mod chat; pub mod entities; pub mod manager; -mod notification; +pub mod notification; mod persistence; mod protobuf; diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 4db72cfe83b4b..f64a40ea22b07 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -5,7 +5,7 @@ use crate::persistence::{ insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, }; use dashmap::DashMap; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageOffset, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageCursor, RepeatedChatMessage}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::{DBConnection, QueryResult}; use lib_infra::util::timestamp; @@ -116,6 +116,7 @@ impl ChatManager { return Ok(ChatMessageListPB { messages, has_more: true, + total: 0, }); } @@ -128,6 +129,7 @@ impl ChatManager { Ok(ChatMessageListPB { messages, has_more: true, + total: 0, }) } @@ -218,16 +220,16 @@ async fn _load_remote_chat_messages( if after_message_id.is_some() && before_message_id.is_some() { warn!("Cannot specify both after_message_id and before_message_id"); } - let offset = if after_message_id.is_some() { - MessageOffset::AfterMessageId(after_message_id.unwrap()) + let cursor = if after_message_id.is_some() { + MessageCursor::AfterMessageId(after_message_id.unwrap()) } else if before_message_id.is_some() { - MessageOffset::BeforeMessageId(before_message_id.unwrap()) + MessageCursor::BeforeMessageId(before_message_id.unwrap()) } else { - MessageOffset::Offset(0) + MessageCursor::NextBack }; let resp = cloud_service - .get_chat_messages(&workspace_id, &chat_id, offset, limit as u64) + .get_chat_messages(&workspace_id, &chat_id, cursor, limit as u64) .await?; Ok(resp) } diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index de61ec4a9c94b..0c2c79a488260 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -15,7 +15,7 @@ use tracing::debug; use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageOffset, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageCursor, RepeatedChatMessage}; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, }; @@ -476,7 +476,7 @@ impl ChatCloudService for ServerProvider { &self, workspace_id: &str, chat_id: &str, - offset: MessageOffset, + offset: MessageCursor, limit: u64, ) -> FutureResult { let workspace_id = workspace_id.to_string(); diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 744d791c3fa9e..11852f83b774c 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -1,6 +1,6 @@ use crate::af_cloud::AFServer; use client_api::entity::{ - CreateChatMessageParams, CreateChatParams, MessageOffset, RepeatedChatMessage, + CreateChatMessageParams, CreateChatParams, MessageCursor, RepeatedChatMessage, }; use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage}; use flowy_error::FlowyError; @@ -65,7 +65,7 @@ where &self, workspace_id: &str, chat_id: &str, - offset: MessageOffset, + offset: MessageCursor, limit: u64, ) -> FutureResult { let workspace_id = workspace_id.to_string(); diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index ce4fb2f02b8a6..d4dac1961f48f 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,4 +1,4 @@ -use client_api::entity::{MessageOffset, RepeatedChatMessage}; +use client_api::entity::{MessageCursor, RepeatedChatMessage}; use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -32,7 +32,7 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { &self, workspace_id: &str, chat_id: &str, - offset: MessageOffset, + offset: MessageCursor, limit: u64, ) -> FutureResult { FutureResult::new(async move { From cc4511869b917cb584f03f7614259c9591d3b504 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 23 May 2024 22:34:16 +0800 Subject: [PATCH 10/41] chore: update test --- .../workspace/application/view/view_ext.dart | 4 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 22 +++++----- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 +++++++++++------ frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 28 ++++++------ .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 44 ++++++++++++------- frontend/rust-lib/Cargo.toml | 2 +- .../event-integration-test/src/chat_event.rs | 9 ++-- .../tests/chat/chat_message_test.rs | 7 +-- frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 5 ++- frontend/rust-lib/flowy-chat/src/chat.rs | 1 + frontend/rust-lib/flowy-chat/src/entities.rs | 5 ++- .../rust-lib/flowy-chat/src/event_handler.rs | 2 +- frontend/rust-lib/flowy-chat/src/manager.rs | 31 ++++++++----- .../src/persistence/chat_message_sql.rs | 22 ---------- .../src/deps_resolve/folder_deps.rs | 34 +++++++------- .../flowy-core/src/integrate/trait_impls.rs | 9 ++-- .../flowy-server/src/af_cloud/impls/chat.rs | 10 +++-- .../src/af_cloud/impls/database.rs | 4 +- .../src/af_cloud/impls/document.rs | 4 +- .../flowy-server/src/af_cloud/impls/folder.rs | 6 +-- .../af_cloud/impls/user/cloud_service_impl.rs | 4 +- .../flowy-server/src/af_cloud/server.rs | 2 +- .../rust-lib/flowy-server/src/default_impl.rs | 19 ++++---- 26 files changed, 173 insertions(+), 147 deletions(-) diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart index b71bb44e69351..4ae9a3fa1f63d 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -152,11 +152,13 @@ extension ViewLayoutExtension on ViewLayoutPB { ViewLayoutPB.Board => FlowySvgs.board_s, ViewLayoutPB.Calendar => FlowySvgs.date_s, ViewLayoutPB.Document => FlowySvgs.document_s, + ViewLayoutPB.Chat => FlowySvgs.document_s, _ => throw Exception('Unknown layout type'), }; bool get isDocumentView => switch (this) { ViewLayoutPB.Document => true, + ViewLayoutPB.Chat || ViewLayoutPB.Grid || ViewLayoutPB.Board || ViewLayoutPB.Calendar => @@ -169,7 +171,7 @@ extension ViewLayoutExtension on ViewLayoutPB { ViewLayoutPB.Board || ViewLayoutPB.Calendar => true, - ViewLayoutPB.Document => false, + ViewLayoutPB.Document || ViewLayoutPB.Chat => false, _ => throw Exception('Unknown layout type'), }; } diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index fc385665d964e..307e1d191767f 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "serde", @@ -753,7 +753,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "again", "anyhow", @@ -800,7 +800,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "futures-channel", "futures-util", @@ -1039,7 +1039,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -1064,7 +1064,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "async-trait", @@ -1421,7 +1421,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -2825,7 +2825,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "futures-util", @@ -2842,7 +2842,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "reqwest", @@ -5762,7 +5762,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 88befd4827d2d..8dbba9c16863e 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index a2865ca4b9ff3..4c9f7af6d0e6c 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "serde", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "again", "anyhow", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "async-trait", @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1024,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -1811,7 +1811,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "futures-util", @@ -1828,7 +1828,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -2129,7 +2129,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "reqwest", @@ -2813,7 +2813,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2833,6 +2833,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2900,6 +2901,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3755,7 +3769,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index ddfb1c65dce13..665f397ae3e94 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 6c3d5fa5d48b2..cbd84d38de9ca 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "serde", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "again", "anyhow", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "futures-channel", "futures-util", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -1047,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "async-trait", @@ -1297,7 +1297,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1408,7 +1408,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -2899,7 +2899,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "futures-util", @@ -2916,7 +2916,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -3353,7 +3353,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "reqwest", @@ -4858,7 +4858,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4879,7 +4879,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.55", @@ -5857,7 +5857,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 4d7e8aba9bacd..726c9eb3b906a 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 5035d0ce45e57..69e474aefcfc6 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "serde", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "again", "anyhow", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "bincode", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "async-trait", @@ -1162,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1261,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -2509,7 +2509,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "futures-util", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", @@ -2891,7 +2891,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "reqwest", @@ -3766,7 +3766,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3786,6 +3786,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3853,6 +3854,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.47", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -4056,7 +4070,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4077,7 +4091,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", @@ -4974,7 +4988,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=9479a645e0b07accdf31e1f21f045a54dab5b51a#9479a645e0b07accdf31e1f21f045a54dab5b51a" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index f6c64a0545332..c7f14ef6e5e6b 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "9479a645e0b07accdf31e1f21f045a54dab5b51a" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/event-integration-test/src/chat_event.rs b/frontend/rust-lib/event-integration-test/src/chat_event.rs index eac5f40af7a98..840bfcb4e2626 100644 --- a/frontend/rust-lib/event-integration-test/src/chat_event.rs +++ b/frontend/rust-lib/event-integration-test/src/chat_event.rs @@ -19,20 +19,19 @@ impl EventIntegrationTest { index: None, section: None, }; - let view = EventBuilder::new(self.clone()) + EventBuilder::new(self.clone()) .event(FolderEvent::CreateView) .payload(payload) .async_send() .await - .parse::(); - - view + .parse::() } - pub async fn send_message(&self, chat_id: &str, message: impl ToString) { + pub async fn send_message(&self, chat_id: &str, message: impl ToString, require_answer: bool) { let payload = SendChatPayloadPB { chat_id: chat_id.to_string(), message: message.to_string(), + require_answer, }; EventBuilder::new(self.clone()) diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index ec90ead3488f3..420236d9e423e 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -3,8 +3,7 @@ use event_integration_test::user_event::user_localhost_af_cloud; use event_integration_test::EventIntegrationTest; use flowy_chat::entities::ChatMessageListPB; use flowy_chat::notification::ChatNotification; -use flowy_folder::entities::ChildViewUpdatePB; -use flowy_folder::notification::FolderNotification; + use std::time::Duration; #[tokio::test] @@ -59,6 +58,7 @@ async fn af_cloud_load_remote_chat_message_test() { ¤t_workspace.id, &chat_id, &format!("hello server {}", i), + false, ) .await .unwrap(); @@ -77,7 +77,7 @@ async fn af_cloud_load_remote_chat_message_test() { .await .unwrap(); assert_eq!(next_back_five.messages.len(), 5); - assert_eq!(next_back_five.has_more, true); + assert!(next_back_five.has_more); assert_eq!(next_back_five.total, 10); assert_eq!(next_back_five.messages[0].content, "hello server 5"); assert_eq!(next_back_five.messages[1].content, "hello server 6"); @@ -100,6 +100,7 @@ async fn af_cloud_load_remote_chat_message_test() { let first_five_messages = receive_with_timeout(rx, Duration::from_secs(30)) .await .unwrap(); + assert!(!first_five_messages.has_more); assert_eq!(first_five_messages.messages[0].content, "hello server 0"); assert_eq!(first_five_messages.messages[1].content, "hello server 1"); assert_eq!(first_five_messages.messages[2].content, "hello server 2"); diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 811b3621c36c7..221fc5eac540f 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,4 +1,4 @@ -pub use client_api::entity::{ChatMessage, MessageCursor, RepeatedChatMessage}; +pub use client_api::entity::{ChatMessage, MessageCursor, QAChatMessage, RepeatedChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -15,7 +15,8 @@ pub trait ChatCloudService: Send + Sync + 'static { workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult; + require_answer: bool, + ) -> FutureResult; fn get_chat_messages( &self, diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index eb5ec92c6fdef..c048dd40b93bd 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -1,6 +1,7 @@ use flowy_chat_pub::cloud::ChatCloudService; use std::sync::Arc; +#[allow(dead_code)] pub struct Chat { chat_id: String, cloud_service: Arc, diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index 6ef5478460b3c..f84013828253a 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -1,6 +1,6 @@ use flowy_chat_pub::cloud::{ChatMessage, RepeatedChatMessage}; use flowy_derive::ProtoBuf; -use lib_infra::validator_fn::{required_not_empty_str, required_valid_path}; +use lib_infra::validator_fn::required_not_empty_str; use validator::Validate; #[derive(Default, ProtoBuf, Validate, Clone, Debug)] @@ -12,6 +12,9 @@ pub struct SendChatPayloadPB { #[pb(index = 2)] #[validate(custom = "required_not_empty_str")] pub message: String, + + #[pb(index = 3)] + pub require_answer: bool, } #[derive(Default, ProtoBuf, Validate, Clone, Debug)] diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 06f9a2a327153..5977b07471114 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -26,7 +26,7 @@ pub(crate) async fn send_chat_message_handler( data.validate()?; chat_manager - .send_chat_message(&data.chat_id, &data.message) + .send_chat_message(&data.chat_id, &data.message, data.require_answer) .await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index f64a40ea22b07..07f1943859767 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -7,7 +7,7 @@ use crate::persistence::{ use dashmap::DashMap; use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageCursor, RepeatedChatMessage}; use flowy_error::{FlowyError, FlowyResult}; -use flowy_sqlite::{DBConnection, QueryResult}; +use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; use std::sync::Arc; use tracing::{error, instrument, trace, warn}; @@ -39,15 +39,15 @@ impl ChatManager { } } - pub async fn open_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + pub async fn open_chat(&self, _chat_id: &str) -> Result<(), FlowyError> { Ok(()) } - pub async fn close_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + pub async fn close_chat(&self, _chat_id: &str) -> Result<(), FlowyError> { Ok(()) } - pub async fn delete_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + pub async fn delete_chat(&self, _chat_id: &str) -> Result<(), FlowyError> { Ok(()) } @@ -61,18 +61,25 @@ impl ChatManager { Ok(()) } - pub async fn send_chat_message(&self, chat_id: &str, message: &str) -> Result<(), FlowyError> { + pub async fn send_chat_message( + &self, + chat_id: &str, + message: &str, + require_answer: bool, + ) -> Result<(), FlowyError> { let uid = self.user_service.user_id()?; let workspace_id = self.user_service.workspace_id()?; - let message = self + let qa = self .cloud_service - .send_message(&workspace_id, chat_id, message) + .send_message(&workspace_id, chat_id, message, require_answer) .await?; - save_chat_message( - self.user_service.sqlite_connection(uid)?, - chat_id, - vec![message], - )?; + + let mut messages = Vec::with_capacity(2); + messages.push(qa.question); + if let Some(answer) = qa.answer { + messages.push(answer); + } + save_chat_message(self.user_service.sqlite_connection(uid)?, chat_id, messages)?; Ok(()) } diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs index 9c1dbda172f12..6e943eee418e8 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs @@ -1,4 +1,3 @@ -use flowy_chat_pub::cloud::ChatMessage; use flowy_sqlite::{ diesel, query_dsl::*, @@ -25,27 +24,6 @@ pub fn insert_chat_messages( .execute(&mut *conn) } -pub fn read_chat_message( - mut conn: DBConnection, - message_id_val: i64, -) -> QueryResult { - dsl::chat_message_table - .filter(chat_message_table::message_id.eq(message_id_val)) - .first::(&mut *conn) -} - -// pub fn select_chat_messages( -// mut conn: DBConnection, -// chat_id_val: &str, -// limit_val: i64, -// ) -> QueryResult> { -// dsl::chat_message_table -// .filter(chat_message_table::chat_id.eq(chat_id_val)) -// .order(chat_message_table::created_at.asc()) -// .limit(limit_val) -// .load::(&mut *conn) -// } - pub fn select_chat_messages( mut conn: DBConnection, chat_id_val: &str, diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs index e8cbb21006cd2..92e09996d5e3d 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs @@ -501,18 +501,18 @@ impl FolderOperationHandler for ChatFolderOperation { }) } - fn duplicate_view(&self, view_id: &str) -> FutureResult { + fn duplicate_view(&self, _view_id: &str) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support()) }) } fn create_view_with_view_data( &self, - user_id: i64, - view_id: &str, - name: &str, - data: Vec, - layout: ViewLayout, - meta: HashMap, + _user_id: i64, + _view_id: &str, + _name: &str, + _data: Vec, + _layout: ViewLayout, + _meta: HashMap, ) -> FutureResult<(), FlowyError> { FutureResult::new(async move { Err(FlowyError::not_support()) }) } @@ -521,8 +521,8 @@ impl FolderOperationHandler for ChatFolderOperation { &self, user_id: i64, view_id: &str, - name: &str, - layout: ViewLayout, + _name: &str, + _layout: ViewLayout, ) -> FutureResult<(), FlowyError> { let manager = self.0.clone(); let view_id = view_id.to_string(); @@ -534,20 +534,20 @@ impl FolderOperationHandler for ChatFolderOperation { fn import_from_bytes( &self, - uid: i64, - view_id: &str, - name: &str, - import_type: ImportType, - bytes: Vec, + _uid: i64, + _view_id: &str, + _name: &str, + _import_type: ImportType, + _bytes: Vec, ) -> FutureResult<(), FlowyError> { FutureResult::new(async move { Err(FlowyError::not_support()) }) } fn import_from_file_path( &self, - view_id: &str, - name: &str, - path: String, + _view_id: &str, + _name: &str, + _path: String, ) -> FutureResult<(), FlowyError> { FutureResult::new(async move { Err(FlowyError::not_support()) }) } diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 0c2c79a488260..094f88b0133d9 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -15,7 +15,7 @@ use tracing::debug; use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageCursor, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, MessageCursor, QAChatMessage, RepeatedChatMessage}; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, }; @@ -377,7 +377,7 @@ impl CollabCloudPluginProvider for ServerProvider { let sync_object = SyncObject::new( &collab_object.object_id, &collab_object.workspace_id, - collab_object.collab_type.into(), + collab_object.collab_type, &collab_object.device_id, ); let (sink, stream) = (channel.sink(), channel.stream()); @@ -459,7 +459,8 @@ impl ChatCloudService for ServerProvider { workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult { + require_answer: bool, + ) -> FutureResult { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); let message = message.to_string(); @@ -467,7 +468,7 @@ impl ChatCloudService for ServerProvider { FutureResult::new(async move { server? .chat_service() - .send_message(&workspace_id, &chat_id, &message) + .send_message(&workspace_id, &chat_id, &message, require_answer) .await }) } diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 11852f83b774c..5a3a9d02df2ce 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -2,7 +2,7 @@ use crate::af_cloud::AFServer; use client_api::entity::{ CreateChatMessageParams, CreateChatParams, MessageCursor, RepeatedChatMessage, }; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, QAChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -44,14 +44,18 @@ where workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult { + require_answer: bool, + ) -> FutureResult { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); let message = message.to_string(); let try_get_client = self.inner.try_get_client(); FutureResult::new(async move { - let params = CreateChatMessageParams { content: message }; + let params = CreateChatMessageParams { + content: message, + require_answer, + }; let message = try_get_client? .create_chat_message(&workspace_id, &chat_id, params) .await diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs index 80c143d9426f2..ea995b7b1e432 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/database.rs @@ -42,7 +42,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab::new(object_id.clone(), collab_type.clone().into()), + inner: QueryCollab::new(object_id.clone(), collab_type.clone()), }; match try_get_client?.get_collab(params).await { Ok(data) => { @@ -78,7 +78,7 @@ where let client = try_get_client?; let params = object_ids .into_iter() - .map(|object_id| QueryCollab::new(object_id, object_ty.clone().into())) + .map(|object_id| QueryCollab::new(object_id, object_ty.clone())) .collect(); let results = client.batch_get_collab(&workspace_id, params).await?; check_request_workspace_id_is_match( diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs index 73c001e60b995..98732aa521cfb 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/document.rs @@ -37,7 +37,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab::new(document_id.to_string(), CollabType::Document.into()), + inner: QueryCollab::new(document_id.to_string(), CollabType::Document), }; let doc_state = try_get_client? .get_collab(params) @@ -79,7 +79,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab::new(document_id.clone(), CollabType::Document.into()), + inner: QueryCollab::new(document_id.clone(), CollabType::Document), }; let doc_state = try_get_client? .get_collab(params) diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs index 63b0b69cc418d..fe58f3fc16083 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/folder.rs @@ -93,7 +93,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab::new(workspace_id.clone(), CollabType::Folder.into()), + inner: QueryCollab::new(workspace_id.clone(), CollabType::Folder), }; let doc_state = try_get_client? .get_collab(params) @@ -137,7 +137,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab::new(object_id, collab_type.into()), + inner: QueryCollab::new(object_id, collab_type), }; let doc_state = try_get_client? .get_collab(params) @@ -164,7 +164,7 @@ where .map(|object| { CollabParams::new( object.object_id, - object.collab_type.into(), + object.collab_type, object.encoded_collab_v1, ) }) diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs index 7b3827561f19e..858e74f5012f1 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/cloud_service_impl.rs @@ -348,7 +348,7 @@ where FutureResult::new(async move { let params = QueryCollabParams { workspace_id: workspace_id.clone(), - inner: QueryCollab::new(object_id, CollabType::UserAwareness.into()), + inner: QueryCollab::new(object_id, CollabType::UserAwareness), }; let resp = try_get_client?.get_collab(params).await?; check_request_workspace_id_is_match( @@ -380,7 +380,7 @@ where let params = CreateCollabParams { workspace_id: collab_object.workspace_id, object_id: collab_object.object_id, - collab_type: collab_object.collab_type.into(), + collab_type: collab_object.collab_type, encoded_collab_v1: data, }; client.create_collab(params).await?; diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/server.rs b/frontend/rust-lib/flowy-server/src/af_cloud/server.rs index b8a636fe7d18f..4effa6394594f 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/server.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/server.rs @@ -34,7 +34,7 @@ use crate::af_cloud::impls::{ AFCloudChatCloudServiceImpl, AFCloudDatabaseCloudServiceImpl, AFCloudDocumentCloudServiceImpl, AFCloudFileStorageServiceImpl, AFCloudFolderCloudServiceImpl, AFCloudUserAuthServiceImpl, }; -use crate::default_impl::DefaultChatCloudServiceImpl; + use crate::AppFlowyServer; pub(crate) type AFCloudClient = Client; diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index d4dac1961f48f..f4805b8f4a7f4 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,5 +1,5 @@ use client_api::entity::{MessageCursor, RepeatedChatMessage}; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, QAChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -8,9 +8,9 @@ pub(crate) struct DefaultChatCloudServiceImpl; impl ChatCloudService for DefaultChatCloudServiceImpl { fn create_chat( &self, - uid: &i64, - workspace_id: &str, - chat_id: &str, + _uid: &i64, + _workspace_id: &str, + _chat_id: &str, ) -> FutureResult<(), FlowyError> { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) @@ -22,7 +22,8 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult { + require_answer: bool, + ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) }) @@ -30,10 +31,10 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { fn get_chat_messages( &self, - workspace_id: &str, - chat_id: &str, - offset: MessageCursor, - limit: u64, + _workspace_id: &str, + _chat_id: &str, + _offset: MessageCursor, + _limit: u64, ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) From 98e2ad97a01b1370f81153565073f733f1a8812d Mon Sep 17 00:00:00 2001 From: nathan Date: Sat, 25 May 2024 09:01:29 +0800 Subject: [PATCH 11/41] chore: load chat message --- .../presentation/base/mobile_view_page.dart | 4 +- .../ai_chat/application/chat_bloc.dart | 199 ++++++++++ .../ai_chat/{ai_chat.dart => chat.dart} | 73 ++-- .../lib/plugins/ai_chat/chat_page.dart | 113 ++++++ .../lib/plugins/blank/blank.dart | 5 +- .../database/tab_bar/tab_bar_view.dart | 7 +- .../widgets/database_view_widget.dart | 1 + .../database_document_plugin.dart | 5 +- .../lib/plugins/document/document.dart | 7 +- .../lib/plugins/trash/trash.dart | 5 +- .../lib/startup/plugin/plugin.dart | 14 +- .../lib/startup/tasks/load_plugin.dart | 2 +- .../workspace/application/view/view_ext.dart | 2 +- .../home/desktop_home_screen.dart | 1 + .../presentation/home/home_stack.dart | 22 +- frontend/appflowy_flutter/pubspec.lock | 2 +- frontend/appflowy_flutter/pubspec.yaml | 1 + frontend/appflowy_tauri/src-tauri/Cargo.lock | 33 +- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 +-- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 28 +- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 44 +-- frontend/rust-lib/Cargo.toml | 2 +- .../event-integration-test/src/chat_event.rs | 13 +- .../tests/chat/chat_message_test.rs | 36 +- frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 14 +- frontend/rust-lib/flowy-chat/src/chat.rs | 339 +++++++++++++++++- frontend/rust-lib/flowy-chat/src/entities.rs | 33 +- .../rust-lib/flowy-chat/src/event_handler.rs | 21 +- frontend/rust-lib/flowy-chat/src/event_map.rs | 2 +- frontend/rust-lib/flowy-chat/src/manager.rs | 204 +++-------- .../src/persistence/chat_message_sql.rs | 4 +- .../flowy-chat/src/persistence/chat_sql.rs | 2 + .../flowy-core/src/integrate/trait_impls.rs | 27 +- .../flowy-server/src/af_cloud/impls/chat.rs | 32 +- .../rust-lib/flowy-server/src/default_impl.rs | 16 +- .../2024-05-23-061639_chat_message/up.sql | 10 +- frontend/rust-lib/flowy-sqlite/src/schema.rs | 2 + 40 files changed, 1037 insertions(+), 334 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart rename frontend/appflowy_flutter/lib/plugins/ai_chat/{ai_chat.dart => chat.dart} (58%) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart index 22b46ced57d18..5ae710e8ce4a0 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart @@ -8,6 +8,7 @@ import 'package:appflowy/plugins/base/emoji/emoji_text.dart'; import 'package:appflowy/plugins/document/presentation/document_collaborators.dart'; import 'package:appflowy/plugins/shared/sync_indicator.dart'; import 'package:appflowy/shared/feature_flags.dart'; +import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/reminder/reminder_bloc.dart'; import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart'; @@ -154,7 +155,8 @@ class _MobileViewPageState extends State { (view) { final plugin = view.plugin(arguments: widget.arguments ?? const {}) ..init(); - return plugin.widgetBuilder.buildWidget(shrinkWrap: false); + return plugin.widgetBuilder + .buildWidget(shrinkWrap: false, context: PluginContext()); }, (error) { return FlowyMobileStateContainer.error( diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart new file mode 100644 index 0000000000000..5f366deb760e2 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -0,0 +1,199 @@ +import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:fixnum/fixnum.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'chat_bloc.freezed.dart'; + +const loadingMessageId = 'chat_message_loading_id'; + +class ChatBloc extends Bloc { + ChatBloc({ + required ViewPB view, + required UserProfilePB userProfile, + }) : super( + ChatState.initial( + view, + userProfile, + ), + ) { + _dispatch(); + } + + void _dispatch() { + on( + (event, emit) async { + await event.when( + loadMessage: () async { + Int64? beforeMessageId; + if (state.messages.isNotEmpty) { + beforeMessageId = Int64.parseInt(state.messages.last.id); + } + + _loadMessage(beforeMessageId); + if (beforeMessageId == null) { + emit( + state.copyWith( + loadingStatus: const LoadingState.loading(), + ), + ); + } else { + emit( + state.copyWith( + loadingPreviousStatus: const LoadingState.loading(), + ), + ); + } + }, + sendMessage: (String message) { + _handleSentMessage(message, emit); + final loadingMessage = CustomMessage( + author: User(id: state.userProfile.id.toString()), + id: loadingMessageId, + ); + final List allMessages = List.from(state.messages); + allMessages.insert(0, loadingMessage); + emit( + state.copyWith( + messages: allMessages, + loadingStatus: const LoadingState.loading(), + ), + ); + }, + didReceiveMessages: (List messages) { + final List allMessages = List.from(state.messages); + allMessages + .removeWhere((element) => element.id == loadingMessageId); + allMessages.addAll(messages); + emit( + state.copyWith( + messages: allMessages, + loadingStatus: const LoadingState.finish(), + ), + ); + }, + didLoadPreviousMessages: (List messages, bool hasMore) { + final List allMessages = List.from(state.messages); + allMessages.addAll(messages); + Log.info("did load previous messages: ${allMessages.length}"); + emit( + state.copyWith( + messages: allMessages, + loadingPreviousStatus: const LoadingState.finish(), + hasMore: hasMore, + ), + ); + }, + tapMessage: (Message message) {}, + ); + }, + ); + } + + void _loadMessage( + Int64? beforeMessageId, + ) { + final payload = LoadChatMessagePB( + chatId: state.view.id, + limit: Int64(10), + beforeMessageId: beforeMessageId, + ); + ChatEventLoadMessage(payload).send().then((result) { + result.fold( + (list) { + final messages = + list.messages.map((m) => _fromChatMessage(m)).toList(); + + if (!isClosed) { + if (beforeMessageId != null) { + add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); + } else { + add(ChatEvent.didReceiveMessages(messages)); + } + } + }, + (err) { + Log.error("Failed to load message: $err"); + }, + ); + }); + } + + Future _handleSentMessage( + String message, + Emitter emit, + ) async { + final payload = SendChatPayloadPB( + chatId: state.view.id, + message: message, + messageType: ChatMessageTypePB.User, + ); + final result = await ChatEventSendMessage(payload).send(); + result.fold((repeatedMessage) { + final messages = + repeatedMessage.items.map((m) => _fromChatMessage(m)).toList(); + if (!isClosed) { + add(ChatEvent.didReceiveMessages(messages)); + } + }, (err) { + Log.error("Failed to send message: $err"); + }); + } +} + +Message _fromChatMessage(ChatMessagePB message) { + return TextMessage( + author: User(id: message.authorId), + id: message.messageId.toString(), + text: message.content, + createdAt: message.createdAt.toInt(), + ); +} + +@freezed +class ChatEvent with _$ChatEvent { + const factory ChatEvent.sendMessage(String message) = _SendMessage; + const factory ChatEvent.tapMessage(Message message) = _TapMessage; + const factory ChatEvent.loadMessage() = _LoadMessage; + const factory ChatEvent.didReceiveMessages(List messages) = + _DidLoadMessages; + const factory ChatEvent.didLoadPreviousMessages( + List messages, bool hasMore,) = _DidLoadPreviousMessages; +} + +@freezed +class ChatState with _$ChatState { + const factory ChatState({ + required ViewPB view, + required List messages, + required UserProfilePB userProfile, + required LoadingState loadingStatus, + required LoadingState loadingPreviousStatus, + required bool hasMore, + }) = _ChatState; + + factory ChatState.initial( + ViewPB view, + UserProfilePB userProfile, + ) => + ChatState( + view: view, + messages: [], + userProfile: userProfile, + loadingStatus: const LoadingState.finish(), + loadingPreviousStatus: const LoadingState.finish(), + hasMore: true, + ); +} + +@freezed +class LoadingState with _$LoadingState { + const factory LoadingState.loading() = _Loading; + const factory LoadingState.finish() = _Finish; +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart similarity index 58% rename from frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart rename to frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart index 4524918a5be86..3036c570b6426 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/ai_chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart @@ -1,12 +1,15 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/ai_chat/chat_page.dart'; import 'package:appflowy/plugins/util.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; +import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; class AIChatPluginBuilder extends PluginBuilder { @override @@ -41,53 +44,71 @@ class AIChatPagePlugin extends Plugin { required ViewPB view, }) : notifier = ViewPluginNotifier(view: view); + late final ViewInfoBloc _viewInfoBloc; + @override final ViewPluginNotifier notifier; @override - PluginWidgetBuilder get widgetBuilder => AIChatPagePluginWidgetBuilder(); + PluginWidgetBuilder get widgetBuilder => AIChatPagePluginWidgetBuilder( + bloc: _viewInfoBloc, + notifier: notifier, + ); @override - PluginId get id => "AIChatStack"; + PluginId get id => notifier.view.id; @override PluginType get pluginType => PluginType.chat; + + @override + void init() { + _viewInfoBloc = ViewInfoBloc(view: notifier.view) + ..add(const ViewInfoEvent.started()); + } } class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder with NavigationItem { - @override - Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr()); + AIChatPagePluginWidgetBuilder({ + required this.bloc, + required this.notifier, + }); - @override - Widget tabBarItem(String pluginId) => leftBarItem; - - @override - Widget buildWidget({PluginContext? context, required bool shrinkWrap}) => - const AIChatPage(); + final ViewInfoBloc bloc; + final ViewPluginNotifier notifier; + int? deletedViewIndex; @override - List get navigationItems => [this]; -} - -class AIChatPage extends StatefulWidget { - const AIChatPage({super.key}); + Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr()); @override - State createState() => _AIChatPageState(); -} + Widget tabBarItem(String pluginId) => leftBarItem; -class _AIChatPageState extends State { @override - Widget build(BuildContext context) { - return SizedBox.expand( - child: Container( - color: Theme.of(context).colorScheme.surface, - child: const Padding( - padding: EdgeInsets.all(10), - child: SizedBox.shrink(), - ), + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }) { + notifier.isDeleted.addListener(() { + final deletedView = notifier.isDeleted.value; + if (deletedView != null && deletedView.hasIndex()) { + deletedViewIndex = deletedView.index; + } + }); + + return BlocProvider.value( + value: bloc, + child: AIChatPage( + userProfile: context.userProfile!, + key: ValueKey(notifier.view.id), + view: notifier.view, + onDeleted: () => + context.onDeleted?.call(notifier.view, deletedViewIndex), ), ); } + + @override + List get navigationItems => [this]; } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart new file mode 100644 index 0000000000000..30c5c4a76f53f --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -0,0 +1,113 @@ +import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; +import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_ui/flutter_chat_ui.dart' + show Chat, DarkChatTheme, InputOptions; +// ignore: depend_on_referenced_packages +import 'package:flutter_chat_types/flutter_chat_types.dart' as types; + +class AIChatPage extends StatefulWidget { + const AIChatPage({ + super.key, + required this.view, + required this.onDeleted, + required this.userProfile, + }); + + final ViewPB view; + final VoidCallback onDeleted; + final UserProfilePB userProfile; + + @override + State createState() => _AIChatPageState(); +} + +class _AIChatPageState extends State { + @override + void initState() { + super.initState(); + _user = types.User( + id: widget.userProfile.id.toString(), + ); + } + + late types.User _user; + final chatTheme = const DarkChatTheme(); + var inputOption = const InputOptions(); + + @override + Widget build(BuildContext context) { + return SizedBox.expand( + child: Container( + color: Theme.of(context).colorScheme.background, + child: Padding( + padding: const EdgeInsets.all(10), + child: BlocProvider( + create: (context) => ChatBloc( + view: widget.view, + userProfile: widget.userProfile, + )..add(const ChatEvent.loadMessage()), + child: BlocListener( + listenWhen: (previous, current) => + previous.loadingStatus != current.loadingStatus, + listener: (context, state) { + // inputOption = InputOptions( + // enabled: state.loadingStatus.when( + // loading: () => false, + // finish: () => true, + // ), + // ); + }, + child: BlocBuilder( + builder: (blocContext, state) { + return Chat( + inputOptions: inputOption, + messages: state.messages, + onAttachmentPressed: () {}, + onMessageTap: (BuildContext _, types.Message message) { + blocContext + .read() + .add(ChatEvent.tapMessage(message)); + }, + onSendPressed: (types.PartialText message) { + blocContext + .read() + .add(ChatEvent.sendMessage(message.text)); + }, + user: _user, + theme: chatTheme, + customMessageBuilder: (message, {required messageWidth}) { + return const SizedBox( + width: 100, + height: 50, + child: CircularProgressIndicator.adaptive(), + ); + }, + onEndReached: () async { + if (state.hasMore) { + state.loadingPreviousStatus.when( + loading: () { + Log.debug("loading"); + }, + finish: () { + Log.debug("loading more messages"); + blocContext + .read() + .add(const ChatEvent.loadMessage()); + }, + ); + } + }, + ); + }, + ), + ), + ), + ), + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/blank/blank.dart b/frontend/appflowy_flutter/lib/plugins/blank/blank.dart index 61864b4b7f300..1aec6b7037f6a 100644 --- a/frontend/appflowy_flutter/lib/plugins/blank/blank.dart +++ b/frontend/appflowy_flutter/lib/plugins/blank/blank.dart @@ -51,7 +51,10 @@ class BlankPagePluginWidgetBuilder extends PluginWidgetBuilder Widget tabBarItem(String pluginId) => leftBarItem; @override - Widget buildWidget({PluginContext? context, required bool shrinkWrap}) => + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }) => const BlankPage(); @override diff --git a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart index d8aa978e12518..2d1bc4d515a45 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart @@ -242,11 +242,14 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder { Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view); @override - Widget buildWidget({PluginContext? context, required bool shrinkWrap}) { + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }) { notifier.isDeleted.addListener(() { final deletedView = notifier.isDeleted.value; if (deletedView != null && deletedView.hasIndex()) { - context?.onDeleted(notifier.view, deletedView.index); + context.onDeleted?.call(notifier.view, deletedView.index); } }); diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/database_view_widget.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/database_view_widget.dart index 97e13a626aab0..ee64eb84af439 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/database_view_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/database_view_widget.dart @@ -54,6 +54,7 @@ class _DatabaseViewWidgetState extends State { valueListenable: _layoutTypeChangeNotifier, builder: (_, __, ___) => viewPlugin.widgetBuilder.buildWidget( shrinkWrap: widget.shrinkWrap, + context: PluginContext(), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart b/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart index c0385ec479463..cd709e21544e8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_document/database_document_plugin.dart @@ -101,7 +101,10 @@ class DatabaseDocumentPluginWidgetBuilder extends PluginWidgetBuilder EdgeInsets get contentPadding => EdgeInsets.zero; @override - Widget buildWidget({PluginContext? context, required bool shrinkWrap}) { + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }) { return BlocBuilder( builder: (_, state) => DatabaseDocumentPage( key: ValueKey(documentId), diff --git a/frontend/appflowy_flutter/lib/plugins/document/document.dart b/frontend/appflowy_flutter/lib/plugins/document/document.dart index 43122daced472..69abbc64d6365 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/document.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/document.dart @@ -108,7 +108,10 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder EdgeInsets get contentPadding => EdgeInsets.zero; @override - Widget buildWidget({PluginContext? context, required bool shrinkWrap}) { + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }) { notifier.isDeleted.addListener(() { final deletedView = notifier.isDeleted.value; if (deletedView != null && deletedView.hasIndex()) { @@ -122,7 +125,7 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder builder: (_, state) => DocumentPage( key: ValueKey(view.id), view: view, - onDeleted: () => context?.onDeleted(view, deletedViewIndex), + onDeleted: () => context.onDeleted?.call(view, deletedViewIndex), initialSelection: initialSelection, ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/trash/trash.dart b/frontend/appflowy_flutter/lib/plugins/trash/trash.dart index aa6445a65f62b..e2f312373e9a4 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/trash.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/trash.dart @@ -63,7 +63,10 @@ class TrashPluginDisplay extends PluginWidgetBuilder { Widget? get rightBarItem => null; @override - Widget buildWidget({PluginContext? context, required bool shrinkWrap}) => + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }) => const TrashPage( key: ValueKey('TrashPage'), ); diff --git a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart index 2fa8dbeaad08f..b81860cd99c30 100644 --- a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart @@ -1,5 +1,6 @@ library flowy_plugin; +import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flutter/widgets.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart'; @@ -72,14 +73,21 @@ abstract class PluginWidgetBuilder with NavigationItem { EdgeInsets get contentPadding => const EdgeInsets.symmetric(horizontal: 40, vertical: 28); - Widget buildWidget({PluginContext? context, required bool shrinkWrap}); + Widget buildWidget({ + required PluginContext context, + required bool shrinkWrap, + }); } class PluginContext { - PluginContext({required this.onDeleted}); + PluginContext({ + this.userProfile, + this.onDeleted, + }); // calls when widget of the plugin get deleted - final Function(ViewPB, int?) onDeleted; + final Function(ViewPB, int?)? onDeleted; + final UserProfilePB? userProfile; } void registerPlugin({required PluginBuilder builder, PluginConfig? config}) { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart b/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart index bb1b769fdbc97..9a75607d74270 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/load_plugin.dart @@ -1,4 +1,4 @@ -import 'package:appflowy/plugins/ai_chat/ai_chat.dart'; +import 'package:appflowy/plugins/ai_chat/chat.dart'; import 'package:appflowy/plugins/database/calendar/calendar.dart'; import 'package:appflowy/plugins/database/board/board.dart'; import 'package:appflowy/plugins/database/grid/grid.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart index 4ae9a3fa1f63d..6ce02723fec5e 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/mobile/application/page_style/document_page_style_bloc.dart'; -import 'package:appflowy/plugins/ai_chat/ai_chat.dart'; +import 'package:appflowy/plugins/ai_chat/chat.dart'; import 'package:appflowy/plugins/database/board/presentation/board_page.dart'; import 'package:appflowy/plugins/database/calendar/presentation/calendar_page.dart'; import 'package:appflowy/plugins/database/grid/presentation/grid_page.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart index e7b74ef4e9335..28e793eba1460 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart @@ -146,6 +146,7 @@ class DesktopHomeScreen extends StatelessWidget { final homeStack = HomeStack( layout: layout, delegate: DesktopHomeScreenStackAdaptor(context), + userProfile: userProfile, ); final menu = _buildHomeSidebar( context, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart index 2a0eb6ec7d353..41b33bd95f7c0 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart @@ -1,3 +1,4 @@ +import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -30,10 +31,12 @@ class HomeStack extends StatelessWidget { super.key, required this.delegate, required this.layout, + required this.userProfile, }); final HomeStackDelegate delegate; final HomeLayout layout; + final UserProfilePB userProfile; @override Widget build(BuildContext context) { @@ -56,7 +59,11 @@ class HomeStack extends StatelessWidget { controller: pageController, children: state.pageManagers .map( - (pm) => PageStack(pageManager: pm, delegate: delegate), + (pm) => PageStack( + pageManager: pm, + delegate: delegate, + userProfile: userProfile, + ), ) .toList(), ), @@ -74,11 +81,13 @@ class PageStack extends StatefulWidget { super.key, required this.pageManager, required this.delegate, + required this.userProfile, }); final PageManager pageManager; final HomeStackDelegate delegate; + final UserProfilePB userProfile; @override State createState() => _PageStackState(); @@ -94,6 +103,7 @@ class _PageStackState extends State color: Theme.of(context).colorScheme.surface, child: FocusTraversalGroup( child: widget.pageManager.stackWidget( + userProfile: widget.userProfile, onDeleted: (view, index) { widget.delegate.didDeleteStackWidget(view, index); }, @@ -228,7 +238,10 @@ class PageManager { ); } - Widget stackWidget({required Function(ViewPB, int?) onDeleted}) { + Widget stackWidget({ + required UserProfilePB userProfile, + required Function(ViewPB, int?) onDeleted, + }) { return MultiProvider( providers: [ChangeNotifierProvider.value(value: _notifier)], child: Consumer( @@ -240,7 +253,10 @@ class PageManager { if (pluginType == notifier.plugin.pluginType) { final builder = notifier.plugin.widgetBuilder; final pluginWidget = builder.buildWidget( - context: PluginContext(onDeleted: onDeleted), + context: PluginContext( + onDeleted: onDeleted, + userProfile: userProfile, + ), shrinkWrap: false, ); diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index 3fa25daa467e9..fd66b7bb302dc 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -595,7 +595,7 @@ packages: source: git version: "3.3.1" flutter_chat_types: - dependency: transitive + dependency: "direct main" description: name: flutter_chat_types sha256: e285b588f6d19d907feb1f6d912deaf22e223656769c34093b64e1c59b094fb9 diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 8f88a10ac1f82..22a12a5213c05 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -137,6 +137,7 @@ dependencies: permission_handler: ^11.3.1 scaled_app: ^2.2.0 flutter_chat_ui: ^1.6.13 + flutter_chat_types: ^3.6.2 dev_dependencies: flutter_lints: ^3.0.1 diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 307e1d191767f..be1bbf13c7c84 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "serde", @@ -606,11 +606,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -753,7 +754,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "again", "anyhow", @@ -800,7 +801,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "futures-channel", "futures-util", @@ -1039,7 +1040,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -1064,7 +1065,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "async-trait", @@ -1310,7 +1311,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1421,7 +1422,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -2825,7 +2826,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "futures-util", @@ -2842,7 +2843,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -3274,7 +3275,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "reqwest", @@ -4777,7 +4778,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4798,7 +4799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -5762,7 +5763,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 8dbba9c16863e..3ffcdfc3a12a5 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 4c9f7af6d0e6c..df9d42590596b 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "serde", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "again", "anyhow", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "async-trait", @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1024,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -1811,7 +1811,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "futures-util", @@ -1828,7 +1828,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -2129,7 +2129,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "reqwest", @@ -2813,7 +2813,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2833,7 +2833,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2901,19 +2900,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -3769,7 +3755,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 665f397ae3e94..89f34f680f890 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index cbd84d38de9ca..3cfce89bb1934 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "serde", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "again", "anyhow", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "futures-channel", "futures-util", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -1047,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "async-trait", @@ -1297,7 +1297,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1408,7 +1408,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -2899,7 +2899,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "futures-util", @@ -2916,7 +2916,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -3353,7 +3353,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "reqwest", @@ -4858,7 +4858,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4879,7 +4879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5857,7 +5857,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 726c9eb3b906a..987f12a6bc956 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 69e474aefcfc6..abed92b55059e 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "serde", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "again", "anyhow", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "bincode", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "async-trait", @@ -1162,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1261,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -2509,7 +2509,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "futures-util", @@ -2526,7 +2526,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", @@ -2891,7 +2891,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "reqwest", @@ -3766,7 +3766,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3786,7 +3786,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3854,19 +3853,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4070,7 +4056,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4091,7 +4077,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4988,7 +4974,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=74826e79038eecda6bdef7edd026ed6930a4a58f#74826e79038eecda6bdef7edd026ed6930a4a58f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index c7f14ef6e5e6b..1db3bb202eb57 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "74826e79038eecda6bdef7edd026ed6930a4a58f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/event-integration-test/src/chat_event.rs b/frontend/rust-lib/event-integration-test/src/chat_event.rs index 840bfcb4e2626..a8be7a91da8d3 100644 --- a/frontend/rust-lib/event-integration-test/src/chat_event.rs +++ b/frontend/rust-lib/event-integration-test/src/chat_event.rs @@ -1,6 +1,8 @@ use crate::event_builder::EventBuilder; use crate::EventIntegrationTest; -use flowy_chat::entities::{ChatMessageListPB, LoadChatMessagePB, SendChatPayloadPB}; +use flowy_chat::entities::{ + ChatMessageListPB, ChatMessageTypePB, LoadChatMessagePB, SendChatPayloadPB, +}; use flowy_chat::event_map::ChatEvent; use flowy_folder::entities::{CreateViewPayloadPB, ViewLayoutPB, ViewPB}; use flowy_folder::event_map::FolderEvent; @@ -27,11 +29,16 @@ impl EventIntegrationTest { .parse::() } - pub async fn send_message(&self, chat_id: &str, message: impl ToString, require_answer: bool) { + pub async fn send_message( + &self, + chat_id: &str, + message: impl ToString, + message_type: ChatMessageTypePB, + ) { let payload = SendChatPayloadPB { chat_id: chat_id.to_string(), message: message.to_string(), - require_answer, + message_type, }; EventBuilder::new(self.clone()) diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index 420236d9e423e..499e08745d686 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -1,7 +1,7 @@ use crate::util::receive_with_timeout; use event_integration_test::user_event::user_localhost_af_cloud; use event_integration_test::EventIntegrationTest; -use flowy_chat::entities::ChatMessageListPB; +use flowy_chat::entities::{ChatMessageListPB, ChatMessageTypePB}; use flowy_chat::notification::ChatNotification; use std::time::Duration; @@ -17,7 +17,11 @@ async fn af_cloud_create_chat_message_test() { let chat_id = view.id.clone(); for i in 0..10 { test - .send_message(&chat_id, format!("hello world {}", i)) + .send_message( + &chat_id, + format!("hello world {}", i), + ChatMessageTypePB::System, + ) .await; } let all = test.load_message(&chat_id, 10, None, None).await; @@ -42,7 +46,7 @@ async fn af_cloud_create_chat_message_test() { } #[tokio::test] -async fn af_cloud_load_remote_chat_message_test() { +async fn af_cloud_load_remote_system_message_test() { user_localhost_af_cloud().await; let test = EventIntegrationTest::new().await; test.af_cloud_sign_up().await; @@ -54,11 +58,10 @@ async fn af_cloud_load_remote_chat_message_test() { let chat_service = test.server_provider.get_server().unwrap().chat_service(); for i in 0..10 { chat_service - .send_message( + .send_system_message( ¤t_workspace.id, &chat_id, &format!("hello server {}", i), - false, ) .await .unwrap(); @@ -107,3 +110,26 @@ async fn af_cloud_load_remote_chat_message_test() { assert_eq!(first_five_messages.messages[3].content, "hello server 3"); assert_eq!(first_five_messages.messages[4].content, "hello server 4"); } + +#[tokio::test] +async fn af_cloud_load_remote_user_message_test() { + user_localhost_af_cloud().await; + let test = EventIntegrationTest::new().await; + test.af_cloud_sign_up().await; + + let current_workspace = test.get_current_workspace().await; + let view = test.create_chat(¤t_workspace.id).await; + let chat_id = view.id.clone(); + test + .send_message(&chat_id, "hello world", ChatMessageTypePB::User) + .await; + + let all = test.load_message(&chat_id, 5, None, None).await; + assert_eq!(all.messages.len(), 2); + // 2 means User + assert_eq!(all.messages[0].author_type, 1); + // 3 means AI + assert_eq!(all.messages[1].author_type, 3); + // The message ID is incremented by 1. + assert_eq!(all.messages[0].message_id + 1, all.messages[1].message_id); +} diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 221fc5eac540f..bb0b799cfb49e 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,4 +1,6 @@ -pub use client_api::entity::{ChatMessage, MessageCursor, QAChatMessage, RepeatedChatMessage}; +pub use client_api::entity::{ + ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, +}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -10,12 +12,18 @@ pub trait ChatCloudService: Send + Sync + 'static { chat_id: &str, ) -> FutureResult<(), FlowyError>; - fn send_message( + fn send_system_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult; + + fn send_user_message( &self, workspace_id: &str, chat_id: &str, message: &str, - require_answer: bool, ) -> FutureResult; fn get_chat_messages( diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index c048dd40b93bd..588fde9bfbfd2 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -1,17 +1,350 @@ -use flowy_chat_pub::cloud::ChatCloudService; +use crate::entities::{ChatMessageListPB, ChatMessagePB}; +use crate::manager::ChatUserService; +use crate::notification::{send_notification, ChatNotification}; +use crate::persistence::{ + insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, +}; +use flowy_chat_pub::cloud::{ + ChatCloudService, ChatMessage, ChatMessageType, MessageCursor, RepeatedChatMessage, +}; +use flowy_error::{FlowyError, FlowyResult}; +use flowy_sqlite::DBConnection; +use lib_infra::util::timestamp; +use std::sync::atomic::AtomicBool; use std::sync::Arc; +use tokio::sync::RwLock; +use tracing::{error, instrument, trace, warn}; + +enum PrevMessageState { + HasMore, + NoMore, + Loading, +} -#[allow(dead_code)] pub struct Chat { chat_id: String, + uid: i64, + user_service: Arc, cloud_service: Arc, + prev_message_state: Arc>, } impl Chat { - pub fn new(chat_id: String, cloud_service: Arc) -> Chat { + pub fn new( + uid: i64, + chat_id: String, + user_service: Arc, + cloud_service: Arc, + ) -> Chat { Chat { + uid, chat_id, cloud_service, + user_service, + prev_message_state: Arc::new(RwLock::new(PrevMessageState::HasMore)), + } + } + + pub fn close(&self) {} + + #[instrument(level = "info", skip_all, err)] + pub async fn send_chat_message( + &self, + message: &str, + message_type: ChatMessageType, + ) -> Result, FlowyError> { + let _uid = self.user_service.user_id()?; + let workspace_id = self.user_service.workspace_id()?; + let mut messages = Vec::with_capacity(2); + + trace!( + "Sending chat message: chat_id={}, message={}, type={:?}", + self.chat_id, + message, + message_type + ); + match message_type { + ChatMessageType::System => { + let message = self + .cloud_service + .send_system_message(&workspace_id, &self.chat_id, message) + .await?; + messages.push(message); + }, + ChatMessageType::User => { + let qa = self + .cloud_service + .send_user_message(&workspace_id, &self.chat_id, message) + .await?; + messages.push(qa.question); + if let Some(answer) = qa.answer { + messages.push(answer); + } + }, + }; + + trace!( + "Saving chat messages to local disk: chat_id={}, messages:{:?}", + self.chat_id, + messages + ); + + save_chat_message( + self.user_service.sqlite_connection(self.uid)?, + &self.chat_id, + messages.clone(), + )?; + Ok(messages) + } + + /// Load chat messages for a given `chat_id`. + /// + /// 1. When opening a chat: + /// - Loads local chat messages. + /// - `after_message_id` and `before_message_id` are `None`. + /// - Spawns a task to load messages from the remote server, notifying the user when the remote messages are loaded. + /// + /// 2. Loading more messages in an existing chat with `after_message_id`: + /// - `after_message_id` is the last message ID in the current chat messages. + /// + /// 3. Loading more messages in an existing chat with `before_message_id`: + /// - `before_message_id` is the first message ID in the current chat messages. + /// + /// 4. `after_message_id` and `before_message_id` cannot be specified at the same time. + pub async fn load_prev_chat_messages( + &self, + limit: i64, + before_message_id: Option, + ) -> Result { + if matches!( + *self.prev_message_state.read().await, + PrevMessageState::NoMore + ) { + return Ok(ChatMessageListPB { + messages: vec![], + has_more: false, + total: 0, + }); } + + trace!( + "Loading chat messages: chat_id={}, limit={}, before_message_id={:?}", + self.chat_id, + limit, + before_message_id + ); + let messages = self + .load_local_chat_messages(limit, None, before_message_id) + .await?; + + // If the number of messages equals the limit, then no need to load more messages from remote + let has_more = !messages.is_empty(); + if messages.len() == limit as usize { + return Ok(ChatMessageListPB { + messages, + has_more, + total: 0, + }); + } + + self + .load_remote_prev_chat_messages(limit, before_message_id) + .await; + Ok(ChatMessageListPB { + messages, + has_more, + total: 0, + }) } + + #[instrument(level = "info", skip_all, err)] + async fn load_remote_prev_chat_messages(&self, limit: i64, before_message_id: Option) { + if matches!( + *self.prev_message_state.read().await, + PrevMessageState::Loading + ) { + return; + } + + let workspace_id = self.user_service.workspace_id()?; + let chat_id = self.chat_id.clone(); + let cloud_service = self.cloud_service.clone(); + let user_service = self.user_service.clone(); + let uid = self.uid; + let load_prev_message_state = self.prev_message_state.clone(); + + tokio::spawn(async move { + // + let cursor = if before_message_id.is_some() { + MessageCursor::BeforeMessageId(before_message_id.unwrap()) + } else { + MessageCursor::NextBack + }; + match cloud_service + .get_chat_messages(&workspace_id, &chat_id, cursor, limit as u64) + .await + { + Ok(resp) => { + // Save chat messages to local disk + save_chat_message( + user_service.sqlite_connection(uid)?, + &chat_id, + resp.messages.clone(), + )?; + + if resp.has_more { + *load_prev_message_state.write().await = PrevMessageState::HasMore; + } else { + *load_prev_message_state.write().await = PrevMessageState::NoMore; + } + + let pb = ChatMessageListPB::from(resp); + send_notification(&chat_id, ChatNotification::DidLoadChatMessage) + .payload(pb) + .send(); + }, + Err(err) => error!("Failed to load chat messages: {}", err), + } + Ok(()) + }); + } + + pub async fn load_after_chat_messages( + &self, + limit: i64, + after_message_id: Option, + ) -> Result { + trace!( + "Loading chat messages: chat_id={}, limit={}, after_message_id={:?}", + self.chat_id, + limit, + after_message_id, + ); + let messages = self + .load_local_chat_messages(limit, after_message_id, None) + .await?; + + // If the number of messages equals the limit, then no need to load more messages from remote + let has_more = !messages.is_empty(); + if messages.len() == limit as usize { + return Ok(ChatMessageListPB { + messages, + has_more, + total: 0, + }); + } + + let _ = self + .load_remote_after_chat_messages(limit, after_message_id) + .await; + Ok(ChatMessageListPB { + messages, + has_more, + total: 0, + }) + } + + async fn load_remote_after_chat_messages( + &self, + limit: i64, + after_message_id: Option, + ) -> FlowyResult<()> { + if matches!( + *self.prev_message_state.read().await, + PrevMessageState::Loading + ) { + return; + } + let workspace_id = self.user_service.workspace_id()?; + let chat_id = self.chat_id.clone(); + let cloud_service = self.cloud_service.clone(); + let user_service = self.user_service.clone(); + let uid = self.uid; + tokio::spawn(async move { + let cursor = if after_message_id.is_some() { + MessageCursor::AfterMessageId(after_message_id.unwrap()) + } else { + MessageCursor::NextBack + }; + match cloud_service + .get_chat_messages(&workspace_id, &chat_id, cursor, limit as u64) + .await + { + Ok(resp) => { + // Save chat messages to local disk + save_chat_message( + user_service.sqlite_connection(uid)?, + &chat_id, + resp.messages.clone(), + )?; + + let pb = ChatMessageListPB::from(resp); + send_notification(&chat_id, ChatNotification::DidLoadChatMessage) + .payload(pb) + .send(); + }, + Err(err) => error!("Failed to load chat messages: {}", err), + } + Ok(()) + }); + } + + async fn load_local_chat_messages( + &self, + limit: i64, + after_message_id: Option, + before_message_id: Option, + ) -> Result, FlowyError> { + let conn = self.user_service.sqlite_connection(self.uid)?; + let records = select_chat_messages( + conn, + &self.chat_id, + limit, + after_message_id, + before_message_id, + )?; + let messages = records + .into_iter() + .map(|record| ChatMessagePB { + message_id: record.message_id, + content: record.content, + created_at: record.created_at, + author_type: record.author_type, + author_id: record.author_id, + }) + .collect::>(); + + Ok(messages) + } +} + +fn save_chat_message( + conn: DBConnection, + chat_id: &str, + messages: Vec, +) -> FlowyResult<()> { + let records = messages + .into_iter() + .map(|message| ChatMessageTable { + message_id: message.message_id, + chat_id: chat_id.to_string(), + content: message.content, + created_at: message.created_at.timestamp(), + author_type: message.author.author_type as i64, + author_id: message.author.author_id.to_string(), + }) + .collect::>(); + insert_chat_messages(conn, &records)?; + Ok(()) +} + +fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { + let row = ChatTable { + chat_id: chat_id.to_string(), + created_at: timestamp(), + name: "".to_string(), + }; + + insert_chat(conn, &row)?; + Ok(()) } diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index f84013828253a..ce01b249ceec5 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -1,5 +1,5 @@ use flowy_chat_pub::cloud::{ChatMessage, RepeatedChatMessage}; -use flowy_derive::ProtoBuf; +use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_infra::validator_fn::required_not_empty_str; use validator::Validate; @@ -14,7 +14,14 @@ pub struct SendChatPayloadPB { pub message: String, #[pb(index = 3)] - pub require_answer: bool, + pub message_type: ChatMessageTypePB, +} + +#[derive(Debug, Default, Clone, ProtoBuf_Enum, PartialEq, Eq, Copy)] +pub enum ChatMessageTypePB { + #[default] + System = 0, + User = 1, } #[derive(Default, ProtoBuf, Validate, Clone, Debug)] @@ -71,6 +78,12 @@ pub struct ChatMessagePB { #[pb(index = 3)] pub created_at: i64, + + #[pb(index = 4)] + pub author_type: i64, + + #[pb(index = 5)] + pub author_id: String, } impl From for ChatMessagePB { @@ -79,6 +92,22 @@ impl From for ChatMessagePB { message_id: chat_message.message_id, content: chat_message.content, created_at: chat_message.created_at.timestamp(), + author_type: chat_message.author.author_type as i64, + author_id: chat_message.author.author_id.to_string(), + } + } +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct RepeatedChatMessagePB { + #[pb(index = 1)] + items: Vec, +} + +impl From> for RepeatedChatMessagePB { + fn from(messages: Vec) -> Self { + RepeatedChatMessagePB { + items: messages.into_iter().map(ChatMessagePB::from).collect(), } } } diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 5977b07471114..968351935b85a 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -1,3 +1,4 @@ +use flowy_chat_pub::cloud::ChatMessageType; use std::sync::{Arc, Weak}; use validator::Validate; @@ -20,15 +21,20 @@ fn upgrade_chat_manager( pub(crate) async fn send_chat_message_handler( data: AFPluginData, chat_manager: AFPluginState>, -) -> Result<(), FlowyError> { +) -> DataResult { let chat_manager = upgrade_chat_manager(chat_manager)?; let data = data.into_inner(); data.validate()?; - chat_manager - .send_chat_message(&data.chat_id, &data.message, data.require_answer) + let message_type = match data.message_type { + ChatMessageTypePB::System => ChatMessageType::System, + ChatMessageTypePB::User => ChatMessageType::User, + }; + let messages = chat_manager + .send_chat_message(&data.chat_id, &data.message, message_type) .await?; - Ok(()) + + data_result_ok(RepeatedChatMessagePB::from(messages)) } #[tracing::instrument(level = "debug", skip_all, err)] @@ -41,12 +47,7 @@ pub(crate) async fn load_message_handler( data.validate()?; let messages = chat_manager - .load_chat_messages( - &data.chat_id, - data.limit, - data.after_message_id, - data.before_message_id, - ) + .load_prev_chat_messages(&data.chat_id, data.limit, data.before_message_id) .await?; data_result_ok(messages) } diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 80d3ec44705a6..f4b2006123057 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -23,6 +23,6 @@ pub enum ChatEvent { #[event(input = "LoadChatMessagePB", output = "ChatMessageListPB")] LoadMessage = 0, - #[event(input = "SendChatPayloadPB")] + #[event(input = "SendChatPayloadPB", output = "RepeatedChatMessagePB")] SendMessage = 1, } diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 07f1943859767..716b604b49192 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,11 +1,8 @@ use crate::chat::Chat; -use crate::entities::{ChatMessageListPB, ChatMessagePB}; -use crate::notification::{send_notification, ChatNotification}; -use crate::persistence::{ - insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, -}; +use crate::entities::ChatMessageListPB; +use crate::persistence::{insert_chat, insert_chat_messages, ChatMessageTable, ChatTable}; use dashmap::DashMap; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, MessageCursor, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; @@ -39,7 +36,16 @@ impl ChatManager { } } - pub async fn open_chat(&self, _chat_id: &str) -> Result<(), FlowyError> { + pub async fn open_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + self.chats.entry(chat_id.to_string()).or_insert_with(|| { + Arc::new(Chat::new( + self.user_service.user_id().unwrap(), + chat_id.to_string(), + self.user_service.clone(), + self.cloud_service.clone(), + )) + }); + Ok(()) } @@ -47,7 +53,10 @@ impl ChatManager { Ok(()) } - pub async fn delete_chat(&self, _chat_id: &str) -> Result<(), FlowyError> { + pub async fn delete_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + if let Some((_, chat)) = self.chats.remove(chat_id) { + chat.close(); + } Ok(()) } @@ -58,29 +67,32 @@ impl ChatManager { .create_chat(uid, &workspace_id, chat_id) .await?; save_chat(self.user_service.sqlite_connection(*uid)?, chat_id)?; + + let chat = Arc::new(Chat::new( + self.user_service.user_id().unwrap(), + chat_id.to_string(), + self.user_service.clone(), + self.cloud_service.clone(), + )); + self.chats.insert(chat_id.to_string(), chat); Ok(()) } + #[instrument(level = "info", skip_all, err)] pub async fn send_chat_message( &self, chat_id: &str, message: &str, - require_answer: bool, - ) -> Result<(), FlowyError> { - let uid = self.user_service.user_id()?; - let workspace_id = self.user_service.workspace_id()?; - let qa = self - .cloud_service - .send_message(&workspace_id, chat_id, message, require_answer) - .await?; - - let mut messages = Vec::with_capacity(2); - messages.push(qa.question); - if let Some(answer) = qa.answer { - messages.push(answer); + message_type: ChatMessageType, + ) -> Result, FlowyError> { + let chat = self.chats.get(chat_id).as_deref().cloned(); + match chat { + None => Err(FlowyError::internal().with_context("Should call open chat first")), + Some(chat) => { + let messages = chat.send_chat_message(message, message_type).await?; + Ok(messages) + }, } - save_chat_message(self.user_service.sqlite_connection(uid)?, chat_id, messages)?; - Ok(()) } /// Load chat messages for a given `chat_id`. @@ -98,147 +110,23 @@ impl ChatManager { /// /// 4. `after_message_id` and `before_message_id` cannot be specified at the same time. - pub async fn load_chat_messages( + pub async fn load_prev_chat_messages( &self, chat_id: &str, limit: i64, - after_message_id: Option, before_message_id: Option, ) -> Result { - trace!( - "Loading chat messages: chat_id={}, limit={}, after_message_id={:?}, before_message_id={:?}", - chat_id, - limit, - after_message_id, - before_message_id - ); - - let uid = self.user_service.user_id()?; - let messages = self - .load_local_chat_messages(uid, chat_id, limit, after_message_id, before_message_id) - .await?; - - // If the number of messages equals the limit, then no need to load more messages from remote - if messages.len() == limit as usize { - return Ok(ChatMessageListPB { - messages, - has_more: true, - total: 0, - }); - } - - if let Err(err) = self - .load_remote_chat_messages(chat_id, limit, after_message_id, before_message_id) - .await - { - error!("Failed to load remote chat messages: {}", err); + let chat = self.chats.get(chat_id).as_deref().cloned(); + match chat { + None => Err(FlowyError::internal().with_context("Should call open chat first")), + Some(chat) => { + let list = chat + .load_prev_chat_messages(limit, before_message_id) + .await?; + Ok(list) + }, } - Ok(ChatMessageListPB { - messages, - has_more: true, - total: 0, - }) } - - async fn load_local_chat_messages( - &self, - uid: i64, - chat_id: &str, - limit: i64, - after_message_id: Option, - before_message_id: Option, - ) -> Result, FlowyError> { - let conn = self.user_service.sqlite_connection(uid)?; - let records = select_chat_messages(conn, chat_id, limit, after_message_id, before_message_id)?; - let messages = records - .into_iter() - .map(|record| ChatMessagePB { - message_id: record.message_id, - content: record.content, - created_at: record.created_at, - }) - .collect::>(); - - Ok(messages) - } - - #[instrument(level = "info", skip_all, err)] - async fn load_remote_chat_messages( - &self, - chat_id: &str, - limit: i64, - after_message_id: Option, - before_message_id: Option, - ) -> Result<(), FlowyError> { - trace!( - "Loading chat messages from remote: chat_id={}, limit={}, after_message_id={:?}, before_message_id={:?}", - chat_id, - limit, - after_message_id, - before_message_id - ); - - let chat_id = chat_id.to_string(); - let user_service = self.user_service.clone(); - let cloud_service = self.cloud_service.clone(); - tokio::spawn(async move { - let uid = user_service.user_id()?; - let workspace_id = user_service.workspace_id()?; - match _load_remote_chat_messages( - workspace_id, - chat_id.to_string(), - limit, - after_message_id, - before_message_id, - cloud_service, - ) - .await - { - Ok(resp) => { - // Save chat messages to local disk - save_chat_message( - user_service.sqlite_connection(uid)?, - &chat_id, - resp.messages.clone(), - )?; - let pb = ChatMessageListPB::from(resp); - send_notification(&chat_id, ChatNotification::DidLoadChatMessage) - .payload(pb) - .send(); - }, - Err(err) => { - error!("Failed to load chat messages: {}", err); - }, - } - Ok::<(), FlowyError>(()) - }); - Ok(()) - } -} - -async fn _load_remote_chat_messages( - workspace_id: String, - chat_id: String, - limit: i64, - after_message_id: Option, - before_message_id: Option, - cloud_service: Arc, -) -> Result { - if after_message_id.is_some() && before_message_id.is_some() { - warn!("Cannot specify both after_message_id and before_message_id"); - } - let cursor = if after_message_id.is_some() { - MessageCursor::AfterMessageId(after_message_id.unwrap()) - } else if before_message_id.is_some() { - MessageCursor::BeforeMessageId(before_message_id.unwrap()) - } else { - MessageCursor::NextBack - }; - - let resp = cloud_service - .get_chat_messages(&workspace_id, &chat_id, cursor, limit as u64) - .await?; - Ok(resp) } fn save_chat_message( @@ -253,6 +141,8 @@ fn save_chat_message( chat_id: chat_id.to_string(), content: message.content, created_at: message.created_at.timestamp(), + author_type: message.author.author_type as i64, + author_id: message.author.author_id.to_string(), }) .collect::>(); insert_chat_messages(conn, &records)?; diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs index 6e943eee418e8..9ad18b3b02dd7 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs @@ -13,6 +13,8 @@ pub struct ChatMessageTable { pub chat_id: String, pub content: String, pub created_at: i64, + pub author_type: i64, + pub author_id: String, } pub fn insert_chat_messages( @@ -42,7 +44,7 @@ pub fn select_chat_messages( query = query.filter(chat_message_table::message_id.lt(before_message_id)); } query = query - .order(chat_message_table::created_at.asc()) + .order((chat_message_table::message_id.desc(),)) .limit(limit_val); let messages: Vec = query.load::(&mut *conn)?; diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs index 480e57ca6e52b..160a2fa01e326 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs @@ -27,6 +27,7 @@ pub fn read_chat(mut conn: DBConnection, chat_id_val: &str) -> QueryResult QueryResult { diesel::delete(dsl::chat_table.filter(chat_table::chat_id.eq(chat_id_val))).execute(&mut *conn) } diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 094f88b0133d9..81d697b96ea5e 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -15,7 +15,9 @@ use tracing::debug; use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; -use flowy_chat_pub::cloud::{ChatCloudService, MessageCursor, QAChatMessage, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ + ChatCloudService, ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, +}; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, }; @@ -454,12 +456,29 @@ impl ChatCloudService for ServerProvider { }) } - fn send_message( + fn send_system_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let message = message.to_string(); + let server = self.get_server(); + FutureResult::new(async move { + server? + .chat_service() + .send_system_message(&workspace_id, &chat_id, &message) + .await + }) + } + + fn send_user_message( &self, workspace_id: &str, chat_id: &str, message: &str, - require_answer: bool, ) -> FutureResult { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); @@ -468,7 +487,7 @@ impl ChatCloudService for ServerProvider { FutureResult::new(async move { server? .chat_service() - .send_message(&workspace_id, &chat_id, &message, require_answer) + .send_user_message(&workspace_id, &chat_id, &message) .await }) } diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 5a3a9d02df2ce..5543d18973451 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -2,7 +2,7 @@ use crate::af_cloud::AFServer; use client_api::entity::{ CreateChatMessageParams, CreateChatParams, MessageCursor, RepeatedChatMessage, }; -use flowy_chat_pub::cloud::{ChatCloudService, QAChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, QAChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -39,13 +39,12 @@ where }) } - fn send_message( + fn send_system_message( &self, workspace_id: &str, chat_id: &str, message: &str, - require_answer: bool, - ) -> FutureResult { + ) -> FutureResult { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); let message = message.to_string(); @@ -54,7 +53,30 @@ where FutureResult::new(async move { let params = CreateChatMessageParams { content: message, - require_answer, + message_type: ChatMessageType::System, + }; + let message = try_get_client? + .create_chat_message(&workspace_id, &chat_id, params) + .await + .map_err(FlowyError::from)?; + Ok(message.question) + }) + } + + fn send_user_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let message = message.to_string(); + let try_get_client = self.inner.try_get_client(); + FutureResult::new(async move { + let params = CreateChatMessageParams { + content: message, + message_type: ChatMessageType::User, }; let message = try_get_client? .create_chat_message(&workspace_id, &chat_id, params) diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index f4805b8f4a7f4..1ab2418bbd91b 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,5 +1,5 @@ use client_api::entity::{MessageCursor, RepeatedChatMessage}; -use flowy_chat_pub::cloud::{ChatCloudService, QAChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, QAChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -17,12 +17,22 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { }) } - fn send_message( + fn send_system_message( + &self, + workspace_id: &str, + chat_id: &str, + message: &str, + ) -> FutureResult { + FutureResult::new(async move { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) + }) + } + + fn send_user_message( &self, workspace_id: &str, chat_id: &str, message: &str, - require_answer: bool, ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql index c93a283179a66..a46036308ab7b 100644 --- a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql @@ -10,10 +10,12 @@ CREATE TABLE chat_table -- Create table for chat messages CREATE TABLE chat_message_table ( - message_id BIGINT PRIMARY KEY NOT NULL, - chat_id TEXT NOT NULL, - content TEXT NOT NULL, - created_at BIGINT NOT NULL, + message_id BIGINT PRIMARY KEY NOT NULL, + chat_id TEXT NOT NULL, + content TEXT NOT NULL, + created_at BIGINT NOT NULL, + author_type BIGINT NOT NULL, + author_id TEXT NOT NULL, FOREIGN KEY (chat_id) REFERENCES chat_table (chat_id) ON DELETE CASCADE ); diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index eee23311009e2..348f884c2533e 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -6,6 +6,8 @@ diesel::table! { chat_id -> Text, content -> Text, created_at -> BigInt, + author_type -> BigInt, + author_id -> Text, } } From 1362483ed5820d5056f10350e6dd18e273f80917 Mon Sep 17 00:00:00 2001 From: nathan Date: Sat, 25 May 2024 09:30:32 +0800 Subject: [PATCH 12/41] chore: load chat message --- .../lib/plugins/ai_chat/chat_page.dart | 24 ++- frontend/rust-lib/flowy-chat/src/chat.rs | 141 ++++++------------ frontend/rust-lib/flowy-chat/src/manager.rs | 22 +-- .../flowy-chat/src/persistence/chat_sql.rs | 1 + .../flowy-core/src/integrate/trait_impls.rs | 3 +- .../rust-lib/flowy-server/src/default_impl.rs | 14 +- 6 files changed, 73 insertions(+), 132 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 30c5c4a76f53f..11601c301f3ee 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -5,7 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_ui/flutter_chat_ui.dart' - show Chat, DarkChatTheme, InputOptions; + show Chat, DarkChatTheme, Input, InputOptions; // ignore: depend_on_referenced_packages import 'package:flutter_chat_types/flutter_chat_types.dart' as types; @@ -64,7 +64,6 @@ class _AIChatPageState extends State { child: BlocBuilder( builder: (blocContext, state) { return Chat( - inputOptions: inputOption, messages: state.messages, onAttachmentPressed: () {}, onMessageTap: (BuildContext _, types.Message message) { @@ -73,12 +72,18 @@ class _AIChatPageState extends State { .add(ChatEvent.tapMessage(message)); }, onSendPressed: (types.PartialText message) { - blocContext - .read() - .add(ChatEvent.sendMessage(message.text)); + // Do nothing. We use the custom input widget. }, user: _user, theme: chatTheme, + customBottomWidget: Input( + isAttachmentUploading: false, + onAttachmentPressed: () {}, + onSendPressed: (types.PartialText message) { + onSendPressed(blocContext, message); + }, + options: inputOption, + ), customMessageBuilder: (message, {required messageWidth}) { return const SizedBox( width: 100, @@ -99,6 +104,8 @@ class _AIChatPageState extends State { .add(const ChatEvent.loadMessage()); }, ); + } else { + Log.debug("no more messages"); } }, ); @@ -110,4 +117,11 @@ class _AIChatPageState extends State { ), ); } + + void onSendPressed( + BuildContext context, + types.PartialText message, + ) { + context.read().add(ChatEvent.sendMessage(message.text)); + } } diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index 588fde9bfbfd2..ae27559bf1ec9 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -4,16 +4,14 @@ use crate::notification::{send_notification, ChatNotification}; use crate::persistence::{ insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, }; -use flowy_chat_pub::cloud::{ - ChatCloudService, ChatMessage, ChatMessageType, MessageCursor, RepeatedChatMessage, -}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, MessageCursor}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; -use std::sync::atomic::AtomicBool; + use std::sync::Arc; use tokio::sync::RwLock; -use tracing::{error, instrument, trace, warn}; +use tracing::{error, instrument, trace}; enum PrevMessageState { HasMore, @@ -116,19 +114,8 @@ impl Chat { limit: i64, before_message_id: Option, ) -> Result { - if matches!( - *self.prev_message_state.read().await, - PrevMessageState::NoMore - ) { - return Ok(ChatMessageListPB { - messages: vec![], - has_more: false, - total: 0, - }); - } - trace!( - "Loading chat messages: chat_id={}, limit={}, before_message_id={:?}", + "Loading old messages: chat_id={}, limit={}, before_message_id={:?}", self.chat_id, limit, before_message_id @@ -147,75 +134,34 @@ impl Chat { }); } - self - .load_remote_prev_chat_messages(limit, before_message_id) - .await; - Ok(ChatMessageListPB { - messages, - has_more, - total: 0, - }) - } - - #[instrument(level = "info", skip_all, err)] - async fn load_remote_prev_chat_messages(&self, limit: i64, before_message_id: Option) { if matches!( *self.prev_message_state.read().await, - PrevMessageState::Loading + PrevMessageState::HasMore ) { - return; - } - - let workspace_id = self.user_service.workspace_id()?; - let chat_id = self.chat_id.clone(); - let cloud_service = self.cloud_service.clone(); - let user_service = self.user_service.clone(); - let uid = self.uid; - let load_prev_message_state = self.prev_message_state.clone(); - - tokio::spawn(async move { - // - let cursor = if before_message_id.is_some() { - MessageCursor::BeforeMessageId(before_message_id.unwrap()) - } else { - MessageCursor::NextBack - }; - match cloud_service - .get_chat_messages(&workspace_id, &chat_id, cursor, limit as u64) + *self.prev_message_state.write().await = PrevMessageState::Loading; + if let Err(err) = self + .load_remote_chat_messages(limit, before_message_id, None) .await { - Ok(resp) => { - // Save chat messages to local disk - save_chat_message( - user_service.sqlite_connection(uid)?, - &chat_id, - resp.messages.clone(), - )?; - - if resp.has_more { - *load_prev_message_state.write().await = PrevMessageState::HasMore; - } else { - *load_prev_message_state.write().await = PrevMessageState::NoMore; - } - - let pb = ChatMessageListPB::from(resp); - send_notification(&chat_id, ChatNotification::DidLoadChatMessage) - .payload(pb) - .send(); - }, - Err(err) => error!("Failed to load chat messages: {}", err), + error!("Failed to load chat messages: {}", err); } - Ok(()) - }); + } + + Ok(ChatMessageListPB { + messages, + has_more, + total: 0, + }) } + #[allow(dead_code)] pub async fn load_after_chat_messages( &self, limit: i64, after_message_id: Option, ) -> Result { trace!( - "Loading chat messages: chat_id={}, limit={}, after_message_id={:?}", + "Loading new messages: chat_id={}, limit={}, after_message_id={:?}", self.chat_id, limit, after_message_id, @@ -235,7 +181,7 @@ impl Chat { } let _ = self - .load_remote_after_chat_messages(limit, after_message_id) + .load_remote_chat_messages(limit, None, after_message_id) .await; Ok(ChatMessageListPB { messages, @@ -244,30 +190,33 @@ impl Chat { }) } - async fn load_remote_after_chat_messages( + async fn load_remote_chat_messages( &self, limit: i64, + before_message_id: Option, after_message_id: Option, ) -> FlowyResult<()> { - if matches!( - *self.prev_message_state.read().await, - PrevMessageState::Loading - ) { - return; - } + trace!( + "Loading chat messages from remote: chat_id={}, limit={}, before_message_id={:?}, after_message_id={:?}", + self.chat_id, + limit, + before_message_id, + after_message_id + ); let workspace_id = self.user_service.workspace_id()?; let chat_id = self.chat_id.clone(); let cloud_service = self.cloud_service.clone(); let user_service = self.user_service.clone(); let uid = self.uid; + let prev_message_state = self.prev_message_state.clone(); tokio::spawn(async move { - let cursor = if after_message_id.is_some() { - MessageCursor::AfterMessageId(after_message_id.unwrap()) - } else { - MessageCursor::NextBack + let cursor = match (before_message_id, after_message_id) { + (Some(bid), _) => MessageCursor::BeforeMessageId(bid), + (_, Some(aid)) => MessageCursor::AfterMessageId(aid), + _ => MessageCursor::NextBack, }; match cloud_service - .get_chat_messages(&workspace_id, &chat_id, cursor, limit as u64) + .get_chat_messages(&workspace_id, &chat_id, cursor.clone(), limit as u64) .await { Ok(resp) => { @@ -278,6 +227,14 @@ impl Chat { resp.messages.clone(), )?; + if matches!(cursor, MessageCursor::BeforeMessageId(_)) { + if resp.has_more { + *prev_message_state.write().await = PrevMessageState::HasMore; + } else { + *prev_message_state.write().await = PrevMessageState::NoMore; + } + } + let pb = ChatMessageListPB::from(resp); send_notification(&chat_id, ChatNotification::DidLoadChatMessage) .payload(pb) @@ -285,8 +242,9 @@ impl Chat { }, Err(err) => error!("Failed to load chat messages: {}", err), } - Ok(()) + Ok::<(), FlowyError>(()) }); + Ok(()) } async fn load_local_chat_messages( @@ -337,14 +295,3 @@ fn save_chat_message( insert_chat_messages(conn, &records)?; Ok(()) } - -fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { - let row = ChatTable { - chat_id: chat_id.to_string(), - created_at: timestamp(), - name: "".to_string(), - }; - - insert_chat(conn, &row)?; - Ok(()) -} diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 716b604b49192..baaa10e2497bc 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -7,7 +7,7 @@ use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; use std::sync::Arc; -use tracing::{error, instrument, trace, warn}; +use tracing::instrument; pub trait ChatUserService: Send + Sync + 'static { fn user_id(&self) -> Result; @@ -129,26 +129,6 @@ impl ChatManager { } } -fn save_chat_message( - conn: DBConnection, - chat_id: &str, - messages: Vec, -) -> FlowyResult<()> { - let records = messages - .into_iter() - .map(|message| ChatMessageTable { - message_id: message.message_id, - chat_id: chat_id.to_string(), - content: message.content, - created_at: message.created_at.timestamp(), - author_type: message.author.author_type as i64, - author_id: message.author.author_id.to_string(), - }) - .collect::>(); - insert_chat_messages(conn, &records)?; - Ok(()) -} - fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { let row = ChatTable { chat_id: chat_id.to_string(), diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs index 160a2fa01e326..85b5fea13da00 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs @@ -20,6 +20,7 @@ pub fn insert_chat(mut conn: DBConnection, new_chat: &ChatTable) -> QueryResult< .execute(&mut *conn) } +#[allow(dead_code)] pub fn read_chat(mut conn: DBConnection, chat_id_val: &str) -> QueryResult { let row = dsl::chat_table .filter(chat_table::chat_id.eq(chat_id_val)) diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 81d697b96ea5e..9ddbc7ed547d3 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -5,7 +5,6 @@ use anyhow::Error; use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin}; use collab::core::origin::{CollabClient, CollabOrigin}; -// use collab::core::origin::{CollabClient, CollabOrigin}; use collab::preclude::CollabPlugin; use collab_entity::CollabType; use collab_plugins::cloud_storage::postgres::SupabaseDBPlugin; @@ -16,7 +15,7 @@ use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; use flowy_chat_pub::cloud::{ - ChatCloudService, ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, + ChatCloudService, ChatMessage, MessageCursor, QAChatMessage, RepeatedChatMessage, }; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index 1ab2418bbd91b..b48a3b9cdf4fa 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,5 +1,5 @@ use client_api::entity::{MessageCursor, RepeatedChatMessage}; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, QAChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, QAChatMessage}; use flowy_error::FlowyError; use lib_infra::future::FutureResult; @@ -19,9 +19,9 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { fn send_system_message( &self, - workspace_id: &str, - chat_id: &str, - message: &str, + _workspace_id: &str, + _chat_id: &str, + _message: &str, ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) @@ -30,9 +30,9 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { fn send_user_message( &self, - workspace_id: &str, - chat_id: &str, - message: &str, + _workspace_id: &str, + _chat_id: &str, + _message: &str, ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) From 6032fba58f61e34e0eb80badbbb0500a3ee79c54 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 26 May 2024 20:23:49 +0800 Subject: [PATCH 13/41] chore: chat ui --- .../ai_chat/application/chat_bloc.dart | 126 +++++-- .../application/chat_message_listener.dart | 84 +++++ .../application/chat_notification.dart | 45 +++ .../lib/plugins/ai_chat/chat_page.dart | 26 +- .../ai_chat/presentation/chat_input.dart | 321 ++++++++++++++++++ frontend/appflowy_tauri/src-tauri/Cargo.lock | 31 +- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 42 ++- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 29 +- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 47 ++- frontend/rust-lib/Cargo.toml | 2 +- frontend/rust-lib/flowy-chat-pub/Cargo.toml | 3 +- frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 17 +- frontend/rust-lib/flowy-chat/Cargo.toml | 1 + frontend/rust-lib/flowy-chat/src/chat.rs | 160 ++++++--- frontend/rust-lib/flowy-chat/src/entities.rs | 16 + .../rust-lib/flowy-chat/src/event_handler.rs | 7 +- frontend/rust-lib/flowy-chat/src/event_map.rs | 2 +- frontend/rust-lib/flowy-chat/src/manager.rs | 10 +- .../rust-lib/flowy-chat/src/notification.rs | 6 + .../flowy-core/src/integrate/trait_impls.rs | 40 +-- .../flowy-server/src/af_cloud/impls/chat.rs | 54 +-- .../rust-lib/flowy-server/src/default_impl.rs | 26 +- 25 files changed, 838 insertions(+), 263 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_notification.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 5f366deb760e2..f1cb2fc9c968a 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -9,6 +9,8 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; +import 'chat_message_listener.dart'; + part 'chat_bloc.freezed.dart'; const loadingMessageId = 'chat_message_loading_id'; @@ -17,15 +19,31 @@ class ChatBloc extends Bloc { ChatBloc({ required ViewPB view, required UserProfilePB userProfile, - }) : super( - ChatState.initial( - view, - userProfile, - ), + }) : listener = ChatMessageListener(chatId: view.id), + super( + ChatState.initial(view, userProfile), ) { _dispatch(); + + listener.start( + chatMessageCallback: _handleChatMessage, + chatErrorMessageCallback: _handleErrorMessage, + finishAnswerQuestionCallback: () { + if (!isClosed) { + add(const ChatEvent.didFinishStreamingChatMessage()); + } + }, + ); } + final ChatMessageListener listener; + + @override + Future close() { + listener.stop(); + return super.close(); + } + void _dispatch() { on( (event, emit) async { @@ -51,26 +69,11 @@ class ChatBloc extends Bloc { ); } }, - sendMessage: (String message) { - _handleSentMessage(message, emit); - final loadingMessage = CustomMessage( - author: User(id: state.userProfile.id.toString()), - id: loadingMessageId, - ); - final List allMessages = List.from(state.messages); - allMessages.insert(0, loadingMessage); - emit( - state.copyWith( - messages: allMessages, - loadingStatus: const LoadingState.loading(), - ), - ); - }, - didReceiveMessages: (List messages) { + didLoadMessages: (List messages) { final List allMessages = List.from(state.messages); allMessages .removeWhere((element) => element.id == loadingMessageId); - allMessages.addAll(messages); + allMessages.insertAll(0, messages); emit( state.copyWith( messages: allMessages, @@ -91,11 +94,39 @@ class ChatBloc extends Bloc { ); }, tapMessage: (Message message) {}, + streamingChatMessage: (List messages) { + final List allMessages = List.from(state.messages); + allMessages + .removeWhere((element) => element.id == loadingMessageId); + allMessages.insertAll(0, messages); + emit(state.copyWith(messages: allMessages)); + }, + didFinishStreamingChatMessage: () { + emit( + state.copyWith( + answerQuestionStatus: const LoadingState.finish(), + ), + ); + }, + sendMessage: (String message) async { + await _handleSentMessage(message, emit); + final loadingMessage = + _loaddingMessage(state.userProfile.id.toString()); + final List allMessages = List.from(state.messages); + allMessages.insert(0, loadingMessage); + emit( + state.copyWith( + messages: allMessages, + answerQuestionStatus: const LoadingState.loading(), + ), + ); + }, ); }, ); } + void _loadMessage( Int64? beforeMessageId, ) { @@ -109,12 +140,11 @@ class ChatBloc extends Bloc { (list) { final messages = list.messages.map((m) => _fromChatMessage(m)).toList(); - if (!isClosed) { if (beforeMessageId != null) { add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); } else { - add(ChatEvent.didReceiveMessages(messages)); + add(ChatEvent.didLoadMessages(messages)); } } }, @@ -134,17 +164,35 @@ class ChatBloc extends Bloc { message: message, messageType: ChatMessageTypePB.User, ); - final result = await ChatEventSendMessage(payload).send(); - result.fold((repeatedMessage) { - final messages = - repeatedMessage.items.map((m) => _fromChatMessage(m)).toList(); - if (!isClosed) { - add(ChatEvent.didReceiveMessages(messages)); + await ChatEventSendMessage(payload).send(); + } + + void _handleChatMessage(ChatMessagePB pb) { + if (!isClosed) { + final message = _fromChatMessage(pb); + final List messages = []; + if (pb.hasFollowing) { + messages.addAll([_loaddingMessage(0.toString()), message]); + } else { + messages.add(message); } - }, (err) { - Log.error("Failed to send message: $err"); - }); + add(ChatEvent.streamingChatMessage(messages)); + } } + + void _handleErrorMessage(ChatMessageErrorPB message) { + if (!isClosed) { + Log.error("Received error: $message"); + } + } +} + +Message _loaddingMessage(String id) { + final loadingMessage = CustomMessage( + author: User(id: id), + id: loadingMessageId, + ); + return loadingMessage; } Message _fromChatMessage(ChatMessagePB message) { @@ -161,10 +209,16 @@ class ChatEvent with _$ChatEvent { const factory ChatEvent.sendMessage(String message) = _SendMessage; const factory ChatEvent.tapMessage(Message message) = _TapMessage; const factory ChatEvent.loadMessage() = _LoadMessage; - const factory ChatEvent.didReceiveMessages(List messages) = + const factory ChatEvent.didLoadMessages(List messages) = _DidLoadMessages; + const factory ChatEvent.streamingChatMessage(List messages) = + _DidStreamMessage; + const factory ChatEvent.didFinishStreamingChatMessage() = + _FinishStreamingMessage; const factory ChatEvent.didLoadPreviousMessages( - List messages, bool hasMore,) = _DidLoadPreviousMessages; + List messages, + bool hasMore, + ) = _DidLoadPreviousMessages; } @freezed @@ -175,6 +229,7 @@ class ChatState with _$ChatState { required UserProfilePB userProfile, required LoadingState loadingStatus, required LoadingState loadingPreviousStatus, + required LoadingState answerQuestionStatus, required bool hasMore, }) = _ChatState; @@ -188,6 +243,7 @@ class ChatState with _$ChatState { userProfile: userProfile, loadingStatus: const LoadingState.finish(), loadingPreviousStatus: const LoadingState.finish(), + answerQuestionStatus: const LoadingState.finish(), hasMore: true, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart new file mode 100644 index 0000000000000..aa7ceb949afdd --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart @@ -0,0 +1,84 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-chat/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; +import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; + +import 'chat_notification.dart'; + +typedef ChatMessageCallback = void Function( + ChatMessagePB message, +); + +typedef ChatErrorMessageCallback = void Function( + ChatMessageErrorPB message, +); + +class ChatMessageListener { + ChatMessageListener({ + required this.chatId, + }) { + _parser = ChatNotificationParser( + id: chatId, + callback: _callback, + ); + _subscription = RustStreamReceiver.listen( + (observable) => _parser?.parse(observable), + ); + } + + final String chatId; + StreamSubscription? _subscription; + ChatNotificationParser? _parser; + ChatMessageCallback? chatMessageCallback; + ChatErrorMessageCallback? chatErrorMessageCallback; + void Function()? finishAnswerQuestionCallback; + + void start({ + ChatMessageCallback? chatMessageCallback, + ChatErrorMessageCallback? chatErrorMessageCallback, + void Function()? finishAnswerQuestionCallback, + }) { + this.chatMessageCallback = chatMessageCallback; + this.chatErrorMessageCallback = chatErrorMessageCallback; + this.finishAnswerQuestionCallback = finishAnswerQuestionCallback; + } + + void _callback( + ChatNotification ty, + FlowyResult result, + ) { + switch (ty) { + case ChatNotification.DidReceiveChatMessage: + result.map( + (r) { + final value = ChatMessagePB.fromBuffer(r); + chatMessageCallback?.call(value); + }, + ); + break; + case ChatNotification.ChatMessageError: + result.map( + (r) { + final value = ChatMessageErrorPB.fromBuffer(r); + chatErrorMessageCallback?.call(value); + }, + ); + break; + case ChatNotification.FinishAnswerQuestion: + finishAnswerQuestionCallback?.call(); + break; + default: + break; + } + } + + Future stop() async { + await _subscription?.cancel(); + _subscription = null; + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_notification.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_notification.dart new file mode 100644 index 0000000000000..194748858b466 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_notification.dart @@ -0,0 +1,45 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:appflowy/core/notification/notification_helper.dart'; +import 'package:appflowy_backend/protobuf/flowy-chat/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; +import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; + +class ChatNotificationParser + extends NotificationParser { + ChatNotificationParser({ + super.id, + required super.callback, + }) : super( + tyParser: (ty, source) => + source == "Chat" ? ChatNotification.valueOf(ty) : null, + errorParser: (bytes) => FlowyError.fromBuffer(bytes), + ); +} + +typedef ChatNotificationHandler = Function( + ChatNotification ty, + FlowyResult result, +); + +class ChatNotificationListener { + ChatNotificationListener({ + required String objectId, + required ChatNotificationHandler handler, + }) : _parser = ChatNotificationParser(id: objectId, callback: handler) { + _subscription = + RustStreamReceiver.listen((observable) => _parser?.parse(observable)); + } + + ChatNotificationParser? _parser; + StreamSubscription? _subscription; + + Future stop() async { + _parser = null; + await _subscription?.cancel(); + _subscription = null; + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 11601c301f3ee..9a27eb76bc23a 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -4,8 +4,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_chat_ui/flutter_chat_ui.dart' - show Chat, DarkChatTheme, Input, InputOptions; +import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat, DarkChatTheme; // ignore: depend_on_referenced_packages import 'package:flutter_chat_types/flutter_chat_types.dart' as types; @@ -36,7 +35,6 @@ class _AIChatPageState extends State { late types.User _user; final chatTheme = const DarkChatTheme(); - var inputOption = const InputOptions(); @override Widget build(BuildContext context) { @@ -53,14 +51,7 @@ class _AIChatPageState extends State { child: BlocListener( listenWhen: (previous, current) => previous.loadingStatus != current.loadingStatus, - listener: (context, state) { - // inputOption = InputOptions( - // enabled: state.loadingStatus.when( - // loading: () => false, - // finish: () => true, - // ), - // ); - }, + listener: (context, state) {}, child: BlocBuilder( builder: (blocContext, state) { return Chat( @@ -73,17 +64,10 @@ class _AIChatPageState extends State { }, onSendPressed: (types.PartialText message) { // Do nothing. We use the custom input widget. + onSendPressed(blocContext, message); }, user: _user, theme: chatTheme, - customBottomWidget: Input( - isAttachmentUploading: false, - onAttachmentPressed: () {}, - onSendPressed: (types.PartialText message) { - onSendPressed(blocContext, message); - }, - options: inputOption, - ), customMessageBuilder: (message, {required messageWidth}) { return const SizedBox( width: 100, @@ -94,9 +78,7 @@ class _AIChatPageState extends State { onEndReached: () async { if (state.hasMore) { state.loadingPreviousStatus.when( - loading: () { - Log.debug("loading"); - }, + loading: () => Log.debug("loading"), finish: () { Log.debug("loading more messages"); blocContext diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart new file mode 100644 index 0000000000000..e842a9a3d66e8 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -0,0 +1,321 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart' as types; +import 'package:flutter_chat_ui/flutter_chat_ui.dart'; + +/// A class that represents bottom bar widget with a text field, attachment and +/// send buttons inside. By default hides send button when text field is empty. +class ChatInput extends StatefulWidget { + /// Creates [ChatInput] widget. + const ChatInput({ + super.key, + this.isAttachmentUploading, + this.onAttachmentPressed, + required this.onSendPressed, + this.options = const InputOptions(), + }); + + /// Whether attachment is uploading. Will replace attachment button with a + /// [CircularProgressIndicator]. Since we don't have libraries for + /// managing media in dependencies we have no way of knowing if + /// something is uploading so you need to set this manually. + final bool? isAttachmentUploading; + + /// See [AttachmentButton.onPressed]. + final VoidCallback? onAttachmentPressed; + + /// Will be called on [SendButton] tap. Has [types.PartialText] which can + /// be transformed to [types.TextMessage] and added to the messages list. + final void Function(types.PartialText) onSendPressed; + + /// Customisation options for the [ChatInput]. + final InputOptions options; + + @override + State createState() => _ChatInputState(); +} + +/// [ChatInput] widget state. +class _ChatInputState extends State { + late final _inputFocusNode = FocusNode( + onKeyEvent: (node, event) { + if (event.physicalKey == PhysicalKeyboardKey.enter && + !HardwareKeyboard.instance.physicalKeysPressed.any( + (el) => { + PhysicalKeyboardKey.shiftLeft, + PhysicalKeyboardKey.shiftRight, + }.contains(el), + )) { + if (kIsWeb && _textController.value.isComposingRangeValid) { + return KeyEventResult.ignored; + } + if (event is KeyDownEvent) { + _handleSendPressed(); + } + return KeyEventResult.handled; + } else { + return KeyEventResult.ignored; + } + }, + ); + + bool _sendButtonVisible = false; + late TextEditingController _textController; + + @override + void initState() { + super.initState(); + + _textController = + widget.options.textEditingController ?? InputTextFieldController(); + _handleSendButtonVisibilityModeChange(); + } + + void _handleSendButtonVisibilityModeChange() { + _textController.removeListener(_handleTextControllerChange); + if (widget.options.sendButtonVisibilityMode == + SendButtonVisibilityMode.hidden) { + _sendButtonVisible = false; + } else if (widget.options.sendButtonVisibilityMode == + SendButtonVisibilityMode.editing) { + _sendButtonVisible = _textController.text.trim() != ''; + _textController.addListener(_handleTextControllerChange); + } else { + _sendButtonVisible = true; + } + } + + void _handleSendPressed() { + final trimmedText = _textController.text.trim(); + if (trimmedText != '') { + final partialText = types.PartialText(text: trimmedText); + widget.onSendPressed(partialText); + + if (widget.options.inputClearMode == InputClearMode.always) { + _textController.clear(); + } + } + } + + void _handleTextControllerChange() { + if (_textController.value.isComposingRangeValid) { + return; + } + setState(() { + _sendButtonVisible = _textController.text.trim() != ''; + }); + } + + Widget _inputBuilder() { + final query = MediaQuery.of(context); + final buttonPadding = InheritedChatTheme.of(context) + .theme + .inputPadding + .copyWith(left: 16, right: 16); + final safeAreaInsets = isMobile + ? EdgeInsets.fromLTRB( + query.padding.left, + 0, + query.padding.right, + query.viewInsets.bottom + query.padding.bottom, + ) + : EdgeInsets.zero; + final textPadding = InheritedChatTheme.of(context) + .theme + .inputPadding + .copyWith(left: 0, right: 0) + .add( + EdgeInsets.fromLTRB( + widget.onAttachmentPressed != null ? 0 : 24, + 0, + _sendButtonVisible ? 0 : 24, + 0, + ), + ); + + return Focus( + autofocus: !widget.options.autofocus, + child: Padding( + padding: InheritedChatTheme.of(context).theme.inputMargin, + child: Material( + borderRadius: InheritedChatTheme.of(context).theme.inputBorderRadius, + color: InheritedChatTheme.of(context).theme.inputBackgroundColor, + surfaceTintColor: + InheritedChatTheme.of(context).theme.inputSurfaceTintColor, + elevation: InheritedChatTheme.of(context).theme.inputElevation, + child: Container( + decoration: + InheritedChatTheme.of(context).theme.inputContainerDecoration, + padding: safeAreaInsets, + child: Row( + textDirection: TextDirection.ltr, + children: [ + if (widget.onAttachmentPressed != null) + AttachmentButton( + isLoading: widget.isAttachmentUploading ?? false, + onPressed: widget.onAttachmentPressed, + padding: buttonPadding, + ), + Expanded( + child: Padding( + padding: textPadding, + child: TextField( + enabled: widget.options.enabled, + autocorrect: widget.options.autocorrect, + autofocus: widget.options.autofocus, + enableSuggestions: widget.options.enableSuggestions, + controller: _textController, + cursorColor: InheritedChatTheme.of(context) + .theme + .inputTextCursorColor, + decoration: InheritedChatTheme.of(context) + .theme + .inputTextDecoration + .copyWith( + hintStyle: InheritedChatTheme.of(context) + .theme + .inputTextStyle + .copyWith( + color: InheritedChatTheme.of(context) + .theme + .inputTextColor + .withOpacity(0.5), + ), + hintText: "", + ), + focusNode: _inputFocusNode, + keyboardType: widget.options.keyboardType, + maxLines: 5, + minLines: 1, + onChanged: widget.options.onTextChanged, + onTap: widget.options.onTextFieldTap, + style: InheritedChatTheme.of(context) + .theme + .inputTextStyle + .copyWith( + color: InheritedChatTheme.of(context) + .theme + .inputTextColor, + ), + textCapitalization: TextCapitalization.sentences, + ), + ), + ), + ConstrainedBox( + constraints: BoxConstraints( + minHeight: buttonPadding.bottom + buttonPadding.top + 24, + ), + child: Visibility( + visible: _sendButtonVisible, + child: SendButton( + onPressed: _handleSendPressed, + padding: buttonPadding, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + @override + void didUpdateWidget(covariant ChatInput oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.options.sendButtonVisibilityMode != + oldWidget.options.sendButtonVisibilityMode) { + _handleSendButtonVisibilityModeChange(); + } + } + + @override + void dispose() { + _inputFocusNode.dispose(); + _textController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) => GestureDetector( + onTap: () => _inputFocusNode.requestFocus(), + child: _inputBuilder(), + ); +} + +@immutable +class InputOptions { + const InputOptions({ + this.inputClearMode = InputClearMode.always, + this.keyboardType = TextInputType.multiline, + this.onTextChanged, + this.onTextFieldTap, + this.sendButtonVisibilityMode = SendButtonVisibilityMode.editing, + this.textEditingController, + this.autocorrect = true, + this.autofocus = false, + this.enableSuggestions = true, + this.enabled = true, + }); + + /// Controls the [ChatInput] clear behavior. Defaults to [InputClearMode.always]. + final InputClearMode inputClearMode; + + /// Controls the [ChatInput] keyboard type. Defaults to [TextInputType.multiline]. + final TextInputType keyboardType; + + /// Will be called whenever the text inside [TextField] changes. + final void Function(String)? onTextChanged; + + /// Will be called on [TextField] tap. + final VoidCallback? onTextFieldTap; + + /// Controls the visibility behavior of the [SendButton] based on the + /// [TextField] state inside the [ChatInput] widget. + /// Defaults to [SendButtonVisibilityMode.editing]. + final SendButtonVisibilityMode sendButtonVisibilityMode; + + /// Custom [TextEditingController]. If not provided, defaults to the + /// [InputTextFieldController], which extends [TextEditingController] and has + /// additional fatures like markdown support. If you want to keep additional + /// features but still need some methods from the default [TextEditingController], + /// you can create your own [InputTextFieldController] (imported from this lib) + /// and pass it here. + final TextEditingController? textEditingController; + + /// Controls the [TextInput] autocorrect behavior. Defaults to [true]. + final bool autocorrect; + + /// Whether [TextInput] should have focus. Defaults to [false]. + final bool autofocus; + + /// Controls the [TextInput] enableSuggestions behavior. Defaults to [true]. + final bool enableSuggestions; + + /// Controls the [TextInput] enabled behavior. Defaults to [true]. + final bool enabled; +} + +class InheritedChatTheme extends InheritedWidget { + /// Creates [InheritedWidget] from a provided [ChatTheme] class. + const InheritedChatTheme({ + super.key, + required this.theme, + required super.child, + }); + + static InheritedChatTheme of(BuildContext context) => + context.dependOnInheritedWidgetOfExactType()!; + + /// Represents chat theme. + final ChatTheme theme; + + @override + bool updateShouldNotify(InheritedChatTheme oldWidget) => + theme.hashCode != oldWidget.theme.hashCode; +} + +final isMobile = defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS; diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index be1bbf13c7c84..05de31462f34f 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "serde", @@ -754,7 +754,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "again", "anyhow", @@ -801,7 +801,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "futures-channel", "futures-util", @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -1065,7 +1065,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "async-trait", @@ -1311,7 +1311,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1422,7 +1422,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -1821,6 +1821,7 @@ dependencies = [ "flowy-error", "flowy-notification", "flowy-sqlite", + "futures", "lib-dispatch", "lib-infra", "protobuf", @@ -1837,6 +1838,7 @@ version = "0.1.0" dependencies = [ "client-api", "flowy-error", + "futures", "lib-infra", ] @@ -2826,7 +2828,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "futures-util", @@ -2843,7 +2845,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -3275,7 +3277,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "reqwest", @@ -4778,7 +4780,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4799,7 +4801,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", @@ -5763,7 +5765,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -5771,6 +5773,7 @@ dependencies = [ "chrono", "collab-entity", "database-entity", + "futures", "gotrue-entity", "reqwest", "serde", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 3ffcdfc3a12a5..d03cc5f5f890f 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index df9d42590596b..3e00e40b16b7b 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "serde", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "again", "anyhow", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "async-trait", @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1024,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -1260,6 +1260,7 @@ version = "0.1.0" dependencies = [ "client-api", "flowy-error", + "futures", "lib-infra", ] @@ -1811,7 +1812,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "futures-util", @@ -1828,7 +1829,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -2129,7 +2130,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "reqwest", @@ -2813,7 +2814,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2833,6 +2834,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2900,6 +2902,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3755,7 +3770,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -3763,6 +3778,7 @@ dependencies = [ "chrono", "collab-entity", "database-entity", + "futures", "gotrue-entity", "reqwest", "serde", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 89f34f680f890..574c88be39436 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 3cfce89bb1934..334bae991de1b 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "serde", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "again", "anyhow", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "futures-channel", "futures-util", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -1047,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "async-trait", @@ -1297,7 +1297,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1408,7 +1408,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -2899,7 +2899,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "futures-util", @@ -2916,7 +2916,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -3353,7 +3353,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "reqwest", @@ -4858,7 +4858,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4879,7 +4879,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.55", @@ -5857,7 +5857,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -5865,6 +5865,7 @@ dependencies = [ "chrono", "collab-entity", "database-entity", + "futures", "gotrue-entity", "reqwest", "serde", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 987f12a6bc956..6f840f85395fd 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index abed92b55059e..bdbacaadf1f2a 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "serde", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "again", "anyhow", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "bincode", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "async-trait", @@ -1162,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1261,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -1653,6 +1653,7 @@ dependencies = [ "flowy-error", "flowy-notification", "flowy-sqlite", + "futures", "lib-dispatch", "lib-infra", "protobuf", @@ -1669,6 +1670,7 @@ version = "0.1.0" dependencies = [ "client-api", "flowy-error", + "futures", "lib-infra", ] @@ -2509,7 +2511,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "futures-util", @@ -2526,7 +2528,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -2891,7 +2893,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "reqwest", @@ -3766,7 +3768,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3786,6 +3788,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3853,6 +3856,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.47", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -4056,7 +4072,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4077,7 +4093,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", @@ -4974,7 +4990,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f#a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" dependencies = [ "anyhow", "app-error", @@ -4982,6 +4998,7 @@ dependencies = [ "chrono", "collab-entity", "database-entity", + "futures", "gotrue-entity", "reqwest", "serde", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 1db3bb202eb57..bf08c02160692 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a1bc37f959c8bdfdd7e4fbf23bb893c50e3c3f5f" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/flowy-chat-pub/Cargo.toml b/frontend/rust-lib/flowy-chat-pub/Cargo.toml index 9ec2b18b1b64c..0cfdae0ec9dae 100644 --- a/frontend/rust-lib/flowy-chat-pub/Cargo.toml +++ b/frontend/rust-lib/flowy-chat-pub/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] lib-infra = { workspace = true } flowy-error = { workspace = true } -client-api = { workspace = true } \ No newline at end of file +client-api = { workspace = true } +futures.workspace = true \ No newline at end of file diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index bb0b799cfb49e..36ca710d321ee 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,9 +1,14 @@ pub use client_api::entity::{ ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, }; +use client_api::error::AppResponseError; use flowy_error::FlowyError; +use futures::stream::BoxStream; +use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; +pub type ChatMessageStream = BoxStream<'static, Result>; +#[async_trait] pub trait ChatCloudService: Send + Sync + 'static { fn create_chat( &self, @@ -12,19 +17,13 @@ pub trait ChatCloudService: Send + Sync + 'static { chat_id: &str, ) -> FutureResult<(), FlowyError>; - fn send_system_message( + async fn send_chat_message( &self, workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult; - - fn send_user_message( - &self, - workspace_id: &str, - chat_id: &str, - message: &str, - ) -> FutureResult; + message_type: ChatMessageType, + ) -> Result; fn get_chat_messages( &self, diff --git a/frontend/rust-lib/flowy-chat/Cargo.toml b/frontend/rust-lib/flowy-chat/Cargo.toml index 331520c54c946..e1a7175442d0a 100644 --- a/frontend/rust-lib/flowy-chat/Cargo.toml +++ b/frontend/rust-lib/flowy-chat/Cargo.toml @@ -24,6 +24,7 @@ flowy-chat-pub.workspace = true dashmap = "5.5" flowy-sqlite = { workspace = true } tokio.workspace = true +futures.workspace = true [build-dependencies] flowy-codegen.workspace = true diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index ae27559bf1ec9..b1b7724e4e539 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -1,13 +1,17 @@ -use crate::entities::{ChatMessageListPB, ChatMessagePB}; +use crate::entities::{ChatMessageErrorPB, ChatMessageListPB, ChatMessagePB}; use crate::manager::ChatUserService; use crate::notification::{send_notification, ChatNotification}; use crate::persistence::{ insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, }; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, MessageCursor}; +use flowy_chat_pub::cloud::{ + ChatCloudService, ChatMessage, ChatMessageStream, ChatMessageType, MessageCursor, +}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; +use futures::StreamExt; use lib_infra::util::timestamp; +use std::future::Future; use std::sync::Arc; use tokio::sync::RwLock; @@ -50,49 +54,20 @@ impl Chat { &self, message: &str, message_type: ChatMessageType, - ) -> Result, FlowyError> { - let _uid = self.user_service.user_id()?; + ) -> Result<(), FlowyError> { + let uid = self.user_service.user_id()?; let workspace_id = self.user_service.workspace_id()?; - let mut messages = Vec::with_capacity(2); - - trace!( - "Sending chat message: chat_id={}, message={}, type={:?}", - self.chat_id, - message, - message_type - ); - match message_type { - ChatMessageType::System => { - let message = self - .cloud_service - .send_system_message(&workspace_id, &self.chat_id, message) - .await?; - messages.push(message); - }, - ChatMessageType::User => { - let qa = self - .cloud_service - .send_user_message(&workspace_id, &self.chat_id, message) - .await?; - messages.push(qa.question); - if let Some(answer) = qa.answer { - messages.push(answer); - } - }, - }; - - trace!( - "Saving chat messages to local disk: chat_id={}, messages:{:?}", - self.chat_id, - messages + stream_send_chat_messages( + uid, + workspace_id, + self.chat_id.clone(), + message.to_string(), + message_type, + self.cloud_service.clone(), + self.user_service.clone(), ); - save_chat_message( - self.user_service.sqlite_connection(self.uid)?, - &self.chat_id, - messages.clone(), - )?; - Ok(messages) + Ok(()) } /// Load chat messages for a given `chat_id`. @@ -269,6 +244,7 @@ impl Chat { created_at: record.created_at, author_type: record.author_type, author_id: record.author_id, + has_following: false, }) .collect::>(); @@ -276,6 +252,106 @@ impl Chat { } } +fn stream_send_chat_messages( + uid: i64, + workspace_id: String, + chat_id: String, + message_content: String, + message_type: ChatMessageType, + cloud_service: Arc, + user_service: Arc, +) { + tokio::spawn(async move { + trace!( + "Sending chat message: chat_id={}, message={}, type={:?}", + chat_id, + message_content, + message_type + ); + + let mut messages = Vec::with_capacity(2); + let stream_result = cloud_service + .send_chat_message(&workspace_id, &chat_id, &message_content, message_type) + .await; + + let mut has_following = true; + + match stream_result { + Ok(mut stream) => { + while let Some(result) = stream.next().await { + match result { + Ok(message) => { + let mut pb = ChatMessagePB::from(message.clone()); + if has_following { + pb.has_following = has_following; + has_following = false; + } + send_notification(&chat_id, ChatNotification::DidReceiveChatMessage) + .payload(pb) + .send(); + messages.push(message); + }, + Err(err) => { + let pb = ChatMessageErrorPB { + chat_id: chat_id.clone(), + content: message_content.clone(), + error_message: err.to_string(), + }; + send_notification(&chat_id, ChatNotification::ChatMessageError) + .payload(pb) + .send(); + break; + }, + } + } + + // Mark chat as finished + send_notification(&chat_id, ChatNotification::FinishAnswerQuestion).send(); + }, + Err(err) => { + error!("Failed to send chat message: {}", err); + let pb = ChatMessageErrorPB { + chat_id: chat_id.clone(), + content: message_content.clone(), + error_message: err.to_string(), + }; + send_notification(&chat_id, ChatNotification::ChatMessageError) + .payload(pb) + .send(); + return; + }, + } + + if messages.is_empty() { + return; + } + + trace!( + "Saving chat messages to local disk: chat_id={}, messages:{:?}", + chat_id, + messages + ); + + // Insert chat messages to local disk + if let Err(err) = user_service.sqlite_connection(uid).and_then(|conn| { + let records = messages + .into_iter() + .map(|message| ChatMessageTable { + message_id: message.message_id, + chat_id: chat_id.clone(), + content: message.content, + created_at: message.created_at.timestamp(), + author_type: message.author.author_type as i64, + author_id: message.author.author_id.to_string(), + }) + .collect::>(); + insert_chat_messages(conn, &records)?; + Ok(()) + }) { + error!("Failed to save chat messages: {}", err); + } + }); +} fn save_chat_message( conn: DBConnection, chat_id: &str, diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index ce01b249ceec5..cf5ce11e98966 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -84,6 +84,21 @@ pub struct ChatMessagePB { #[pb(index = 5)] pub author_id: String, + + #[pb(index = 6)] + pub has_following: bool, +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct ChatMessageErrorPB { + #[pb(index = 1)] + pub chat_id: String, + + #[pb(index = 2)] + pub content: String, + + #[pb(index = 3)] + pub error_message: String, } impl From for ChatMessagePB { @@ -94,6 +109,7 @@ impl From for ChatMessagePB { created_at: chat_message.created_at.timestamp(), author_type: chat_message.author.author_type as i64, author_id: chat_message.author.author_id.to_string(), + has_following: false, } } } diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 968351935b85a..65ae7c8340776 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -21,7 +21,7 @@ fn upgrade_chat_manager( pub(crate) async fn send_chat_message_handler( data: AFPluginData, chat_manager: AFPluginState>, -) -> DataResult { +) -> Result<(), FlowyError> { let chat_manager = upgrade_chat_manager(chat_manager)?; let data = data.into_inner(); data.validate()?; @@ -30,11 +30,10 @@ pub(crate) async fn send_chat_message_handler( ChatMessageTypePB::System => ChatMessageType::System, ChatMessageTypePB::User => ChatMessageType::User, }; - let messages = chat_manager + chat_manager .send_chat_message(&data.chat_id, &data.message, message_type) .await?; - - data_result_ok(RepeatedChatMessagePB::from(messages)) + Ok(()) } #[tracing::instrument(level = "debug", skip_all, err)] diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index f4b2006123057..80d3ec44705a6 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -23,6 +23,6 @@ pub enum ChatEvent { #[event(input = "LoadChatMessagePB", output = "ChatMessageListPB")] LoadMessage = 0, - #[event(input = "SendChatPayloadPB", output = "RepeatedChatMessagePB")] + #[event(input = "SendChatPayloadPB")] SendMessage = 1, } diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index baaa10e2497bc..9d70f482fcab7 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,8 +1,8 @@ use crate::chat::Chat; use crate::entities::ChatMessageListPB; -use crate::persistence::{insert_chat, insert_chat_messages, ChatMessageTable, ChatTable}; +use crate::persistence::{insert_chat, ChatTable}; use dashmap::DashMap; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageType}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; @@ -84,13 +84,13 @@ impl ChatManager { chat_id: &str, message: &str, message_type: ChatMessageType, - ) -> Result, FlowyError> { + ) -> Result<(), FlowyError> { let chat = self.chats.get(chat_id).as_deref().cloned(); match chat { None => Err(FlowyError::internal().with_context("Should call open chat first")), Some(chat) => { - let messages = chat.send_chat_message(message, message_type).await?; - Ok(messages) + chat.send_chat_message(message, message_type).await?; + Ok(()) }, } } diff --git a/frontend/rust-lib/flowy-chat/src/notification.rs b/frontend/rust-lib/flowy-chat/src/notification.rs index 3e02bcee8abca..e50b8014506c2 100644 --- a/frontend/rust-lib/flowy-chat/src/notification.rs +++ b/frontend/rust-lib/flowy-chat/src/notification.rs @@ -8,6 +8,9 @@ pub enum ChatNotification { #[default] Unknown = 0, DidLoadChatMessage = 1, + DidReceiveChatMessage = 2, + ChatMessageError = 3, + FinishAnswerQuestion = 4, } impl std::convert::From for i32 { @@ -19,6 +22,9 @@ impl std::convert::From for ChatNotification { fn from(notification: i32) -> Self { match notification { 1 => ChatNotification::DidLoadChatMessage, + 2 => ChatNotification::DidReceiveChatMessage, + 3 => ChatNotification::ChatMessageError, + 4 => ChatNotification::ChatMessageError, _ => ChatNotification::Unknown, } } diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 9ddbc7ed547d3..b5a66e9fd5d2f 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use anyhow::Error; use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin}; +use client_api::entity::ChatMessageType; use collab::core::origin::{CollabClient, CollabOrigin}; use collab::preclude::CollabPlugin; @@ -15,7 +16,7 @@ use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; use flowy_chat_pub::cloud::{ - ChatCloudService, ChatMessage, MessageCursor, QAChatMessage, RepeatedChatMessage, + ChatCloudService, ChatMessageStream, MessageCursor, RepeatedChatMessage, }; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, @@ -31,6 +32,7 @@ use flowy_server_pub::supabase_config::SupabaseConfiguration; use flowy_storage::ObjectValue; use flowy_user_pub::cloud::{UserCloudService, UserCloudServiceProvider}; use flowy_user_pub::entities::{Authenticator, UserTokenState}; +use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; use crate::integrate::server::{Server, ServerProvider}; @@ -436,6 +438,7 @@ impl CollabCloudPluginProvider for ServerProvider { } } +#[async_trait] impl ChatCloudService for ServerProvider { fn create_chat( &self, @@ -455,40 +458,21 @@ impl ChatCloudService for ServerProvider { }) } - fn send_system_message( + async fn send_chat_message( &self, workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult { + message_type: ChatMessageType, + ) -> Result { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); let message = message.to_string(); - let server = self.get_server(); - FutureResult::new(async move { - server? - .chat_service() - .send_system_message(&workspace_id, &chat_id, &message) - .await - }) - } - - fn send_user_message( - &self, - workspace_id: &str, - chat_id: &str, - message: &str, - ) -> FutureResult { - let workspace_id = workspace_id.to_string(); - let chat_id = chat_id.to_string(); - let message = message.to_string(); - let server = self.get_server(); - FutureResult::new(async move { - server? - .chat_service() - .send_user_message(&workspace_id, &chat_id, &message) - .await - }) + let server = self.get_server()?; + server + .chat_service() + .send_chat_message(&workspace_id, &chat_id, &message, message_type) + .await } fn get_chat_messages( diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 5543d18973451..88a3aa64ec2c5 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -2,14 +2,17 @@ use crate::af_cloud::AFServer; use client_api::entity::{ CreateChatMessageParams, CreateChatParams, MessageCursor, RepeatedChatMessage, }; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, QAChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageStream, ChatMessageType}; use flowy_error::FlowyError; +use futures_util::StreamExt; +use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; pub(crate) struct AFCloudChatCloudServiceImpl { pub inner: T, } +#[async_trait] impl ChatCloudService for AFCloudChatCloudServiceImpl where T: AFServer, @@ -39,52 +42,27 @@ where }) } - fn send_system_message( + async fn send_chat_message( &self, workspace_id: &str, chat_id: &str, message: &str, - ) -> FutureResult { + message_type: ChatMessageType, + ) -> Result { let workspace_id = workspace_id.to_string(); let chat_id = chat_id.to_string(); let message = message.to_string(); let try_get_client = self.inner.try_get_client(); + let params = CreateChatMessageParams { + content: message, + message_type, + }; + let stream = try_get_client? + .create_chat_message(&workspace_id, &chat_id, params) + .await + .map_err(FlowyError::from)?; - FutureResult::new(async move { - let params = CreateChatMessageParams { - content: message, - message_type: ChatMessageType::System, - }; - let message = try_get_client? - .create_chat_message(&workspace_id, &chat_id, params) - .await - .map_err(FlowyError::from)?; - Ok(message.question) - }) - } - - fn send_user_message( - &self, - workspace_id: &str, - chat_id: &str, - message: &str, - ) -> FutureResult { - let workspace_id = workspace_id.to_string(); - let chat_id = chat_id.to_string(); - let message = message.to_string(); - let try_get_client = self.inner.try_get_client(); - FutureResult::new(async move { - let params = CreateChatMessageParams { - content: message, - message_type: ChatMessageType::User, - }; - let message = try_get_client? - .create_chat_message(&workspace_id, &chat_id, params) - .await - .map_err(FlowyError::from)?; - - Ok(message) - }) + Ok(stream.boxed()) } fn get_chat_messages( diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index b48a3b9cdf4fa..d34f4a0d24bca 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,10 +1,12 @@ -use client_api::entity::{MessageCursor, RepeatedChatMessage}; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, QAChatMessage}; +use client_api::entity::{ChatMessageType, MessageCursor, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageStream}; use flowy_error::FlowyError; +use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; pub(crate) struct DefaultChatCloudServiceImpl; +#[async_trait] impl ChatCloudService for DefaultChatCloudServiceImpl { fn create_chat( &self, @@ -17,26 +19,14 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { }) } - fn send_system_message( + async fn send_chat_message( &self, _workspace_id: &str, _chat_id: &str, _message: &str, - ) -> FutureResult { - FutureResult::new(async move { - Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) - }) - } - - fn send_user_message( - &self, - _workspace_id: &str, - _chat_id: &str, - _message: &str, - ) -> FutureResult { - FutureResult::new(async move { - Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) - }) + _message_type: ChatMessageType, + ) -> Result { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) } fn get_chat_messages( From 2d3ac9d61cb7b6641818fafe7259910215e06d38 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 26 May 2024 20:24:37 +0800 Subject: [PATCH 14/41] chore: disable create chat --- frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart index 3036c570b6426..63404ee777825 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart @@ -36,7 +36,7 @@ class AIChatPluginBuilder extends PluginBuilder { class AIChatPluginConfig implements PluginConfig { @override - bool get creatable => true; + bool get creatable => false; } class AIChatPagePlugin extends Plugin { From 7e7cba664afa932cfb918942fe19c5b3ecf70609 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 26 May 2024 23:50:27 +0800 Subject: [PATCH 15/41] chore: update client api --- frontend/appflowy_tauri/src-tauri/Cargo.lock | 28 ++++++------ frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 ++++++----------- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 30 +++++++------ .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 44 +++++++------------ frontend/rust-lib/Cargo.toml | 2 +- 8 files changed, 62 insertions(+), 88 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 05de31462f34f..a3f73ca1375ed 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "serde", @@ -754,7 +754,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "again", "anyhow", @@ -801,7 +801,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "futures-channel", "futures-util", @@ -1040,7 +1040,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -1065,7 +1065,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "async-trait", @@ -1311,7 +1311,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1422,7 +1422,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -2828,7 +2828,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "futures-util", @@ -2845,7 +2845,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -3277,7 +3277,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "reqwest", @@ -4780,7 +4780,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4801,7 +4801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -5765,7 +5765,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index d03cc5f5f890f..7d9e011a7af28 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 3e00e40b16b7b..a26f254c28d4f 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "serde", @@ -560,7 +560,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "again", "anyhow", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +785,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -810,7 +810,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "async-trait", @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1024,7 +1024,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -1812,7 +1812,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "futures-util", @@ -1829,7 +1829,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -2130,7 +2130,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "reqwest", @@ -2814,7 +2814,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2834,7 +2834,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2902,19 +2901,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -3770,7 +3756,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 574c88be39436..77c639f044fd8 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 334bae991de1b..312ca437efafe 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "serde", @@ -727,7 +727,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "again", "anyhow", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "futures-channel", "futures-util", @@ -1022,7 +1022,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -1047,7 +1047,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "async-trait", @@ -1297,7 +1297,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1408,7 +1408,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -1857,6 +1857,7 @@ dependencies = [ "flowy-error", "flowy-notification", "flowy-sqlite", + "futures", "lib-dispatch", "lib-infra", "protobuf", @@ -1873,6 +1874,7 @@ version = "0.1.0" dependencies = [ "client-api", "flowy-error", + "futures", "lib-infra", ] @@ -2899,7 +2901,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "futures-util", @@ -2916,7 +2918,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -3353,7 +3355,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "reqwest", @@ -4858,7 +4860,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4879,7 +4881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5857,7 +5859,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 6f840f85395fd..f48d3cca85173 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index bdbacaadf1f2a..1796cf01b115e 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "serde", @@ -662,7 +662,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "again", "anyhow", @@ -709,7 +709,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +917,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "bincode", @@ -942,7 +942,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "async-trait", @@ -1162,7 +1162,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1261,7 +1261,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -2511,7 +2511,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "futures-util", @@ -2528,7 +2528,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "reqwest", @@ -3768,7 +3768,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3788,7 +3788,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3856,19 +3855,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4072,7 +4058,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4093,7 +4079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4990,7 +4976,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=a01926b90396179407dc55a279a02c439c886bb1#a01926b90396179407dc55a279a02c439c886bb1" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index bf08c02160692..6af33adce45f9 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "a01926b90396179407dc55a279a02c439c886bb1" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } [profile.dev] opt-level = 1 From 760be42f2782b3de6c9053448f0e96f81001a34e Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 28 May 2024 09:55:05 +0800 Subject: [PATCH 16/41] chore: disable chat --- .../lib/plugins/ai_chat/chat_page.dart | 106 +++++++++--------- frontend/appflowy_web/wasm-libs/Cargo.lock | 23 +++- 2 files changed, 71 insertions(+), 58 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 9a27eb76bc23a..c6ea1cca00bd7 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -5,7 +5,6 @@ import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat, DarkChatTheme; -// ignore: depend_on_referenced_packages import 'package:flutter_chat_types/flutter_chat_types.dart' as types; class AIChatPage extends StatefulWidget { @@ -39,60 +38,59 @@ class _AIChatPageState extends State { @override Widget build(BuildContext context) { return SizedBox.expand( - child: Container( - color: Theme.of(context).colorScheme.background, - child: Padding( - padding: const EdgeInsets.all(10), - child: BlocProvider( - create: (context) => ChatBloc( - view: widget.view, - userProfile: widget.userProfile, - )..add(const ChatEvent.loadMessage()), - child: BlocListener( - listenWhen: (previous, current) => - previous.loadingStatus != current.loadingStatus, - listener: (context, state) {}, - child: BlocBuilder( - builder: (blocContext, state) { - return Chat( - messages: state.messages, - onAttachmentPressed: () {}, - onMessageTap: (BuildContext _, types.Message message) { - blocContext - .read() - .add(ChatEvent.tapMessage(message)); - }, - onSendPressed: (types.PartialText message) { - // Do nothing. We use the custom input widget. - onSendPressed(blocContext, message); - }, - user: _user, - theme: chatTheme, - customMessageBuilder: (message, {required messageWidth}) { - return const SizedBox( - width: 100, - height: 50, - child: CircularProgressIndicator.adaptive(), + child: Padding( + padding: const EdgeInsets.all(10), + child: BlocProvider( + create: (context) => ChatBloc( + view: widget.view, + userProfile: widget.userProfile, + )..add(const ChatEvent.loadMessage()), + child: BlocListener( + listenWhen: (previous, current) => + previous.loadingStatus != current.loadingStatus, + listener: (context, state) {}, + child: BlocBuilder( + builder: (blocContext, state) { + return Chat( + messages: state.messages, + onAttachmentPressed: () {}, + onMessageTap: (BuildContext _, types.Message message) { + blocContext + .read() + .add(ChatEvent.tapMessage(message)); + }, + onSendPressed: (types.PartialText message) { + // Do nothing. We use the custom input widget. + onSendPressed(blocContext, message); + }, + user: _user, + theme: chatTheme, + customMessageBuilder: (message, {required messageWidth}) { + return const SizedBox( + width: 100, + height: 50, + child: CircularProgressIndicator.adaptive(), + ); + }, + onMessageLongPress: + (BuildContext _, types.Message message) {}, + onEndReached: () async { + if (state.hasMore) { + state.loadingPreviousStatus.when( + loading: () => Log.debug("loading"), + finish: () { + Log.debug("loading more messages"); + blocContext + .read() + .add(const ChatEvent.loadMessage()); + }, ); - }, - onEndReached: () async { - if (state.hasMore) { - state.loadingPreviousStatus.when( - loading: () => Log.debug("loading"), - finish: () { - Log.debug("loading more messages"); - blocContext - .read() - .add(const ChatEvent.loadMessage()); - }, - ); - } else { - Log.debug("no more messages"); - } - }, - ); - }, - ), + } else { + Log.debug("no more messages"); + } + }, + ); + }, ), ), ), diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index a26f254c28d4f..c696b6929bd2c 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -979,7 +979,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1507,6 +1507,7 @@ dependencies = [ "postgrest", "rand 0.8.5", "reqwest", + "semver", "serde", "serde_json", "thiserror", @@ -2814,7 +2815,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2834,6 +2835,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2901,6 +2903,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3627,9 +3642,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" From 9d081a34946c738de426ffa4252765b3bac37b15 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 10:54:22 +0800 Subject: [PATCH 17/41] chore: ui theme --- .../lib/plugins/ai_chat/chat.dart | 2 +- .../lib/plugins/ai_chat/chat_page.dart | 62 ++++- .../ai_chat/presentation/chat_input.dart | 93 ++------ .../ai_chat/presentation/chat_theme.dart | 222 ++++++++++++++++++ frontend/rust-lib/flowy-chat/src/chat.rs | 11 +- 5 files changed, 307 insertions(+), 83 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart index 63404ee777825..3036c570b6426 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart @@ -36,7 +36,7 @@ class AIChatPluginBuilder extends PluginBuilder { class AIChatPluginConfig implements PluginConfig { @override - bool get creatable => false; + bool get creatable => true; } class AIChatPagePlugin extends Plugin { diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index c6ea1cca00bd7..83485e489b072 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -2,11 +2,15 @@ import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat, DarkChatTheme; +import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; +import 'presentation/chat_input.dart'; +import 'presentation/chat_theme.dart'; + class AIChatPage extends StatefulWidget { const AIChatPage({ super.key, @@ -33,7 +37,6 @@ class _AIChatPageState extends State { } late types.User _user; - final chatTheme = const DarkChatTheme(); @override Widget build(BuildContext context) { @@ -61,10 +64,15 @@ class _AIChatPageState extends State { }, onSendPressed: (types.PartialText message) { // Do nothing. We use the custom input widget. - onSendPressed(blocContext, message); + // onSendPressed(blocContext, message); }, + customBottomWidget: ChatInput( + onSendPressed: (message) { + onSendPressed(blocContext, message); + }, + ), user: _user, - theme: chatTheme, + theme: buildTheme(context), customMessageBuilder: (message, {required messageWidth}) { return const SizedBox( width: 100, @@ -98,6 +106,52 @@ class _AIChatPageState extends State { ); } + AFDefaultChatTheme buildTheme(BuildContext context) { + return AFDefaultChatTheme( + backgroundColor: AFThemeExtension.of(context).background, + primaryColor: Theme.of(context).colorScheme.primary, + secondaryColor: AFThemeExtension.of(context).tint1, + receivedMessageDocumentIconColor: Theme.of(context).primaryColor, + receivedMessageCaptionTextStyle: TextStyle( + color: AFThemeExtension.of(context).textColor, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + receivedMessageBodyTextStyle: TextStyle( + color: AFThemeExtension.of(context).textColor, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + receivedMessageLinkTitleTextStyle: TextStyle( + color: AFThemeExtension.of(context).textColor, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + receivedMessageBodyLinkTextStyle: const TextStyle( + color: Colors.lightBlue, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + sentMessageBodyTextStyle: TextStyle( + color: AFThemeExtension.of(context).textColor, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + sentMessageBodyLinkTextStyle: const TextStyle( + color: Colors.blue, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + inputElevation: 2, + ); + } + void onSendPressed( BuildContext context, types.PartialText message, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart index e842a9a3d66e8..af8897392af41 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -1,9 +1,13 @@ +import 'package:flowy_infra/theme_extension.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; +// final isMobile = defaultTargetPlatform == TargetPlatform.android || +// defaultTargetPlatform == TargetPlatform.iOS; + /// A class that represents bottom bar widget with a text field, attachment and /// send buttons inside. By default hides send button when text field is empty. class ChatInput extends StatefulWidget { @@ -109,10 +113,10 @@ class _ChatInputState extends State { Widget _inputBuilder() { final query = MediaQuery.of(context); - final buttonPadding = InheritedChatTheme.of(context) - .theme - .inputPadding - .copyWith(left: 16, right: 16); + const textPadding = EdgeInsets.symmetric(horizontal: 16, vertical: 6); + const buttonPadding = EdgeInsets.symmetric(horizontal: 16, vertical: 6); + const inputPadding = EdgeInsets.all(6); + final safeAreaInsets = isMobile ? EdgeInsets.fromLTRB( query.padding.left, @@ -121,32 +125,16 @@ class _ChatInputState extends State { query.viewInsets.bottom + query.padding.bottom, ) : EdgeInsets.zero; - final textPadding = InheritedChatTheme.of(context) - .theme - .inputPadding - .copyWith(left: 0, right: 0) - .add( - EdgeInsets.fromLTRB( - widget.onAttachmentPressed != null ? 0 : 24, - 0, - _sendButtonVisible ? 0 : 24, - 0, - ), - ); return Focus( autofocus: !widget.options.autofocus, child: Padding( - padding: InheritedChatTheme.of(context).theme.inputMargin, + padding: inputPadding, child: Material( - borderRadius: InheritedChatTheme.of(context).theme.inputBorderRadius, - color: InheritedChatTheme.of(context).theme.inputBackgroundColor, - surfaceTintColor: - InheritedChatTheme.of(context).theme.inputSurfaceTintColor, - elevation: InheritedChatTheme.of(context).theme.inputElevation, + borderRadius: BorderRadius.circular(12), + color: Theme.of(context).colorScheme.surfaceContainerHighest, + elevation: 0.6, child: Container( - decoration: - InheritedChatTheme.of(context).theme.inputContainerDecoration, padding: safeAreaInsets, child: Row( textDirection: TextDirection.ltr, @@ -166,38 +154,24 @@ class _ChatInputState extends State { autofocus: widget.options.autofocus, enableSuggestions: widget.options.enableSuggestions, controller: _textController, - cursorColor: InheritedChatTheme.of(context) - .theme - .inputTextCursorColor, - decoration: InheritedChatTheme.of(context) - .theme - .inputTextDecoration - .copyWith( - hintStyle: InheritedChatTheme.of(context) - .theme - .inputTextStyle - .copyWith( - color: InheritedChatTheme.of(context) - .theme - .inputTextColor - .withOpacity(0.5), - ), - hintText: "", - ), + decoration: InputDecoration( + border: InputBorder.none, + hintText: '', + hintStyle: TextStyle( + color: AFThemeExtension.of(context) + .textColor + .withOpacity(0.5), + ), + ), focusNode: _inputFocusNode, keyboardType: widget.options.keyboardType, maxLines: 5, minLines: 1, onChanged: widget.options.onTextChanged, onTap: widget.options.onTextFieldTap, - style: InheritedChatTheme.of(context) - .theme - .inputTextStyle - .copyWith( - color: InheritedChatTheme.of(context) - .theme - .inputTextColor, - ), + style: TextStyle( + color: AFThemeExtension.of(context).textColor, + ), textCapitalization: TextCapitalization.sentences, ), ), @@ -298,24 +272,5 @@ class InputOptions { final bool enabled; } -class InheritedChatTheme extends InheritedWidget { - /// Creates [InheritedWidget] from a provided [ChatTheme] class. - const InheritedChatTheme({ - super.key, - required this.theme, - required super.child, - }); - - static InheritedChatTheme of(BuildContext context) => - context.dependOnInheritedWidgetOfExactType()!; - - /// Represents chat theme. - final ChatTheme theme; - - @override - bool updateShouldNotify(InheritedChatTheme oldWidget) => - theme.hashCode != oldWidget.theme.hashCode; -} - final isMobile = defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS; diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart new file mode 100644 index 0000000000000..4c8ceac535d3d --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_chat_ui/flutter_chat_ui.dart'; + +// For internal usage only. Use values from theme itself. + +/// See [ChatTheme.userAvatarNameColors]. +const colors = [ + Color(0xffff6767), + Color(0xff66e0da), + Color(0xfff5a2d9), + Color(0xfff0c722), + Color(0xff6a85e5), + Color(0xfffd9a6f), + Color(0xff92db6e), + Color(0xff73b8e5), + Color(0xfffd7590), + Color(0xffc78ae5), +]; + +/// Dark. +const dark = Color(0xff1f1c38); + +/// Error. +const error = Color(0xffff6767); + +/// N0. +const neutral0 = Color(0xff1d1c21); + +/// N1. +const neutral1 = Color(0xff615e6e); + +/// N2. +const neutral2 = Color(0xff9e9cab); + +/// N7. +const neutral7 = Color(0xffffffff); + +/// N7 with opacity. +const neutral7WithOpacity = Color(0x80ffffff); + +/// Primary. +const primary = Color(0xff6f61e8); + +/// Secondary. +const secondary = Color(0xfff5f5f7); + +/// Secondary dark. +const secondaryDark = Color(0xff2b2250); + +/// Default chat theme which extends [ChatTheme]. +@immutable +class AFDefaultChatTheme extends ChatTheme { + /// Creates a default chat theme. Use this constructor if you want to + /// override only a couple of properties, otherwise create a new class + /// which extends [ChatTheme]. + const AFDefaultChatTheme({ + super.attachmentButtonIcon, + super.attachmentButtonMargin, + super.backgroundColor = neutral7, + super.bubbleMargin, + super.dateDividerMargin = const EdgeInsets.only( + bottom: 32, + top: 16, + ), + super.dateDividerTextStyle = const TextStyle( + color: neutral2, + fontSize: 12, + fontWeight: FontWeight.w800, + height: 1.333, + ), + super.deliveredIcon, + super.documentIcon, + super.emptyChatPlaceholderTextStyle = const TextStyle( + color: neutral2, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + super.errorColor = error, + super.errorIcon, + super.inputBackgroundColor = neutral0, + super.inputSurfaceTintColor = neutral0, + super.inputElevation = 0, + super.inputBorderRadius = const BorderRadius.vertical( + top: Radius.circular(20), + ), + super.inputContainerDecoration, + super.inputMargin = EdgeInsets.zero, + super.inputPadding = const EdgeInsets.fromLTRB(14, 20, 14, 20), + super.inputTextColor = neutral7, + super.inputTextCursorColor, + super.inputTextDecoration = const InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.zero, + isCollapsed: true, + ), + super.inputTextStyle = const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + super.messageBorderRadius = 20, + super.messageInsetsHorizontal = 20, + super.messageInsetsVertical = 16, + super.messageMaxWidth = 440, + super.primaryColor = primary, + super.receivedEmojiMessageTextStyle = const TextStyle(fontSize: 40), + super.receivedMessageBodyBoldTextStyle, + super.receivedMessageBodyCodeTextStyle, + super.receivedMessageBodyLinkTextStyle, + super.receivedMessageBodyTextStyle = const TextStyle( + color: neutral0, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + super.receivedMessageCaptionTextStyle = const TextStyle( + color: neutral2, + fontSize: 12, + fontWeight: FontWeight.w500, + height: 1.333, + ), + super.receivedMessageDocumentIconColor = primary, + super.receivedMessageLinkDescriptionTextStyle = const TextStyle( + color: neutral0, + fontSize: 14, + fontWeight: FontWeight.w400, + height: 1.428, + ), + super.receivedMessageLinkTitleTextStyle = const TextStyle( + color: neutral0, + fontSize: 16, + fontWeight: FontWeight.w800, + height: 1.375, + ), + super.secondaryColor = secondary, + super.seenIcon, + super.sendButtonIcon, + super.sendButtonMargin, + super.sendingIcon, + super.sentEmojiMessageTextStyle = const TextStyle(fontSize: 40), + super.sentMessageBodyBoldTextStyle, + super.sentMessageBodyCodeTextStyle, + super.sentMessageBodyLinkTextStyle, + super.sentMessageBodyTextStyle = const TextStyle( + color: neutral7, + fontSize: 16, + fontWeight: FontWeight.w500, + height: 1.5, + ), + super.sentMessageCaptionTextStyle = const TextStyle( + color: neutral7WithOpacity, + fontSize: 12, + fontWeight: FontWeight.w500, + height: 1.333, + ), + super.sentMessageDocumentIconColor = neutral7, + super.sentMessageLinkDescriptionTextStyle = const TextStyle( + color: neutral7, + fontSize: 14, + fontWeight: FontWeight.w400, + height: 1.428, + ), + super.sentMessageLinkTitleTextStyle = const TextStyle( + color: neutral7, + fontSize: 16, + fontWeight: FontWeight.w800, + height: 1.375, + ), + super.statusIconPadding = const EdgeInsets.symmetric(horizontal: 4), + super.systemMessageTheme = const SystemMessageTheme( + margin: EdgeInsets.only( + bottom: 24, + top: 8, + left: 8, + right: 8, + ), + textStyle: TextStyle( + color: neutral2, + fontSize: 12, + fontWeight: FontWeight.w800, + height: 1.333, + ), + ), + super.typingIndicatorTheme = const TypingIndicatorTheme( + animatedCirclesColor: neutral1, + animatedCircleSize: 5.0, + bubbleBorder: BorderRadius.all(Radius.circular(27.0)), + bubbleColor: neutral7, + countAvatarColor: primary, + countTextColor: secondary, + multipleUserTextStyle: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: neutral2, + ), + ), + super.unreadHeaderTheme = const UnreadHeaderTheme( + color: secondary, + textStyle: TextStyle( + color: neutral2, + fontSize: 12, + fontWeight: FontWeight.w500, + height: 1.333, + ), + ), + super.userAvatarImageBackgroundColor = Colors.transparent, + super.userAvatarNameColors = colors, + super.userAvatarTextStyle = const TextStyle( + color: neutral7, + fontSize: 12, + fontWeight: FontWeight.w800, + height: 1.333, + ), + super.userNameTextStyle = const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w800, + height: 1.333, + ), + super.highlightMessageColor, + }); +} diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index b1b7724e4e539..89391fbdd7c1a 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -1,18 +1,11 @@ use crate::entities::{ChatMessageErrorPB, ChatMessageListPB, ChatMessagePB}; use crate::manager::ChatUserService; use crate::notification::{send_notification, ChatNotification}; -use crate::persistence::{ - insert_chat, insert_chat_messages, select_chat_messages, ChatMessageTable, ChatTable, -}; -use flowy_chat_pub::cloud::{ - ChatCloudService, ChatMessage, ChatMessageStream, ChatMessageType, MessageCursor, -}; +use crate::persistence::{insert_chat_messages, select_chat_messages, ChatMessageTable}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, MessageCursor}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use futures::StreamExt; -use lib_infra::util::timestamp; -use std::future::Future; - use std::sync::Arc; use tokio::sync::RwLock; use tracing::{error, instrument, trace}; From 55180739280f4c8538a5c6b75b40de242fbb7475 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 11:39:15 +0800 Subject: [PATCH 18/41] chore: ui theme --- .../lib/plugins/ai_chat/chat_page.dart | 27 +++++++++++++++++-- .../ai_chat/presentation/chat_popmenu.dart | 1 + 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 83485e489b072..5df495aecc554 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -80,8 +80,10 @@ class _AIChatPageState extends State { child: CircularProgressIndicator.adaptive(), ); }, - onMessageLongPress: - (BuildContext _, types.Message message) {}, + // onMessageLongPress: + // (BuildContext context, types.Message message) { + // // show menu + // }, onEndReached: () async { if (state.hasMore) { state.loadingPreviousStatus.when( @@ -97,6 +99,27 @@ class _AIChatPageState extends State { Log.debug("no more messages"); } }, + bubbleBuilder: ( + child, { + required message, + required nextMessageInGroup, + }) { + final isAuthor = message.author.id == _user.id; + const borderRadius = BorderRadius.all(Radius.circular(20)); + return DecoratedBox( + decoration: BoxDecoration( + borderRadius: borderRadius, + color: + !isAuthor || message.type == types.MessageType.image + ? AFThemeExtension.of(context).tint1 + : Theme.of(context).colorScheme.primary, + ), + child: ClipRRect( + borderRadius: borderRadius, + child: Container(child: child), + ), + ); + }, ); }, ), diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart @@ -0,0 +1 @@ + From f7216f9261e952ec9e092037a8939a288f53ea2d Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 12:08:41 +0800 Subject: [PATCH 19/41] chore: copy message --- .../lib/plugins/ai_chat/chat_page.dart | 63 ++++++++++++----- .../ai_chat/presentation/chat_popmenu.dart | 69 +++++++++++++++++++ .../tests/chat/chat_message_test.rs | 2 +- 3 files changed, 114 insertions(+), 20 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 5df495aecc554..bba8010c285a8 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -1,14 +1,20 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; +import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'presentation/chat_input.dart'; +import 'presentation/chat_popmenu.dart'; import 'presentation/chat_theme.dart'; class AIChatPage extends StatefulWidget { @@ -95,31 +101,14 @@ class _AIChatPageState extends State { .add(const ChatEvent.loadMessage()); }, ); - } else { - Log.debug("no more messages"); } }, bubbleBuilder: ( child, { required message, required nextMessageInGroup, - }) { - final isAuthor = message.author.id == _user.id; - const borderRadius = BorderRadius.all(Radius.circular(20)); - return DecoratedBox( - decoration: BoxDecoration( - borderRadius: borderRadius, - color: - !isAuthor || message.type == types.MessageType.image - ? AFThemeExtension.of(context).tint1 - : Theme.of(context).colorScheme.primary, - ), - child: ClipRRect( - borderRadius: borderRadius, - child: Container(child: child), - ), - ); - }, + }) => + buildBubble(message, child), ); }, ), @@ -129,6 +118,42 @@ class _AIChatPageState extends State { ); } + ChatPopupMenu buildBubble(Message message, Widget child) { + final isAuthor = message.author.id == _user.id; + const borderRadius = BorderRadius.all(Radius.circular(20)); + + return ChatPopupMenu( + onAction: (action) { + switch (action) { + case ChatMessageAction.copy: + if (message is TextMessage) { + Clipboard.setData( + ClipboardData(text: message.text), + ); + showMessageToast( + LocaleKeys.grid_row_copyProperty.tr(), + ); + } + break; + } + }, + builder: (context) { + return DecoratedBox( + decoration: BoxDecoration( + borderRadius: borderRadius, + color: !isAuthor || message.type == types.MessageType.image + ? AFThemeExtension.of(context).tint1 + : Theme.of(context).colorScheme.primary, + ), + child: ClipRRect( + borderRadius: borderRadius, + child: Container(child: child), + ), + ); + }, + ); + } + AFDefaultChatTheme buildTheme(BuildContext context) { return AFDefaultChatTheme( backgroundColor: AFThemeExtension.of(context).background, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart index 8b137891791fe..6b0b50dcca034 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_popmenu.dart @@ -1 +1,70 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class ChatPopupMenu extends StatefulWidget { + const ChatPopupMenu({ + super.key, + required this.onAction, + required this.builder, + }); + + final Function(ChatMessageAction) onAction; + final Widget Function(BuildContext context) builder; + + @override + State createState() => _ChatPopupMenuState(); +} + +class _ChatPopupMenuState extends State { + @override + Widget build(BuildContext context) { + return PopoverActionList( + asBarrier: true, + actions: ChatMessageAction.values + .map((action) => ChatMessageActionWrapper(action)) + .toList(), + buildChild: (controller) { + return GestureDetector( + onLongPress: () { + controller.show(); + }, + child: widget.builder(context), + ); + }, + onSelected: (action, controller) async { + widget.onAction(action.inner); + controller.close(); + }, + direction: PopoverDirection.bottomWithCenterAligned, + ); + } +} + +enum ChatMessageAction { + copy, +} + +class ChatMessageActionWrapper extends ActionCell { + ChatMessageActionWrapper(this.inner); + + final ChatMessageAction inner; + + @override + Widget? leftIcon(Color iconColor) => null; + + @override + String get name => inner.name; +} + +extension ChatMessageActionExtension on ChatMessageAction { + String get name { + switch (this) { + case ChatMessageAction.copy: + return LocaleKeys.document_plugins_contextMenu_copy.tr(); + } + } +} diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index 499e08745d686..b92e8a0935ac3 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -58,7 +58,7 @@ async fn af_cloud_load_remote_system_message_test() { let chat_service = test.server_provider.get_server().unwrap().chat_service(); for i in 0..10 { chat_service - .send_system_message( + .send_chat_message( ¤t_workspace.id, &chat_id, &format!("hello server {}", i), From f2f7fd6bc3885da70c70c8964a4e0cc7bc2c2bbb Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 12:16:33 +0800 Subject: [PATCH 20/41] chore: fix test --- .../presentation/chat/mobile_chat_screen.dart | 28 +++++++++++++++++++ frontend/rust-lib/Cargo.lock | 1 + .../event-integration-test/Cargo.toml | 1 + .../tests/chat/chat_message_test.rs | 2 ++ 4 files changed, 32 insertions(+) create mode 100644 frontend/appflowy_flutter/lib/mobile/presentation/chat/mobile_chat_screen.dart diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/chat/mobile_chat_screen.dart b/frontend/appflowy_flutter/lib/mobile/presentation/chat/mobile_chat_screen.dart new file mode 100644 index 0000000000000..31fcbdcdfd0b2 --- /dev/null +++ b/frontend/appflowy_flutter/lib/mobile/presentation/chat/mobile_chat_screen.dart @@ -0,0 +1,28 @@ +import 'package:appflowy/mobile/presentation/base/mobile_view_page.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:flutter/material.dart'; + +class MobileChatScreen extends StatelessWidget { + const MobileChatScreen({ + super.key, + required this.id, + this.title, + }); + + /// view id + final String id; + final String? title; + + static const routeName = '/chat'; + static const viewId = 'id'; + static const viewTitle = 'title'; + + @override + Widget build(BuildContext context) { + return MobileViewPage( + id: id, + title: title, + viewLayout: ViewLayoutPB.Chat, + ); + } +} diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index bc4dbd438e6b9..1076026141bfd 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -1501,6 +1501,7 @@ dependencies = [ "collab-plugins", "dotenv", "flowy-chat", + "flowy-chat-pub", "flowy-core", "flowy-database-pub", "flowy-database2", diff --git a/frontend/rust-lib/event-integration-test/Cargo.toml b/frontend/rust-lib/event-integration-test/Cargo.toml index 7095a0148098d..aca158bfaf44d 100644 --- a/frontend/rust-lib/event-integration-test/Cargo.toml +++ b/frontend/rust-lib/event-integration-test/Cargo.toml @@ -57,6 +57,7 @@ chrono = "0.4.31" zip = "0.6.6" walkdir = "2.5.0" futures = "0.3.30" +flowy-chat-pub = { workspace = true } [features] default = ["supabase_cloud_test"] diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index b92e8a0935ac3..b601710366efa 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -4,6 +4,7 @@ use event_integration_test::EventIntegrationTest; use flowy_chat::entities::{ChatMessageListPB, ChatMessageTypePB}; use flowy_chat::notification::ChatNotification; +use flowy_chat_pub::cloud::ChatMessageType; use std::time::Duration; #[tokio::test] @@ -62,6 +63,7 @@ async fn af_cloud_load_remote_system_message_test() { ¤t_workspace.id, &chat_id, &format!("hello server {}", i), + ChatMessageType::System, ) .await .unwrap(); From c3f43a30c80bf335236fa9d52ff2912c17f13503 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 20:34:47 +0800 Subject: [PATCH 21/41] chore: show error --- frontend/appflowy_flutter/ios/Podfile.lock | 4 +- .../lib/mobile/application/mobile_router.dart | 9 + .../presentation/base/mobile_view_page.dart | 6 +- .../ai_chat/application/chat_bloc.dart | 175 ++++++++++-------- .../application/chat_message_listener.dart | 29 +++ .../lib/plugins/ai_chat/chat_page.dart | 12 +- .../lib/startup/tasks/generate_router.dart | 17 ++ frontend/appflowy_tauri/src-tauri/Cargo.lock | 1 + frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 1 + frontend/rust-lib/Cargo.toml | 2 +- frontend/rust-lib/dart-ffi/Cargo.toml | 4 +- .../event-integration-test/src/chat_event.rs | 30 ++- .../event-integration-test/src/user_event.rs | 20 ++ .../tests/chat/chat_message_test.rs | 98 ++++++---- frontend/rust-lib/flowy-chat/src/chat.rs | 89 ++++++--- frontend/rust-lib/flowy-chat/src/entities.rs | 22 ++- .../rust-lib/flowy-chat/src/event_handler.rs | 19 +- frontend/rust-lib/flowy-chat/src/event_map.rs | 12 +- frontend/rust-lib/flowy-chat/src/manager.rs | 21 ++- .../rust-lib/flowy-chat/src/notification.rs | 16 +- .../src/persistence/chat_message_sql.rs | 30 ++- frontend/rust-lib/flowy-folder/src/manager.rs | 5 +- .../2024-05-23-061639_chat_message/up.sql | 13 +- frontend/rust-lib/flowy-sqlite/src/schema.rs | 1 + 26 files changed, 452 insertions(+), 188 deletions(-) diff --git a/frontend/appflowy_flutter/ios/Podfile.lock b/frontend/appflowy_flutter/ios/Podfile.lock index 93a8eb77e180c..10aa1f9df1ab8 100644 --- a/frontend/appflowy_flutter/ios/Podfile.lock +++ b/frontend/appflowy_flutter/ios/Podfile.lock @@ -170,7 +170,7 @@ SPEC CHECKSUMS: file_picker: 09aa5ec1ab24135ccd7a1621c46c84134bfd6655 flowy_infra_ui: 0455e1fa8c51885aa1437848e361e99419f34ebc Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 - fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265 + fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c image_gallery_saver: cb43cc43141711190510e92c460eb1655cd343cb image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425 integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4 @@ -191,4 +191,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: d0d9b4ff572d8695c38eb3f9b490f55cdfc57eca -COCOAPODS: 1.15.2 +COCOAPODS: 1.11.3 diff --git a/frontend/appflowy_flutter/lib/mobile/application/mobile_router.dart b/frontend/appflowy_flutter/lib/mobile/application/mobile_router.dart index 600dace29ff8c..0b4f80e2c190a 100644 --- a/frontend/appflowy_flutter/lib/mobile/application/mobile_router.dart +++ b/frontend/appflowy_flutter/lib/mobile/application/mobile_router.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:appflowy/mobile/presentation/chat/mobile_chat_screen.dart'; import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart'; import 'package:flutter/material.dart'; @@ -37,6 +38,9 @@ extension on ViewPB { return MobileCalendarScreen.routeName; case ViewLayoutPB.Board: return MobileBoardScreen.routeName; + case ViewLayoutPB.Chat: + return MobileChatScreen.routeName; + default: throw UnimplementedError('routeName for $this is not implemented'); } @@ -65,6 +69,11 @@ extension on ViewPB { MobileBoardScreen.viewId: id, MobileBoardScreen.viewTitle: name, }; + case ViewLayoutPB.Chat: + return { + MobileChatScreen.viewId: id, + MobileChatScreen.viewTitle: name, + }; default: throw UnimplementedError( 'queryParameters for $this is not implemented', diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart index 5ae710e8ce4a0..591f708546b4c 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart @@ -155,8 +155,10 @@ class _MobileViewPageState extends State { (view) { final plugin = view.plugin(arguments: widget.arguments ?? const {}) ..init(); - return plugin.widgetBuilder - .buildWidget(shrinkWrap: false, context: PluginContext()); + return plugin.widgetBuilder.buildWidget( + shrinkWrap: false, + context: PluginContext(userProfile: state.userProfilePB), + ); }, (error) { return FlowyMobileStateContainer.error( diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index f1cb2fc9c968a..9d3d6d1bb6dd7 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -4,6 +4,7 @@ import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:collection/collection.dart'; import 'package:fixnum/fixnum.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart'; @@ -13,8 +14,6 @@ import 'chat_message_listener.dart'; part 'chat_bloc.freezed.dart'; -const loadingMessageId = 'chat_message_loading_id'; - class ChatBloc extends Bloc { ChatBloc({ required ViewPB view, @@ -27,7 +26,28 @@ class ChatBloc extends Bloc { listener.start( chatMessageCallback: _handleChatMessage, - chatErrorMessageCallback: _handleErrorMessage, + chatErrorMessageCallback: (err) { + final error = TextMessage( + metadata: { + CustomMessageType.streamError.toString(): + CustomMessageType.streamError, + }, + text: err.errorMessage, + author: const User(id: "system"), + id: 'system', + ); + add(ChatEvent.streamingChatMessage([error])); + }, + latestMessageCallback: (list) { + final messages = + list.messages.map((m) => _createChatMessage(m)).toList(); + add(ChatEvent.didLoadLatestMessages(messages)); + }, + prevMessageCallback: (list) { + final messages = + list.messages.map((m) => _createChatMessage(m)).toList(); + add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); + }, finishAnswerQuestionCallback: () { if (!isClosed) { add(const ChatEvent.didFinishStreamingChatMessage()); @@ -43,51 +63,59 @@ class ChatBloc extends Bloc { listener.stop(); return super.close(); } - + void _dispatch() { on( (event, emit) async { await event.when( - loadMessage: () async { + initialLoad: () { + final payload = LoadNextChatMessagePB( + chatId: state.view.id, + limit: Int64(10), + ); + ChatEventLoadNextMessage(payload).send(); + }, + loadPrevMessage: () async { Int64? beforeMessageId; if (state.messages.isNotEmpty) { beforeMessageId = Int64.parseInt(state.messages.last.id); } - - _loadMessage(beforeMessageId); - if (beforeMessageId == null) { - emit( - state.copyWith( - loadingStatus: const LoadingState.loading(), - ), - ); - } else { - emit( - state.copyWith( - loadingPreviousStatus: const LoadingState.loading(), - ), - ); - } + _loadPrevMessage(beforeMessageId); + emit( + state.copyWith( + loadingPreviousStatus: const LoadingState.loading(), + ), + ); }, - didLoadMessages: (List messages) { - final List allMessages = List.from(state.messages); - allMessages - .removeWhere((element) => element.id == loadingMessageId); - allMessages.insertAll(0, messages); + didLoadLatestMessages: (List messages) { + final Set uniqueMessages = { + ...state.messages, + ...messages, + }; emit( state.copyWith( - messages: allMessages, + messages: uniqueMessages.toList(), + loadingStatus: const LoadingState.finish(), + ), + ); + emit( + state.copyWith( + messages: uniqueMessages.toList(), loadingStatus: const LoadingState.finish(), ), ); }, didLoadPreviousMessages: (List messages, bool hasMore) { - final List allMessages = List.from(state.messages); - allMessages.addAll(messages); - Log.info("did load previous messages: ${allMessages.length}"); + Log.debug("did load previous messages: ${messages.length}"); + // reorder all messages by message id by desc order + final Set uniqueMessages = { + ...state.messages, + ...messages, + }; + emit( state.copyWith( - messages: allMessages, + messages: uniqueMessages.toList(), loadingPreviousStatus: const LoadingState.finish(), hasMore: hasMore, ), @@ -96,8 +124,14 @@ class ChatBloc extends Bloc { tapMessage: (Message message) {}, streamingChatMessage: (List messages) { final List allMessages = List.from(state.messages); - allMessages - .removeWhere((element) => element.id == loadingMessageId); + allMessages.removeWhere((element) { + return element.metadata + ?.containsValue(CustomMessageType.loading) == + true || + element.metadata + ?.containsValue(CustomMessageType.streamError) == + true; + }); allMessages.insertAll(0, messages); emit(state.copyWith(messages: allMessages)); }, @@ -126,33 +160,15 @@ class ChatBloc extends Bloc { ); } - - void _loadMessage( + void _loadPrevMessage( Int64? beforeMessageId, ) { - final payload = LoadChatMessagePB( + final payload = LoadPrevChatMessagePB( chatId: state.view.id, limit: Int64(10), beforeMessageId: beforeMessageId, ); - ChatEventLoadMessage(payload).send().then((result) { - result.fold( - (list) { - final messages = - list.messages.map((m) => _fromChatMessage(m)).toList(); - if (!isClosed) { - if (beforeMessageId != null) { - add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); - } else { - add(ChatEvent.didLoadMessages(messages)); - } - } - }, - (err) { - Log.error("Failed to load message: $err"); - }, - ); - }); + ChatEventLoadPrevMessage(payload).send(); } Future _handleSentMessage( @@ -169,7 +185,7 @@ class ChatBloc extends Bloc { void _handleChatMessage(ChatMessagePB pb) { if (!isClosed) { - final message = _fromChatMessage(pb); + final message = _createChatMessage(pb); final List messages = []; if (pb.hasFollowing) { messages.addAll([_loaddingMessage(0.toString()), message]); @@ -180,36 +196,43 @@ class ChatBloc extends Bloc { } } - void _handleErrorMessage(ChatMessageErrorPB message) { - if (!isClosed) { - Log.error("Received error: $message"); - } + Message _loaddingMessage(String id) { + final loadingMessage = CustomMessage( + author: User(id: id), + metadata: { + CustomMessageType.loading.toString(): CustomMessageType.loading, + }, + id: 'chat_message_loading_id', + ); + return loadingMessage; } -} -Message _loaddingMessage(String id) { - final loadingMessage = CustomMessage( - author: User(id: id), - id: loadingMessageId, - ); - return loadingMessage; -} + Message _createChatMessage(ChatMessagePB message) { + final id = message.messageId.toString(); + return TextMessage( + author: User(id: message.authorId), + id: id, + text: message.content, + createdAt: message.createdAt.toInt(), + repliedMessage: _getReplyMessage(state.messages, id), + ); + } -Message _fromChatMessage(ChatMessagePB message) { - return TextMessage( - author: User(id: message.authorId), - id: message.messageId.toString(), - text: message.content, - createdAt: message.createdAt.toInt(), - ); + Message? _getReplyMessage(List messages, String messageId) { + final message = messages.firstWhereOrNull( + (element) => element!.id == messageId, + ); + return message; + } } @freezed class ChatEvent with _$ChatEvent { const factory ChatEvent.sendMessage(String message) = _SendMessage; const factory ChatEvent.tapMessage(Message message) = _TapMessage; - const factory ChatEvent.loadMessage() = _LoadMessage; - const factory ChatEvent.didLoadMessages(List messages) = + const factory ChatEvent.loadPrevMessage() = _LoadPrevMessage; + const factory ChatEvent.initialLoad() = _InitialLoadMessage; + const factory ChatEvent.didLoadLatestMessages(List messages) = _DidLoadMessages; const factory ChatEvent.streamingChatMessage(List messages) = _DidStreamMessage; @@ -253,3 +276,5 @@ class LoadingState with _$LoadingState { const factory LoadingState.loading() = _Loading; const factory LoadingState.finish() = _Finish; } + +enum CustomMessageType { loading, streamError } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart index aa7ceb949afdd..8d0a5b9b39c59 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart @@ -18,6 +18,13 @@ typedef ChatErrorMessageCallback = void Function( ChatMessageErrorPB message, ); +typedef LatestMessageCallback = void Function( + ChatMessageListPB list, +); +typedef PrevMessageCallback = void Function( + ChatMessageListPB list, +); + class ChatMessageListener { ChatMessageListener({ required this.chatId, @@ -36,16 +43,22 @@ class ChatMessageListener { ChatNotificationParser? _parser; ChatMessageCallback? chatMessageCallback; ChatErrorMessageCallback? chatErrorMessageCallback; + LatestMessageCallback? latestMessageCallback; + PrevMessageCallback? prevMessageCallback; void Function()? finishAnswerQuestionCallback; void start({ ChatMessageCallback? chatMessageCallback, ChatErrorMessageCallback? chatErrorMessageCallback, + LatestMessageCallback? latestMessageCallback, + PrevMessageCallback? prevMessageCallback, void Function()? finishAnswerQuestionCallback, }) { this.chatMessageCallback = chatMessageCallback; this.chatErrorMessageCallback = chatErrorMessageCallback; this.finishAnswerQuestionCallback = finishAnswerQuestionCallback; + this.latestMessageCallback = latestMessageCallback; + this.prevMessageCallback = prevMessageCallback; } void _callback( @@ -69,6 +82,22 @@ class ChatMessageListener { }, ); break; + case ChatNotification.DidLoadLatestChatMessage: + result.map( + (r) { + final value = ChatMessageListPB.fromBuffer(r); + latestMessageCallback?.call(value); + }, + ); + break; + case ChatNotification.DidLoadPrevChatMessage: + result.map( + (r) { + final value = ChatMessageListPB.fromBuffer(r); + prevMessageCallback?.call(value); + }, + ); + break; case ChatNotification.FinishAnswerQuestion: finishAnswerQuestionCallback?.call(); break; diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index bba8010c285a8..e8d2821577562 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -53,7 +53,7 @@ class _AIChatPageState extends State { create: (context) => ChatBloc( view: widget.view, userProfile: widget.userProfile, - )..add(const ChatEvent.loadMessage()), + )..add(const ChatEvent.initialLoad()), child: BlocListener( listenWhen: (previous, current) => previous.loadingStatus != current.loadingStatus, @@ -86,10 +86,6 @@ class _AIChatPageState extends State { child: CircularProgressIndicator.adaptive(), ); }, - // onMessageLongPress: - // (BuildContext context, types.Message message) { - // // show menu - // }, onEndReached: () async { if (state.hasMore) { state.loadingPreviousStatus.when( @@ -98,11 +94,14 @@ class _AIChatPageState extends State { Log.debug("loading more messages"); blocContext .read() - .add(const ChatEvent.loadMessage()); + .add(const ChatEvent.loadPrevMessage()); }, ); } }, + emptyState: const Center( + child: CircularProgressIndicator.adaptive(), + ), bubbleBuilder: ( child, { required message, @@ -121,6 +120,7 @@ class _AIChatPageState extends State { ChatPopupMenu buildBubble(Message message, Widget child) { final isAuthor = message.author.id == _user.id; const borderRadius = BorderRadius.all(Radius.circular(20)); + if (isMobile) {} return ChatPopupMenu( onAction: (action) { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart b/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart index 6f1a338c3f593..65096984bd83a 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:appflowy/mobile/presentation/chat/mobile_chat_screen.dart'; import 'package:appflowy/mobile/presentation/database/board/mobile_board_screen.dart'; import 'package:appflowy/mobile/presentation/database/card/card.dart'; import 'package:appflowy/mobile/presentation/database/date_picker/mobile_date_picker_screen.dart'; @@ -61,6 +62,7 @@ GoRouter generateRouter(Widget child) { _mobileGridScreenRoute(), _mobileBoardScreenRoute(), _mobileCalendarScreenRoute(), + _mobileChatScreenRoute(), // card detail page _mobileCardDetailScreenRoute(), _mobileDateCellEditScreenRoute(), @@ -488,6 +490,21 @@ GoRoute _mobileEditorScreenRoute() { ); } +GoRoute _mobileChatScreenRoute() { + return GoRoute( + path: MobileChatScreen.routeName, + parentNavigatorKey: AppGlobals.rootNavKey, + pageBuilder: (context, state) { + final id = state.uri.queryParameters[MobileChatScreen.viewId]!; + final title = state.uri.queryParameters[MobileChatScreen.viewTitle]; + + return MaterialExtendedPage( + child: MobileChatScreen(id: id, title: title), + ); + }, + ); +} + GoRoute _mobileGridScreenRoute() { return GoRoute( path: MobileGridScreen.routeName, diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index f3f9123c17d69..9c69e8db590fb 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -1501,6 +1501,7 @@ dependencies = [ "diesel_derives", "libsqlite3-sys", "r2d2", + "serde_json", "time", ] diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 027c09a3d9be9..382f3332d27d4 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -20,7 +20,7 @@ bytes = "1.5.0" serde = "1.0" serde_json = "1.0.108" protobuf = { version = "2.28.0" } -diesel = { version = "2.1.0", features = ["sqlite", "chrono", "r2d2"] } +diesel = { version = "2.1.0", features = ["sqlite", "chrono", "r2d2", "serde_json"] } uuid = { version = "1.5.0", features = ["serde", "v4"] } serde_repr = "0.1" parking_lot = "0.12" diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 620dc73170c06..aea296b1168a9 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -20,7 +20,7 @@ bytes = "1.5.0" serde = "1.0" serde_json = "1.0.108" protobuf = { version = "2.28.0" } -diesel = { version = "2.1.0", features = ["sqlite", "chrono", "r2d2"] } +diesel = { version = "2.1.0", features = ["sqlite", "chrono", "r2d2", "serde_json"] } uuid = { version = "1.5.0", features = ["serde", "v4"] } serde_repr = "0.1" parking_lot = "0.12" diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 1076026141bfd..36b675ac9f5bd 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -1353,6 +1353,7 @@ dependencies = [ "diesel_derives", "libsqlite3-sys", "r2d2", + "serde_json", "time", ] diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 6af33adce45f9..bb81863be9027 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -70,7 +70,7 @@ bytes = "1.5.0" serde_json = "1.0.108" serde = "1.0.194" protobuf = { version = "2.28.0" } -diesel = { version = "2.1.0", features = ["sqlite", "chrono", "r2d2"] } +diesel = { version = "2.1.0", features = ["sqlite", "chrono", "r2d2", "serde_json"] } uuid = { version = "1.5.0", features = ["serde", "v4", "v5"] } serde_repr = "0.1" parking_lot = "0.12" diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index e17ede23e57cd..bca0489e7b7a6 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -32,8 +32,8 @@ lib-dispatch = { workspace = true } # Core #flowy-core = { workspace = true, features = ["profiling"] } -flowy-core = { workspace = true, features = ["verbose_log"] } -#flowy-core = { workspace = true } +#flowy-core = { workspace = true, features = ["verbose_log"] } +flowy-core = { workspace = true } flowy-notification = { workspace = true, features = ["dart"] } flowy-document = { workspace = true, features = ["dart"] } diff --git a/frontend/rust-lib/event-integration-test/src/chat_event.rs b/frontend/rust-lib/event-integration-test/src/chat_event.rs index a8be7a91da8d3..ca2c4911f3457 100644 --- a/frontend/rust-lib/event-integration-test/src/chat_event.rs +++ b/frontend/rust-lib/event-integration-test/src/chat_event.rs @@ -1,7 +1,8 @@ use crate::event_builder::EventBuilder; use crate::EventIntegrationTest; use flowy_chat::entities::{ - ChatMessageListPB, ChatMessageTypePB, LoadChatMessagePB, SendChatPayloadPB, + ChatMessageListPB, ChatMessageTypePB, LoadNextChatMessagePB, LoadPrevChatMessagePB, + SendChatPayloadPB, }; use flowy_chat::event_map::ChatEvent; use flowy_folder::entities::{CreateViewPayloadPB, ViewLayoutPB, ViewPB}; @@ -48,21 +49,38 @@ impl EventIntegrationTest { .await; } - pub async fn load_message( + pub async fn load_prev_message( &self, chat_id: &str, limit: i64, - after_message_id: Option, before_message_id: Option, ) -> ChatMessageListPB { - let payload = LoadChatMessagePB { + let payload = LoadPrevChatMessagePB { chat_id: chat_id.to_string(), limit, - after_message_id, before_message_id, }; EventBuilder::new(self.clone()) - .event(ChatEvent::LoadMessage) + .event(ChatEvent::LoadPrevMessage) + .payload(payload) + .async_send() + .await + .parse::() + } + + pub async fn load_next_message( + &self, + chat_id: &str, + limit: i64, + after_message_id: Option, + ) -> ChatMessageListPB { + let payload = LoadNextChatMessagePB { + chat_id: chat_id.to_string(), + limit, + after_message_id, + }; + EventBuilder::new(self.clone()) + .event(ChatEvent::LoadNextMessage) .payload(payload) .async_send() .await diff --git a/frontend/rust-lib/event-integration-test/src/user_event.rs b/frontend/rust-lib/event-integration-test/src/user_event.rs index a2e4dda7c590d..40e8044806105 100644 --- a/frontend/rust-lib/event-integration-test/src/user_event.rs +++ b/frontend/rust-lib/event-integration-test/src/user_event.rs @@ -378,6 +378,26 @@ impl TestNotificationSender { rx } + pub fn subscribe_without_payload( + &self, + id: &str, + ty: impl Into + Send, + ) -> tokio::sync::mpsc::Receiver<()> { + let id = id.to_string(); + let (tx, rx) = tokio::sync::mpsc::channel::<()>(10); + let mut receiver = self.sender.subscribe(); + let ty = ty.into(); + af_spawn(async move { + // DatabaseNotification::DidUpdateDatabaseSnapshotState + while let Ok(value) = receiver.recv().await { + if value.id == id && value.ty == ty { + let _ = tx.send(()).await; + } + } + }); + rx + } + pub fn subscribe_with_condition(&self, id: &str, when: F) -> tokio::sync::mpsc::Receiver where T: TryFrom + Send + 'static, diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index b601710366efa..f9fc6c13e714c 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -5,6 +5,7 @@ use flowy_chat::entities::{ChatMessageListPB, ChatMessageTypePB}; use flowy_chat::notification::ChatNotification; use flowy_chat_pub::cloud::ChatMessageType; +use futures_util::StreamExt; use std::time::Duration; #[tokio::test] @@ -16,34 +17,52 @@ async fn af_cloud_create_chat_message_test() { let current_workspace = test.get_current_workspace().await; let view = test.create_chat(¤t_workspace.id).await; let chat_id = view.id.clone(); + let chat_service = test.server_provider.get_server().unwrap().chat_service(); for i in 0..10 { - test - .send_message( + let mut stream = chat_service + .send_chat_message( + ¤t_workspace.id, &chat_id, - format!("hello world {}", i), - ChatMessageTypePB::System, + &format!("hello world {}", i), + ChatMessageType::System, ) - .await; + .await + .unwrap(); + while let Some(message) = stream.next().await { + message.unwrap(); + } } - let all = test.load_message(&chat_id, 10, None, None).await; + let rx = test + .notification_sender + .subscribe::(&chat_id, ChatNotification::DidLoadLatestChatMessage); + let _ = test.load_next_message(&chat_id, 10, None).await; + let all = receive_with_timeout(rx, Duration::from_secs(30)) + .await + .unwrap(); assert_eq!(all.messages.len(), 10); + // in desc order + assert_eq!(all.messages[4].content, "hello world 5"); + assert_eq!(all.messages[5].content, "hello world 4"); let list = test - .load_message(&chat_id, 10, Some(all.messages[5].message_id), None) + .load_next_message(&chat_id, 5, Some(all.messages[4].message_id)) .await; assert_eq!(list.messages.len(), 4); - assert_eq!(list.messages[0].content, "hello world 6"); - assert_eq!(list.messages[1].content, "hello world 7"); - assert_eq!(list.messages[2].content, "hello world 8"); - assert_eq!(list.messages[3].content, "hello world 9"); + assert_eq!(list.messages[0].content, "hello world 9"); + assert_eq!(list.messages[1].content, "hello world 8"); + assert_eq!(list.messages[2].content, "hello world 7"); + assert_eq!(list.messages[3].content, "hello world 6"); + + assert_eq!(all.messages[6].content, "hello world 3"); + // Load from local let list = test - .load_message(&chat_id, 10, None, Some(all.messages[3].message_id)) + .load_prev_message(&chat_id, 5, Some(all.messages[6].message_id)) .await; assert_eq!(list.messages.len(), 3); - assert_eq!(list.messages[0].content, "hello world 0"); + assert_eq!(list.messages[0].content, "hello world 2"); assert_eq!(list.messages[1].content, "hello world 1"); - assert_eq!(list.messages[2].content, "hello world 2"); + assert_eq!(list.messages[2].content, "hello world 0"); } #[tokio::test] @@ -58,7 +77,7 @@ async fn af_cloud_load_remote_system_message_test() { let chat_service = test.server_provider.get_server().unwrap().chat_service(); for i in 0..10 { - chat_service + let mut stream = chat_service .send_chat_message( ¤t_workspace.id, &chat_id, @@ -67,14 +86,18 @@ async fn af_cloud_load_remote_system_message_test() { ) .await .unwrap(); + while let Some(message) = stream.next().await { + message.unwrap(); + } } + let rx = test .notification_sender - .subscribe::(&chat_id, ChatNotification::DidLoadChatMessage); + .subscribe::(&chat_id, ChatNotification::DidLoadLatestChatMessage); // Previous messages were created by the server, so there are no messages in the local cache. // It will try to load messages in the background. - let all = test.load_message(&chat_id, 5, None, None).await; + let all = test.load_next_message(&chat_id, 5, None).await; assert!(all.messages.is_empty()); // Wait for the messages to be loaded. @@ -84,33 +107,28 @@ async fn af_cloud_load_remote_system_message_test() { assert_eq!(next_back_five.messages.len(), 5); assert!(next_back_five.has_more); assert_eq!(next_back_five.total, 10); - assert_eq!(next_back_five.messages[0].content, "hello server 5"); - assert_eq!(next_back_five.messages[1].content, "hello server 6"); + assert_eq!(next_back_five.messages[0].content, "hello server 9"); + assert_eq!(next_back_five.messages[1].content, "hello server 8"); assert_eq!(next_back_five.messages[2].content, "hello server 7"); - assert_eq!(next_back_five.messages[3].content, "hello server 8"); - assert_eq!(next_back_five.messages[4].content, "hello server 9"); + assert_eq!(next_back_five.messages[3].content, "hello server 6"); + assert_eq!(next_back_five.messages[4].content, "hello server 5"); // Load first five messages let rx = test .notification_sender - .subscribe::(&chat_id, ChatNotification::DidLoadChatMessage); + .subscribe::(&chat_id, ChatNotification::DidLoadLatestChatMessage); test - .load_message( - &chat_id, - 5, - None, - Some(next_back_five.messages[0].message_id), - ) + .load_prev_message(&chat_id, 5, Some(next_back_five.messages[4].message_id)) .await; let first_five_messages = receive_with_timeout(rx, Duration::from_secs(30)) .await .unwrap(); assert!(!first_five_messages.has_more); - assert_eq!(first_five_messages.messages[0].content, "hello server 0"); - assert_eq!(first_five_messages.messages[1].content, "hello server 1"); + assert_eq!(first_five_messages.messages[0].content, "hello server 4"); + assert_eq!(first_five_messages.messages[1].content, "hello server 3"); assert_eq!(first_five_messages.messages[2].content, "hello server 2"); - assert_eq!(first_five_messages.messages[3].content, "hello server 3"); - assert_eq!(first_five_messages.messages[4].content, "hello server 4"); + assert_eq!(first_five_messages.messages[3].content, "hello server 1"); + assert_eq!(first_five_messages.messages[4].content, "hello server 0"); } #[tokio::test] @@ -122,16 +140,22 @@ async fn af_cloud_load_remote_user_message_test() { let current_workspace = test.get_current_workspace().await; let view = test.create_chat(¤t_workspace.id).await; let chat_id = view.id.clone(); + let rx = test + .notification_sender + .subscribe_without_payload(&chat_id, ChatNotification::FinishAnswerQuestion); test .send_message(&chat_id, "hello world", ChatMessageTypePB::User) .await; + let _ = receive_with_timeout(rx, Duration::from_secs(30)) + .await + .unwrap(); - let all = test.load_message(&chat_id, 5, None, None).await; + let all = test.load_next_message(&chat_id, 5, None).await; assert_eq!(all.messages.len(), 2); - // 2 means User - assert_eq!(all.messages[0].author_type, 1); // 3 means AI - assert_eq!(all.messages[1].author_type, 3); + assert_eq!(all.messages[0].author_type, 3); + // 2 means User + assert_eq!(all.messages[1].author_type, 1); // The message ID is incremented by 1. - assert_eq!(all.messages[0].message_id + 1, all.messages[1].message_id); + assert_eq!(all.messages[1].message_id + 1, all.messages[0].message_id); } diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index 89391fbdd7c1a..59d56e9545096 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -6,6 +6,7 @@ use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, Mess use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use futures::StreamExt; +use std::sync::atomic::AtomicI64; use std::sync::Arc; use tokio::sync::RwLock; use tracing::{error, instrument, trace}; @@ -22,6 +23,7 @@ pub struct Chat { user_service: Arc, cloud_service: Arc, prev_message_state: Arc>, + latest_message_id: Arc, } impl Chat { @@ -37,11 +39,24 @@ impl Chat { cloud_service, user_service, prev_message_state: Arc::new(RwLock::new(PrevMessageState::HasMore)), + latest_message_id: Default::default(), } } pub fn close(&self) {} + #[allow(dead_code)] + pub async fn pull_latest_message(&self, limit: i64) { + let latest_message_id = self + .latest_message_id + .load(std::sync::atomic::Ordering::Relaxed); + if latest_message_id > 0 { + let _ = self + .load_remote_chat_messages(limit, None, Some(latest_message_id)) + .await; + } + } + #[instrument(level = "info", skip_all, err)] pub async fn send_chat_message( &self, @@ -75,8 +90,6 @@ impl Chat { /// /// 3. Loading more messages in an existing chat with `before_message_id`: /// - `before_message_id` is the first message ID in the current chat messages. - /// - /// 4. `after_message_id` and `before_message_id` cannot be specified at the same time. pub async fn load_prev_chat_messages( &self, limit: i64, @@ -122,8 +135,7 @@ impl Chat { }) } - #[allow(dead_code)] - pub async fn load_after_chat_messages( + pub async fn load_latest_chat_messages( &self, limit: i64, after_message_id: Option, @@ -138,16 +150,14 @@ impl Chat { .load_local_chat_messages(limit, after_message_id, None) .await?; + trace!( + "Loaded local chat messages: chat_id={}, messages={}", + self.chat_id, + messages.len() + ); + // If the number of messages equals the limit, then no need to load more messages from remote let has_more = !messages.is_empty(); - if messages.len() == limit as usize { - return Ok(ChatMessageListPB { - messages, - has_more, - total: 0, - }); - } - let _ = self .load_remote_chat_messages(limit, None, after_message_id) .await; @@ -177,6 +187,7 @@ impl Chat { let user_service = self.user_service.clone(); let uid = self.uid; let prev_message_state = self.prev_message_state.clone(); + let latest_message_id = self.latest_message_id.clone(); tokio::spawn(async move { let cursor = match (before_message_id, after_message_id) { (Some(bid), _) => MessageCursor::BeforeMessageId(bid), @@ -189,24 +200,42 @@ impl Chat { { Ok(resp) => { // Save chat messages to local disk - save_chat_message( + if let Err(err) = save_chat_message( user_service.sqlite_connection(uid)?, &chat_id, resp.messages.clone(), - )?; + ) { + error!("Failed to save chat:{} messages: {}", chat_id, err); + } + // Update latest message ID + if !resp.messages.is_empty() { + latest_message_id.store( + resp.messages[0].message_id, + std::sync::atomic::Ordering::Relaxed, + ); + } + + let pb = ChatMessageListPB::from(resp); + trace!( + "Loaded chat messages from remote: chat_id={}, messages={}", + chat_id, + pb.messages.len() + ); if matches!(cursor, MessageCursor::BeforeMessageId(_)) { - if resp.has_more { + if pb.has_more { *prev_message_state.write().await = PrevMessageState::HasMore; } else { *prev_message_state.write().await = PrevMessageState::NoMore; } + send_notification(&chat_id, ChatNotification::DidLoadPrevChatMessage) + .payload(pb) + .send(); + } else { + send_notification(&chat_id, ChatNotification::DidLoadLatestChatMessage) + .payload(pb) + .send(); } - - let pb = ChatMessageListPB::from(resp); - send_notification(&chat_id, ChatNotification::DidLoadChatMessage) - .payload(pb) - .send(); }, Err(err) => error!("Failed to load chat messages: {}", err), } @@ -238,6 +267,7 @@ impl Chat { author_type: record.author_type, author_id: record.author_id, has_following: false, + reply_message_id: record.reply_message_id, }) .collect::>(); @@ -267,17 +297,22 @@ fn stream_send_chat_messages( .send_chat_message(&workspace_id, &chat_id, &message_content, message_type) .await; - let mut has_following = true; + let mut reply_message_id = None; + // By default, stream only returns two messages: + // 1. user message + // 2. ai response message match stream_result { Ok(mut stream) => { while let Some(result) = stream.next().await { match result { Ok(message) => { let mut pb = ChatMessagePB::from(message.clone()); - if has_following { - pb.has_following = has_following; - has_following = false; + if reply_message_id.is_none() { + pb.has_following = true; + reply_message_id = Some(pb.message_id); + } else { + pb.reply_message_id = reply_message_id; } send_notification(&chat_id, ChatNotification::DidReceiveChatMessage) .payload(pb) @@ -285,10 +320,11 @@ fn stream_send_chat_messages( messages.push(message); }, Err(err) => { + error!("Failed to send chat message: {}", err); let pb = ChatMessageErrorPB { chat_id: chat_id.clone(), content: message_content.clone(), - error_message: err.to_string(), + error_message: "Service unavailable".to_string(), }; send_notification(&chat_id, ChatNotification::ChatMessageError) .payload(pb) @@ -336,6 +372,7 @@ fn stream_send_chat_messages( created_at: message.created_at.timestamp(), author_type: message.author.author_type as i64, author_id: message.author.author_id.to_string(), + reply_message_id, }) .collect::>(); insert_chat_messages(conn, &records)?; @@ -345,6 +382,7 @@ fn stream_send_chat_messages( } }); } + fn save_chat_message( conn: DBConnection, chat_id: &str, @@ -359,6 +397,7 @@ fn save_chat_message( created_at: message.created_at.timestamp(), author_type: message.author.author_type as i64, author_id: message.author.author_id.to_string(), + reply_message_id: None, }) .collect::>(); insert_chat_messages(conn, &records)?; diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index cf5ce11e98966..cab3b90847758 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -25,7 +25,7 @@ pub enum ChatMessageTypePB { } #[derive(Default, ProtoBuf, Validate, Clone, Debug)] -pub struct LoadChatMessagePB { +pub struct LoadPrevChatMessagePB { #[pb(index = 1)] #[validate(custom = "required_not_empty_str")] pub chat_id: String, @@ -33,13 +33,23 @@ pub struct LoadChatMessagePB { #[pb(index = 2)] pub limit: i64, - #[pb(index = 3, one_of)] - pub after_message_id: Option, - #[pb(index = 4, one_of)] pub before_message_id: Option, } +#[derive(Default, ProtoBuf, Validate, Clone, Debug)] +pub struct LoadNextChatMessagePB { + #[pb(index = 1)] + #[validate(custom = "required_not_empty_str")] + pub chat_id: String, + + #[pb(index = 2)] + pub limit: i64, + + #[pb(index = 4, one_of)] + pub after_message_id: Option, +} + #[derive(Default, ProtoBuf, Validate, Clone, Debug)] pub struct ChatMessageListPB { #[pb(index = 1)] @@ -87,6 +97,9 @@ pub struct ChatMessagePB { #[pb(index = 6)] pub has_following: bool, + + #[pb(index = 7, one_of)] + pub reply_message_id: Option, } #[derive(Debug, Clone, Default, ProtoBuf)] @@ -110,6 +123,7 @@ impl From for ChatMessagePB { author_type: chat_message.author.author_type as i64, author_id: chat_message.author.author_id.to_string(), has_following: false, + reply_message_id: None, } } } diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 65ae7c8340776..6f2db442770f3 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -37,8 +37,8 @@ pub(crate) async fn send_chat_message_handler( } #[tracing::instrument(level = "debug", skip_all, err)] -pub(crate) async fn load_message_handler( - data: AFPluginData, +pub(crate) async fn load_prev_message_handler( + data: AFPluginData, chat_manager: AFPluginState>, ) -> DataResult { let chat_manager = upgrade_chat_manager(chat_manager)?; @@ -50,3 +50,18 @@ pub(crate) async fn load_message_handler( .await?; data_result_ok(messages) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn load_next_message_handler( + data: AFPluginData, + chat_manager: AFPluginState>, +) -> DataResult { + let chat_manager = upgrade_chat_manager(chat_manager)?; + let data = data.into_inner(); + data.validate()?; + + let messages = chat_manager + .load_latest_chat_messages(&data.chat_id, data.limit, data.after_message_id) + .await?; + data_result_ok(messages) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 80d3ec44705a6..41dd0db445176 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -13,16 +13,20 @@ pub fn init(chat_manager: Weak) -> AFPlugin { .name("Flowy-Chat") .state(chat_manager) .event(ChatEvent::SendMessage, send_chat_message_handler) - .event(ChatEvent::LoadMessage, load_message_handler) + .event(ChatEvent::LoadPrevMessage, load_prev_message_handler) + .event(ChatEvent::LoadNextMessage, load_next_message_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] #[event_err = "FlowyError"] pub enum ChatEvent { /// Create a new workspace - #[event(input = "LoadChatMessagePB", output = "ChatMessageListPB")] - LoadMessage = 0, + #[event(input = "LoadPrevChatMessagePB", output = "ChatMessageListPB")] + LoadPrevMessage = 0, + + #[event(input = "LoadNextChatMessagePB", output = "ChatMessageListPB")] + LoadNextMessage = 1, #[event(input = "SendChatPayloadPB")] - SendMessage = 1, + SendMessage = 2, } diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 9d70f482fcab7..3a2e04a267a46 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -7,7 +7,7 @@ use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use lib_infra::util::timestamp; use std::sync::Arc; -use tracing::instrument; +use tracing::{instrument, trace}; pub trait ChatUserService: Send + Sync + 'static { fn user_id(&self) -> Result; @@ -37,6 +37,7 @@ impl ChatManager { } pub async fn open_chat(&self, chat_id: &str) -> Result<(), FlowyError> { + trace!("open chat: {}", chat_id); self.chats.entry(chat_id.to_string()).or_insert_with(|| { Arc::new(Chat::new( self.user_service.user_id().unwrap(), @@ -127,6 +128,24 @@ impl ChatManager { }, } } + + pub async fn load_latest_chat_messages( + &self, + chat_id: &str, + limit: i64, + after_message_id: Option, + ) -> Result { + let chat = self.chats.get(chat_id).as_deref().cloned(); + match chat { + None => Err(FlowyError::internal().with_context("Should call open chat first")), + Some(chat) => { + let list = chat + .load_latest_chat_messages(limit, after_message_id) + .await?; + Ok(list) + }, + } + } } fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-chat/src/notification.rs b/frontend/rust-lib/flowy-chat/src/notification.rs index e50b8014506c2..15918d57be378 100644 --- a/frontend/rust-lib/flowy-chat/src/notification.rs +++ b/frontend/rust-lib/flowy-chat/src/notification.rs @@ -7,10 +7,11 @@ const CHAT_OBSERVABLE_SOURCE: &str = "Chat"; pub enum ChatNotification { #[default] Unknown = 0, - DidLoadChatMessage = 1, - DidReceiveChatMessage = 2, - ChatMessageError = 3, - FinishAnswerQuestion = 4, + DidLoadLatestChatMessage = 1, + DidLoadPrevChatMessage = 2, + DidReceiveChatMessage = 3, + ChatMessageError = 4, + FinishAnswerQuestion = 5, } impl std::convert::From for i32 { @@ -21,10 +22,11 @@ impl std::convert::From for i32 { impl std::convert::From for ChatNotification { fn from(notification: i32) -> Self { match notification { - 1 => ChatNotification::DidLoadChatMessage, - 2 => ChatNotification::DidReceiveChatMessage, - 3 => ChatNotification::ChatMessageError, + 1 => ChatNotification::DidLoadLatestChatMessage, + 2 => ChatNotification::DidLoadPrevChatMessage, + 3 => ChatNotification::DidReceiveChatMessage, 4 => ChatNotification::ChatMessageError, + 5 => ChatNotification::FinishAnswerQuestion, _ => ChatNotification::Unknown, } } diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs index 9ad18b3b02dd7..0570673152cc9 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs @@ -1,5 +1,7 @@ +use flowy_error::{FlowyError, FlowyResult}; +use flowy_sqlite::upsert::excluded; use flowy_sqlite::{ - diesel, + diesel, insert_into, query_dsl::*, schema::{chat_message_table, chat_message_table::dsl}, DBConnection, ExpressionMethods, Identifiable, Insertable, QueryResult, Queryable, @@ -15,15 +17,33 @@ pub struct ChatMessageTable { pub created_at: i64, pub author_type: i64, pub author_id: String, + pub reply_message_id: Option, } pub fn insert_chat_messages( mut conn: DBConnection, new_messages: &[ChatMessageTable], -) -> QueryResult { - diesel::insert_into(chat_message_table::table) - .values(new_messages) - .execute(&mut *conn) +) -> FlowyResult<()> { + conn.immediate_transaction(|conn| { + for message in new_messages { + let _ = insert_into(chat_message_table::table) + .values(message) + .on_conflict(chat_message_table::message_id) + .do_update() + .set(( + chat_message_table::chat_id.eq(excluded(chat_message_table::chat_id)), + chat_message_table::content.eq(excluded(chat_message_table::content)), + chat_message_table::created_at.eq(excluded(chat_message_table::created_at)), + chat_message_table::author_type.eq(excluded(chat_message_table::author_type)), + chat_message_table::author_id.eq(excluded(chat_message_table::author_id)), + chat_message_table::reply_message_id.eq(excluded(chat_message_table::reply_message_id)), + )) + .execute(conn)?; + } + Ok::<(), FlowyError>(()) + })?; + + Ok(()) } pub fn select_chat_messages( diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index 35d2ffc72b6a6..b3a8f6a1f3aa2 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -796,7 +796,10 @@ impl FolderManager { if let Some(view) = &view { let view_layout: ViewLayout = view.layout.clone().into(); if let Some(handle) = self.operation_handlers.get(&view_layout) { - let _ = handle.open_view(view_id).await; + info!("Open view: {}", view.id); + if let Err(err) = handle.open_view(view_id).await { + error!("Open view error: {:?}", err); + } } } diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql index a46036308ab7b..2e304feb75528 100644 --- a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql @@ -10,12 +10,13 @@ CREATE TABLE chat_table -- Create table for chat messages CREATE TABLE chat_message_table ( - message_id BIGINT PRIMARY KEY NOT NULL, - chat_id TEXT NOT NULL, - content TEXT NOT NULL, - created_at BIGINT NOT NULL, - author_type BIGINT NOT NULL, - author_id TEXT NOT NULL, + message_id BIGINT PRIMARY KEY NOT NULL, + chat_id TEXT NOT NULL, + content TEXT NOT NULL, + created_at BIGINT NOT NULL, + author_type BIGINT NOT NULL, + author_id TEXT NOT NULL, + reply_message_id BIGINT, FOREIGN KEY (chat_id) REFERENCES chat_table (chat_id) ON DELETE CASCADE ); diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index 348f884c2533e..d8c5e260c8c0f 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -8,6 +8,7 @@ diesel::table! { created_at -> BigInt, author_type -> BigInt, author_id -> Text, + reply_message_id -> Nullable, } } From 7524df602ac89f3b85963d97921a57f403e1b198 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 20:39:57 +0800 Subject: [PATCH 22/41] chore: update bloc --- .../ai_chat/application/chat_bloc.dart | 81 ++++++------------- frontend/rust-lib/flowy-chat/src/chat.rs | 2 +- 2 files changed, 26 insertions(+), 57 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 9d3d6d1bb6dd7..7ab845472813e 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -39,13 +39,11 @@ class ChatBloc extends Bloc { add(ChatEvent.streamingChatMessage([error])); }, latestMessageCallback: (list) { - final messages = - list.messages.map((m) => _createChatMessage(m)).toList(); + final messages = list.messages.map(_createChatMessage).toList(); add(ChatEvent.didLoadLatestMessages(messages)); }, prevMessageCallback: (list) { - final messages = - list.messages.map((m) => _createChatMessage(m)).toList(); + final messages = list.messages.map(_createChatMessage).toList(); add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); }, finishAnswerQuestionCallback: () { @@ -88,34 +86,22 @@ class ChatBloc extends Bloc { ); }, didLoadLatestMessages: (List messages) { - final Set uniqueMessages = { - ...state.messages, - ...messages, - }; + final uniqueMessages = {...state.messages, ...messages}.toList() + ..sort((a, b) => b.id.compareTo(a.id)); emit( state.copyWith( - messages: uniqueMessages.toList(), - loadingStatus: const LoadingState.finish(), - ), - ); - emit( - state.copyWith( - messages: uniqueMessages.toList(), + messages: uniqueMessages, loadingStatus: const LoadingState.finish(), ), ); }, didLoadPreviousMessages: (List messages, bool hasMore) { Log.debug("did load previous messages: ${messages.length}"); - // reorder all messages by message id by desc order - final Set uniqueMessages = { - ...state.messages, - ...messages, - }; - + final uniqueMessages = {...state.messages, ...messages}.toList() + ..sort((a, b) => b.id.compareTo(a.id)); emit( state.copyWith( - messages: uniqueMessages.toList(), + messages: uniqueMessages, loadingPreviousStatus: const LoadingState.finish(), hasMore: hasMore, ), @@ -123,15 +109,14 @@ class ChatBloc extends Bloc { }, tapMessage: (Message message) {}, streamingChatMessage: (List messages) { - final List allMessages = List.from(state.messages); - allMessages.removeWhere((element) { - return element.metadata + final allMessages = state.messages.where((element) { + return !(element.metadata ?.containsValue(CustomMessageType.loading) == true || element.metadata ?.containsValue(CustomMessageType.streamError) == - true; - }); + true); + }).toList(); allMessages.insertAll(0, messages); emit(state.copyWith(messages: allMessages)); }, @@ -145,9 +130,9 @@ class ChatBloc extends Bloc { sendMessage: (String message) async { await _handleSentMessage(message, emit); final loadingMessage = - _loaddingMessage(state.userProfile.id.toString()); - final List allMessages = List.from(state.messages); - allMessages.insert(0, loadingMessage); + _loadingMessage(state.userProfile.id.toString()); + final allMessages = List.from(state.messages) + ..insert(0, loadingMessage); emit( state.copyWith( messages: allMessages, @@ -160,9 +145,7 @@ class ChatBloc extends Bloc { ); } - void _loadPrevMessage( - Int64? beforeMessageId, - ) { + void _loadPrevMessage(Int64? beforeMessageId) { final payload = LoadPrevChatMessagePB( chatId: state.view.id, limit: Int64(10), @@ -172,9 +155,7 @@ class ChatBloc extends Bloc { } Future _handleSentMessage( - String message, - Emitter emit, - ) async { + String message, Emitter emit) async { final payload = SendChatPayloadPB( chatId: state.view.id, message: message, @@ -186,25 +167,21 @@ class ChatBloc extends Bloc { void _handleChatMessage(ChatMessagePB pb) { if (!isClosed) { final message = _createChatMessage(pb); - final List messages = []; - if (pb.hasFollowing) { - messages.addAll([_loaddingMessage(0.toString()), message]); - } else { - messages.add(message); - } + final messages = pb.hasFollowing + ? [_loadingMessage(0.toString()), message] + : [message]; add(ChatEvent.streamingChatMessage(messages)); } } - Message _loaddingMessage(String id) { - final loadingMessage = CustomMessage( + Message _loadingMessage(String id) { + return CustomMessage( author: User(id: id), metadata: { CustomMessageType.loading.toString(): CustomMessageType.loading, }, id: 'chat_message_loading_id', ); - return loadingMessage; } Message _createChatMessage(ChatMessagePB message) { @@ -219,10 +196,7 @@ class ChatBloc extends Bloc { } Message? _getReplyMessage(List messages, String messageId) { - final message = messages.firstWhereOrNull( - (element) => element!.id == messageId, - ); - return message; + return messages.firstWhereOrNull((element) => element?.id == messageId); } } @@ -239,9 +213,7 @@ class ChatEvent with _$ChatEvent { const factory ChatEvent.didFinishStreamingChatMessage() = _FinishStreamingMessage; const factory ChatEvent.didLoadPreviousMessages( - List messages, - bool hasMore, - ) = _DidLoadPreviousMessages; + List messages, bool hasMore) = _DidLoadPreviousMessages; } @freezed @@ -256,10 +228,7 @@ class ChatState with _$ChatState { required bool hasMore, }) = _ChatState; - factory ChatState.initial( - ViewPB view, - UserProfilePB userProfile, - ) => + factory ChatState.initial(ViewPB view, UserProfilePB userProfile) => ChatState( view: view, messages: [], diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index 59d56e9545096..ef7368a518dd0 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -324,7 +324,7 @@ fn stream_send_chat_messages( let pb = ChatMessageErrorPB { chat_id: chat_id.clone(), content: message_content.clone(), - error_message: "Service unavailable".to_string(), + error_message: "Service Temporarily Unavailable".to_string(), }; send_notification(&chat_id, ChatNotification::ChatMessageError) .payload(pb) From a77804e109744baa61e3804685043963aee0c30f Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 20:58:27 +0800 Subject: [PATCH 23/41] chore: update test --- .../lib/plugins/ai_chat/chat_page.dart | 67 ++++++++++--------- .../tests/chat/chat_message_test.rs | 2 +- frontend/rust-lib/flowy-chat/src/chat.rs | 6 +- 3 files changed, 38 insertions(+), 37 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index e8d2821577562..789cce87706f2 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -91,7 +91,6 @@ class _AIChatPageState extends State { state.loadingPreviousStatus.when( loading: () => Log.debug("loading"), finish: () { - Log.debug("loading more messages"); blocContext .read() .add(const ChatEvent.loadPrevMessage()); @@ -117,41 +116,43 @@ class _AIChatPageState extends State { ); } - ChatPopupMenu buildBubble(Message message, Widget child) { + Widget buildBubble(Message message, Widget child) { final isAuthor = message.author.id == _user.id; const borderRadius = BorderRadius.all(Radius.circular(20)); - if (isMobile) {} - - return ChatPopupMenu( - onAction: (action) { - switch (action) { - case ChatMessageAction.copy: - if (message is TextMessage) { - Clipboard.setData( - ClipboardData(text: message.text), - ); - showMessageToast( - LocaleKeys.grid_row_copyProperty.tr(), - ); - } - break; - } - }, - builder: (context) { - return DecoratedBox( - decoration: BoxDecoration( - borderRadius: borderRadius, - color: !isAuthor || message.type == types.MessageType.image - ? AFThemeExtension.of(context).tint1 - : Theme.of(context).colorScheme.primary, - ), - child: ClipRRect( - borderRadius: borderRadius, - child: Container(child: child), - ), - ); - }, + final decoratedChild = DecoratedBox( + decoration: BoxDecoration( + borderRadius: borderRadius, + color: !isAuthor || message.type == types.MessageType.image + ? AFThemeExtension.of(context).tint1 + : Theme.of(context).colorScheme.primary, + ), + child: ClipRRect( + borderRadius: borderRadius, + child: Container(child: child), + ), ); + + if (isMobile) { + return ChatPopupMenu( + onAction: (action) { + switch (action) { + case ChatMessageAction.copy: + if (message is TextMessage) { + Clipboard.setData( + ClipboardData(text: message.text), + ); + showMessageToast( + LocaleKeys.grid_row_copyProperty.tr(), + ); + } + break; + } + }, + builder: (context) => decoratedChild, + ); + } else { + return decoratedChild; + } } AFDefaultChatTheme buildTheme(BuildContext context) { diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index f9fc6c13e714c..ff59e6114f815 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -116,7 +116,7 @@ async fn af_cloud_load_remote_system_message_test() { // Load first five messages let rx = test .notification_sender - .subscribe::(&chat_id, ChatNotification::DidLoadLatestChatMessage); + .subscribe::(&chat_id, ChatNotification::DidLoadPrevChatMessage); test .load_prev_message(&chat_id, 5, Some(next_back_five.messages[4].message_id)) .await; diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index ef7368a518dd0..c850f71100e6a 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -333,9 +333,6 @@ fn stream_send_chat_messages( }, } } - - // Mark chat as finished - send_notification(&chat_id, ChatNotification::FinishAnswerQuestion).send(); }, Err(err) => { error!("Failed to send chat message: {}", err); @@ -376,6 +373,9 @@ fn stream_send_chat_messages( }) .collect::>(); insert_chat_messages(conn, &records)?; + + // Mark chat as finished + send_notification(&chat_id, ChatNotification::FinishAnswerQuestion).send(); Ok(()) }) { error!("Failed to save chat messages: {}", err); From f7880dec5ee122083d18daec4e025b7bdf4783da Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 22:21:19 +0800 Subject: [PATCH 24/41] chore: lint --- .../ai_chat/application/chat_bloc.dart | 8 ++- .../lib/plugins/ai_chat/chat_page.dart | 49 ++++++---------- .../presentation/chat_message_hover.dart | 0 frontend/rust-lib/flowy-chat/src/manager.rs | 56 ++++++++++--------- .../src/persistence/chat_message_sql.rs | 1 - .../flowy-chat/src/persistence/chat_sql.rs | 7 +++ .../2024-05-23-061639_chat_message/up.sql | 7 +-- frontend/rust-lib/flowy-sqlite/src/schema.rs | 2 - 8 files changed, 62 insertions(+), 68 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 7ab845472813e..959218dd69d62 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -155,7 +155,9 @@ class ChatBloc extends Bloc { } Future _handleSentMessage( - String message, Emitter emit) async { + String message, + Emitter emit, + ) async { final payload = SendChatPayloadPB( chatId: state.view.id, message: message, @@ -213,7 +215,9 @@ class ChatEvent with _$ChatEvent { const factory ChatEvent.didFinishStreamingChatMessage() = _FinishStreamingMessage; const factory ChatEvent.didLoadPreviousMessages( - List messages, bool hasMore) = _DidLoadPreviousMessages; + List messages, + bool hasMore, + ) = _DidLoadPreviousMessages; } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 789cce87706f2..e5d9561cf5360 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -1,7 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart'; -import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -34,16 +33,14 @@ class AIChatPage extends StatefulWidget { } class _AIChatPageState extends State { + late types.User _user; + @override void initState() { super.initState(); - _user = types.User( - id: widget.userProfile.id.toString(), - ); + _user = types.User(id: widget.userProfile.id.toString()); } - late types.User _user; - @override Widget build(BuildContext context) { return SizedBox.expand( @@ -57,7 +54,9 @@ class _AIChatPageState extends State { child: BlocListener( listenWhen: (previous, current) => previous.loadingStatus != current.loadingStatus, - listener: (context, state) {}, + listener: (context, state) { + // Handle state changes if necessary + }, child: BlocBuilder( builder: (blocContext, state) { return Chat( @@ -69,13 +68,11 @@ class _AIChatPageState extends State { .add(ChatEvent.tapMessage(message)); }, onSendPressed: (types.PartialText message) { - // Do nothing. We use the custom input widget. - // onSendPressed(blocContext, message); + // Custom input handling, so do nothing here }, customBottomWidget: ChatInput( - onSendPressed: (message) { - onSendPressed(blocContext, message); - }, + onSendPressed: (message) => + onSendPressed(blocContext, message), ), user: _user, theme: buildTheme(context), @@ -87,15 +84,12 @@ class _AIChatPageState extends State { ); }, onEndReached: () async { - if (state.hasMore) { - state.loadingPreviousStatus.when( - loading: () => Log.debug("loading"), - finish: () { - blocContext - .read() - .add(const ChatEvent.loadPrevMessage()); - }, - ); + if (state.hasMore && + state.loadingPreviousStatus != + const LoadingState.loading()) { + blocContext + .read() + .add(const ChatEvent.loadPrevMessage()); } }, emptyState: const Center( @@ -138,12 +132,8 @@ class _AIChatPageState extends State { switch (action) { case ChatMessageAction.copy: if (message is TextMessage) { - Clipboard.setData( - ClipboardData(text: message.text), - ); - showMessageToast( - LocaleKeys.grid_row_copyProperty.tr(), - ); + Clipboard.setData(ClipboardData(text: message.text)); + showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); } break; } @@ -201,10 +191,7 @@ class _AIChatPageState extends State { ); } - void onSendPressed( - BuildContext context, - types.PartialText message, - ) { + void onSendPressed(BuildContext context, types.PartialText message) { context.read().add(ChatEvent.sendMessage(message.text)); } } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 3a2e04a267a46..7cf34a6e48b38 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -61,7 +61,7 @@ impl ChatManager { Ok(()) } - pub async fn create_chat(&self, uid: &i64, chat_id: &str) -> Result<(), FlowyError> { + pub async fn create_chat(&self, uid: &i64, chat_id: &str) -> Result, FlowyError> { let workspace_id = self.user_service.workspace_id()?; self .cloud_service @@ -75,8 +75,8 @@ impl ChatManager { self.user_service.clone(), self.cloud_service.clone(), )); - self.chats.insert(chat_id.to_string(), chat); - Ok(()) + self.chats.insert(chat_id.to_string(), chat.clone()); + Ok(chat) } #[instrument(level = "info", skip_all, err)] @@ -86,13 +86,25 @@ impl ChatManager { message: &str, message_type: ChatMessageType, ) -> Result<(), FlowyError> { + let chat = self.get_or_create_chat_instance(chat_id).await?; + chat.send_chat_message(message, message_type).await?; + Ok(()) + } + + pub async fn get_or_create_chat_instance(&self, chat_id: &str) -> Result, FlowyError> { let chat = self.chats.get(chat_id).as_deref().cloned(); match chat { - None => Err(FlowyError::internal().with_context("Should call open chat first")), - Some(chat) => { - chat.send_chat_message(message, message_type).await?; - Ok(()) + None => { + let chat = Arc::new(Chat::new( + self.user_service.user_id().unwrap(), + chat_id.to_string(), + self.user_service.clone(), + self.cloud_service.clone(), + )); + self.chats.insert(chat_id.to_string(), chat.clone()); + Ok(chat) }, + Some(chat) => Ok(chat), } } @@ -117,16 +129,11 @@ impl ChatManager { limit: i64, before_message_id: Option, ) -> Result { - let chat = self.chats.get(chat_id).as_deref().cloned(); - match chat { - None => Err(FlowyError::internal().with_context("Should call open chat first")), - Some(chat) => { - let list = chat - .load_prev_chat_messages(limit, before_message_id) - .await?; - Ok(list) - }, - } + let chat = self.get_or_create_chat_instance(chat_id).await?; + let list = chat + .load_prev_chat_messages(limit, before_message_id) + .await?; + Ok(list) } pub async fn load_latest_chat_messages( @@ -135,16 +142,11 @@ impl ChatManager { limit: i64, after_message_id: Option, ) -> Result { - let chat = self.chats.get(chat_id).as_deref().cloned(); - match chat { - None => Err(FlowyError::internal().with_context("Should call open chat first")), - Some(chat) => { - let list = chat - .load_latest_chat_messages(limit, after_message_id) - .await?; - Ok(list) - }, - } + let chat = self.get_or_create_chat_instance(chat_id).await?; + let list = chat + .load_latest_chat_messages(limit, after_message_id) + .await?; + Ok(list) } } diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs index 0570673152cc9..6d9202def02e5 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs @@ -31,7 +31,6 @@ pub fn insert_chat_messages( .on_conflict(chat_message_table::message_id) .do_update() .set(( - chat_message_table::chat_id.eq(excluded(chat_message_table::chat_id)), chat_message_table::content.eq(excluded(chat_message_table::content)), chat_message_table::created_at.eq(excluded(chat_message_table::created_at)), chat_message_table::author_type.eq(excluded(chat_message_table::author_type)), diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs index 85b5fea13da00..1fd0480c54810 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_sql.rs @@ -1,3 +1,4 @@ +use flowy_sqlite::upsert::excluded; use flowy_sqlite::{ diesel, query_dsl::*, @@ -17,6 +18,12 @@ pub struct ChatTable { pub fn insert_chat(mut conn: DBConnection, new_chat: &ChatTable) -> QueryResult { diesel::insert_into(chat_table::table) .values(new_chat) + .on_conflict(chat_table::chat_id) + .do_update() + .set(( + chat_table::created_at.eq(excluded(chat_table::created_at)), + chat_table::name.eq(excluded(chat_table::name)), + )) .execute(&mut *conn) } diff --git a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql index 2e304feb75528..192e7cf763305 100644 --- a/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql +++ b/frontend/rust-lib/flowy-sqlite/migrations/2024-05-23-061639_chat_message/up.sql @@ -1,4 +1,3 @@ --- Your SQL goes here -- Create table for chat documents CREATE TABLE chat_table ( @@ -16,8 +15,6 @@ CREATE TABLE chat_message_table created_at BIGINT NOT NULL, author_type BIGINT NOT NULL, author_id TEXT NOT NULL, - reply_message_id BIGINT, - FOREIGN KEY (chat_id) REFERENCES chat_table (chat_id) ON DELETE CASCADE + reply_message_id BIGINT ); - -CREATE INDEX idx_chat_messages_chat_id_created_at ON chat_message_table (message_id ASC, created_at ASC); +CREATE INDEX idx_chat_messages_chat_id_message_id ON chat_message_table (chat_id, message_id); diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index d8c5e260c8c0f..24290ea5d85df 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -67,8 +67,6 @@ diesel::table! { } } -diesel::joinable!(chat_message_table -> chat_table (chat_id)); - diesel::allow_tables_to_appear_in_same_query!( chat_message_table, chat_table, From 83efb5cff744fe184a27a62636b32a5be810b87c Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 23:15:45 +0800 Subject: [PATCH 25/41] chore: icon --- .github/workflows/flutter_ci.yaml | 1 + frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart | 1 + .../lib/plugins/ai_chat/presentation/chat_theme.dart | 2 +- .../lib/workspace/application/view/view_ext.dart | 3 ++- frontend/resources/flowy_icons/16x/chat_ai_page.svg | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 frontend/resources/flowy_icons/16x/chat_ai_page.svg diff --git a/.github/workflows/flutter_ci.yaml b/.github/workflows/flutter_ci.yaml index b944187ec4047..e29e0e3869f8a 100644 --- a/.github/workflows/flutter_ci.yaml +++ b/.github/workflows/flutter_ci.yaml @@ -89,6 +89,7 @@ jobs: with: os: ${{ matrix.os }} flutter_version: ${{ env.FLUTTER_VERSION }} + DISABLE_CI_TEST_LOG: "true" rust_toolchain: ${{ env.RUST_TOOLCHAIN }} cargo_make_version: ${{ env.CARGO_MAKE_VERSION }} rust_target: ${{ matrix.target }} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index e5d9561cf5360..43f1c61cdda51 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -95,6 +95,7 @@ class _AIChatPageState extends State { emptyState: const Center( child: CircularProgressIndicator.adaptive(), ), + messageWidthRatio: 0.92, bubbleBuilder: ( child, { required message, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart index 4c8ceac535d3d..f3bad391bd5f9 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart @@ -102,7 +102,7 @@ class AFDefaultChatTheme extends ChatTheme { super.messageBorderRadius = 20, super.messageInsetsHorizontal = 20, super.messageInsetsVertical = 16, - super.messageMaxWidth = 440, + super.messageMaxWidth = 1000, super.primaryColor = primary, super.receivedEmojiMessageTextStyle = const TextStyle(fontSize: 40), super.receivedMessageBodyBoldTextStyle, diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart index 07768e6887c6f..3240fae8a1dfb 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -45,6 +45,7 @@ extension ViewExtension on ViewPB { ViewLayoutPB.Calendar => FlowySvgs.date_s, ViewLayoutPB.Grid => FlowySvgs.grid_s, ViewLayoutPB.Document => FlowySvgs.document_s, + ViewLayoutPB.Chat => FlowySvgs.chat_ai_page_s, _ => FlowySvgs.document_s, }, ); @@ -165,7 +166,7 @@ extension ViewLayoutExtension on ViewLayoutPB { ViewLayoutPB.Board => FlowySvgs.board_s, ViewLayoutPB.Calendar => FlowySvgs.date_s, ViewLayoutPB.Document => FlowySvgs.document_s, - ViewLayoutPB.Chat => FlowySvgs.document_s, + ViewLayoutPB.Chat => FlowySvgs.chat_ai_page_s, _ => throw Exception('Unknown layout type'), }; diff --git a/frontend/resources/flowy_icons/16x/chat_ai_page.svg b/frontend/resources/flowy_icons/16x/chat_ai_page.svg new file mode 100644 index 0000000000000..ce748ff5bc982 --- /dev/null +++ b/frontend/resources/flowy_icons/16x/chat_ai_page.svg @@ -0,0 +1 @@ + \ No newline at end of file From 3eb75c9f506f18290237c5333f1126e0148d7de3 Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 30 May 2024 23:36:04 +0800 Subject: [PATCH 26/41] chore: hover --- .../lib/plugins/ai_chat/chat_page.dart | 17 ++- .../presentation/chat_message_hover.dart | 106 ++++++++++++++++++ 2 files changed, 117 insertions(+), 6 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 43f1c61cdda51..506439eff13d2 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -13,6 +13,7 @@ import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'presentation/chat_input.dart'; +import 'presentation/chat_message_hover.dart'; import 'presentation/chat_popmenu.dart'; import 'presentation/chat_theme.dart'; @@ -121,10 +122,7 @@ class _AIChatPageState extends State { ? AFThemeExtension.of(context).tint1 : Theme.of(context).colorScheme.primary, ), - child: ClipRRect( - borderRadius: borderRadius, - child: Container(child: child), - ), + child: child, ); if (isMobile) { @@ -139,10 +137,17 @@ class _AIChatPageState extends State { break; } }, - builder: (context) => decoratedChild, + builder: (context) => + ClipRRect(borderRadius: borderRadius, child: decoratedChild), ); } else { - return decoratedChild; + return ClipRRect( + borderRadius: borderRadius, + child: ChatMessageHover( + message: message, + child: decoratedChild, + ), + ); } } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart index e69de29bb2d1d..4a1f59cbdd8c7 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart @@ -0,0 +1,106 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/workspace/presentation/home/toast.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra/theme_extension.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; +import 'package:styled_widget/styled_widget.dart'; + +class ChatMessageHover extends StatefulWidget { + const ChatMessageHover({ + super.key, + required this.child, + required this.message, + }); + + final Widget child; + final Message message; + + @override + State createState() => _ChatMessageHoverState(); +} + +class _ChatMessageHoverState extends State { + bool _isHover = false; + + @override + Widget build(BuildContext context) { + final List children = [ + DecoratedBox( + decoration: BoxDecoration( + color: _isHover + ? AFThemeExtension.of(context).lightGreyHover + : Colors.transparent, + borderRadius: Corners.s6Border, + ), + child: widget.child, + ), + ]; + + if (_isHover) { + if (widget.message is TextMessage) { + children.add( + Padding( + padding: const EdgeInsets.only(right: 6), + child: CopyButton( + textMessage: widget.message as TextMessage, + ), + ).positioned(top: 12, left: 12), + ); + } + } + + return MouseRegion( + cursor: SystemMouseCursors.click, + opaque: false, + onEnter: (p) => setState(() => _isHover = true), + onExit: (p) => setState(() => _isHover = false), + child: Stack( + alignment: AlignmentDirectional.center, + children: children, + ), + ); + } +} + +class CopyButton extends StatelessWidget { + const CopyButton({ + super.key, + required this.textMessage, + }); + final TextMessage textMessage; + + @override + Widget build(BuildContext context) { + return FlowyTooltip( + message: LocaleKeys.settings_menu_clickToCopy.tr(), + child: Container( + width: 26, + height: 26, + decoration: BoxDecoration( + border: Border.fromBorderSide( + BorderSide(color: Theme.of(context).dividerColor), + ), + borderRadius: Corners.s6Border, + ), + child: FlowyIconButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, + fillColor: Theme.of(context).cardColor, + icon: FlowySvg( + FlowySvgs.ai_copy_s, + color: Theme.of(context).colorScheme.primary, + ), + onPressed: () { + Clipboard.setData(ClipboardData(text: textMessage.text)); + showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); + }, + ), + ), + ); + } +} From 593b0b55854328fb697b816ed58bb375507a19f3 Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 31 May 2024 09:59:43 +0800 Subject: [PATCH 27/41] chore: show unsupported page --- .../lib/plugins/ai_chat/chat_page.dart | 117 ++++++++++-------- .../ai_chat/presentation/chat_input.dart | 16 --- .../home/menu/menu_shared_state.dart | 4 +- .../home/menu/view/view_item.dart | 2 +- .../flowy_icons/16x/chat_ai_page.svg | 2 +- frontend/resources/translations/en.json | 5 +- .../tests/chat/chat_message_test.rs | 6 +- 7 files changed, 76 insertions(+), 76 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 506439eff13d2..df0e214dd648c 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -5,6 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -44,6 +45,14 @@ class _AIChatPageState extends State { @override Widget build(BuildContext context) { + if (widget.userProfile.authenticator == AuthenticatorPB.AppFlowyCloud) { + return buildChatWidget(); + } else { + return buildUnsupportWidget(); + } + } + + Widget buildChatWidget() { return SizedBox.expand( child: Padding( padding: const EdgeInsets.all(10), @@ -52,66 +61,68 @@ class _AIChatPageState extends State { view: widget.view, userProfile: widget.userProfile, )..add(const ChatEvent.initialLoad()), - child: BlocListener( - listenWhen: (previous, current) => - previous.loadingStatus != current.loadingStatus, - listener: (context, state) { - // Handle state changes if necessary - }, - child: BlocBuilder( - builder: (blocContext, state) { - return Chat( - messages: state.messages, - onAttachmentPressed: () {}, - onMessageTap: (BuildContext _, types.Message message) { + child: BlocBuilder( + builder: (blocContext, state) { + return Chat( + messages: state.messages, + onAttachmentPressed: () {}, + onMessageTap: (BuildContext _, types.Message message) { + blocContext + .read() + .add(ChatEvent.tapMessage(message)); + }, + onSendPressed: (types.PartialText message) { + // Custom input handling, so do nothing here + }, + customBottomWidget: ChatInput( + onSendPressed: (message) => + onSendPressed(blocContext, message), + ), + user: _user, + theme: buildTheme(context), + customMessageBuilder: (message, {required messageWidth}) { + return const SizedBox( + width: 100, + height: 50, + child: CircularProgressIndicator.adaptive(), + ); + }, + onEndReached: () async { + if (state.hasMore && + state.loadingPreviousStatus != + const LoadingState.loading()) { blocContext .read() - .add(ChatEvent.tapMessage(message)); - }, - onSendPressed: (types.PartialText message) { - // Custom input handling, so do nothing here - }, - customBottomWidget: ChatInput( - onSendPressed: (message) => - onSendPressed(blocContext, message), - ), - user: _user, - theme: buildTheme(context), - customMessageBuilder: (message, {required messageWidth}) { - return const SizedBox( - width: 100, - height: 50, - child: CircularProgressIndicator.adaptive(), - ); - }, - onEndReached: () async { - if (state.hasMore && - state.loadingPreviousStatus != - const LoadingState.loading()) { - blocContext - .read() - .add(const ChatEvent.loadPrevMessage()); - } - }, - emptyState: const Center( - child: CircularProgressIndicator.adaptive(), - ), - messageWidthRatio: 0.92, - bubbleBuilder: ( - child, { - required message, - required nextMessageInGroup, - }) => - buildBubble(message, child), - ); - }, - ), + .add(const ChatEvent.loadPrevMessage()); + } + }, + emptyState: const Center( + child: CircularProgressIndicator.adaptive(), + ), + messageWidthRatio: 0.92, + bubbleBuilder: ( + child, { + required message, + required nextMessageInGroup, + }) => + buildBubble(message, child), + ); + }, ), ), ), ); } + Widget buildUnsupportWidget() { + return Center( + child: FlowyText( + LocaleKeys.chat_unsupportedCloudPrompt.tr(), + fontSize: 20, + ), + ); + } + Widget buildBubble(Message message, Widget child) { final isAuthor = message.author.id == _user.id; const borderRadius = BorderRadius.all(Radius.circular(20)); @@ -120,7 +131,7 @@ class _AIChatPageState extends State { borderRadius: borderRadius, color: !isAuthor || message.type == types.MessageType.image ? AFThemeExtension.of(context).tint1 - : Theme.of(context).colorScheme.primary, + : Theme.of(context).colorScheme.secondary, ), child: child, ); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart index af8897392af41..031350d3b8474 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -5,11 +5,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; -// final isMobile = defaultTargetPlatform == TargetPlatform.android || -// defaultTargetPlatform == TargetPlatform.iOS; - -/// A class that represents bottom bar widget with a text field, attachment and -/// send buttons inside. By default hides send button when text field is empty. class ChatInput extends StatefulWidget { /// Creates [ChatInput] widget. const ChatInput({ @@ -20,20 +15,9 @@ class ChatInput extends StatefulWidget { this.options = const InputOptions(), }); - /// Whether attachment is uploading. Will replace attachment button with a - /// [CircularProgressIndicator]. Since we don't have libraries for - /// managing media in dependencies we have no way of knowing if - /// something is uploading so you need to set this manually. final bool? isAttachmentUploading; - - /// See [AttachmentButton.onPressed]. final VoidCallback? onAttachmentPressed; - - /// Will be called on [SendButton] tap. Has [types.PartialText] which can - /// be transformed to [types.TextMessage] and added to the messages list. final void Function(types.PartialText) onSendPressed; - - /// Customisation options for the [ChatInput]. final InputOptions options; @override diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu_shared_state.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu_shared_state.dart index 535c89be4e0b0..732824a16e046 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu_shared_state.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu_shared_state.dart @@ -2,7 +2,9 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:flutter/material.dart'; class MenuSharedState { - MenuSharedState({ViewPB? view}) { + MenuSharedState({ + ViewPB? view, + }) { _latestOpenView.value = view; } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart index f5cf360c8cbec..a255fbf246f69 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart @@ -677,7 +677,7 @@ class _SingleInnerViewItemState extends State { case ViewLayoutPB.Calendar: return LocaleKeys.newCalendarText.tr(); case ViewLayoutPB.Chat: - return LocaleKeys.newChatText.tr(); + return LocaleKeys.chat_newChat.tr(); } return LocaleKeys.newPageText.tr(); } diff --git a/frontend/resources/flowy_icons/16x/chat_ai_page.svg b/frontend/resources/flowy_icons/16x/chat_ai_page.svg index ce748ff5bc982..593ee60eeeb42 100644 --- a/frontend/resources/flowy_icons/16x/chat_ai_page.svg +++ b/frontend/resources/flowy_icons/16x/chat_ai_page.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 86a65956f0fe0..a07586a3bc76d 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -147,7 +147,10 @@ "newGridText": "New grid", "newCalendarText": "New calendar", "newBoardText": "New board", - "newChatText": "New chat", + "chat": { + "newChat": "New chat", + "unsupportedCloudPrompt": "This feature is only available when using AppFlowy Cloud" + }, "trash": { "text": "Trash", "restoreAll": "Restore All", diff --git a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs index ff59e6114f815..1efe4c77d0c40 100644 --- a/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs +++ b/frontend/rust-lib/event-integration-test/tests/chat/chat_message_test.rs @@ -101,7 +101,7 @@ async fn af_cloud_load_remote_system_message_test() { assert!(all.messages.is_empty()); // Wait for the messages to be loaded. - let next_back_five = receive_with_timeout(rx, Duration::from_secs(30)) + let next_back_five = receive_with_timeout(rx, Duration::from_secs(60)) .await .unwrap(); assert_eq!(next_back_five.messages.len(), 5); @@ -120,7 +120,7 @@ async fn af_cloud_load_remote_system_message_test() { test .load_prev_message(&chat_id, 5, Some(next_back_five.messages[4].message_id)) .await; - let first_five_messages = receive_with_timeout(rx, Duration::from_secs(30)) + let first_five_messages = receive_with_timeout(rx, Duration::from_secs(60)) .await .unwrap(); assert!(!first_five_messages.has_more); @@ -146,7 +146,7 @@ async fn af_cloud_load_remote_user_message_test() { test .send_message(&chat_id, "hello world", ChatMessageTypePB::User) .await; - let _ = receive_with_timeout(rx, Duration::from_secs(30)) + let _ = receive_with_timeout(rx, Duration::from_secs(60)) .await .unwrap(); From 9f89f0cb6625783866828088e209a9976aab66d1 Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 31 May 2024 10:19:18 +0800 Subject: [PATCH 28/41] chore: adjust mobile ui --- .../lib/plugins/ai_chat/chat_page.dart | 28 ++++- .../ai_chat/presentation/chat_input.dart | 111 ++++++++---------- frontend/rust-lib/flowy-chat/src/manager.rs | 4 +- 3 files changed, 74 insertions(+), 69 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index df0e214dd648c..0bb055b74a741 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -72,12 +72,10 @@ class _AIChatPageState extends State { .add(ChatEvent.tapMessage(message)); }, onSendPressed: (types.PartialText message) { - // Custom input handling, so do nothing here + // We use custom bottom widget for chat input, so + // do not need to handle this event. }, - customBottomWidget: ChatInput( - onSendPressed: (message) => - onSendPressed(blocContext, message), - ), + customBottomWidget: buildChatInput(blocContext), user: _user, theme: buildTheme(context), customMessageBuilder: (message, {required messageWidth}) { @@ -99,7 +97,7 @@ class _AIChatPageState extends State { emptyState: const Center( child: CircularProgressIndicator.adaptive(), ), - messageWidthRatio: 0.92, + messageWidthRatio: 0.7, bubbleBuilder: ( child, { required message, @@ -162,6 +160,24 @@ class _AIChatPageState extends State { } } + Widget buildChatInput(BuildContext context) { + final query = MediaQuery.of(context); + final safeAreaInsets = isMobile + ? EdgeInsets.fromLTRB( + query.padding.left, + 0, + query.padding.right, + query.viewInsets.bottom + query.padding.bottom, + ) + : EdgeInsets.zero; + return Padding( + padding: safeAreaInsets, + child: ChatInput( + onSendPressed: (message) => onSendPressed(context, message), + ), + ); + } + AFDefaultChatTheme buildTheme(BuildContext context) { return AFDefaultChatTheme( backgroundColor: AFThemeExtension.of(context).background, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart index 031350d3b8474..0d091d61586fd 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -96,84 +96,73 @@ class _ChatInputState extends State { } Widget _inputBuilder() { - final query = MediaQuery.of(context); const textPadding = EdgeInsets.symmetric(horizontal: 16, vertical: 6); const buttonPadding = EdgeInsets.symmetric(horizontal: 16, vertical: 6); const inputPadding = EdgeInsets.all(6); - final safeAreaInsets = isMobile - ? EdgeInsets.fromLTRB( - query.padding.left, - 0, - query.padding.right, - query.viewInsets.bottom + query.padding.bottom, - ) - : EdgeInsets.zero; - return Focus( autofocus: !widget.options.autofocus, child: Padding( padding: inputPadding, child: Material( borderRadius: BorderRadius.circular(12), - color: Theme.of(context).colorScheme.surfaceContainerHighest, + color: isMobile + ? Theme.of(context).colorScheme.surfaceContainer + : Theme.of(context).colorScheme.surfaceContainerHighest, elevation: 0.6, - child: Container( - padding: safeAreaInsets, - child: Row( - textDirection: TextDirection.ltr, - children: [ - if (widget.onAttachmentPressed != null) - AttachmentButton( - isLoading: widget.isAttachmentUploading ?? false, - onPressed: widget.onAttachmentPressed, - padding: buttonPadding, - ), - Expanded( - child: Padding( - padding: textPadding, - child: TextField( - enabled: widget.options.enabled, - autocorrect: widget.options.autocorrect, - autofocus: widget.options.autofocus, - enableSuggestions: widget.options.enableSuggestions, - controller: _textController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: '', - hintStyle: TextStyle( - color: AFThemeExtension.of(context) - .textColor - .withOpacity(0.5), - ), - ), - focusNode: _inputFocusNode, - keyboardType: widget.options.keyboardType, - maxLines: 5, - minLines: 1, - onChanged: widget.options.onTextChanged, - onTap: widget.options.onTextFieldTap, - style: TextStyle( - color: AFThemeExtension.of(context).textColor, + child: Row( + textDirection: TextDirection.ltr, + children: [ + if (widget.onAttachmentPressed != null) + AttachmentButton( + isLoading: widget.isAttachmentUploading ?? false, + onPressed: widget.onAttachmentPressed, + padding: buttonPadding, + ), + Expanded( + child: Padding( + padding: textPadding, + child: TextField( + enabled: widget.options.enabled, + autocorrect: widget.options.autocorrect, + autofocus: widget.options.autofocus, + enableSuggestions: widget.options.enableSuggestions, + controller: _textController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: '', + hintStyle: TextStyle( + color: AFThemeExtension.of(context) + .textColor + .withOpacity(0.5), ), - textCapitalization: TextCapitalization.sentences, ), + focusNode: _inputFocusNode, + keyboardType: widget.options.keyboardType, + maxLines: 5, + minLines: 1, + onChanged: widget.options.onTextChanged, + onTap: widget.options.onTextFieldTap, + style: TextStyle( + color: AFThemeExtension.of(context).textColor, + ), + textCapitalization: TextCapitalization.sentences, ), ), - ConstrainedBox( - constraints: BoxConstraints( - minHeight: buttonPadding.bottom + buttonPadding.top + 24, - ), - child: Visibility( - visible: _sendButtonVisible, - child: SendButton( - onPressed: _handleSendPressed, - padding: buttonPadding, - ), + ), + ConstrainedBox( + constraints: BoxConstraints( + minHeight: buttonPadding.bottom + buttonPadding.top + 24, + ), + child: Visibility( + visible: _sendButtonVisible, + child: SendButton( + onPressed: _handleSendPressed, + padding: buttonPadding, ), ), - ], - ), + ), + ], ), ), ), diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 7cf34a6e48b38..1bc2f63b4f2ca 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -19,7 +19,7 @@ pub trait ChatUserService: Send + Sync + 'static { pub struct ChatManager { cloud_service: Arc, user_service: Arc, - chats: DashMap>, + chats: Arc>>, } impl ChatManager { @@ -32,7 +32,7 @@ impl ChatManager { Self { cloud_service, user_service, - chats: DashMap::new(), + chats: Arc::new(DashMap::new()), } } From e0b1a9491f3d0aac2f21b18153f4cc1fa358eecb Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 31 May 2024 10:30:20 +0800 Subject: [PATCH 29/41] chore: adjust view title bar --- .../appflowy_flutter/lib/plugins/ai_chat/chat.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart index 3036c570b6426..cb69ee8d8d734 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart @@ -1,13 +1,12 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; -import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/chat_page.dart'; import 'package:appflowy/plugins/util.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/application/view_info/view_info_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; +import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart'; +import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -25,7 +24,7 @@ class AIChatPluginBuilder extends PluginBuilder { String get menuName => "AIChat"; @override - FlowySvgData get icon => FlowySvgs.ai_summary_s; + FlowySvgData get icon => FlowySvgs.chat_ai_page_s; @override PluginType get pluginType => PluginType.chat; @@ -80,10 +79,11 @@ class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder int? deletedViewIndex; @override - Widget get leftBarItem => FlowyText.medium(LocaleKeys.blankPageTitle.tr()); + Widget get leftBarItem => + ViewTitleBar(key: ValueKey(notifier.view.id), view: notifier.view); @override - Widget tabBarItem(String pluginId) => leftBarItem; + Widget tabBarItem(String pluginId) => ViewTabBarItem(view: notifier.view); @override Widget buildWidget({ From 2926fc0fbac3b3483b558300d0075bd0a114e415 Mon Sep 17 00:00:00 2001 From: nathan Date: Sun, 2 Jun 2024 12:54:07 +0800 Subject: [PATCH 30/41] chore: return related question --- .../application/chat_ai_message_bloc.dart | 42 ++++ .../ai_chat/application/chat_bloc.dart | 70 +++++-- .../application/chat_message_listener.dart | 96 ++++----- .../chat_related_question_bloc.dart | 103 +++++++++ .../application/chat_user_message_bloc.dart | 44 ++++ .../lib/plugins/ai_chat/chat_page.dart | 179 +++++++++++----- .../ai_chat/presentation/chat_ai_message.dart | 197 ++++++++++++++++++ .../ai_chat/presentation/chat_avatar.dart | 184 ++++++++++++++++ .../presentation/chat_error_message.dart | 43 ++++ .../ai_chat/presentation/chat_input.dart | 117 ++++++----- .../presentation/chat_message_hover.dart | 106 ---------- .../presentation/chat_related_question.dart | 81 +++++++ .../ai_chat/presentation/chat_theme.dart | 4 +- .../presentation/chat_user_message.dart | 174 ++++++++++++++++ .../presentation/chat_welcome_page.dart | 10 + .../lib/style_widget/button.dart | 2 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 34 +-- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 29 +-- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 31 +-- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/resources/translations/en.json | 7 +- frontend/rust-lib/Cargo.lock | 28 +-- frontend/rust-lib/Cargo.toml | 2 +- frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 8 + frontend/rust-lib/flowy-chat/src/chat.rs | 40 +++- frontend/rust-lib/flowy-chat/src/entities.rs | 49 ++++- .../rust-lib/flowy-chat/src/event_handler.rs | 13 ++ frontend/rust-lib/flowy-chat/src/event_map.rs | 4 + frontend/rust-lib/flowy-chat/src/manager.rs | 12 +- .../rust-lib/flowy-chat/src/notification.rs | 2 + .../flowy-core/src/integrate/trait_impls.rs | 18 ++ .../flowy-server/src/af_cloud/impls/chat.rs | 21 ++ .../src/af_cloud/impls/user/dto.rs | 1 + .../rust-lib/flowy-server/src/default_impl.rs | 12 ++ .../rust-lib/flowy-user-pub/src/entities.rs | 1 + .../flowy-user/src/entities/workspace.rs | 4 + 38 files changed, 1417 insertions(+), 357 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_ai_message_bloc.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_message_bloc.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart delete mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_welcome_page.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_ai_message_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_ai_message_bloc.dart new file mode 100644 index 0000000000000..2c5c8f5b0e36b --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_ai_message_bloc.dart @@ -0,0 +1,42 @@ +import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'chat_ai_message_bloc.freezed.dart'; + +class ChatAIMessageBloc extends Bloc { + ChatAIMessageBloc({ + required Message message, + }) : super(ChatAIMessageState.initial(message)) { + on( + (event, emit) async { + await event.when( + initial: () async {}, + update: (userProfile, deviceId, states) {}, + ); + }, + ); + } +} + +@freezed +class ChatAIMessageEvent with _$ChatAIMessageEvent { + const factory ChatAIMessageEvent.initial() = Initial; + const factory ChatAIMessageEvent.update( + UserProfilePB userProfile, + String deviceId, + DocumentAwarenessStatesPB states, + ) = Update; +} + +@freezed +class ChatAIMessageState with _$ChatAIMessageState { + const factory ChatAIMessageState({ + required Message message, + }) = _ChatAIMessageState; + + factory ChatAIMessageState.initial(Message message) => + ChatAIMessageState(message: message); +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 959218dd69d62..21bb63510170b 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -27,12 +27,9 @@ class ChatBloc extends Bloc { listener.start( chatMessageCallback: _handleChatMessage, chatErrorMessageCallback: (err) { - final error = TextMessage( - metadata: { - CustomMessageType.streamError.toString(): - CustomMessageType.streamError, - }, - text: err.errorMessage, + Log.error("chat error: ${err.errorMessage}"); + final error = CustomMessage( + metadata: OnetimeMessageType.serverStreamError.toMap(), author: const User(id: "system"), id: 'system', ); @@ -109,13 +106,10 @@ class ChatBloc extends Bloc { }, tapMessage: (Message message) {}, streamingChatMessage: (List messages) { + // filter out loading or error messages final allMessages = state.messages.where((element) { - return !(element.metadata - ?.containsValue(CustomMessageType.loading) == - true || - element.metadata - ?.containsValue(CustomMessageType.streamError) == - true); + return !(element.metadata?.containsKey(onetimeMessageType) == + true); }).toList(); allMessages.insertAll(0, messages); emit(state.copyWith(messages: allMessages)); @@ -140,6 +134,7 @@ class ChatBloc extends Bloc { ), ); }, + retryGenerate: () {}, ); }, ); @@ -179,21 +174,20 @@ class ChatBloc extends Bloc { Message _loadingMessage(String id) { return CustomMessage( author: User(id: id), - metadata: { - CustomMessageType.loading.toString(): CustomMessageType.loading, - }, + metadata: OnetimeMessageType.loading.toMap(), + // fake id id: 'chat_message_loading_id', ); } Message _createChatMessage(ChatMessagePB message) { - final id = message.messageId.toString(); + final messageId = message.messageId.toString(); return TextMessage( author: User(id: message.authorId), - id: id, + id: messageId, text: message.content, createdAt: message.createdAt.toInt(), - repliedMessage: _getReplyMessage(state.messages, id), + repliedMessage: _getReplyMessage(state.messages, messageId), ); } @@ -218,6 +212,7 @@ class ChatEvent with _$ChatEvent { List messages, bool hasMore, ) = _DidLoadPreviousMessages; + const factory ChatEvent.retryGenerate() = _RetryGenerate; } @freezed @@ -229,6 +224,7 @@ class ChatState with _$ChatState { required LoadingState loadingStatus, required LoadingState loadingPreviousStatus, required LoadingState answerQuestionStatus, + required List relatedQuestions, required bool hasMore, }) = _ChatState; @@ -241,6 +237,7 @@ class ChatState with _$ChatState { loadingPreviousStatus: const LoadingState.finish(), answerQuestionStatus: const LoadingState.finish(), hasMore: true, + relatedQuestions: [], ); } @@ -250,4 +247,39 @@ class LoadingState with _$LoadingState { const factory LoadingState.finish() = _Finish; } -enum CustomMessageType { loading, streamError } +enum OnetimeMessageType { unknown, loading, serverStreamError } + +const onetimeMessageType = "OnetimeMessageType"; + +extension OnetimeMessageTypeExtension on OnetimeMessageType { + static OnetimeMessageType fromString(String value) { + switch (value) { + case 'OnetimeMessageType.loading': + return OnetimeMessageType.loading; + case 'OnetimeMessageType.serverStreamError': + return OnetimeMessageType.serverStreamError; + default: + Log.error('Unknown OnetimeMessageType: $value'); + return OnetimeMessageType.unknown; + } + } + + Map toMap() { + return { + onetimeMessageType: toString(), + }; + } +} + +OnetimeMessageType? restoreOnetimeMessageType(Map? metadata) { + if (metadata == null) { + return null; + } + + for (final entry in metadata.entries) { + if (entry.key == onetimeMessageType) { + return OnetimeMessageTypeExtension.fromString(entry.value as String); + } + } + return null; +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart index 8d0a5b9b39c59..c37d25608efd7 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart @@ -10,29 +10,14 @@ import 'package:appflowy_result/appflowy_result.dart'; import 'chat_notification.dart'; -typedef ChatMessageCallback = void Function( - ChatMessagePB message, -); - -typedef ChatErrorMessageCallback = void Function( - ChatMessageErrorPB message, -); - -typedef LatestMessageCallback = void Function( - ChatMessageListPB list, -); -typedef PrevMessageCallback = void Function( - ChatMessageListPB list, -); +typedef ChatMessageCallback = void Function(ChatMessagePB message); +typedef ChatErrorMessageCallback = void Function(ChatMessageErrorPB message); +typedef LatestMessageCallback = void Function(ChatMessageListPB list); +typedef PrevMessageCallback = void Function(ChatMessageListPB list); class ChatMessageListener { - ChatMessageListener({ - required this.chatId, - }) { - _parser = ChatNotificationParser( - id: chatId, - callback: _callback, - ); + ChatMessageListener({required this.chatId}) { + _parser = ChatNotificationParser(id: chatId, callback: _callback); _subscription = RustStreamReceiver.listen( (observable) => _parser?.parse(observable), ); @@ -41,7 +26,9 @@ class ChatMessageListener { final String chatId; StreamSubscription? _subscription; ChatNotificationParser? _parser; + ChatMessageCallback? chatMessageCallback; + ChatMessageCallback? lastSentMessageCallback; ChatErrorMessageCallback? chatErrorMessageCallback; LatestMessageCallback? latestMessageCallback; PrevMessageCallback? prevMessageCallback; @@ -52,58 +39,45 @@ class ChatMessageListener { ChatErrorMessageCallback? chatErrorMessageCallback, LatestMessageCallback? latestMessageCallback, PrevMessageCallback? prevMessageCallback, + ChatMessageCallback? lastSentMessageCallback, void Function()? finishAnswerQuestionCallback, }) { this.chatMessageCallback = chatMessageCallback; this.chatErrorMessageCallback = chatErrorMessageCallback; - this.finishAnswerQuestionCallback = finishAnswerQuestionCallback; this.latestMessageCallback = latestMessageCallback; this.prevMessageCallback = prevMessageCallback; + this.lastSentMessageCallback = lastSentMessageCallback; + this.finishAnswerQuestionCallback = finishAnswerQuestionCallback; } void _callback( ChatNotification ty, FlowyResult result, ) { - switch (ty) { - case ChatNotification.DidReceiveChatMessage: - result.map( - (r) { - final value = ChatMessagePB.fromBuffer(r); - chatMessageCallback?.call(value); - }, - ); - break; - case ChatNotification.ChatMessageError: - result.map( - (r) { - final value = ChatMessageErrorPB.fromBuffer(r); - chatErrorMessageCallback?.call(value); - }, - ); - break; - case ChatNotification.DidLoadLatestChatMessage: - result.map( - (r) { - final value = ChatMessageListPB.fromBuffer(r); - latestMessageCallback?.call(value); - }, - ); - break; - case ChatNotification.DidLoadPrevChatMessage: - result.map( - (r) { - final value = ChatMessageListPB.fromBuffer(r); - prevMessageCallback?.call(value); - }, - ); - break; - case ChatNotification.FinishAnswerQuestion: - finishAnswerQuestionCallback?.call(); - break; - default: - break; - } + result.map((r) { + switch (ty) { + case ChatNotification.DidReceiveChatMessage: + chatMessageCallback?.call(ChatMessagePB.fromBuffer(r)); + break; + case ChatNotification.LastSentMessage: + lastSentMessageCallback?.call(ChatMessagePB.fromBuffer(r)); + break; + case ChatNotification.ChatMessageError: + chatErrorMessageCallback?.call(ChatMessageErrorPB.fromBuffer(r)); + break; + case ChatNotification.DidLoadLatestChatMessage: + latestMessageCallback?.call(ChatMessageListPB.fromBuffer(r)); + break; + case ChatNotification.DidLoadPrevChatMessage: + prevMessageCallback?.call(ChatMessageListPB.fromBuffer(r)); + break; + case ChatNotification.FinishAnswerQuestion: + finishAnswerQuestionCallback?.call(); + break; + default: + break; + } + }); } Future stop() async { diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart new file mode 100644 index 0000000000000..24bf5e56cb014 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart @@ -0,0 +1,103 @@ +import 'package:appflowy/plugins/ai_chat/application/chat_message_listener.dart'; +import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'chat_related_question_bloc.freezed.dart'; + +class ChatRelatedMessageBloc + extends Bloc { + ChatRelatedMessageBloc({ + required String chatId, + }) : listener = ChatMessageListener(chatId: chatId), + super(ChatRelatedMessageState.initial()) { + on( + (event, emit) async { + await event.when( + initial: () async { + listener.start( + lastSentMessageCallback: (message) { + if (!isClosed) { + add(ChatRelatedMessageEvent.updateLastSentMessage(message)); + } + }, + ); + }, + didReceiveRelatedQuestion: (List questions) { + Log.debug("Related questions: $questions"); + emit( + state.copyWith( + relatedQuestions: questions, + ), + ); + }, + updateLastSentMessage: (ChatMessagePB message) { + final payload = + ChatMessageIdPB(chatId: chatId, messageId: message.messageId); + ChatEventGetRelatedQuestion(payload).send().then((result) { + if (!isClosed) { + result.fold( + (list) { + add( + ChatRelatedMessageEvent.didReceiveRelatedQuestion( + list.items, + ), + ); + }, + (err) { + Log.error("Failed to get related question: $err"); + }, + ); + } + }); + + emit( + state.copyWith( + lastSentMessage: message, + relatedQuestions: [], + ), + ); + }, + clear: () { + emit( + state.copyWith( + relatedQuestions: [], + ), + ); + }, + ); + }, + ); + } + + final ChatMessageListener listener; + @override + Future close() { + listener.stop(); + return super.close(); + } +} + +@freezed +class ChatRelatedMessageEvent with _$ChatRelatedMessageEvent { + const factory ChatRelatedMessageEvent.initial() = Initial; + const factory ChatRelatedMessageEvent.updateLastSentMessage( + ChatMessagePB message, + ) = _LastSentMessage; + const factory ChatRelatedMessageEvent.didReceiveRelatedQuestion( + List questions, + ) = _RelatedQuestion; + const factory ChatRelatedMessageEvent.clear() = _Clear; +} + +@freezed +class ChatRelatedMessageState with _$ChatRelatedMessageState { + const factory ChatRelatedMessageState({ + ChatMessagePB? lastSentMessage, + @Default([]) List relatedQuestions, + }) = _ChatRelatedMessageState; + + factory ChatRelatedMessageState.initial() => const ChatRelatedMessageState(); +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_message_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_message_bloc.dart new file mode 100644 index 0000000000000..d75b0533e2385 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_user_message_bloc.dart @@ -0,0 +1,44 @@ +import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'chat_user_message_bloc.freezed.dart'; + +class ChatUserMessageBloc + extends Bloc { + ChatUserMessageBloc({ + required Message message, + }) : super(ChatUserMessageState.initial(message)) { + on( + (event, emit) async { + await event.when( + initial: () async {}, + update: (userProfile, deviceId, states) {}, + ); + }, + ); + } +} + +@freezed +class ChatUserMessageEvent with _$ChatUserMessageEvent { + const factory ChatUserMessageEvent.initial() = Initial; + const factory ChatUserMessageEvent.update( + UserProfilePB userProfile, + String deviceId, + DocumentAwarenessStatesPB states, + ) = Update; +} + +@freezed +class ChatUserMessageState with _$ChatUserMessageState { + const factory ChatUserMessageState({ + required Message message, + WorkspaceMemberPB? member, + }) = _ChatUserMessageState; + + factory ChatUserMessageState.initial(Message message) => + ChatUserMessageState(message: message); +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 0bb055b74a741..273d3e1445199 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -1,5 +1,8 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_ai_message.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_error_message.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_user_message.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; @@ -14,9 +17,9 @@ import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'presentation/chat_input.dart'; -import 'presentation/chat_message_hover.dart'; import 'presentation/chat_popmenu.dart'; import 'presentation/chat_theme.dart'; +import 'presentation/chat_welcome_page.dart'; class AIChatPage extends StatefulWidget { const AIChatPage({ @@ -55,7 +58,7 @@ class _AIChatPageState extends State { Widget buildChatWidget() { return SizedBox.expand( child: Padding( - padding: const EdgeInsets.all(10), + padding: const EdgeInsets.symmetric(horizontal: 60), child: BlocProvider( create: (context) => ChatBloc( view: widget.view, @@ -78,13 +81,7 @@ class _AIChatPageState extends State { customBottomWidget: buildChatInput(blocContext), user: _user, theme: buildTheme(context), - customMessageBuilder: (message, {required messageWidth}) { - return const SizedBox( - width: 100, - height: 50, - child: CircularProgressIndicator.adaptive(), - ); - }, + customMessageBuilder: _customMessageBuilder, onEndReached: () async { if (state.hasMore && state.loadingPreviousStatus != @@ -94,16 +91,47 @@ class _AIChatPageState extends State { .add(const ChatEvent.loadPrevMessage()); } }, - emptyState: const Center( - child: CircularProgressIndicator.adaptive(), + emptyState: BlocBuilder( + builder: (context, state) { + return state.loadingStatus == const LoadingState.finish() + ? const ChatWelcomePage() + : const Center( + child: CircularProgressIndicator.adaptive(), + ); + }, ), - messageWidthRatio: 0.7, + messageWidthRatio: isMobile ? 0.8 : 0.9, bubbleBuilder: ( child, { required message, required nextMessageInGroup, - }) => - buildBubble(message, child), + }) { + if (message.author.id == _user.id) { + return ChatUserMessageBubble( + message: message, + child: child, + ); + } else { + final messageType = + restoreOnetimeMessageType(message.metadata); + + if (messageType == OnetimeMessageType.serverStreamError) { + return ChatErrorMessage( + onRetryPressed: () { + blocContext.read().add( + const ChatEvent.retryGenerate(), + ); + }, + ); + } + + return ChatAIMessageBubble( + message: message, + customMessageType: messageType, + child: child, + ); + } + }, ); }, ), @@ -123,40 +151,85 @@ class _AIChatPageState extends State { Widget buildBubble(Message message, Widget child) { final isAuthor = message.author.id == _user.id; - const borderRadius = BorderRadius.all(Radius.circular(20)); - final decoratedChild = DecoratedBox( - decoration: BoxDecoration( - borderRadius: borderRadius, - color: !isAuthor || message.type == types.MessageType.image - ? AFThemeExtension.of(context).tint1 - : Theme.of(context).colorScheme.secondary, - ), - child: child, - ); + const borderRadius = BorderRadius.all(Radius.circular(6)); - if (isMobile) { - return ChatPopupMenu( - onAction: (action) { - switch (action) { - case ChatMessageAction.copy: - if (message is TextMessage) { - Clipboard.setData(ClipboardData(text: message.text)); - showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); - } - break; - } - }, - builder: (context) => - ClipRRect(borderRadius: borderRadius, child: decoratedChild), - ); - } else { + final childWithPadding = isAuthor + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + child: child, + ) + : Padding( + padding: const EdgeInsets.all(8), + child: child, + ); + + // If the message is from the author, we will decorate it with a different color + final decoratedChild = isAuthor + ? DecoratedBox( + decoration: BoxDecoration( + borderRadius: borderRadius, + color: !isAuthor || message.type == types.MessageType.image + ? AFThemeExtension.of(context).tint1 + : Theme.of(context).colorScheme.secondary, + ), + child: childWithPadding, + ) + : childWithPadding; + + // If the message is from the author, no further actions are needed + if (isAuthor) { return ClipRRect( borderRadius: borderRadius, - child: ChatMessageHover( - message: message, - child: decoratedChild, - ), + child: decoratedChild, ); + } else { + if (isMobile) { + return ChatPopupMenu( + onAction: (action) { + switch (action) { + case ChatMessageAction.copy: + if (message is TextMessage) { + Clipboard.setData(ClipboardData(text: message.text)); + showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); + } + break; + } + }, + builder: (context) => + ClipRRect(borderRadius: borderRadius, child: decoratedChild), + ); + } else { + // Show hover effect only on desktop + return ClipRRect( + borderRadius: borderRadius, + child: ChatAIMessageHover( + message: message, + child: decoratedChild, + ), + ); + } + } + } + + Widget _customMessageBuilder( + types.CustomMessage message, { + required int messageWidth, + }) { + // iteration custom message type + final messageType = restoreOnetimeMessageType(message.metadata); + if (messageType == null) { + return const SizedBox.shrink(); + } + + switch (messageType) { + case OnetimeMessageType.loading: + return const SizedBox( + width: 50, + height: 30, + child: CircularProgressIndicator.adaptive(), + ); + default: + return const SizedBox.shrink(); } } @@ -170,10 +243,16 @@ class _AIChatPageState extends State { query.viewInsets.bottom + query.padding.bottom, ) : EdgeInsets.zero; - return Padding( - padding: safeAreaInsets, - child: ChatInput( - onSendPressed: (message) => onSendPressed(context, message), + return ClipRect( + child: Padding( + padding: safeAreaInsets, + child: ChatInput( + chatId: widget.view.id, + onSendPressed: (message) => onSendPressed(context, message.text), + onQuestionSelected: (question) { + onSendPressed(context, question); + }, + ), ), ); } @@ -224,7 +303,7 @@ class _AIChatPageState extends State { ); } - void onSendPressed(BuildContext context, types.PartialText message) { - context.read().add(ChatEvent.sendMessage(message.text)); + void onSendPressed(BuildContext context, String message) { + context.read().add(ChatEvent.sendMessage(message)); } } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart new file mode 100644 index 0000000000000..39e971f4dd18d --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart @@ -0,0 +1,197 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_ai_message_bloc.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_avatar.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_input.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_popmenu.dart'; +import 'package:appflowy/workspace/presentation/home/toast.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra/theme_extension.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; +import 'package:styled_widget/styled_widget.dart'; + +const _leftPadding = 16.0; + +class ChatAIMessageBubble extends StatelessWidget { + const ChatAIMessageBubble({ + super.key, + required this.message, + required this.child, + this.customMessageType, + }); + + final Message message; + final Widget child; + final OnetimeMessageType? customMessageType; + + @override + Widget build(BuildContext context) { + const padding = EdgeInsets.symmetric(horizontal: _leftPadding); + final childWithPadding = Padding(padding: padding, child: child); + + return BlocProvider( + create: (context) => ChatAIMessageBloc(message: message), + child: BlocBuilder( + builder: (context, state) { + final widget = isMobile + ? _wrapPopMenu(childWithPadding) + : _wrapHover(childWithPadding); + + return Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ChatBorderedCircleAvatar( + child: FlowySvg( + FlowySvgs.flowy_logo_xl, + blendMode: null, + size: Size.square(24), + ), + ), + Expanded(child: widget), + ], + ); + }, + ), + ); + } + + ChatAIMessageHover _wrapHover(Padding child) { + return ChatAIMessageHover( + message: message, + customMessageType: customMessageType, + child: child, + ); + } + + ChatPopupMenu _wrapPopMenu(Padding childWithPadding) { + return ChatPopupMenu( + onAction: (action) { + if (action == ChatMessageAction.copy && message is TextMessage) { + Clipboard.setData(ClipboardData(text: (message as TextMessage).text)); + showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); + } + }, + builder: (context) => childWithPadding, + ); + } +} + +class ChatAIMessageHover extends StatefulWidget { + const ChatAIMessageHover({ + super.key, + required this.child, + required this.message, + this.customMessageType, + }); + + final Widget child; + final Message message; + final bool autoShowHover = true; + final OnetimeMessageType? customMessageType; + + @override + State createState() => _ChatAIMessageHoverState(); +} + +class _ChatAIMessageHoverState extends State { + bool _isHover = false; + + @override + void initState() { + super.initState(); + _isHover = widget.autoShowHover ? false : true; + } + + @override + Widget build(BuildContext context) { + final List children = [ + DecoratedBox( + decoration: const BoxDecoration( + color: Colors.transparent, + borderRadius: Corners.s6Border, + ), + child: Padding( + padding: const EdgeInsets.only(bottom: 40), + child: widget.child, + ), + ), + ]; + + if (_isHover) { + children.addAll(_buildOnHoverItems()); + } + + return MouseRegion( + cursor: SystemMouseCursors.click, + opaque: false, + onEnter: (p) => setState(() { + if (widget.autoShowHover) { + _isHover = true; + } + }), + onExit: (p) => setState(() { + if (widget.autoShowHover) { + _isHover = false; + } + }), + child: Stack( + alignment: AlignmentDirectional.centerStart, + children: children, + ), + ); + } + + List _buildOnHoverItems() { + final List children = []; + if (widget.customMessageType != null) { + // + } else { + if (widget.message is TextMessage) { + children.add( + CopyButton( + textMessage: widget.message as TextMessage, + ).positioned(left: _leftPadding, bottom: 0), + ); + } + } + + return children; + } +} + +class CopyButton extends StatelessWidget { + const CopyButton({ + super.key, + required this.textMessage, + }); + final TextMessage textMessage; + + @override + Widget build(BuildContext context) { + return FlowyTooltip( + message: LocaleKeys.settings_menu_clickToCopy.tr(), + child: FlowyIconButton( + width: 24, + hoverColor: AFThemeExtension.of(context).lightGreyHover, + fillColor: Theme.of(context).cardColor, + icon: FlowySvg( + FlowySvgs.ai_copy_s, + size: const Size.square(14), + color: Theme.of(context).colorScheme.primary, + ), + onPressed: () { + Clipboard.setData(ClipboardData(text: textMessage.text)); + showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); + }, + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart new file mode 100644 index 0000000000000..141432520bb76 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_avatar.dart @@ -0,0 +1,184 @@ +import 'package:flutter/material.dart'; +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/util/built_in_svgs.dart'; +import 'package:appflowy/util/color_generator/color_generator.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:string_validator/string_validator.dart'; + +class ChatChatUserAvatar extends StatelessWidget { + const ChatChatUserAvatar({required this.userId, super.key}); + + final String userId; + + @override + Widget build(BuildContext context) { + return const ChatBorderedCircleAvatar(); + } +} + +class ChatBorderedCircleAvatar extends StatelessWidget { + const ChatBorderedCircleAvatar({ + super.key, + this.border = const BorderSide(), + this.backgroundImage, + this.backgroundColor, + this.child, + }); + + final BorderSide border; + final ImageProvider? backgroundImage; + final Color? backgroundColor; + final Widget? child; + + @override + Widget build(BuildContext context) { + return CircleAvatar( + backgroundColor: border.color, + child: ConstrainedBox( + constraints: const BoxConstraints.expand(), + child: CircleAvatar( + backgroundImage: backgroundImage, + backgroundColor: backgroundColor, + child: child, + ), + ), + ); + } +} + +class ChatUserAvatar extends StatelessWidget { + const ChatUserAvatar({ + super.key, + required this.iconUrl, + required this.name, + required this.size, + this.isHovering = false, + }); + + final String iconUrl; + final String name; + final double size; + + // If true, a border will be applied on top of the avatar + final bool isHovering; + + @override + Widget build(BuildContext context) { + if (iconUrl.isEmpty) { + return _buildEmptyAvatar(context); + } else if (isURL(iconUrl)) { + return _buildUrlAvatar(context); + } else { + return _buildEmojiAvatar(context); + } + } + + Widget _buildEmptyAvatar(BuildContext context) { + final String nameOrDefault = _userName(name); + final Color color = ColorGenerator(name).toColor(); + const initialsCount = 2; + + // Taking the first letters of the name components and limiting to 2 elements + final nameInitials = nameOrDefault + .split(' ') + .where((element) => element.isNotEmpty) + .take(initialsCount) + .map((element) => element[0].toUpperCase()) + .join(); + + return Container( + width: size, + height: size, + alignment: Alignment.center, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + border: isHovering + ? Border.all( + color: _darken(color), + width: 4, + ) + : null, + ), + child: FlowyText.regular( + nameInitials, + color: Colors.black, + ), + ); + } + + Widget _buildUrlAvatar(BuildContext context) { + return SizedBox.square( + dimension: size, + child: DecoratedBox( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: isHovering + ? Border.all( + color: Theme.of(context).colorScheme.primary, + width: 4, + ) + : null, + ), + child: ClipRRect( + borderRadius: Corners.s5Border, + child: CircleAvatar( + backgroundColor: Colors.transparent, + child: Image.network( + iconUrl, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) => + _buildEmptyAvatar(context), + ), + ), + ), + ), + ); + } + + Widget _buildEmojiAvatar(BuildContext context) { + return SizedBox.square( + dimension: size, + child: DecoratedBox( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: isHovering + ? Border.all( + color: Theme.of(context).colorScheme.primary, + width: 4, + ) + : null, + ), + child: ClipRRect( + borderRadius: Corners.s5Border, + child: CircleAvatar( + backgroundColor: Colors.transparent, + child: builtInSVGIcons.contains(iconUrl) + ? FlowySvg( + FlowySvgData('emoji/$iconUrl'), + blendMode: null, + ) + : FlowyText.emoji(iconUrl), + ), + ), + ), + ); + } + + /// Return the user name, if the user name is empty, + /// return the default user name. + /// + String _userName(String name) => + name.isEmpty ? LocaleKeys.defaultUsername.tr() : name; + + /// Used to darken the generated color for the hover border effect. + /// The color is darkened by 15% - Hence the 0.15 value. + /// + Color _darken(Color color) { + final hsl = HSLColor.fromColor(color); + return hsl.withLightness((hsl.lightness - 0.15).clamp(0.0, 1.0)).toColor(); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart new file mode 100644 index 0000000000000..4846df1487476 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart @@ -0,0 +1,43 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; + +class ChatErrorMessage extends StatelessWidget { + const ChatErrorMessage({required this.onRetryPressed, super.key}); + + final void Function() onRetryPressed; + @override + Widget build(BuildContext context) { + return Column( + children: [ + const Divider(height: 4, thickness: 1), + const VSpace(16), + Center( + child: FlowyTooltip( + message: LocaleKeys.chat_clickToRetry.tr(), + child: FlowyButton( + useIntrinsicWidth: true, + text: Padding( + padding: const EdgeInsets.all(8.0), + child: FlowyText( + LocaleKeys.chat_serverUnavailable.tr(), + fontSize: 14, + ), + ), + onTap: () { + onRetryPressed(); + }, + iconPadding: 0, + rightIcon: const Icon( + Icons.refresh, + size: 20, + ), + ), + ), + ), + ], + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart index 0d091d61586fd..88ff3821021e7 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -1,3 +1,5 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -5,6 +7,8 @@ import 'package:flutter/services.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; +import 'chat_related_question.dart'; + class ChatInput extends StatefulWidget { /// Creates [ChatInput] widget. const ChatInput({ @@ -12,6 +16,8 @@ class ChatInput extends StatefulWidget { this.isAttachmentUploading, this.onAttachmentPressed, required this.onSendPressed, + required this.chatId, + required this.onQuestionSelected, this.options = const InputOptions(), }); @@ -19,6 +25,8 @@ class ChatInput extends StatefulWidget { final VoidCallback? onAttachmentPressed; final void Function(types.PartialText) onSendPressed; final InputOptions options; + final String chatId; + final Function(String) onQuestionSelected; @override State createState() => _ChatInputState(); @@ -110,57 +118,23 @@ class _ChatInputState extends State { ? Theme.of(context).colorScheme.surfaceContainer : Theme.of(context).colorScheme.surfaceContainerHighest, elevation: 0.6, - child: Row( - textDirection: TextDirection.ltr, + child: Column( children: [ - if (widget.onAttachmentPressed != null) - AttachmentButton( - isLoading: widget.isAttachmentUploading ?? false, - onPressed: widget.onAttachmentPressed, - padding: buttonPadding, - ), - Expanded( - child: Padding( - padding: textPadding, - child: TextField( - enabled: widget.options.enabled, - autocorrect: widget.options.autocorrect, - autofocus: widget.options.autofocus, - enableSuggestions: widget.options.enableSuggestions, - controller: _textController, - decoration: InputDecoration( - border: InputBorder.none, - hintText: '', - hintStyle: TextStyle( - color: AFThemeExtension.of(context) - .textColor - .withOpacity(0.5), - ), - ), - focusNode: _inputFocusNode, - keyboardType: widget.options.keyboardType, - maxLines: 5, - minLines: 1, - onChanged: widget.options.onTextChanged, - onTap: widget.options.onTextFieldTap, - style: TextStyle( - color: AFThemeExtension.of(context).textColor, - ), - textCapitalization: TextCapitalization.sentences, - ), - ), + RelatedQuestionList( + chatId: widget.chatId, + onQuestionSelected: widget.onQuestionSelected, ), - ConstrainedBox( - constraints: BoxConstraints( - minHeight: buttonPadding.bottom + buttonPadding.top + 24, - ), - child: Visibility( - visible: _sendButtonVisible, - child: SendButton( - onPressed: _handleSendPressed, - padding: buttonPadding, - ), - ), + Row( + children: [ + if (widget.onAttachmentPressed != null) + AttachmentButton( + isLoading: widget.isAttachmentUploading ?? false, + onPressed: widget.onAttachmentPressed, + padding: buttonPadding, + ), + Expanded(child: _inputTextField(textPadding)), + _sendButton(buttonPadding), + ], ), ], ), @@ -169,6 +143,51 @@ class _ChatInputState extends State { ); } + Padding _inputTextField(EdgeInsets textPadding) { + return Padding( + padding: textPadding, + child: TextField( + enabled: widget.options.enabled, + autocorrect: widget.options.autocorrect, + autofocus: widget.options.autofocus, + enableSuggestions: widget.options.enableSuggestions, + controller: _textController, + decoration: InputDecoration( + border: InputBorder.none, + hintText: LocaleKeys.chat_inputMessageHint.tr(), + hintStyle: TextStyle( + color: AFThemeExtension.of(context).textColor.withOpacity(0.5), + ), + ), + focusNode: _inputFocusNode, + keyboardType: widget.options.keyboardType, + maxLines: 5, + minLines: 1, + onChanged: widget.options.onTextChanged, + onTap: widget.options.onTextFieldTap, + style: TextStyle( + color: AFThemeExtension.of(context).textColor, + ), + textCapitalization: TextCapitalization.sentences, + ), + ); + } + + ConstrainedBox _sendButton(EdgeInsets buttonPadding) { + return ConstrainedBox( + constraints: BoxConstraints( + minHeight: buttonPadding.bottom + buttonPadding.top + 24, + ), + child: Visibility( + visible: _sendButtonVisible, + child: SendButton( + onPressed: _handleSendPressed, + padding: buttonPadding, + ), + ), + ); + } + @override void didUpdateWidget(covariant ChatInput oldWidget) { super.didUpdateWidget(oldWidget); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart deleted file mode 100644 index 4a1f59cbdd8c7..0000000000000 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_message_hover.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:appflowy/generated/flowy_svgs.g.dart'; -import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/workspace/presentation/home/toast.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/size.dart'; -import 'package:flowy_infra/theme_extension.dart'; -import 'package:flowy_infra_ui/style_widget/icon_button.dart'; -import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_chat_types/flutter_chat_types.dart'; -import 'package:styled_widget/styled_widget.dart'; - -class ChatMessageHover extends StatefulWidget { - const ChatMessageHover({ - super.key, - required this.child, - required this.message, - }); - - final Widget child; - final Message message; - - @override - State createState() => _ChatMessageHoverState(); -} - -class _ChatMessageHoverState extends State { - bool _isHover = false; - - @override - Widget build(BuildContext context) { - final List children = [ - DecoratedBox( - decoration: BoxDecoration( - color: _isHover - ? AFThemeExtension.of(context).lightGreyHover - : Colors.transparent, - borderRadius: Corners.s6Border, - ), - child: widget.child, - ), - ]; - - if (_isHover) { - if (widget.message is TextMessage) { - children.add( - Padding( - padding: const EdgeInsets.only(right: 6), - child: CopyButton( - textMessage: widget.message as TextMessage, - ), - ).positioned(top: 12, left: 12), - ); - } - } - - return MouseRegion( - cursor: SystemMouseCursors.click, - opaque: false, - onEnter: (p) => setState(() => _isHover = true), - onExit: (p) => setState(() => _isHover = false), - child: Stack( - alignment: AlignmentDirectional.center, - children: children, - ), - ); - } -} - -class CopyButton extends StatelessWidget { - const CopyButton({ - super.key, - required this.textMessage, - }); - final TextMessage textMessage; - - @override - Widget build(BuildContext context) { - return FlowyTooltip( - message: LocaleKeys.settings_menu_clickToCopy.tr(), - child: Container( - width: 26, - height: 26, - decoration: BoxDecoration( - border: Border.fromBorderSide( - BorderSide(color: Theme.of(context).dividerColor), - ), - borderRadius: Corners.s6Border, - ), - child: FlowyIconButton( - hoverColor: AFThemeExtension.of(context).lightGreyHover, - fillColor: Theme.of(context).cardColor, - icon: FlowySvg( - FlowySvgs.ai_copy_s, - color: Theme.of(context).colorScheme.primary, - ), - onPressed: () { - Clipboard.setData(ClipboardData(text: textMessage.text)); - showMessageToast(LocaleKeys.grid_row_copyProperty.tr()); - }, - ), - ), - ); - } -} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart new file mode 100644 index 0000000000000..826bf77e80e5e --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart @@ -0,0 +1,81 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_related_question_bloc.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class RelatedQuestionList extends StatefulWidget { + const RelatedQuestionList({ + required this.chatId, + required this.onQuestionSelected, + super.key, + }); + + final String chatId; + final Function(String) onQuestionSelected; + + @override + State createState() => _RelatedQuestionListState(); +} + +class _RelatedQuestionListState extends State { + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ChatRelatedMessageBloc(chatId: widget.chatId) + ..add( + const ChatRelatedMessageEvent.initial(), + ), + child: BlocBuilder( + builder: (blocContext, state) { + if (state.relatedQuestions.isEmpty) { + return const SizedBox.shrink(); + } else { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + const FlowySvg( + FlowySvgs.ai_summary_generate_s, + size: Size.square(24), + ), + const HSpace(6), + FlowyText( + LocaleKeys.chat_relatedQuestion.tr(), + fontSize: 18, + ), + ], + ), + ), + const Divider(height: 6), + ListView.builder( + shrinkWrap: true, + itemCount: state.relatedQuestions.length, + itemBuilder: (context, index) { + final question = state.relatedQuestions[index]; + return ListTile( + title: Text(question.content), + onTap: () { + widget.onQuestionSelected(question.content); + blocContext.read().add( + const ChatRelatedMessageEvent.clear(), + ); + }, + trailing: const FlowySvg(FlowySvgs.add_m), + ); + }, + ), + ], + ); + } + }, + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart index f3bad391bd5f9..456ac0c184391 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_theme.dart @@ -100,8 +100,8 @@ class AFDefaultChatTheme extends ChatTheme { height: 1.5, ), super.messageBorderRadius = 20, - super.messageInsetsHorizontal = 20, - super.messageInsetsVertical = 16, + super.messageInsetsHorizontal = 0, + super.messageInsetsVertical = 0, super.messageMaxWidth = 1000, super.primaryColor = primary, super.receivedEmojiMessageTextStyle = const TextStyle(fontSize: 40), diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart new file mode 100644 index 0000000000000..8e972315071dd --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart @@ -0,0 +1,174 @@ +import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_user_message_bloc.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_avatar.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra/theme_extension.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; +import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; +import 'package:styled_widget/styled_widget.dart'; + +class ChatUserMessageBubble extends StatelessWidget { + const ChatUserMessageBubble({ + super.key, + required this.message, + required this.child, + }); + + final Message message; + final Widget child; + + @override + Widget build(BuildContext context) { + const borderRadius = BorderRadius.all(Radius.circular(6)); + final backgroundColor = Theme.of(context).colorScheme.secondary; + + return BlocProvider( + create: (context) => ChatUserMessageBloc(message: message), + child: BlocBuilder( + builder: (context, state) { + return Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _wrapHover( + DecoratedBox( + decoration: BoxDecoration( + borderRadius: borderRadius, + color: backgroundColor, + ), + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 12, + ), + child: child, + ), + ), + ), + BlocBuilder( + builder: (context, state) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ChatUserAvatar( + iconUrl: state.member?.avatarUrl ?? "", + name: state.member?.name ?? "", + size: 36, + ), + ); + }, + ), + ], + ); + }, + ), + ); + } + + ChatUserMessageHover _wrapHover(Widget child) { + return ChatUserMessageHover( + message: message, + child: child, + ); + } +} + +class ChatUserMessageHover extends StatefulWidget { + const ChatUserMessageHover({ + super.key, + required this.child, + required this.message, + }); + + final Widget child; + final Message message; + final bool autoShowHover = true; + + @override + State createState() => _ChatUserMessageHoverState(); +} + +class _ChatUserMessageHoverState extends State { + bool _isHover = false; + + @override + void initState() { + super.initState(); + _isHover = widget.autoShowHover ? false : true; + } + + @override + Widget build(BuildContext context) { + final List children = [ + DecoratedBox( + decoration: const BoxDecoration( + color: Colors.transparent, + borderRadius: Corners.s6Border, + ), + child: Padding( + padding: const EdgeInsets.only(bottom: 30), + child: widget.child, + ), + ), + ]; + + if (_isHover) { + if (widget.message is TextMessage) { + children.add( + EditButton( + textMessage: widget.message as TextMessage, + ).positioned(right: 0, bottom: 0), + ); + } + } + + return MouseRegion( + cursor: SystemMouseCursors.click, + opaque: false, + onEnter: (p) => setState(() { + if (widget.autoShowHover) { + _isHover = true; + } + }), + onExit: (p) => setState(() { + if (widget.autoShowHover) { + _isHover = false; + } + }), + child: Stack( + alignment: AlignmentDirectional.centerStart, + children: children, + ), + ); + } +} + +class EditButton extends StatelessWidget { + const EditButton({ + super.key, + required this.textMessage, + }); + final TextMessage textMessage; + + @override + Widget build(BuildContext context) { + return FlowyTooltip( + message: LocaleKeys.settings_menu_clickToCopy.tr(), + child: FlowyIconButton( + width: 24, + hoverColor: AFThemeExtension.of(context).lightGreyHover, + fillColor: Theme.of(context).cardColor, + icon: FlowySvg( + FlowySvgs.ai_copy_s, + size: const Size.square(14), + color: Theme.of(context).colorScheme.primary, + ), + onPressed: () {}, + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_welcome_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_welcome_page.dart new file mode 100644 index 0000000000000..e6fc55a15a130 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_welcome_page.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class ChatWelcomePage extends StatelessWidget { + const ChatWelcomePage({super.key}); + + @override + Widget build(BuildContext context) { + return const SizedBox.shrink(); + } +} diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart index acd628a22204f..e99ee90f56a13 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/button.dart @@ -106,7 +106,7 @@ class FlowyButton extends StatelessWidget { } if (rightIcon != null) { - children.add(const HSpace(6)); + children.add(HSpace(iconPadding)); // No need to define the size of rightIcon. Just use its intrinsic width children.add(rightIcon!); } diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 9c69e8db590fb..38252652c6d09 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -182,9 +182,11 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", + "bytes", + "futures", "serde", "serde_json", "serde_repr", @@ -543,9 +545,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -755,7 +757,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "again", "anyhow", @@ -802,7 +804,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "futures-channel", "futures-util", @@ -1041,7 +1043,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -1066,7 +1068,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "async-trait", @@ -1312,7 +1314,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1423,7 +1425,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -2831,7 +2833,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "futures-util", @@ -2848,7 +2850,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -3280,7 +3282,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "reqwest", @@ -4783,7 +4785,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4804,7 +4806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -5768,7 +5770,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 382f3332d27d4..82fa349dd107b 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index c696b6929bd2c..d0c36ed64dcd5 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -236,9 +236,11 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", + "bytes", + "futures", "serde", "serde_json", "serde_repr", @@ -440,9 +442,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -560,7 +562,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "again", "anyhow", @@ -607,7 +609,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "futures-channel", "futures-util", @@ -785,7 +787,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -810,7 +812,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "async-trait", @@ -1024,7 +1026,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -1813,7 +1815,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "futures-util", @@ -1830,7 +1832,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -2131,7 +2133,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "reqwest", @@ -3771,7 +3773,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -4262,6 +4264,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 77c639f044fd8..c33b10f75da18 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 312ca437efafe..ae8c8e40b9450 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -173,9 +173,11 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", + "bytes", + "futures", "serde", "serde_json", "serde_repr", @@ -197,6 +199,7 @@ dependencies = [ "flowy-notification", "flowy-user", "lib-dispatch", + "semver", "serde", "serde_json", "tauri", @@ -727,7 +730,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "again", "anyhow", @@ -774,7 +777,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "futures-channel", "futures-util", @@ -1022,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -1047,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "async-trait", @@ -1408,7 +1411,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -1507,6 +1510,7 @@ dependencies = [ "diesel_derives", "libsqlite3-sys", "r2d2", + "serde_json", "time", ] @@ -2282,6 +2286,7 @@ dependencies = [ "postgrest", "rand 0.8.5", "reqwest", + "semver", "serde", "serde_json", "thiserror", @@ -2901,7 +2906,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "futures-util", @@ -2918,7 +2923,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -3355,7 +3360,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "reqwest", @@ -5666,9 +5671,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" dependencies = [ "serde", ] @@ -5859,7 +5864,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index aea296b1168a9..d92053ea4421e 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } [dependencies] serde_json.workspace = true diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index a07586a3bc76d..430a17f566aee 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -149,7 +149,12 @@ "newBoardText": "New board", "chat": { "newChat": "New chat", - "unsupportedCloudPrompt": "This feature is only available when using AppFlowy Cloud" + "inputMessageHint": "Message", + "unsupportedCloudPrompt": "This feature is only available when using AppFlowy Cloud", + "relatedQuestion": "Related", + "serverUnavailable": "Service Temporarily Unavailable", + "clickToRetry": "Click to retry", + "aiMistakePrompt": "AI can make mistakes. Check important info." }, "trash": { "text": "Trash", diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 36b675ac9f5bd..395f2c00625ad 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -183,9 +183,11 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", + "bytes", + "futures", "serde", "serde_json", "serde_repr", @@ -542,9 +544,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -662,7 +664,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "again", "anyhow", @@ -709,7 +711,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "futures-channel", "futures-util", @@ -917,7 +919,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "bincode", @@ -942,7 +944,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "async-trait", @@ -1262,7 +1264,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -2516,7 +2518,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "futures-util", @@ -2533,7 +2535,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", @@ -2898,7 +2900,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "reqwest", @@ -4981,7 +4983,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=559d924cd182d8db16df69c030c96e63153988f7#559d924cd182d8db16df69c030c96e63153988f7" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index bb81863be9027..612785200a507 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "559d924cd182d8db16df69c030c96e63153988f7" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 36ca710d321ee..42ab020dd1ab9 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,3 +1,4 @@ +pub use client_api::entity::ai_dto::{RelatedQuestion, RepeatedRelatedQuestion}; pub use client_api::entity::{ ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, }; @@ -32,4 +33,11 @@ pub trait ChatCloudService: Send + Sync + 'static { offset: MessageCursor, limit: u64, ) -> FutureResult; + + fn get_related_message( + &self, + workspace_id: &str, + chat_id: &str, + message_id: i64, + ) -> FutureResult; } diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index c850f71100e6a..a87901bcba584 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -1,4 +1,6 @@ -use crate::entities::{ChatMessageErrorPB, ChatMessageListPB, ChatMessagePB}; +use crate::entities::{ + ChatMessageErrorPB, ChatMessageListPB, ChatMessagePB, RepeatedRelatedQuestionPB, +}; use crate::manager::ChatUserService; use crate::notification::{send_notification, ChatNotification}; use crate::persistence::{insert_chat_messages, select_chat_messages, ChatMessageTable}; @@ -124,7 +126,7 @@ impl Chat { .load_remote_chat_messages(limit, before_message_id, None) .await { - error!("Failed to load chat messages: {}", err); + error!("Failed to load previous chat messages: {}", err); } } @@ -244,6 +246,25 @@ impl Chat { Ok(()) } + pub async fn get_related_question( + &self, + message_id: i64, + ) -> Result { + let workspace_id = self.user_service.workspace_id()?; + let resp = self + .cloud_service + .get_related_message(&workspace_id, &self.chat_id, message_id) + .await?; + + trace!( + "Related messages: chat_id={}, message_id={}, messages:{:?}", + self.chat_id, + message_id, + resp.items + ); + Ok(RepeatedRelatedQuestionPB::from(resp)) + } + async fn load_local_chat_messages( &self, limit: i64, @@ -297,7 +318,7 @@ fn stream_send_chat_messages( .send_chat_message(&workspace_id, &chat_id, &message_content, message_type) .await; - let mut reply_message_id = None; + let mut user_asked_question = None; // By default, stream only returns two messages: // 1. user message @@ -308,11 +329,16 @@ fn stream_send_chat_messages( match result { Ok(message) => { let mut pb = ChatMessagePB::from(message.clone()); - if reply_message_id.is_none() { + if user_asked_question.is_none() { pb.has_following = true; - reply_message_id = Some(pb.message_id); + user_asked_question = Some(pb.clone()); } else { - pb.reply_message_id = reply_message_id; + pb.reply_message_id = user_asked_question.as_ref().map(|m| m.message_id); + if let Some(user_asked_question) = &user_asked_question { + send_notification(&chat_id, ChatNotification::LastSentMessage) + .payload(user_asked_question.clone()) + .send(); + } } send_notification(&chat_id, ChatNotification::DidReceiveChatMessage) .payload(pb) @@ -369,7 +395,7 @@ fn stream_send_chat_messages( created_at: message.created_at.timestamp(), author_type: message.author.author_type as i64, author_id: message.author.author_id.to_string(), - reply_message_id, + reply_message_id: user_asked_question.as_ref().map(|m| m.message_id), }) .collect::>(); insert_chat_messages(conn, &records)?; diff --git a/frontend/rust-lib/flowy-chat/src/entities.rs b/frontend/rust-lib/flowy-chat/src/entities.rs index cab3b90847758..e01c2aaad1bc4 100644 --- a/frontend/rust-lib/flowy-chat/src/entities.rs +++ b/frontend/rust-lib/flowy-chat/src/entities.rs @@ -1,4 +1,6 @@ -use flowy_chat_pub::cloud::{ChatMessage, RepeatedChatMessage}; +use flowy_chat_pub::cloud::{ + ChatMessage, RelatedQuestion, RepeatedChatMessage, RepeatedRelatedQuestion, +}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_infra::validator_fn::required_not_empty_str; use validator::Validate; @@ -141,3 +143,48 @@ impl From> for RepeatedChatMessagePB { } } } + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct ChatMessageIdPB { + #[pb(index = 1)] + pub chat_id: String, + + #[pb(index = 2)] + pub message_id: i64, +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct RelatedQuestionPB { + #[pb(index = 1)] + pub content: String, +} + +impl From for RelatedQuestionPB { + fn from(value: RelatedQuestion) -> Self { + RelatedQuestionPB { + content: value.content, + } + } +} + +#[derive(Debug, Clone, Default, ProtoBuf)] +pub struct RepeatedRelatedQuestionPB { + #[pb(index = 1)] + pub message_id: i64, + + #[pb(index = 2)] + pub items: Vec, +} + +impl From for RepeatedRelatedQuestionPB { + fn from(value: RepeatedRelatedQuestion) -> Self { + RepeatedRelatedQuestionPB { + message_id: value.message_id, + items: value + .items + .into_iter() + .map(RelatedQuestionPB::from) + .collect(), + } + } +} diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 6f2db442770f3..607ee8e5dfd0b 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -65,3 +65,16 @@ pub(crate) async fn load_next_message_handler( .await?; data_result_ok(messages) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_related_question_handler( + data: AFPluginData, + chat_manager: AFPluginState>, +) -> DataResult { + let chat_manager = upgrade_chat_manager(chat_manager)?; + let data = data.into_inner(); + let messages = chat_manager + .get_related_questions(&data.chat_id, data.message_id) + .await?; + data_result_ok(messages) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index 41dd0db445176..b2ea726394ce0 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -15,6 +15,7 @@ pub fn init(chat_manager: Weak) -> AFPlugin { .event(ChatEvent::SendMessage, send_chat_message_handler) .event(ChatEvent::LoadPrevMessage, load_prev_message_handler) .event(ChatEvent::LoadNextMessage, load_next_message_handler) + .event(ChatEvent::GetRelatedQuestion, get_related_question_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] @@ -29,4 +30,7 @@ pub enum ChatEvent { #[event(input = "SendChatPayloadPB")] SendMessage = 2, + + #[event(input = "ChatMessageIdPB", output = "RepeatedRelatedQuestionPB")] + GetRelatedQuestion = 3, } diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 1bc2f63b4f2ca..67cec38761555 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,5 +1,5 @@ use crate::chat::Chat; -use crate::entities::ChatMessageListPB; +use crate::entities::{ChatMessageListPB, RepeatedRelatedQuestionPB}; use crate::persistence::{insert_chat, ChatTable}; use dashmap::DashMap; use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageType}; @@ -148,6 +148,16 @@ impl ChatManager { .await?; Ok(list) } + + pub async fn get_related_questions( + &self, + chat_id: &str, + message_id: i64, + ) -> Result { + let chat = self.get_or_create_chat_instance(chat_id).await?; + let resp = chat.get_related_question(message_id).await?; + Ok(resp) + } } fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-chat/src/notification.rs b/frontend/rust-lib/flowy-chat/src/notification.rs index 15918d57be378..c13936c667075 100644 --- a/frontend/rust-lib/flowy-chat/src/notification.rs +++ b/frontend/rust-lib/flowy-chat/src/notification.rs @@ -12,6 +12,7 @@ pub enum ChatNotification { DidReceiveChatMessage = 3, ChatMessageError = 4, FinishAnswerQuestion = 5, + LastSentMessage = 6, } impl std::convert::From for i32 { @@ -27,6 +28,7 @@ impl std::convert::From for ChatNotification { 3 => ChatNotification::DidReceiveChatMessage, 4 => ChatNotification::ChatMessageError, 5 => ChatNotification::FinishAnswerQuestion, + 6 => ChatNotification::LastSentMessage, _ => ChatNotification::Unknown, } } diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index b5a66e9fd5d2f..4e02d26068689 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use anyhow::Error; use client_api::collab_sync::{SinkConfig, SyncObject, SyncPlugin}; +use client_api::entity::ai_dto::RepeatedRelatedQuestion; use client_api::entity::ChatMessageType; use collab::core::origin::{CollabClient, CollabOrigin}; @@ -492,4 +493,21 @@ impl ChatCloudService for ServerProvider { .await }) } + + fn get_related_message( + &self, + workspace_id: &str, + chat_id: &str, + message_id: i64, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let server = self.get_server(); + FutureResult::new(async move { + server? + .chat_service() + .get_related_message(&workspace_id, &chat_id, message_id) + .await + }) + } } diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 88a3aa64ec2c5..673586979b2e2 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -1,4 +1,5 @@ use crate::af_cloud::AFServer; +use client_api::entity::ai_dto::RepeatedRelatedQuestion; use client_api::entity::{ CreateChatMessageParams, CreateChatParams, MessageCursor, RepeatedChatMessage, }; @@ -85,4 +86,24 @@ where Ok(resp) }) } + + fn get_related_message( + &self, + workspace_id: &str, + chat_id: &str, + message_id: i64, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let try_get_client = self.inner.try_get_client(); + + FutureResult::new(async move { + let resp = try_get_client? + .get_chat_related_question(&workspace_id, &chat_id, message_id) + .await + .map_err(FlowyError::from)?; + + Ok(resp) + }) + } } diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs index c24ddbb51eead..a33852dd53c1e 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/user/dto.rs @@ -89,6 +89,7 @@ pub fn from_af_workspace_member(member: AFWorkspaceMember) -> WorkspaceMember { email: member.email, role: from_af_role(member.role), name: member.name, + avatar_url: member.avatar_url, } } diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index d34f4a0d24bca..c1cc631e8017c 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,3 +1,4 @@ +use client_api::entity::ai_dto::RepeatedRelatedQuestion; use client_api::entity::{ChatMessageType, MessageCursor, RepeatedChatMessage}; use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageStream}; use flowy_error::FlowyError; @@ -40,4 +41,15 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) }) } + + fn get_related_message( + &self, + workspace_id: &str, + chat_id: &str, + message_id: i64, + ) -> FutureResult { + FutureResult::new(async move { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) + }) + } } diff --git a/frontend/rust-lib/flowy-user-pub/src/entities.rs b/frontend/rust-lib/flowy-user-pub/src/entities.rs index db9a81e8d81d8..6d579c70dc0f6 100644 --- a/frontend/rust-lib/flowy-user-pub/src/entities.rs +++ b/frontend/rust-lib/flowy-user-pub/src/entities.rs @@ -395,6 +395,7 @@ pub struct WorkspaceMember { pub email: String, pub role: Role, pub name: String, + pub avatar_url: Option, } /// represent the user awareness object id for the workspace. diff --git a/frontend/rust-lib/flowy-user/src/entities/workspace.rs b/frontend/rust-lib/flowy-user/src/entities/workspace.rs index cdbd928fe09c6..bef8151d527ab 100644 --- a/frontend/rust-lib/flowy-user/src/entities/workspace.rs +++ b/frontend/rust-lib/flowy-user/src/entities/workspace.rs @@ -14,6 +14,9 @@ pub struct WorkspaceMemberPB { #[pb(index = 3)] pub role: AFRolePB, + + #[pb(index = 4, one_of)] + pub avatar_url: Option, } impl From for WorkspaceMemberPB { @@ -22,6 +25,7 @@ impl From for WorkspaceMemberPB { email: value.email, name: value.name, role: value.role.into(), + avatar_url: value.avatar_url, } } } From 2dab75cf68d8e41e06d7a8253369991132bbdabe Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 00:10:10 +0800 Subject: [PATCH 31/41] chore: error page --- .../ai_chat/application/chat_bloc.dart | 139 ++++++++++++--- .../application/chat_message_listener.dart | 12 +- .../chat_related_question_bloc.dart | 2 +- .../lib/plugins/ai_chat/chat_page.dart | 57 ++++--- .../ai_chat/presentation/chat_ai_message.dart | 5 +- .../presentation/chat_error_message.dart | 86 +++++++--- .../ai_chat/presentation/chat_input.dart | 30 +--- .../presentation/chat_related_question.dart | 158 +++++++++++++----- .../presentation/chat_user_message.dart | 13 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 22 +-- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 ++--- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 28 ++-- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- .../flowy_icons/16x/flowy_ai_chat_logo.svg | 13 ++ frontend/resources/translations/en.json | 6 +- frontend/rust-lib/Cargo.lock | 44 +++-- frontend/rust-lib/Cargo.toml | 2 +- frontend/rust-lib/flowy-chat-pub/src/cloud.rs | 9 +- frontend/rust-lib/flowy-chat/src/chat.rs | 70 ++++++-- .../rust-lib/flowy-chat/src/event_handler.rs | 13 ++ frontend/rust-lib/flowy-chat/src/event_map.rs | 4 + frontend/rust-lib/flowy-chat/src/manager.rs | 12 +- .../rust-lib/flowy-chat/src/notification.rs | 8 +- .../src/persistence/chat_message_sql.rs | 35 ++++ .../flowy-core/src/integrate/trait_impls.rs | 19 ++- .../flowy-server/src/af_cloud/impls/chat.rs | 21 ++- .../rust-lib/flowy-server/src/default_impl.rs | 19 ++- 29 files changed, 608 insertions(+), 265 deletions(-) create mode 100644 frontend/resources/flowy_icons/16x/flowy_ai_chat_logo.svg diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 21bb63510170b..28a86b3d8420c 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -19,6 +19,7 @@ class ChatBloc extends Bloc { required ViewPB view, required UserProfilePB userProfile, }) : listener = ChatMessageListener(chatId: view.id), + chatId = view.id, super( ChatState.initial(view, userProfile), ) { @@ -26,14 +27,23 @@ class ChatBloc extends Bloc { listener.start( chatMessageCallback: _handleChatMessage, + lastUserSentMessageCallback: (message) { + if (!isClosed) { + add(ChatEvent.didSentUserMessage(message)); + } + }, chatErrorMessageCallback: (err) { Log.error("chat error: ${err.errorMessage}"); + final metadata = OnetimeMessageType.serverStreamError.toMap(); + if (state.lastSentMessage != null) { + metadata["canRetry"] = "true"; + } final error = CustomMessage( - metadata: OnetimeMessageType.serverStreamError.toMap(), + metadata: metadata, author: const User(id: "system"), id: 'system', ); - add(ChatEvent.streamingChatMessage([error])); + add(ChatEvent.streaming([error])); }, latestMessageCallback: (list) { final messages = list.messages.map(_createChatMessage).toList(); @@ -45,13 +55,33 @@ class ChatBloc extends Bloc { }, finishAnswerQuestionCallback: () { if (!isClosed) { - add(const ChatEvent.didFinishStreamingChatMessage()); + add(const ChatEvent.didFinishStreaming()); + if (state.lastSentMessage != null) { + final payload = ChatMessageIdPB( + chatId: chatId, messageId: state.lastSentMessage!.messageId); + // When user message was sent to the server, we start gettting related question + ChatEventGetRelatedQuestion(payload).send().then((result) { + if (!isClosed) { + result.fold( + (list) { + add( + ChatEvent.didReceiveRelatedQuestion(list.items), + ); + }, + (err) { + Log.error("Failed to get related question: $err"); + }, + ); + } + }); + } } }, ); } final ChatMessageListener listener; + final String chatId; @override Future close() { @@ -70,7 +100,7 @@ class ChatBloc extends Bloc { ); ChatEventLoadNextMessage(payload).send(); }, - loadPrevMessage: () async { + startLoadingPrevMessage: () async { Int64? beforeMessageId; if (state.messages.isNotEmpty) { beforeMessageId = Int64.parseInt(state.messages.last.id); @@ -82,30 +112,29 @@ class ChatBloc extends Bloc { ), ); }, - didLoadLatestMessages: (List messages) { + didLoadPreviousMessages: (List messages, bool hasMore) { + Log.debug("did load previous messages: ${messages.length}"); final uniqueMessages = {...state.messages, ...messages}.toList() ..sort((a, b) => b.id.compareTo(a.id)); emit( state.copyWith( messages: uniqueMessages, - loadingStatus: const LoadingState.finish(), + loadingPreviousStatus: const LoadingState.finish(), + hasMore: hasMore, ), ); }, - didLoadPreviousMessages: (List messages, bool hasMore) { - Log.debug("did load previous messages: ${messages.length}"); + didLoadLatestMessages: (List messages) { final uniqueMessages = {...state.messages, ...messages}.toList() ..sort((a, b) => b.id.compareTo(a.id)); emit( state.copyWith( messages: uniqueMessages, - loadingPreviousStatus: const LoadingState.finish(), - hasMore: hasMore, + loadingStatus: const LoadingState.finish(), ), ); }, - tapMessage: (Message message) {}, - streamingChatMessage: (List messages) { + streaming: (List messages) { // filter out loading or error messages final allMessages = state.messages.where((element) { return !(element.metadata?.containsKey(onetimeMessageType) == @@ -114,7 +143,7 @@ class ChatBloc extends Bloc { allMessages.insertAll(0, messages); emit(state.copyWith(messages: allMessages)); }, - didFinishStreamingChatMessage: () { + didFinishStreaming: () { emit( state.copyWith( answerQuestionStatus: const LoadingState.finish(), @@ -131,10 +160,62 @@ class ChatBloc extends Bloc { state.copyWith( messages: allMessages, answerQuestionStatus: const LoadingState.loading(), + relatedQuestions: [], + ), + ); + }, + retryGenerate: () { + if (state.lastSentMessage == null) { + return; + } + final payload = ChatMessageIdPB( + chatId: chatId, + messageId: state.lastSentMessage!.messageId, + ); + ChatEventGetAnswerForQuestion(payload).send().then((result) { + if (!isClosed) { + result.fold( + (answer) => _handleChatMessage(answer), + (err) { + Log.error("Failed to get answer: $err"); + }, + ); + } + }); + }, + didReceiveRelatedQuestion: (List questions) { + final allMessages = state.messages.where((element) { + return !(element.metadata?.containsKey(onetimeMessageType) == + true); + }).toList(); + + final message = CustomMessage( + metadata: OnetimeMessageType.relatedQuestion.toMap(), + author: const User(id: "system"), + id: 'system', + ); + allMessages.insert(0, message); + emit( + state.copyWith( + messages: allMessages, + relatedQuestions: questions, + ), + ); + }, + clearReleatedQuestion: () { + emit( + state.copyWith( + relatedQuestions: [], + ), + ); + }, + didSentUserMessage: (ChatMessagePB message) { + emit( + state.copyWith( + lastSentMessage: message, ), ); }, - retryGenerate: () {}, ); }, ); @@ -167,7 +248,7 @@ class ChatBloc extends Bloc { final messages = pb.hasFollowing ? [_loadingMessage(0.toString()), message] : [message]; - add(ChatEvent.streamingChatMessage(messages)); + add(ChatEvent.streaming(messages)); } } @@ -198,21 +279,24 @@ class ChatBloc extends Bloc { @freezed class ChatEvent with _$ChatEvent { - const factory ChatEvent.sendMessage(String message) = _SendMessage; - const factory ChatEvent.tapMessage(Message message) = _TapMessage; - const factory ChatEvent.loadPrevMessage() = _LoadPrevMessage; const factory ChatEvent.initialLoad() = _InitialLoadMessage; - const factory ChatEvent.didLoadLatestMessages(List messages) = - _DidLoadMessages; - const factory ChatEvent.streamingChatMessage(List messages) = - _DidStreamMessage; - const factory ChatEvent.didFinishStreamingChatMessage() = - _FinishStreamingMessage; + const factory ChatEvent.sendMessage(String message) = _SendMessage; + const factory ChatEvent.startLoadingPrevMessage() = _StartLoadPrevMessage; const factory ChatEvent.didLoadPreviousMessages( List messages, bool hasMore, ) = _DidLoadPreviousMessages; + const factory ChatEvent.didLoadLatestMessages(List messages) = + _DidLoadMessages; + const factory ChatEvent.streaming(List messages) = _DidStreamMessage; + const factory ChatEvent.didFinishStreaming() = _FinishStreamingMessage; + const factory ChatEvent.didReceiveRelatedQuestion( + List questions, + ) = _DidReceiveRelatedQueston; + const factory ChatEvent.clearReleatedQuestion() = _ClearRelatedQuestion; const factory ChatEvent.retryGenerate() = _RetryGenerate; + const factory ChatEvent.didSentUserMessage(ChatMessagePB message) = + _DidSendUserMessage; } @freezed @@ -224,8 +308,9 @@ class ChatState with _$ChatState { required LoadingState loadingStatus, required LoadingState loadingPreviousStatus, required LoadingState answerQuestionStatus, - required List relatedQuestions, required bool hasMore, + required List relatedQuestions, + ChatMessagePB? lastSentMessage, }) = _ChatState; factory ChatState.initial(ViewPB view, UserProfilePB userProfile) => @@ -247,7 +332,7 @@ class LoadingState with _$LoadingState { const factory LoadingState.finish() = _Finish; } -enum OnetimeMessageType { unknown, loading, serverStreamError } +enum OnetimeMessageType { unknown, loading, serverStreamError, relatedQuestion } const onetimeMessageType = "OnetimeMessageType"; @@ -258,6 +343,8 @@ extension OnetimeMessageTypeExtension on OnetimeMessageType { return OnetimeMessageType.loading; case 'OnetimeMessageType.serverStreamError': return OnetimeMessageType.serverStreamError; + case 'OnetimeMessageType.relatedQuestion': + return OnetimeMessageType.relatedQuestion; default: Log.error('Unknown OnetimeMessageType: $value'); return OnetimeMessageType.unknown; diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart index c37d25608efd7..3b40c18d36797 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_message_listener.dart @@ -28,7 +28,7 @@ class ChatMessageListener { ChatNotificationParser? _parser; ChatMessageCallback? chatMessageCallback; - ChatMessageCallback? lastSentMessageCallback; + ChatMessageCallback? lastUserSentMessageCallback; ChatErrorMessageCallback? chatErrorMessageCallback; LatestMessageCallback? latestMessageCallback; PrevMessageCallback? prevMessageCallback; @@ -39,14 +39,14 @@ class ChatMessageListener { ChatErrorMessageCallback? chatErrorMessageCallback, LatestMessageCallback? latestMessageCallback, PrevMessageCallback? prevMessageCallback, - ChatMessageCallback? lastSentMessageCallback, + ChatMessageCallback? lastUserSentMessageCallback, void Function()? finishAnswerQuestionCallback, }) { this.chatMessageCallback = chatMessageCallback; this.chatErrorMessageCallback = chatErrorMessageCallback; this.latestMessageCallback = latestMessageCallback; this.prevMessageCallback = prevMessageCallback; - this.lastSentMessageCallback = lastSentMessageCallback; + this.lastUserSentMessageCallback = lastUserSentMessageCallback; this.finishAnswerQuestionCallback = finishAnswerQuestionCallback; } @@ -59,10 +59,10 @@ class ChatMessageListener { case ChatNotification.DidReceiveChatMessage: chatMessageCallback?.call(ChatMessagePB.fromBuffer(r)); break; - case ChatNotification.LastSentMessage: - lastSentMessageCallback?.call(ChatMessagePB.fromBuffer(r)); + case ChatNotification.LastUserSentMessage: + lastUserSentMessageCallback?.call(ChatMessagePB.fromBuffer(r)); break; - case ChatNotification.ChatMessageError: + case ChatNotification.StreamChatMessageError: chatErrorMessageCallback?.call(ChatMessageErrorPB.fromBuffer(r)); break; case ChatNotification.DidLoadLatestChatMessage: diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart index 24bf5e56cb014..d6db6afc37773 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_related_question_bloc.dart @@ -18,7 +18,7 @@ class ChatRelatedMessageBloc await event.when( initial: () async { listener.start( - lastSentMessageCallback: (message) { + lastUserSentMessageCallback: (message) { if (!isClosed) { add(ChatRelatedMessageEvent.updateLastSentMessage(message)); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 273d3e1445199..41b327097511c 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -2,6 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_ai_message.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_error_message.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_related_question.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_user_message.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; @@ -51,7 +52,12 @@ class _AIChatPageState extends State { if (widget.userProfile.authenticator == AuthenticatorPB.AppFlowyCloud) { return buildChatWidget(); } else { - return buildUnsupportWidget(); + return Center( + child: FlowyText( + LocaleKeys.chat_unsupportedCloudPrompt.tr(), + fontSize: 20, + ), + ); } } @@ -69,11 +75,6 @@ class _AIChatPageState extends State { return Chat( messages: state.messages, onAttachmentPressed: () {}, - onMessageTap: (BuildContext _, types.Message message) { - blocContext - .read() - .add(ChatEvent.tapMessage(message)); - }, onSendPressed: (types.PartialText message) { // We use custom bottom widget for chat input, so // do not need to handle this event. @@ -88,7 +89,7 @@ class _AIChatPageState extends State { const LoadingState.loading()) { blocContext .read() - .add(const ChatEvent.loadPrevMessage()); + .add(const ChatEvent.startLoadingPrevMessage()); } }, emptyState: BlocBuilder( @@ -100,7 +101,7 @@ class _AIChatPageState extends State { ); }, ), - messageWidthRatio: isMobile ? 0.8 : 0.9, + messageWidthRatio: isMobile ? 0.8 : 0.86, bubbleBuilder: ( child, { required message, @@ -112,16 +113,32 @@ class _AIChatPageState extends State { child: child, ); } else { - final messageType = - restoreOnetimeMessageType(message.metadata); - + final messageType = restoreOnetimeMessageType( + message.metadata, + ); if (messageType == OnetimeMessageType.serverStreamError) { return ChatErrorMessage( + message: message, onRetryPressed: () { - blocContext.read().add( - const ChatEvent.retryGenerate(), - ); + blocContext + .read() + .add(const ChatEvent.retryGenerate()); + }, + ); + } + + if (messageType == OnetimeMessageType.relatedQuestion) { + return RelatedQuestionList( + onQuestionSelected: (question) { + blocContext + .read() + .add(ChatEvent.sendMessage(question)); + blocContext + .read() + .add(const ChatEvent.clearReleatedQuestion()); }, + chatId: widget.view.id, + relatedQuestions: state.relatedQuestions, ); } @@ -140,15 +157,6 @@ class _AIChatPageState extends State { ); } - Widget buildUnsupportWidget() { - return Center( - child: FlowyText( - LocaleKeys.chat_unsupportedCloudPrompt.tr(), - fontSize: 20, - ), - ); - } - Widget buildBubble(Message message, Widget child) { final isAuthor = message.author.id == _user.id; const borderRadius = BorderRadius.all(Radius.circular(6)); @@ -249,9 +257,6 @@ class _AIChatPageState extends State { child: ChatInput( chatId: widget.view.id, onSendPressed: (message) => onSendPressed(context, message.text), - onQuestionSelected: (question) { - onSendPressed(context, question); - }, ), ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart index 39e971f4dd18d..0a1ad8bab5da8 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart @@ -50,8 +50,9 @@ class ChatAIMessageBubble extends StatelessWidget { children: [ const ChatBorderedCircleAvatar( child: FlowySvg( - FlowySvgs.flowy_logo_xl, - blendMode: null, + FlowySvgs.flowy_ai_chat_logo_s, + // color: Theme.of(context).colorScheme.primary, + // blendMode: null, size: Size.square(24), ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart index 4846df1487476..cbdf544d28ef7 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart @@ -3,41 +3,75 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; class ChatErrorMessage extends StatelessWidget { - const ChatErrorMessage({required this.onRetryPressed, super.key}); + const ChatErrorMessage({ + required this.message, + required this.onRetryPressed, + super.key, + }); final void Function() onRetryPressed; + final Message message; @override Widget build(BuildContext context) { - return Column( - children: [ - const Divider(height: 4, thickness: 1), - const VSpace(16), - Center( - child: FlowyTooltip( - message: LocaleKeys.chat_clickToRetry.tr(), - child: FlowyButton( - useIntrinsicWidth: true, - text: Padding( - padding: const EdgeInsets.all(8.0), - child: FlowyText( - LocaleKeys.chat_serverUnavailable.tr(), - fontSize: 14, + final canRetry = message.metadata?["canRetry"] != null; + + if (canRetry) { + return Column( + children: [ + const Divider(height: 4, thickness: 1), + const VSpace(16), + Center( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: FlowyText( + LocaleKeys.chat_aiServerUnavailable.tr(), + fontSize: 14, + ), ), - ), - onTap: () { - onRetryPressed(); - }, - iconPadding: 0, - rightIcon: const Icon( - Icons.refresh, - size: 20, - ), + const VSpace(10), + FlowyButton( + radius: BorderRadius.circular(20), + useIntrinsicWidth: true, + text: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: FlowyText( + LocaleKeys.chat_regenerateAnswer.tr(), + fontSize: 14, + ), + ), + onTap: onRetryPressed, + iconPadding: 0, + leftIcon: const Icon( + Icons.refresh, + size: 20, + ), + ), + ], ), ), + ], + ); + } else { + return Center( + child: Column( + children: [ + const Divider(height: 20, thickness: 1), + Padding( + padding: const EdgeInsets.all(8.0), + child: FlowyText( + LocaleKeys.chat_serverUnavailable.tr(), + fontSize: 14, + ), + ), + ], ), - ], - ); + ); + } } } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart index 88ff3821021e7..207280187d943 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -7,8 +7,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; -import 'chat_related_question.dart'; - class ChatInput extends StatefulWidget { /// Creates [ChatInput] widget. const ChatInput({ @@ -17,7 +15,6 @@ class ChatInput extends StatefulWidget { this.onAttachmentPressed, required this.onSendPressed, required this.chatId, - required this.onQuestionSelected, this.options = const InputOptions(), }); @@ -26,7 +23,6 @@ class ChatInput extends StatefulWidget { final void Function(types.PartialText) onSendPressed; final InputOptions options; final String chatId; - final Function(String) onQuestionSelected; @override State createState() => _ChatInputState(); @@ -118,24 +114,16 @@ class _ChatInputState extends State { ? Theme.of(context).colorScheme.surfaceContainer : Theme.of(context).colorScheme.surfaceContainerHighest, elevation: 0.6, - child: Column( + child: Row( children: [ - RelatedQuestionList( - chatId: widget.chatId, - onQuestionSelected: widget.onQuestionSelected, - ), - Row( - children: [ - if (widget.onAttachmentPressed != null) - AttachmentButton( - isLoading: widget.isAttachmentUploading ?? false, - onPressed: widget.onAttachmentPressed, - padding: buttonPadding, - ), - Expanded(child: _inputTextField(textPadding)), - _sendButton(buttonPadding), - ], - ), + if (widget.onAttachmentPressed != null) + AttachmentButton( + isLoading: widget.isAttachmentUploading ?? false, + onPressed: widget.onAttachmentPressed, + padding: buttonPadding, + ), + Expanded(child: _inputTextField(textPadding)), + _sendButton(buttonPadding), ], ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart index 826bf77e80e5e..f4709f2263792 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_related_question.dart @@ -1,14 +1,15 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_related_question_bloc.dart'; +import 'package:appflowy_backend/protobuf/flowy-chat/entities.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class RelatedQuestionList extends StatefulWidget { - const RelatedQuestionList({ +class RelatedQuestionPage extends StatefulWidget { + const RelatedQuestionPage({ required this.chatId, required this.onQuestionSelected, super.key, @@ -18,10 +19,10 @@ class RelatedQuestionList extends StatefulWidget { final Function(String) onQuestionSelected; @override - State createState() => _RelatedQuestionListState(); + State createState() => _RelatedQuestionPageState(); } -class _RelatedQuestionListState extends State { +class _RelatedQuestionPageState extends State { @override Widget build(BuildContext context) { return BlocProvider( @@ -31,50 +32,115 @@ class _RelatedQuestionListState extends State { ), child: BlocBuilder( builder: (blocContext, state) { - if (state.relatedQuestions.isEmpty) { - return const SizedBox.shrink(); - } else { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - const FlowySvg( - FlowySvgs.ai_summary_generate_s, - size: Size.square(24), - ), - const HSpace(6), - FlowyText( - LocaleKeys.chat_relatedQuestion.tr(), - fontSize: 18, - ), - ], - ), - ), - const Divider(height: 6), - ListView.builder( - shrinkWrap: true, - itemCount: state.relatedQuestions.length, - itemBuilder: (context, index) { - final question = state.relatedQuestions[index]; - return ListTile( - title: Text(question.content), - onTap: () { - widget.onQuestionSelected(question.content); - blocContext.read().add( - const ChatRelatedMessageEvent.clear(), - ); - }, - trailing: const FlowySvg(FlowySvgs.add_m), - ); - }, + return RelatedQuestionList( + chatId: widget.chatId, + onQuestionSelected: widget.onQuestionSelected, + relatedQuestions: state.relatedQuestions, + ); + }, + ), + ); + } +} + +class RelatedQuestionList extends StatelessWidget { + const RelatedQuestionList({ + required this.chatId, + required this.onQuestionSelected, + required this.relatedQuestions, + super.key, + }); + + final String chatId; + final Function(String) onQuestionSelected; + final List relatedQuestions; + + @override + Widget build(BuildContext context) { + return ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: relatedQuestions.length, + itemBuilder: (context, index) { + final question = relatedQuestions[index]; + if (index == 0) { + return Column( + children: [ + const Divider(height: 36), + Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + const FlowySvg( + FlowySvgs.ai_summary_generate_s, + size: Size.square(24), + ), + const HSpace(6), + FlowyText( + LocaleKeys.chat_relatedQuestion.tr(), + fontSize: 18, + ), + ], ), - ], - ); - } + ), + const Divider(height: 6), + RelatedQuestionItem( + question: question, + onQuestionSelected: onQuestionSelected, + ), + ], + ); + } else { + return RelatedQuestionItem( + question: question, + onQuestionSelected: onQuestionSelected, + ); + } + }, + ); + } +} + +class RelatedQuestionItem extends StatefulWidget { + const RelatedQuestionItem({ + required this.question, + required this.onQuestionSelected, + super.key, + }); + + final RelatedQuestionPB question; + final Function(String) onQuestionSelected; + + @override + State createState() => _RelatedQuestionItemState(); +} + +class _RelatedQuestionItemState extends State { + bool _isHovered = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + onEnter: (_) => setState(() => _isHovered = true), + onExit: (_) => setState(() => _isHovered = false), + child: ListTile( + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + ), + title: Text( + widget.question.content, + style: TextStyle( + color: _isHovered ? Theme.of(context).colorScheme.primary : null, + fontSize: 14, + ), + ), + onTap: () { + widget.onQuestionSelected(widget.question.content); }, + trailing: FlowySvg( + FlowySvgs.add_m, + color: Theme.of(context).colorScheme.primary, + ), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart index 8e972315071dd..f6e55b80905f0 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_message.dart @@ -35,8 +35,9 @@ class ChatUserMessageBubble extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - _wrapHover( - DecoratedBox( + // _wrapHover( + Flexible( + child: DecoratedBox( decoration: BoxDecoration( borderRadius: borderRadius, color: backgroundColor, @@ -50,6 +51,7 @@ class ChatUserMessageBubble extends StatelessWidget { ), ), ), + // ), BlocBuilder( builder: (context, state) { return Padding( @@ -68,13 +70,6 @@ class ChatUserMessageBubble extends StatelessWidget { ), ); } - - ChatUserMessageHover _wrapHover(Widget child) { - return ChatUserMessageHover( - message: message, - child: child, - ); - } } class ChatUserMessageHover extends StatefulWidget { diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 38252652c6d09..19f7539de5a1f 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -162,7 +162,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -182,7 +182,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bytes", @@ -757,7 +757,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "again", "anyhow", @@ -804,7 +804,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "futures-channel", "futures-util", @@ -1043,7 +1043,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -1068,7 +1068,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "async-trait", @@ -1425,7 +1425,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -2833,7 +2833,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "futures-util", @@ -2850,7 +2850,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -3282,7 +3282,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "reqwest", @@ -5770,7 +5770,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 82fa349dd107b..48d1f5b44f1bd 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index d0c36ed64dcd5..48e7783a95088 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bytes", @@ -562,7 +562,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "again", "anyhow", @@ -609,7 +609,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "futures-channel", "futures-util", @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "async-trait", @@ -981,7 +981,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1026,7 +1026,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -1815,7 +1815,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "futures-util", @@ -1832,7 +1832,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -2133,7 +2133,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "reqwest", @@ -2817,7 +2817,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2837,7 +2837,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2905,19 +2904,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -3773,7 +3759,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index c33b10f75da18..5ceabaf70e0a7 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index ae8c8e40b9450..9374636497afa 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bytes", @@ -730,7 +730,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "again", "anyhow", @@ -777,7 +777,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "futures-channel", "futures-util", @@ -1025,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "async-trait", @@ -1300,7 +1300,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1411,7 +1411,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "futures-util", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -3360,7 +3360,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "reqwest", @@ -4865,7 +4865,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4886,7 +4886,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.55", @@ -5864,7 +5864,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index d92053ea4421e..84752a416065f 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } [dependencies] serde_json.workspace = true diff --git a/frontend/resources/flowy_icons/16x/flowy_ai_chat_logo.svg b/frontend/resources/flowy_icons/16x/flowy_ai_chat_logo.svg new file mode 100644 index 0000000000000..a719222956504 --- /dev/null +++ b/frontend/resources/flowy_icons/16x/flowy_ai_chat_logo.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index 430a17f566aee..4d3367b47860d 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -149,11 +149,13 @@ "newBoardText": "New board", "chat": { "newChat": "New chat", - "inputMessageHint": "Message", + "inputMessageHint": "Message AppFlowy AI", "unsupportedCloudPrompt": "This feature is only available when using AppFlowy Cloud", "relatedQuestion": "Related", - "serverUnavailable": "Service Temporarily Unavailable", + "serverUnavailable": "Service Temporarily Unavailable. Please try again later.", + "aiServerUnavailable": "There was an error generating a response.", "clickToRetry": "Click to retry", + "regenerateAnswer": "Regenerate", "aiMistakePrompt": "AI can make mistakes. Check important info." }, "trash": { diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 395f2c00625ad..71a76c2783908 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bytes", @@ -664,7 +664,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "again", "anyhow", @@ -711,7 +711,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "futures-channel", "futures-util", @@ -919,7 +919,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "bincode", @@ -944,7 +944,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "async-trait", @@ -1164,7 +1164,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1264,7 +1264,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -2518,7 +2518,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "futures-util", @@ -2535,7 +2535,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", @@ -2900,7 +2900,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "reqwest", @@ -3775,7 +3775,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3795,6 +3795,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3862,6 +3863,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.47", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -4065,7 +4079,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.10.5", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -4086,7 +4100,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", @@ -4983,7 +4997,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=98534de86557e3f1166cd8fce19314f3138426f0#98534de86557e3f1166cd8fce19314f3138426f0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 612785200a507..41d93653e4cbb 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "98534de86557e3f1166cd8fce19314f3138426f0" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } [profile.dev] opt-level = 1 diff --git a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs index 42ab020dd1ab9..51de79422a3fc 100644 --- a/frontend/rust-lib/flowy-chat-pub/src/cloud.rs +++ b/frontend/rust-lib/flowy-chat-pub/src/cloud.rs @@ -1,6 +1,6 @@ pub use client_api::entity::ai_dto::{RelatedQuestion, RepeatedRelatedQuestion}; pub use client_api::entity::{ - ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, + ChatAuthorType, ChatMessage, ChatMessageType, MessageCursor, QAChatMessage, RepeatedChatMessage, }; use client_api::error::AppResponseError; use flowy_error::FlowyError; @@ -40,4 +40,11 @@ pub trait ChatCloudService: Send + Sync + 'static { chat_id: &str, message_id: i64, ) -> FutureResult; + + fn generate_answer( + &self, + workspace_id: &str, + chat_id: &str, + question_message_id: i64, + ) -> FutureResult; } diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index a87901bcba584..95cc9e90ca619 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -3,8 +3,12 @@ use crate::entities::{ }; use crate::manager::ChatUserService; use crate::notification::{send_notification, ChatNotification}; -use crate::persistence::{insert_chat_messages, select_chat_messages, ChatMessageTable}; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageType, MessageCursor}; +use crate::persistence::{ + insert_answer_message, insert_chat_messages, select_chat_messages, ChatMessageTable, +}; +use flowy_chat_pub::cloud::{ + ChatAuthorType, ChatCloudService, ChatMessage, ChatMessageType, MessageCursor, +}; use flowy_error::{FlowyError, FlowyResult}; use flowy_sqlite::DBConnection; use futures::StreamExt; @@ -265,6 +269,25 @@ impl Chat { Ok(RepeatedRelatedQuestionPB::from(resp)) } + #[instrument(level = "debug", skip_all, err)] + pub async fn generate_answer(&self, question_message_id: i64) -> FlowyResult { + let workspace_id = self.user_service.workspace_id()?; + let resp = self + .cloud_service + .generate_answer(&workspace_id, &self.chat_id, question_message_id) + .await?; + + save_answer( + self.user_service.sqlite_connection(self.uid)?, + &self.chat_id, + resp.clone(), + question_message_id, + )?; + + let pb = ChatMessagePB::from(resp); + Ok(pb) + } + async fn load_local_chat_messages( &self, limit: i64, @@ -318,8 +341,6 @@ fn stream_send_chat_messages( .send_chat_message(&workspace_id, &chat_id, &message_content, message_type) .await; - let mut user_asked_question = None; - // By default, stream only returns two messages: // 1. user message // 2. ai response message @@ -329,17 +350,14 @@ fn stream_send_chat_messages( match result { Ok(message) => { let mut pb = ChatMessagePB::from(message.clone()); - if user_asked_question.is_none() { + if matches!(message.author.author_type, ChatAuthorType::Human) { pb.has_following = true; - user_asked_question = Some(pb.clone()); - } else { - pb.reply_message_id = user_asked_question.as_ref().map(|m| m.message_id); - if let Some(user_asked_question) = &user_asked_question { - send_notification(&chat_id, ChatNotification::LastSentMessage) - .payload(user_asked_question.clone()) - .send(); - } + send_notification(&chat_id, ChatNotification::LastUserSentMessage) + .payload(pb.clone()) + .send(); } + + // send_notification(&chat_id, ChatNotification::DidReceiveChatMessage) .payload(pb) .send(); @@ -352,7 +370,7 @@ fn stream_send_chat_messages( content: message_content.clone(), error_message: "Service Temporarily Unavailable".to_string(), }; - send_notification(&chat_id, ChatNotification::ChatMessageError) + send_notification(&chat_id, ChatNotification::StreamChatMessageError) .payload(pb) .send(); break; @@ -367,7 +385,7 @@ fn stream_send_chat_messages( content: message_content.clone(), error_message: err.to_string(), }; - send_notification(&chat_id, ChatNotification::ChatMessageError) + send_notification(&chat_id, ChatNotification::StreamChatMessageError) .payload(pb) .send(); return; @@ -395,7 +413,7 @@ fn stream_send_chat_messages( created_at: message.created_at.timestamp(), author_type: message.author.author_type as i64, author_id: message.author.author_id.to_string(), - reply_message_id: user_asked_question.as_ref().map(|m| m.message_id), + reply_message_id: message.reply_message_id, }) .collect::>(); insert_chat_messages(conn, &records)?; @@ -423,9 +441,27 @@ fn save_chat_message( created_at: message.created_at.timestamp(), author_type: message.author.author_type as i64, author_id: message.author.author_id.to_string(), - reply_message_id: None, + reply_message_id: message.reply_message_id, }) .collect::>(); insert_chat_messages(conn, &records)?; Ok(()) } +fn save_answer( + conn: DBConnection, + chat_id: &str, + message: ChatMessage, + question_message_id: i64, +) -> FlowyResult<()> { + let record = ChatMessageTable { + message_id: message.message_id, + chat_id: chat_id.to_string(), + content: message.content, + created_at: message.created_at.timestamp(), + author_type: message.author.author_type as i64, + author_id: message.author.author_id.to_string(), + reply_message_id: message.reply_message_id, + }; + insert_answer_message(conn, question_message_id, record)?; + Ok(()) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_handler.rs b/frontend/rust-lib/flowy-chat/src/event_handler.rs index 607ee8e5dfd0b..959c0398b4929 100644 --- a/frontend/rust-lib/flowy-chat/src/event_handler.rs +++ b/frontend/rust-lib/flowy-chat/src/event_handler.rs @@ -78,3 +78,16 @@ pub(crate) async fn get_related_question_handler( .await?; data_result_ok(messages) } + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn get_answer_handler( + data: AFPluginData, + chat_manager: AFPluginState>, +) -> DataResult { + let chat_manager = upgrade_chat_manager(chat_manager)?; + let data = data.into_inner(); + let message = chat_manager + .generate_answer(&data.chat_id, data.message_id) + .await?; + data_result_ok(message) +} diff --git a/frontend/rust-lib/flowy-chat/src/event_map.rs b/frontend/rust-lib/flowy-chat/src/event_map.rs index b2ea726394ce0..9fae853459452 100644 --- a/frontend/rust-lib/flowy-chat/src/event_map.rs +++ b/frontend/rust-lib/flowy-chat/src/event_map.rs @@ -16,6 +16,7 @@ pub fn init(chat_manager: Weak) -> AFPlugin { .event(ChatEvent::LoadPrevMessage, load_prev_message_handler) .event(ChatEvent::LoadNextMessage, load_next_message_handler) .event(ChatEvent::GetRelatedQuestion, get_related_question_handler) + .event(ChatEvent::GetAnswerForQuestion, get_answer_handler) } #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] @@ -33,4 +34,7 @@ pub enum ChatEvent { #[event(input = "ChatMessageIdPB", output = "RepeatedRelatedQuestionPB")] GetRelatedQuestion = 3, + + #[event(input = "ChatMessageIdPB", output = "ChatMessagePB")] + GetAnswerForQuestion = 4, } diff --git a/frontend/rust-lib/flowy-chat/src/manager.rs b/frontend/rust-lib/flowy-chat/src/manager.rs index 67cec38761555..b2cc679eb2779 100644 --- a/frontend/rust-lib/flowy-chat/src/manager.rs +++ b/frontend/rust-lib/flowy-chat/src/manager.rs @@ -1,5 +1,5 @@ use crate::chat::Chat; -use crate::entities::{ChatMessageListPB, RepeatedRelatedQuestionPB}; +use crate::entities::{ChatMessageListPB, ChatMessagePB, RepeatedRelatedQuestionPB}; use crate::persistence::{insert_chat, ChatTable}; use dashmap::DashMap; use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageType}; @@ -158,6 +158,16 @@ impl ChatManager { let resp = chat.get_related_question(message_id).await?; Ok(resp) } + + pub async fn generate_answer( + &self, + chat_id: &str, + question_message_id: i64, + ) -> Result { + let chat = self.get_or_create_chat_instance(chat_id).await?; + let resp = chat.generate_answer(question_message_id).await?; + Ok(resp) + } } fn save_chat(conn: DBConnection, chat_id: &str) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-chat/src/notification.rs b/frontend/rust-lib/flowy-chat/src/notification.rs index c13936c667075..830c464a72390 100644 --- a/frontend/rust-lib/flowy-chat/src/notification.rs +++ b/frontend/rust-lib/flowy-chat/src/notification.rs @@ -10,9 +10,9 @@ pub enum ChatNotification { DidLoadLatestChatMessage = 1, DidLoadPrevChatMessage = 2, DidReceiveChatMessage = 3, - ChatMessageError = 4, + StreamChatMessageError = 4, FinishAnswerQuestion = 5, - LastSentMessage = 6, + LastUserSentMessage = 6, } impl std::convert::From for i32 { @@ -26,9 +26,9 @@ impl std::convert::From for ChatNotification { 1 => ChatNotification::DidLoadLatestChatMessage, 2 => ChatNotification::DidLoadPrevChatMessage, 3 => ChatNotification::DidReceiveChatMessage, - 4 => ChatNotification::ChatMessageError, + 4 => ChatNotification::StreamChatMessageError, 5 => ChatNotification::FinishAnswerQuestion, - 6 => ChatNotification::LastSentMessage, + 6 => ChatNotification::LastUserSentMessage, _ => ChatNotification::Unknown, } } diff --git a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs index 6d9202def02e5..3e65123c27887 100644 --- a/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs +++ b/frontend/rust-lib/flowy-chat/src/persistence/chat_message_sql.rs @@ -45,6 +45,41 @@ pub fn insert_chat_messages( Ok(()) } +pub fn insert_answer_message( + mut conn: DBConnection, + question_message_id: i64, + message: ChatMessageTable, +) -> FlowyResult<()> { + conn.immediate_transaction(|conn| { + // Step 1: Get the message with the given question_message_id + let question_message = dsl::chat_message_table + .filter(chat_message_table::message_id.eq(question_message_id)) + .first::(conn)?; + + // Step 2: Use reply_message_id from the retrieved message to delete the existing message + if let Some(reply_id) = question_message.reply_message_id { + diesel::delete(dsl::chat_message_table.filter(chat_message_table::message_id.eq(reply_id))) + .execute(conn)?; + } + + // Step 3: Insert the new message + let _ = insert_into(chat_message_table::table) + .values(message) + .on_conflict(chat_message_table::message_id) + .do_update() + .set(( + chat_message_table::content.eq(excluded(chat_message_table::content)), + chat_message_table::created_at.eq(excluded(chat_message_table::created_at)), + chat_message_table::author_type.eq(excluded(chat_message_table::author_type)), + chat_message_table::author_id.eq(excluded(chat_message_table::author_id)), + chat_message_table::reply_message_id.eq(excluded(chat_message_table::reply_message_id)), + )) + .execute(conn)?; + Ok::<(), FlowyError>(()) + })?; + + Ok(()) +} pub fn select_chat_messages( mut conn: DBConnection, chat_id_val: &str, diff --git a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs index 4e02d26068689..2e672dec6cd94 100644 --- a/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs +++ b/frontend/rust-lib/flowy-core/src/integrate/trait_impls.rs @@ -17,7 +17,7 @@ use collab_integrate::collab_builder::{ CollabCloudPluginProvider, CollabPluginProviderContext, CollabPluginProviderType, }; use flowy_chat_pub::cloud::{ - ChatCloudService, ChatMessageStream, MessageCursor, RepeatedChatMessage, + ChatCloudService, ChatMessage, ChatMessageStream, MessageCursor, RepeatedChatMessage, }; use flowy_database_pub::cloud::{ CollabDocStateByOid, DatabaseCloudService, DatabaseSnapshot, SummaryRowContent, @@ -510,4 +510,21 @@ impl ChatCloudService for ServerProvider { .await }) } + + fn generate_answer( + &self, + workspace_id: &str, + chat_id: &str, + question_message_id: i64, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let server = self.get_server(); + FutureResult::new(async move { + server? + .chat_service() + .generate_answer(&workspace_id, &chat_id, question_message_id) + .await + }) + } } diff --git a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs index 673586979b2e2..cc484a9346b25 100644 --- a/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs +++ b/frontend/rust-lib/flowy-server/src/af_cloud/impls/chat.rs @@ -3,7 +3,7 @@ use client_api::entity::ai_dto::RepeatedRelatedQuestion; use client_api::entity::{ CreateChatMessageParams, CreateChatParams, MessageCursor, RepeatedChatMessage, }; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageStream, ChatMessageType}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageStream, ChatMessageType}; use flowy_error::FlowyError; use futures_util::StreamExt; use lib_infra::async_trait::async_trait; @@ -106,4 +106,23 @@ where Ok(resp) }) } + + fn generate_answer( + &self, + workspace_id: &str, + chat_id: &str, + question_message_id: i64, + ) -> FutureResult { + let workspace_id = workspace_id.to_string(); + let chat_id = chat_id.to_string(); + let try_get_client = self.inner.try_get_client(); + + FutureResult::new(async move { + let resp = try_get_client? + .generate_question_answer(&workspace_id, &chat_id, question_message_id) + .await + .map_err(FlowyError::from)?; + Ok(resp) + }) + } } diff --git a/frontend/rust-lib/flowy-server/src/default_impl.rs b/frontend/rust-lib/flowy-server/src/default_impl.rs index c1cc631e8017c..654bffcb1ce56 100644 --- a/frontend/rust-lib/flowy-server/src/default_impl.rs +++ b/frontend/rust-lib/flowy-server/src/default_impl.rs @@ -1,6 +1,6 @@ use client_api::entity::ai_dto::RepeatedRelatedQuestion; use client_api::entity::{ChatMessageType, MessageCursor, RepeatedChatMessage}; -use flowy_chat_pub::cloud::{ChatCloudService, ChatMessageStream}; +use flowy_chat_pub::cloud::{ChatCloudService, ChatMessage, ChatMessageStream}; use flowy_error::FlowyError; use lib_infra::async_trait::async_trait; use lib_infra::future::FutureResult; @@ -44,12 +44,23 @@ impl ChatCloudService for DefaultChatCloudServiceImpl { fn get_related_message( &self, - workspace_id: &str, - chat_id: &str, - message_id: i64, + _workspace_id: &str, + _chat_id: &str, + _message_id: i64, ) -> FutureResult { FutureResult::new(async move { Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) }) } + + fn generate_answer( + &self, + _workspace_id: &str, + _chat_id: &str, + _question_message_id: i64, + ) -> FutureResult { + FutureResult::new(async move { + Err(FlowyError::not_support().with_context("Chat is not supported in local server.")) + }) + } } From 7e778d69c2cfc37fcee3be4f66f8e61079687b2d Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 00:10:28 +0800 Subject: [PATCH 32/41] chore: error page --- .../lib/plugins/ai_chat/application/chat_bloc.dart | 4 +++- .../lib/plugins/ai_chat/presentation/chat_error_message.dart | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 28a86b3d8420c..3aaef7cd68c28 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -58,7 +58,9 @@ class ChatBloc extends Bloc { add(const ChatEvent.didFinishStreaming()); if (state.lastSentMessage != null) { final payload = ChatMessageIdPB( - chatId: chatId, messageId: state.lastSentMessage!.messageId); + chatId: chatId, + messageId: state.lastSentMessage!.messageId, + ); // When user message was sent to the server, we start gettting related question ChatEventGetRelatedQuestion(payload).send().then((result) { if (!isClosed) { diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart index cbdf544d28ef7..6b3e49d799106 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart @@ -1,7 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flutter/material.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart'; From 85453f8958529083c087ab74622991e10fa3a16d Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 08:49:41 +0800 Subject: [PATCH 33/41] chore: code format --- .../ai_chat/application/chat_bloc.dart | 61 ++++++++++++------- .../lib/plugins/ai_chat/chat_page.dart | 9 +-- .../presentation/chat_error_message.dart | 60 ++++++++++-------- 3 files changed, 79 insertions(+), 51 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 3aaef7cd68c28..8811ee96ee8b3 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -14,6 +14,8 @@ import 'chat_message_listener.dart'; part 'chat_bloc.freezed.dart'; +const canRetryKey = "canRetry"; + class ChatBloc extends Bloc { ChatBloc({ required ViewPB view, @@ -33,25 +35,32 @@ class ChatBloc extends Bloc { } }, chatErrorMessageCallback: (err) { - Log.error("chat error: ${err.errorMessage}"); - final metadata = OnetimeMessageType.serverStreamError.toMap(); - if (state.lastSentMessage != null) { - metadata["canRetry"] = "true"; + if (!isClosed) { + Log.error("chat error: ${err.errorMessage}"); + final metadata = OnetimeMessageType.serverStreamError.toMap(); + if (state.lastSentMessage != null) { + metadata[canRetryKey] = "true"; + } + final error = CustomMessage( + metadata: metadata, + author: const User(id: "system"), + id: 'system', + ); + add(ChatEvent.streaming([error])); + add(const ChatEvent.didFinishStreaming()); } - final error = CustomMessage( - metadata: metadata, - author: const User(id: "system"), - id: 'system', - ); - add(ChatEvent.streaming([error])); }, latestMessageCallback: (list) { - final messages = list.messages.map(_createChatMessage).toList(); - add(ChatEvent.didLoadLatestMessages(messages)); + if (!isClosed) { + final messages = list.messages.map(_createChatMessage).toList(); + add(ChatEvent.didLoadLatestMessages(messages)); + } }, prevMessageCallback: (list) { - final messages = list.messages.map(_createChatMessage).toList(); - add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); + if (!isClosed) { + final messages = list.messages.map(_createChatMessage).toList(); + add(ChatEvent.didLoadPreviousMessages(messages, list.hasMore)); + } }, finishAnswerQuestionCallback: () { if (!isClosed) { @@ -122,7 +131,7 @@ class ChatBloc extends Bloc { state.copyWith( messages: uniqueMessages, loadingPreviousStatus: const LoadingState.finish(), - hasMore: hasMore, + hasMorePrevMessage: hasMore, ), ); }, @@ -132,7 +141,7 @@ class ChatBloc extends Bloc { emit( state.copyWith( messages: uniqueMessages, - loadingStatus: const LoadingState.finish(), + initialLoadingStatus: const LoadingState.finish(), ), ); }, @@ -160,6 +169,7 @@ class ChatBloc extends Bloc { ..insert(0, loadingMessage); emit( state.copyWith( + lastSentMessage: null, messages: allMessages, answerQuestionStatus: const LoadingState.loading(), relatedQuestions: [], @@ -307,11 +317,20 @@ class ChatState with _$ChatState { required ViewPB view, required List messages, required UserProfilePB userProfile, - required LoadingState loadingStatus, + // When opening the chat, the initial loading status will be set as loading. + //After the initial loading is done, the status will be set as finished. + required LoadingState initialLoadingStatus, + // When loading previous messages, the status will be set as loading. + // After the loading is done, the status will be set as finished. required LoadingState loadingPreviousStatus, + // When sending a user message, the status will be set as loading. + // After the message is sent, the status will be set as finished. required LoadingState answerQuestionStatus, - required bool hasMore, + // Indicate whether there are more previous messages to load. + required bool hasMorePrevMessage, + // The related questions that are received after the user message is sent. required List relatedQuestions, + // The last user message that is sent to the server. ChatMessagePB? lastSentMessage, }) = _ChatState; @@ -320,10 +339,10 @@ class ChatState with _$ChatState { view: view, messages: [], userProfile: userProfile, - loadingStatus: const LoadingState.finish(), + initialLoadingStatus: const LoadingState.finish(), loadingPreviousStatus: const LoadingState.finish(), answerQuestionStatus: const LoadingState.finish(), - hasMore: true, + hasMorePrevMessage: true, relatedQuestions: [], ); } @@ -360,7 +379,7 @@ extension OnetimeMessageTypeExtension on OnetimeMessageType { } } -OnetimeMessageType? restoreOnetimeMessageType(Map? metadata) { +OnetimeMessageType? onetimeMessageTypeFromMeta(Map? metadata) { if (metadata == null) { return null; } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 41b327097511c..4d85a5280eaf8 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -84,7 +84,7 @@ class _AIChatPageState extends State { theme: buildTheme(context), customMessageBuilder: _customMessageBuilder, onEndReached: () async { - if (state.hasMore && + if (state.hasMorePrevMessage && state.loadingPreviousStatus != const LoadingState.loading()) { blocContext @@ -94,7 +94,8 @@ class _AIChatPageState extends State { }, emptyState: BlocBuilder( builder: (context, state) { - return state.loadingStatus == const LoadingState.finish() + return state.initialLoadingStatus == + const LoadingState.finish() ? const ChatWelcomePage() : const Center( child: CircularProgressIndicator.adaptive(), @@ -113,7 +114,7 @@ class _AIChatPageState extends State { child: child, ); } else { - final messageType = restoreOnetimeMessageType( + final messageType = onetimeMessageTypeFromMeta( message.metadata, ); if (messageType == OnetimeMessageType.serverStreamError) { @@ -224,7 +225,7 @@ class _AIChatPageState extends State { required int messageWidth, }) { // iteration custom message type - final messageType = restoreOnetimeMessageType(message.metadata); + final messageType = onetimeMessageTypeFromMeta(message.metadata); if (messageType == null) { return const SizedBox.shrink(); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart index 6b3e49d799106..5604253ffb9ce 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart @@ -1,4 +1,5 @@ import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -15,7 +16,7 @@ class ChatErrorMessage extends StatelessWidget { final Message message; @override Widget build(BuildContext context) { - final canRetry = message.metadata?["canRetry"] != null; + final canRetry = message.metadata?[canRetryKey] != null; if (canRetry) { return Column( @@ -25,32 +26,9 @@ class ChatErrorMessage extends StatelessWidget { Center( child: Column( children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: FlowyText( - LocaleKeys.chat_aiServerUnavailable.tr(), - fontSize: 14, - ), - ), + _aiUnvaliable(), const VSpace(10), - FlowyButton( - radius: BorderRadius.circular(20), - useIntrinsicWidth: true, - text: Padding( - padding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - child: FlowyText( - LocaleKeys.chat_regenerateAnswer.tr(), - fontSize: 14, - ), - ), - onTap: onRetryPressed, - iconPadding: 0, - leftIcon: const Icon( - Icons.refresh, - size: 20, - ), - ), + _retryButton(), ], ), ), @@ -73,4 +51,34 @@ class ChatErrorMessage extends StatelessWidget { ); } } + + FlowyButton _retryButton() { + return FlowyButton( + radius: BorderRadius.circular(20), + useIntrinsicWidth: true, + text: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: FlowyText( + LocaleKeys.chat_regenerateAnswer.tr(), + fontSize: 14, + ), + ), + onTap: onRetryPressed, + iconPadding: 0, + leftIcon: const Icon( + Icons.refresh, + size: 20, + ), + ); + } + + Padding _aiUnvaliable() { + return Padding( + padding: const EdgeInsets.all(8.0), + child: FlowyText( + LocaleKeys.chat_aiServerUnavailable.tr(), + fontSize: 14, + ), + ); + } } From 5e701422db3fa433f382285d3cdfe41c9538c3d2 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 09:16:35 +0800 Subject: [PATCH 34/41] chore: prompt --- .../lib/plugins/ai_chat/chat_page.dart | 27 ++++++++++++++----- .../ai_chat/presentation/chat_ai_message.dart | 7 +++-- .../flowy_icons/16x/chat_ai_page.svg | 5 +++- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 4d85a5280eaf8..2a90b0faa63b9 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -10,6 +10,7 @@ import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -252,14 +253,26 @@ class _AIChatPageState extends State { query.viewInsets.bottom + query.padding.bottom, ) : EdgeInsets.zero; - return ClipRect( - child: Padding( - padding: safeAreaInsets, - child: ChatInput( - chatId: widget.view.id, - onSendPressed: (message) => onSendPressed(context, message.text), + return Column( + children: [ + ClipRect( + child: Padding( + padding: safeAreaInsets, + child: ChatInput( + chatId: widget.view.id, + onSendPressed: (message) => onSendPressed(context, message.text), + ), + ), ), - ), + const VSpace(6), + Opacity( + opacity: 0.6, + child: FlowyText( + LocaleKeys.chat_aiMistakePrompt.tr(), + fontSize: 12, + ), + ), + ], ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart index 0a1ad8bab5da8..652502c1d6fec 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart @@ -48,11 +48,10 @@ class ChatAIMessageBubble extends StatelessWidget { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - const ChatBorderedCircleAvatar( - child: FlowySvg( + ChatBorderedCircleAvatar( + backgroundColor: Theme.of(context).colorScheme.secondary, + child: const FlowySvg( FlowySvgs.flowy_ai_chat_logo_s, - // color: Theme.of(context).colorScheme.primary, - // blendMode: null, size: Size.square(24), ), ), diff --git a/frontend/resources/flowy_icons/16x/chat_ai_page.svg b/frontend/resources/flowy_icons/16x/chat_ai_page.svg index 593ee60eeeb42..e39815f94f483 100644 --- a/frontend/resources/flowy_icons/16x/chat_ai_page.svg +++ b/frontend/resources/flowy_icons/16x/chat_ai_page.svg @@ -1 +1,4 @@ - \ No newline at end of file + + + + From 53b2732fd788271109f344456cf05602556620ec Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 09:20:30 +0800 Subject: [PATCH 35/41] chore: fix test --- .github/workflows/flutter_ci.yaml | 1 + .../test/bloc_test/home_test/view_bloc_test.dart | 3 +++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/flutter_ci.yaml b/.github/workflows/flutter_ci.yaml index 9dcbff0f8aa97..c1cdd7bc177a1 100644 --- a/.github/workflows/flutter_ci.yaml +++ b/.github/workflows/flutter_ci.yaml @@ -203,6 +203,7 @@ jobs: - name: Run Flutter unit tests env: DISABLE_EVENT_LOG: true + DISABLE_CI_TEST_LOG: "true" working-directory: frontend run: | if [ "$RUNNER_OS" == "macOS" ]; then diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart index b816a8b68e22d..d6d0351414408 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/view_bloc_test.dart @@ -213,6 +213,9 @@ void main() { const layouts = ViewLayoutPB.values; for (var i = 0; i < layouts.length; i++) { final layout = layouts[i]; + if (layout == ViewLayoutPB.Chat) { + continue; + } viewBloc.add( ViewEvent.createView( 'Test $layout', From b4c3c59dc89d4efca1d8d34777ae066b8b4a8531 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 09:33:10 +0800 Subject: [PATCH 36/41] chore: ui adjust --- .../appflowy_flutter/lib/plugins/ai_chat/chat_page.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 2a90b0faa63b9..7ec4006a9e021 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -233,10 +233,14 @@ class _AIChatPageState extends State { switch (messageType) { case OnetimeMessageType.loading: - return const SizedBox( + return SizedBox( width: 50, height: 30, - child: CircularProgressIndicator.adaptive(), + child: CircularProgressIndicator.adaptive( + valueColor: AlwaysStoppedAnimation( + Theme.of(context).colorScheme.primary, + ), + ), ); default: return const SizedBox.shrink(); From ad0f8bc7af7367b661803fb8c91bca30c4e148ee Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 10:03:58 +0800 Subject: [PATCH 37/41] chore: disable create chat --- frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart index cb69ee8d8d734..1fa8efe3d82bf 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart @@ -35,7 +35,7 @@ class AIChatPluginBuilder extends PluginBuilder { class AIChatPluginConfig implements PluginConfig { @override - bool get creatable => true; + bool get creatable => false; } class AIChatPagePlugin extends Plugin { From 416411366016d73c53274b4e0762b0d6d0f6320b Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 11:08:07 +0800 Subject: [PATCH 38/41] chore: add loading page --- .../ai_chat/application/chat_bloc.dart | 25 ++-- .../lib/plugins/ai_chat/chat_page.dart | 11 +- .../ai_chat/presentation/chat_loading.dart | 69 ++++++++++ frontend/appflowy_flutter/pubspec.lock | 8 ++ frontend/appflowy_flutter/pubspec.yaml | 1 + frontend/appflowy_tauri/src-tauri/Cargo.lock | 119 +++++++++++++----- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/appflowy_web/wasm-libs/Cargo.lock | 40 ++++-- frontend/appflowy_web/wasm-libs/Cargo.toml | 2 +- .../appflowy_web_app/src-tauri/Cargo.lock | 28 ++--- .../appflowy_web_app/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/Cargo.lock | 44 +++---- frontend/rust-lib/Cargo.toml | 2 +- 13 files changed, 240 insertions(+), 113 deletions(-) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_loading.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 8811ee96ee8b3..81cbbcca9b364 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -9,7 +9,7 @@ import 'package:fixnum/fixnum.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; - +import 'package:nanoid/nanoid.dart'; import 'chat_message_listener.dart'; part 'chat_bloc.freezed.dart'; @@ -146,11 +146,7 @@ class ChatBloc extends Bloc { ); }, streaming: (List messages) { - // filter out loading or error messages - final allMessages = state.messages.where((element) { - return !(element.metadata?.containsKey(onetimeMessageType) == - true); - }).toList(); + final allMessages = _perminentMessages(); allMessages.insertAll(0, messages); emit(state.copyWith(messages: allMessages)); }, @@ -196,11 +192,7 @@ class ChatBloc extends Bloc { }); }, didReceiveRelatedQuestion: (List questions) { - final allMessages = state.messages.where((element) { - return !(element.metadata?.containsKey(onetimeMessageType) == - true); - }).toList(); - + final allMessages = _perminentMessages(); final message = CustomMessage( metadata: OnetimeMessageType.relatedQuestion.toMap(), author: const User(id: "system"), @@ -233,6 +225,15 @@ class ChatBloc extends Bloc { ); } +// Returns the list of messages that are not include one-time messages. + List _perminentMessages() { + final allMessages = state.messages.where((element) { + return !(element.metadata?.containsKey(onetimeMessageType) == true); + }).toList(); + + return allMessages; + } + void _loadPrevMessage(Int64? beforeMessageId) { final payload = LoadPrevChatMessagePB( chatId: state.view.id, @@ -269,7 +270,7 @@ class ChatBloc extends Bloc { author: User(id: id), metadata: OnetimeMessageType.loading.toMap(), // fake id - id: 'chat_message_loading_id', + id: nanoid(), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 7ec4006a9e021..172772f968ad1 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -19,6 +19,7 @@ import 'package:flutter_chat_ui/flutter_chat_ui.dart' show Chat; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'presentation/chat_input.dart'; +import 'presentation/chat_loading.dart'; import 'presentation/chat_popmenu.dart'; import 'presentation/chat_theme.dart'; import 'presentation/chat_welcome_page.dart'; @@ -233,15 +234,7 @@ class _AIChatPageState extends State { switch (messageType) { case OnetimeMessageType.loading: - return SizedBox( - width: 50, - height: 30, - child: CircularProgressIndicator.adaptive( - valueColor: AlwaysStoppedAnimation( - Theme.of(context).colorScheme.primary, - ), - ), - ); + return const ChatAILoading(); default: return const SizedBox.shrink(); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_loading.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_loading.dart new file mode 100644 index 0000000000000..4b5c9843826b9 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_loading.dart @@ -0,0 +1,69 @@ +import 'package:flowy_infra/theme_extension.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:shimmer/shimmer.dart'; + +class ChatAILoading extends StatelessWidget { + const ChatAILoading({super.key}); + + @override + Widget build(BuildContext context) { + return Shimmer.fromColors( + baseColor: AFThemeExtension.of(context).lightGreyHover, + highlightColor: + AFThemeExtension.of(context).lightGreyHover.withOpacity(0.5), + period: const Duration(seconds: 3), + child: const ContentPlaceholder(), + ); + } +} + +class ContentPlaceholder extends StatelessWidget { + const ContentPlaceholder({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 30, + height: 16.0, + margin: const EdgeInsets.only(bottom: 8.0), + decoration: BoxDecoration( + color: AFThemeExtension.of(context).lightGreyHover, + borderRadius: BorderRadius.circular(4.0), + ), + ), + const HSpace(10), + Container( + width: 100, + height: 16.0, + margin: const EdgeInsets.only(bottom: 8.0), + decoration: BoxDecoration( + color: AFThemeExtension.of(context).lightGreyHover, + borderRadius: BorderRadius.circular(4.0), + ), + ), + ], + ), + Container( + width: 140, + height: 16.0, + margin: const EdgeInsets.only(bottom: 8.0), + decoration: BoxDecoration( + color: AFThemeExtension.of(context).lightGreyHover, + borderRadius: BorderRadius.circular(4.0), + ), + ), + ], + ), + ); + } +} diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index 00248a553cd15..2ee1b5eb065cb 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -1850,6 +1850,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + shimmer: + dependency: "direct main" + description: + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" + source: hosted + version: "3.0.0" simple_gesture_detector: dependency: transitive description: diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index d804ef0096713..92e82d0c193fa 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -140,6 +140,7 @@ dependencies: scaled_app: ^2.3.0 auto_size_text_field: ^2.2.3 reorderable_tabbar: ^1.0.6 + shimmer: ^3.0.0 dev_dependencies: flutter_lints: ^3.0.1 diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 35a508e64e49c..d02983e577319 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -155,14 +155,14 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -179,12 +179,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "appflowy-ai-client" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" +dependencies = [ + "anyhow", + "bytes", + "futures", + "serde", + "serde_json", + "serde_repr", + "thiserror", +] + [[package]] name = "appflowy_tauri" version = "0.0.0" dependencies = [ "bytes", "dotenv", + "flowy-chat", "flowy-config", "flowy-core", "flowy-date", @@ -530,9 +545,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -741,7 +756,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "again", "anyhow", @@ -771,6 +786,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", + "serde_urlencoded", "shared-entity", "thiserror", "tokio", @@ -787,7 +803,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "futures-channel", "futures-util", @@ -861,7 +877,7 @@ dependencies = [ [[package]] name = "collab" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -885,7 +901,7 @@ dependencies = [ [[package]] name = "collab-database" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-trait", @@ -915,7 +931,7 @@ dependencies = [ [[package]] name = "collab-document" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -934,7 +950,7 @@ dependencies = [ [[package]] name = "collab-entity" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "bytes", @@ -949,7 +965,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "chrono", @@ -987,7 +1003,7 @@ dependencies = [ [[package]] name = "collab-plugins" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "async-stream", @@ -1026,7 +1042,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -1051,7 +1067,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "async-trait", @@ -1068,7 +1084,7 @@ dependencies = [ [[package]] name = "collab-user" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=0b52164#0b521646f5d609abe11a213ab063402c32496e9b" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=cca5135f0010fa5de22a298cbed939e21575538c#cca5135f0010fa5de22a298cbed939e21575538c" dependencies = [ "anyhow", "collab", @@ -1297,7 +1313,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.6", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1408,7 +1424,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -1486,6 +1502,7 @@ dependencies = [ "diesel_derives", "libsqlite3-sys", "r2d2", + "serde_json", "time", ] @@ -1795,6 +1812,39 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "flowy-chat" +version = "0.1.0" +dependencies = [ + "bytes", + "dashmap", + "flowy-chat-pub", + "flowy-codegen", + "flowy-derive", + "flowy-error", + "flowy-notification", + "flowy-sqlite", + "futures", + "lib-dispatch", + "lib-infra", + "protobuf", + "strum_macros 0.21.1", + "tokio", + "tracing", + "uuid", + "validator", +] + +[[package]] +name = "flowy-chat-pub" +version = "0.1.0" +dependencies = [ + "client-api", + "flowy-error", + "futures", + "lib-infra", +] + [[package]] name = "flowy-codegen" version = "0.1.0" @@ -1846,6 +1896,8 @@ dependencies = [ "collab-integrate", "collab-plugins", "diesel", + "flowy-chat", + "flowy-chat-pub", "flowy-config", "flowy-database-pub", "flowy-database2", @@ -2176,6 +2228,7 @@ dependencies = [ "collab-entity", "collab-folder", "collab-plugins", + "flowy-chat-pub", "flowy-database-pub", "flowy-document-pub", "flowy-encrypt", @@ -2779,7 +2832,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "futures-util", @@ -2796,7 +2849,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -3228,7 +3281,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "reqwest", @@ -4731,7 +4784,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4752,7 +4805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -5535,18 +5588,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.195" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -5716,13 +5769,15 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ef96b42e43c7b929a928f6c334967c7edffc1319#ef96b42e43c7b929a928f6c334967c7edffc1319" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", + "appflowy-ai-client", "chrono", "collab-entity", "database-entity", + "futures", "gotrue-entity", "reqwest", "serde", @@ -6568,18 +6623,18 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 48d1f5b44f1bd..9cfcf94740024 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "b36715dc2427e23a15fa81c629e1817d3dbf1e1a" } [dependencies] serde_json.workspace = true diff --git a/frontend/appflowy_web/wasm-libs/Cargo.lock b/frontend/appflowy_web/wasm-libs/Cargo.lock index 48e7783a95088..0ed88408715ca 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.lock +++ b/frontend/appflowy_web/wasm-libs/Cargo.lock @@ -216,7 +216,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -236,7 +236,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bytes", @@ -562,7 +562,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "again", "anyhow", @@ -609,7 +609,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "futures-channel", "futures-util", @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "async-trait", @@ -981,7 +981,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.8.0", + "phf 0.11.2", "smallvec", ] @@ -1026,7 +1026,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -1815,7 +1815,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "futures-util", @@ -1832,7 +1832,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -2133,7 +2133,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "reqwest", @@ -2817,7 +2817,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros", + "phf_macros 0.8.0", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -2837,6 +2837,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ + "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -2904,6 +2905,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "phf_shared" version = "0.8.0" @@ -3759,7 +3773,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web/wasm-libs/Cargo.toml b/frontend/appflowy_web/wasm-libs/Cargo.toml index 5ceabaf70e0a7..01fc3fad33104 100644 --- a/frontend/appflowy_web/wasm-libs/Cargo.toml +++ b/frontend/appflowy_web/wasm-libs/Cargo.toml @@ -55,7 +55,7 @@ yrs = "0.18.8" # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "b36715dc2427e23a15fa81c629e1817d3dbf1e1a" } diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.lock b/frontend/appflowy_web_app/src-tauri/Cargo.lock index 9374636497afa..23252b551c38d 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.lock +++ b/frontend/appflowy_web_app/src-tauri/Cargo.lock @@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -173,7 +173,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bytes", @@ -730,7 +730,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "again", "anyhow", @@ -777,7 +777,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "futures-channel", "futures-util", @@ -1025,7 +1025,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -1050,7 +1050,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "async-trait", @@ -1300,7 +1300,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa 1.0.10", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1411,7 +1411,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -2906,7 +2906,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "futures-util", @@ -2923,7 +2923,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -3360,7 +3360,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "reqwest", @@ -4865,7 +4865,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4886,7 +4886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.55", @@ -5864,7 +5864,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/appflowy_web_app/src-tauri/Cargo.toml b/frontend/appflowy_web_app/src-tauri/Cargo.toml index 84752a416065f..9db2fea415970 100644 --- a/frontend/appflowy_web_app/src-tauri/Cargo.toml +++ b/frontend/appflowy_web_app/src-tauri/Cargo.toml @@ -52,7 +52,7 @@ collab-user = { version = "0.2" } # Run the script: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "b36715dc2427e23a15fa81c629e1817d3dbf1e1a" } [dependencies] serde_json.workspace = true diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 71a76c2783908..9a48c6db270e3 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -163,7 +163,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "app-error" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -183,7 +183,7 @@ dependencies = [ [[package]] name = "appflowy-ai-client" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bytes", @@ -664,7 +664,7 @@ dependencies = [ [[package]] name = "client-api" version = "0.2.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "again", "anyhow", @@ -711,7 +711,7 @@ dependencies = [ [[package]] name = "client-websocket" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "futures-channel", "futures-util", @@ -919,7 +919,7 @@ dependencies = [ [[package]] name = "collab-rt-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "bincode", @@ -944,7 +944,7 @@ dependencies = [ [[package]] name = "collab-rt-protocol" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "async-trait", @@ -1164,7 +1164,7 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf 0.11.2", + "phf 0.8.0", "smallvec", ] @@ -1264,7 +1264,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "database-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -2518,7 +2518,7 @@ dependencies = [ [[package]] name = "gotrue" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "futures-util", @@ -2535,7 +2535,7 @@ dependencies = [ [[package]] name = "gotrue-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", @@ -2900,7 +2900,7 @@ dependencies = [ [[package]] name = "infra" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "reqwest", @@ -3775,7 +3775,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "phf_macros 0.8.0", + "phf_macros", "phf_shared 0.8.0", "proc-macro-hack", ] @@ -3795,7 +3795,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros 0.11.2", "phf_shared 0.11.2", ] @@ -3863,19 +3862,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "phf_shared" version = "0.8.0" @@ -4079,7 +4065,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" dependencies = [ "bytes", "heck 0.4.1", - "itertools 0.11.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -4100,7 +4086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.47", @@ -4997,7 +4983,7 @@ dependencies = [ [[package]] name = "shared-entity" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=39c5a5ab65ea052079f4ff9214d73a6efe6e3668#39c5a5ab65ea052079f4ff9214d73a6efe6e3668" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=b36715dc2427e23a15fa81c629e1817d3dbf1e1a#b36715dc2427e23a15fa81c629e1817d3dbf1e1a" dependencies = [ "anyhow", "app-error", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 41d93653e4cbb..c793b3ec4616e 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -93,7 +93,7 @@ yrs = "0.18.8" # Run the script.add_workspace_members: # scripts/tool/update_client_api_rev.sh new_rev_id # ⚠️⚠️⚠️️ -client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "39c5a5ab65ea052079f4ff9214d73a6efe6e3668" } +client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "b36715dc2427e23a15fa81c629e1817d3dbf1e1a" } [profile.dev] opt-level = 1 From 9a85045170b063e931941da24bc85b7d9b7dd14a Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 11:10:28 +0800 Subject: [PATCH 39/41] chore: fix test --- .../integration_test/desktop/sidebar/sidebar_icon_test.dart | 6 ++++++ .../integration_test/desktop/sidebar/sidebar_test.dart | 3 +++ 2 files changed, 9 insertions(+) diff --git a/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_icon_test.dart b/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_icon_test.dart index 1782c0d0ba19c..4659c98b5553e 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_icon_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_icon_test.dart @@ -18,6 +18,9 @@ void main() { // create document, board, grid and calendar views for (final value in ViewLayoutPB.values) { + if (value == ViewLayoutPB.Chat) { + continue; + } await tester.createNewPageWithNameUnderParent( name: value.name, parentName: gettingStarted, @@ -46,6 +49,9 @@ void main() { // create document, board, grid and calendar views for (final value in ViewLayoutPB.values) { + if (value == ViewLayoutPB.Chat) { + continue; + } await tester.createNewPageWithNameUnderParent( name: value.name, parentName: gettingStarted, diff --git a/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart b/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart index 7ac59c77a4854..006d7ff0b6a08 100644 --- a/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart +++ b/frontend/appflowy_flutter/integration_test/desktop/sidebar/sidebar_test.dart @@ -39,6 +39,9 @@ void main() { await tester.tapAnonymousSignInButton(); for (final layout in ViewLayoutPB.values) { + if (layout == ViewLayoutPB.Chat) { + continue; + } // create a new page final name = 'AppFlowy_$layout'; await tester.createNewPageWithNameUnderParent( From dcab8f830431449935ba4436eba52e67524174bc Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 11:33:11 +0800 Subject: [PATCH 40/41] chore: disable chat action --- .../menu/view/view_more_action_button.dart | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart index 68d179da50709..d1a6c172572a6 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart @@ -63,31 +63,46 @@ class ViewMoreActionButton extends StatelessWidget { List _buildActionTypes() { final List actionTypes = []; - switch (spaceType) { - case FolderSpaceType.favorite: - actionTypes.addAll([ - ViewMoreActionType.unFavorite, - ViewMoreActionType.divider, - ViewMoreActionType.rename, - ViewMoreActionType.openInNewTab, - ]); - break; - default: + + if (spaceType == FolderSpaceType.favorite) { + actionTypes.addAll([ + ViewMoreActionType.unFavorite, + ViewMoreActionType.divider, + ViewMoreActionType.rename, + ViewMoreActionType.openInNewTab, + ]); + } else { + actionTypes.add( + view.isFavorite + ? ViewMoreActionType.unFavorite + : ViewMoreActionType.favorite, + ); + + actionTypes.addAll([ + ViewMoreActionType.divider, + ViewMoreActionType.rename, + ]); + + if (view.layout != ViewLayoutPB.Chat) { actionTypes.addAll([ - view.isFavorite - ? ViewMoreActionType.unFavorite - : ViewMoreActionType.favorite, - ViewMoreActionType.divider, - ViewMoreActionType.rename, ViewMoreActionType.changeIcon, ViewMoreActionType.duplicate, - ViewMoreActionType.delete, - ViewMoreActionType.divider, - ViewMoreActionType.collapseAllPages, - ViewMoreActionType.divider, - ViewMoreActionType.openInNewTab, ]); + } + + actionTypes.addAll([ + ViewMoreActionType.delete, + ViewMoreActionType.divider, + ]); + + if (view.layout != ViewLayoutPB.Chat) { + actionTypes.add(ViewMoreActionType.collapseAllPages); + actionTypes.add(ViewMoreActionType.divider); + } + + actionTypes.add(ViewMoreActionType.openInNewTab); } + return actionTypes; } } From e7be0efeedeb9d48460f3a066abe367d68110430 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 3 Jun 2024 12:14:24 +0800 Subject: [PATCH 41/41] chore: add maximum text limit --- .../ai_chat/application/chat_bloc.dart | 69 +++++++++++++------ .../lib/plugins/ai_chat/chat_page.dart | 17 +++-- .../ai_chat/presentation/chat_ai_message.dart | 4 +- .../ai_chat/presentation/chat_input.dart | 21 +++--- ...dart => chat_streaming_error_message.dart} | 4 +- .../chat_user_invalid_message.dart | 31 +++++++++ .../menu/view/view_more_action_button.dart | 2 + frontend/rust-lib/flowy-chat/src/chat.rs | 4 ++ 8 files changed, 113 insertions(+), 39 deletions(-) rename frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/{chat_error_message.dart => chat_streaming_error_message.dart} (96%) create mode 100644 frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_invalid_message.dart diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart index 81cbbcca9b364..17eaad8c9242a 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/application/chat_bloc.dart @@ -15,6 +15,7 @@ import 'chat_message_listener.dart'; part 'chat_bloc.freezed.dart'; const canRetryKey = "canRetry"; +const sendMessageErrorKey = "sendMessageError"; class ChatBloc extends Bloc { ChatBloc({ @@ -37,7 +38,7 @@ class ChatBloc extends Bloc { chatErrorMessageCallback: (err) { if (!isClosed) { Log.error("chat error: ${err.errorMessage}"); - final metadata = OnetimeMessageType.serverStreamError.toMap(); + final metadata = OnetimeShotType.serverStreamError.toMap(); if (state.lastSentMessage != null) { metadata[canRetryKey] = "true"; } @@ -159,10 +160,13 @@ class ChatBloc extends Bloc { }, sendMessage: (String message) async { await _handleSentMessage(message, emit); + + // Create a loading indicator final loadingMessage = _loadingMessage(state.userProfile.id.toString()); final allMessages = List.from(state.messages) ..insert(0, loadingMessage); + emit( state.copyWith( lastSentMessage: null, @@ -194,7 +198,7 @@ class ChatBloc extends Bloc { didReceiveRelatedQuestion: (List questions) { final allMessages = _perminentMessages(); final message = CustomMessage( - metadata: OnetimeMessageType.relatedQuestion.toMap(), + metadata: OnetimeShotType.relatedQuestion.toMap(), author: const User(id: "system"), id: 'system', ); @@ -228,7 +232,7 @@ class ChatBloc extends Bloc { // Returns the list of messages that are not include one-time messages. List _perminentMessages() { final allMessages = state.messages.where((element) { - return !(element.metadata?.containsKey(onetimeMessageType) == true); + return !(element.metadata?.containsKey(onetimeShotType) == true); }).toList(); return allMessages; @@ -252,7 +256,24 @@ class ChatBloc extends Bloc { message: message, messageType: ChatMessageTypePB.User, ); - await ChatEventSendMessage(payload).send(); + final result = await ChatEventSendMessage(payload).send(); + result.fold( + (_) {}, + (err) { + if (!isClosed) { + Log.error("Failed to send message: ${err.msg}"); + final metadata = OnetimeShotType.invalidSendMesssage.toMap(); + metadata[sendMessageErrorKey] = err.msg; + final error = CustomMessage( + metadata: metadata, + author: const User(id: "system"), + id: 'system', + ); + + add(ChatEvent.streaming([error])); + } + }, + ); } void _handleChatMessage(ChatMessagePB pb) { @@ -268,7 +289,7 @@ class ChatBloc extends Bloc { Message _loadingMessage(String id) { return CustomMessage( author: User(id: id), - metadata: OnetimeMessageType.loading.toMap(), + metadata: OnetimeShotType.loading.toMap(), // fake id id: nanoid(), ); @@ -354,39 +375,47 @@ class LoadingState with _$LoadingState { const factory LoadingState.finish() = _Finish; } -enum OnetimeMessageType { unknown, loading, serverStreamError, relatedQuestion } +enum OnetimeShotType { + unknown, + loading, + serverStreamError, + relatedQuestion, + invalidSendMesssage +} -const onetimeMessageType = "OnetimeMessageType"; +const onetimeShotType = "OnetimeShotType"; -extension OnetimeMessageTypeExtension on OnetimeMessageType { - static OnetimeMessageType fromString(String value) { +extension OnetimeMessageTypeExtension on OnetimeShotType { + static OnetimeShotType fromString(String value) { switch (value) { - case 'OnetimeMessageType.loading': - return OnetimeMessageType.loading; - case 'OnetimeMessageType.serverStreamError': - return OnetimeMessageType.serverStreamError; - case 'OnetimeMessageType.relatedQuestion': - return OnetimeMessageType.relatedQuestion; + case 'OnetimeShotType.loading': + return OnetimeShotType.loading; + case 'OnetimeShotType.serverStreamError': + return OnetimeShotType.serverStreamError; + case 'OnetimeShotType.relatedQuestion': + return OnetimeShotType.relatedQuestion; + case 'OnetimeShotType.invalidSendMesssage': + return OnetimeShotType.invalidSendMesssage; default: - Log.error('Unknown OnetimeMessageType: $value'); - return OnetimeMessageType.unknown; + Log.error('Unknown OnetimeShotType: $value'); + return OnetimeShotType.unknown; } } Map toMap() { return { - onetimeMessageType: toString(), + onetimeShotType: toString(), }; } } -OnetimeMessageType? onetimeMessageTypeFromMeta(Map? metadata) { +OnetimeShotType? onetimeMessageTypeFromMeta(Map? metadata) { if (metadata == null) { return null; } for (final entry in metadata.entries) { - if (entry.key == onetimeMessageType) { + if (entry.key == onetimeShotType) { return OnetimeMessageTypeExtension.fromString(entry.value as String); } } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart index 172772f968ad1..481076dd5cf57 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat_page.dart @@ -1,7 +1,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_ai_message.dart'; -import 'package:appflowy/plugins/ai_chat/presentation/chat_error_message.dart'; +import 'package:appflowy/plugins/ai_chat/presentation/chat_streaming_error_message.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_related_question.dart'; import 'package:appflowy/plugins/ai_chat/presentation/chat_user_message.dart'; import 'package:appflowy/workspace/presentation/home/toast.dart'; @@ -22,6 +22,7 @@ import 'presentation/chat_input.dart'; import 'presentation/chat_loading.dart'; import 'presentation/chat_popmenu.dart'; import 'presentation/chat_theme.dart'; +import 'presentation/chat_user_invalid_message.dart'; import 'presentation/chat_welcome_page.dart'; class AIChatPage extends StatefulWidget { @@ -119,8 +120,8 @@ class _AIChatPageState extends State { final messageType = onetimeMessageTypeFromMeta( message.metadata, ); - if (messageType == OnetimeMessageType.serverStreamError) { - return ChatErrorMessage( + if (messageType == OnetimeShotType.serverStreamError) { + return ChatStreamingError( message: message, onRetryPressed: () { blocContext @@ -130,7 +131,13 @@ class _AIChatPageState extends State { ); } - if (messageType == OnetimeMessageType.relatedQuestion) { + if (messageType == OnetimeShotType.invalidSendMesssage) { + return ChatInvalidUserMessage( + message: message, + ); + } + + if (messageType == OnetimeShotType.relatedQuestion) { return RelatedQuestionList( onQuestionSelected: (question) { blocContext @@ -233,7 +240,7 @@ class _AIChatPageState extends State { } switch (messageType) { - case OnetimeMessageType.loading: + case OnetimeShotType.loading: return const ChatAILoading(); default: return const SizedBox.shrink(); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart index 652502c1d6fec..5a8e65012d7a1 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_ai_message.dart @@ -29,7 +29,7 @@ class ChatAIMessageBubble extends StatelessWidget { final Message message; final Widget child; - final OnetimeMessageType? customMessageType; + final OnetimeShotType? customMessageType; @override Widget build(BuildContext context) { @@ -95,7 +95,7 @@ class ChatAIMessageHover extends StatefulWidget { final Widget child; final Message message; final bool autoShowHover = true; - final OnetimeMessageType? customMessageType; + final OnetimeShotType? customMessageType; @override State createState() => _ChatAIMessageHoverState(); diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart index 207280187d943..732726b952fea 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_input.dart @@ -135,11 +135,8 @@ class _ChatInputState extends State { return Padding( padding: textPadding, child: TextField( - enabled: widget.options.enabled, - autocorrect: widget.options.autocorrect, - autofocus: widget.options.autofocus, - enableSuggestions: widget.options.enableSuggestions, controller: _textController, + focusNode: _inputFocusNode, decoration: InputDecoration( border: InputBorder.none, hintText: LocaleKeys.chat_inputMessageHint.tr(), @@ -147,16 +144,20 @@ class _ChatInputState extends State { color: AFThemeExtension.of(context).textColor.withOpacity(0.5), ), ), - focusNode: _inputFocusNode, - keyboardType: widget.options.keyboardType, - maxLines: 5, - minLines: 1, - onChanged: widget.options.onTextChanged, - onTap: widget.options.onTextFieldTap, style: TextStyle( color: AFThemeExtension.of(context).textColor, ), + enabled: widget.options.enabled, + autocorrect: widget.options.autocorrect, + autofocus: widget.options.autofocus, + enableSuggestions: widget.options.enableSuggestions, + spellCheckConfiguration: const SpellCheckConfiguration(), + keyboardType: widget.options.keyboardType, textCapitalization: TextCapitalization.sentences, + maxLines: 10, + minLines: 1, + onChanged: widget.options.onTextChanged, + onTap: widget.options.onTextFieldTap, ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_streaming_error_message.dart similarity index 96% rename from frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart rename to frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_streaming_error_message.dart index 5604253ffb9ce..c0552a7e8e418 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_error_message.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_streaming_error_message.dart @@ -5,8 +5,8 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart'; -class ChatErrorMessage extends StatelessWidget { - const ChatErrorMessage({ +class ChatStreamingError extends StatelessWidget { + const ChatStreamingError({ required this.message, required this.onRetryPressed, super.key, diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_invalid_message.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_invalid_message.dart new file mode 100644 index 0000000000000..8ae9b91d32a31 --- /dev/null +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/presentation/chat_user_invalid_message.dart @@ -0,0 +1,31 @@ +import 'package:appflowy/plugins/ai_chat/application/chat_bloc.dart'; +import 'package:flowy_infra_ui/flowy_infra_ui.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_chat_types/flutter_chat_types.dart'; + +class ChatInvalidUserMessage extends StatelessWidget { + const ChatInvalidUserMessage({ + required this.message, + super.key, + }); + + final Message message; + @override + Widget build(BuildContext context) { + final errorMessage = message.metadata?[sendMessageErrorKey] ?? ""; + return Center( + child: Column( + children: [ + const Divider(height: 20, thickness: 1), + Padding( + padding: const EdgeInsets.all(8.0), + child: FlowyText( + errorMessage, + fontSize: 14, + ), + ), + ], + ), + ); + } +} diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart index d1a6c172572a6..57730ada05d20 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_more_action_button.dart @@ -83,6 +83,7 @@ class ViewMoreActionButton extends StatelessWidget { ViewMoreActionType.rename, ]); + // Chat doesn't change icon and duplicate if (view.layout != ViewLayoutPB.Chat) { actionTypes.addAll([ ViewMoreActionType.changeIcon, @@ -95,6 +96,7 @@ class ViewMoreActionButton extends StatelessWidget { ViewMoreActionType.divider, ]); + // Chat doesn't change collapse if (view.layout != ViewLayoutPB.Chat) { actionTypes.add(ViewMoreActionType.collapseAllPages); actionTypes.add(ViewMoreActionType.divider); diff --git a/frontend/rust-lib/flowy-chat/src/chat.rs b/frontend/rust-lib/flowy-chat/src/chat.rs index 95cc9e90ca619..712caad91a7b6 100644 --- a/frontend/rust-lib/flowy-chat/src/chat.rs +++ b/frontend/rust-lib/flowy-chat/src/chat.rs @@ -69,6 +69,10 @@ impl Chat { message: &str, message_type: ChatMessageType, ) -> Result<(), FlowyError> { + if message.len() > 2000 { + return Err(FlowyError::text_too_long().with_context("Exceeds maximum message 2000 length")); + } + let uid = self.user_service.user_id()?; let workspace_id = self.user_service.workspace_id()?; stream_send_chat_messages(