From cf93e92e64ed4b4320d4dbcab4af5f8c5c3f8e53 Mon Sep 17 00:00:00 2001 From: Samiksha Garg <79906086+Samiksha-Garg@users.noreply.github.com> Date: Mon, 3 Apr 2023 16:35:34 +0530 Subject: [PATCH 1/7] fix: support for arrow key and tab selection in referenced board/grid (#2165) * fix: added support for navigating reference board/grid menu using keyboard keys * refactor: made some minor changes according to reviews * refactor: replaced loading logic with future builder --- .../plugins/base/link_to_page_widget.dart | 94 +++++++++++++++++-- 1 file changed, 88 insertions(+), 6 deletions(-) diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart index 46c8298b49..19c21739cc 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart @@ -7,6 +7,7 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'insert_page_command.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -92,14 +93,50 @@ class LinkToPageMenu extends StatefulWidget { } class _LinkToPageMenuState extends State { + final _focusNode = FocusNode(debugLabel: 'reference_list_widget'); EditorStyle get style => widget.editorState.editorStyle; + int _selectedIndex = 0; + int _totalItems = 0; + Future>>>? _availableLayout; + final Map> _items = {}; + + Future>>> fetchItems() async { + final items = await AppBackendService().fetchViews(widget.layoutType); + + int index = 0; + for (final app in items) { + for (final view in app.value2) { + _items.putIfAbsent(index, () => dartz.Tuple2(app.value1, view)); + index += 1; + } + } + + _totalItems = _items.length; + return items; + } + + @override + void initState() { + _availableLayout = fetchItems(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _focusNode.requestFocus(); + }); + super.initState(); + } + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { - return Container( - color: Colors.transparent, - width: 300, + return Focus( + focusNode: _focusNode, + onKey: _onKey, child: Container( + width: 300, padding: const EdgeInsets.fromLTRB(10, 6, 10, 6), decoration: BoxDecoration( color: style.selectionMenuBackgroundColor, @@ -112,12 +149,54 @@ class _LinkToPageMenuState extends State { ], borderRadius: BorderRadius.circular(6.0), ), - child: _buildListWidget(context), + child: _buildListWidget(context, _selectedIndex, _availableLayout), ), ); } - Widget _buildListWidget(BuildContext context) { + KeyEventResult _onKey(FocusNode node, RawKeyEvent event) { + if (event is! RawKeyDownEvent || + _availableLayout == null || + _items.isEmpty) { + return KeyEventResult.ignored; + } + + final acceptedKeys = [ + LogicalKeyboardKey.arrowUp, + LogicalKeyboardKey.arrowDown, + LogicalKeyboardKey.tab, + LogicalKeyboardKey.enter + ]; + + if (!acceptedKeys.contains(event.logicalKey)) { + return KeyEventResult.handled; + } + + var newSelectedIndex = _selectedIndex; + if (event.logicalKey == LogicalKeyboardKey.arrowDown && + newSelectedIndex != _totalItems - 1) { + newSelectedIndex += 1; + } else if (event.logicalKey == LogicalKeyboardKey.arrowUp && + newSelectedIndex != 0) { + newSelectedIndex -= 1; + } else if (event.logicalKey == LogicalKeyboardKey.tab) { + newSelectedIndex += 1; + newSelectedIndex %= _totalItems; + } else if (event.logicalKey == LogicalKeyboardKey.enter) { + widget.onSelected( + _items[_selectedIndex]!.value1, _items[_selectedIndex]!.value2); + } + + setState(() { + _selectedIndex = newSelectedIndex; + }); + + return KeyEventResult.handled; + } + + Widget _buildListWidget(BuildContext context, int selectedIndex, + Future>>>? items) { + int index = 0; return FutureBuilder>>>( builder: (context, snapshot) { if (snapshot.hasData && @@ -147,6 +226,7 @@ class _LinkToPageMenuState extends State { for (final value in app.value2) { children.add( FlowyButton( + isSelected: index == _selectedIndex, leftIcon: svgWidget( _iconName(value), color: Theme.of(context).iconTheme.color, @@ -155,6 +235,8 @@ class _LinkToPageMenuState extends State { onTap: () => widget.onSelected(app.value1, value), ), ); + + index += 1; } } } @@ -169,7 +251,7 @@ class _LinkToPageMenuState extends State { ); } }, - future: AppBackendService().fetchViews(widget.layoutType), + future: items, ); } From e1c8135f5d4952f3e1c96f044de6e7970cbcde69 Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Tue, 4 Apr 2023 08:41:16 +0800 Subject: [PATCH 2/7] refactor: folder with yrs * feat: try using folder2 * feat: update * feat: implement handlers * fix: compile errors * chore: add unsafe send + sync * feat: remove unsafe impl * fix: replace folder with foler2 * chore: dart compile errors * test: fix test * test: fix test * test: bypass existing tests * feat: open latest view * chore: fix dart warnings * chore: config notification * fix: folder notification bugs * fix: doesn't open the new view after creating * chore: rename struct * refactor: user id * test: fix test * chore: remove unused user_id * fix: fix read workspace views * chore: rename appflowy data folder * chore: update ref * fix: tauri build --- .../lib/core/folder_notification.dart | 2 +- .../application/database_controller.dart | 2 +- .../application/database_view_service.dart | 2 +- .../board/application/board_bloc.dart | 2 +- .../plugins/database_view/board/board.dart | 2 +- .../board/presentation/board_page.dart | 2 +- .../calendar/application/calendar_bloc.dart | 2 +- .../database_view/calendar/calendar.dart | 2 +- .../calendar/presentation/calendar_page.dart | 2 +- .../grid/application/grid_bloc.dart | 2 +- .../lib/plugins/database_view/grid/grid.dart | 2 +- .../grid/presentation/grid_page.dart | 2 +- .../document/application/doc_bloc.dart | 6 +- .../document/application/doc_service.dart | 2 +- .../document/application/share_bloc.dart | 2 +- .../document/application/share_service.dart | 2 +- .../lib/plugins/document/document.dart | 2 +- .../lib/plugins/document/document_page.dart | 2 +- .../plugins/base/built_in_page_widget.dart | 4 +- .../plugins/base/insert_page_command.dart | 5 +- .../plugins/base/link_to_page_widget.dart | 25 +- .../plugins/board/board_menu_item.dart | 2 +- .../plugins/board/board_view_menu_item.dart | 9 +- .../plugins/grid/grid_menu_item.dart | 2 +- .../plugins/grid/grid_view_menu_item.dart | 9 +- .../presentation/share/share_button.dart | 2 +- .../plugins/trash/application/trash_bloc.dart | 5 +- .../trash/application/trash_listener.dart | 9 +- .../trash/application/trash_service.dart | 11 +- .../lib/plugins/trash/src/trash_cell.dart | 2 +- .../appflowy_flutter/lib/plugins/util.dart | 2 +- .../lib/startup/deps_resolver.dart | 9 +- .../lib/startup/plugin/plugin.dart | 2 +- .../lib/startup/tasks/rust_sdk.dart | 4 +- .../lib/user/application/user_listener.dart | 11 +- .../lib/user/application/user_service.dart | 5 +- .../lib/user/presentation/router.dart | 2 +- .../user/presentation/skip_log_in_screen.dart | 2 +- .../lib/user/presentation/welcome_screen.dart | 2 +- .../workspace/application/app/app_bloc.dart | 35 +- .../application/app/app_listener.dart | 18 +- .../application/app/app_service.dart | 60 +- .../workspace/application/home/home_bloc.dart | 4 +- .../application/home/home_service.dart | 8 +- .../application/home/home_setting_bloc.dart | 2 +- .../workspace/application/menu/menu_bloc.dart | 52 +- .../application/menu/menu_user_bloc.dart | 2 +- .../menu/menu_view_section_bloc.dart | 2 +- .../settings_file_exporter_cubit.dart | 24 +- .../workspace/application/view/view_bloc.dart | 2 +- .../workspace/application/view/view_ext.dart | 2 +- .../application/view/view_listener.dart | 4 +- .../application/view/view_service.dart | 2 +- .../application/workspace/welcome_bloc.dart | 2 +- .../workspace/workspace_listener.dart | 12 +- .../workspace/workspace_service.dart | 26 +- .../presentation/home/home_screen.dart | 6 +- .../presentation/home/home_stack.dart | 2 +- .../home/menu/app/header/header.dart | 10 +- .../presentation/home/menu/app/menu_app.dart | 12 +- .../home/menu/app/section/item.dart | 2 +- .../presentation/home/menu/menu.dart | 6 +- .../settings_file_exporter_widget.dart | 12 +- .../presentation/widgets/left_bar_item.dart | 2 +- .../lib/dispatch/dispatch.dart | 4 +- .../test/bloc_test/board_test/util.dart | 2 +- .../test/bloc_test/grid_test/util.dart | 2 +- .../bloc_test/home_test/app_bloc_test.dart | 20 +- .../bloc_test/home_test/create_page_test.dart | 10 +- .../bloc_test/home_test/home_bloc_test.dart | 2 +- .../bloc_test/home_test/menu_bloc_test.dart | 8 +- .../bloc_test/home_test/trash_bloc_test.dart | 17 +- .../bloc_test/home_test/view_bloc_test.dart | 6 +- frontend/appflowy_flutter/test/util.dart | 8 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 367 ++++++++--- frontend/appflowy_tauri/src-tauri/Cargo.toml | 7 + .../components/auth/auth.hooks.ts | 4 +- .../NavigationPanel/FolderItem.hooks.ts | 4 +- .../components/layout/Workspace.hooks.ts | 10 +- .../components/tests/DatabaseTestHelper.ts | 4 +- .../components/tests/DocumentTestHelper.ts | 8 +- .../components/tests/TestApiButton.tsx | 129 ---- .../effects/database/database_bd_svc.ts | 2 +- .../effects/document/document_bd_svc.ts | 2 +- .../stores/effects/folder/app/app_bd_svc.ts | 29 +- .../stores/effects/folder/app/app_observer.ts | 10 +- .../stores/effects/folder/view/view_bd_svc.ts | 2 +- .../folder/workspace/workspace_bd_svc.ts | 19 +- .../folder/workspace/workspace_observer.ts | 16 +- .../stores/effects/user/user_bd_svc.ts | 4 +- .../stores/reducers/current-user/slice.ts | 4 +- .../src/services/backend/index.ts | 2 +- frontend/rust-lib/Cargo.lock | 299 +++++++-- frontend/rust-lib/Cargo.toml | 11 +- frontend/rust-lib/flowy-core/Cargo.toml | 4 + .../src/deps_resolve/document_deps.rs | 2 +- .../src/deps_resolve/folder2_deps.rs | 258 ++++++++ .../flowy-core/src/deps_resolve/grid_deps.rs | 2 +- .../flowy-core/src/deps_resolve/mod.rs | 4 +- frontend/rust-lib/flowy-core/src/lib.rs | 102 ++- frontend/rust-lib/flowy-core/src/module.rs | 7 +- .../rust-lib/flowy-database/src/manager.rs | 21 +- .../src/services/database/block_editor.rs | 5 - .../src/services/database/block_manager.rs | 10 +- .../src/services/database/database_editor.rs | 7 +- .../src/services/database_view/editor.rs | 22 +- .../services/database_view/editor_manager.rs | 14 +- .../src/services/database_view/trait_impl.rs | 5 +- .../migration/database_migration.rs | 14 +- .../migration/database_view_migration.rs | 11 +- .../src/services/persistence/migration/mod.rs | 2 +- .../persistence/rev_sqlite/block_impl.rs | 21 +- .../persistence/rev_sqlite/database_impl.rs | 21 +- .../persistence/rev_sqlite/view_impl.rs | 21 +- .../tests/database/database_editor.rs | 8 +- .../rust-lib/flowy-document/src/manager.rs | 18 +- .../flowy-document/src/old_editor/editor.rs | 1 - .../src/old_editor/web_socket.rs | 17 +- .../flowy-document/src/services/migration.rs | 12 +- .../src/services/persistence/mod.rs | 2 +- .../rev_sqlite/document_rev_sqlite_v0.rs | 28 +- .../rev_sqlite/document_rev_sqlite_v1.rs | 21 +- .../tests/new_document/script.rs | 2 +- .../tests/old_document/script.rs | 1 - frontend/rust-lib/flowy-folder/build.rs | 10 +- frontend/rust-lib/flowy-folder/src/manager.rs | 31 +- .../src/services/folder_editor.rs | 8 +- .../src/services/persistence/migration.rs | 4 +- .../src/services/persistence/mod.rs | 4 +- .../rev_sqlite/folder_rev_sqlite.rs | 21 +- .../flowy-folder/src/services/web_socket.rs | 9 +- .../flowy-folder/tests/workspace/main.rs | 4 +- frontend/rust-lib/flowy-folder2/Cargo.toml | 41 ++ frontend/rust-lib/flowy-folder2/Flowy.toml | 3 + frontend/rust-lib/flowy-folder2/build.rs | 10 + .../flowy-folder2/src/entities/app.rs | 183 ++++++ .../flowy-folder2/src/entities/mod.rs | 10 + .../entities/parser/app/app_color_style.rs | 13 + .../src/entities/parser/app/app_desc.rs | 20 + .../src/entities/parser/app/app_id.rs | 20 + .../src/entities/parser/app/app_name.rs | 20 + .../src/entities/parser/app/mod.rs | 9 + .../flowy-folder2/src/entities/parser/mod.rs | 4 + .../src/entities/parser/trash/mod.rs | 3 + .../src/entities/parser/trash/trash_id.rs | 34 + .../src/entities/parser/view/mod.rs | 9 + .../src/entities/parser/view/view_desc.rs | 21 + .../src/entities/parser/view/view_id.rs | 20 + .../src/entities/parser/view/view_name.rs | 25 + .../entities/parser/view/view_thumbnail.rs | 21 + .../src/entities/parser/workspace/mod.rs | 7 + .../parser/workspace/workspace_desc.rs | 21 + .../entities/parser/workspace/workspace_id.rs | 20 + .../parser/workspace/workspace_name.rs | 25 + .../flowy-folder2/src/entities/trash.rs | 73 +++ .../flowy-folder2/src/entities/view.rs | 349 ++++++++++ .../flowy-folder2/src/entities/workspace.rs | 141 ++++ .../flowy-folder2/src/event_handler.rs | 201 ++++++ .../rust-lib/flowy-folder2/src/event_map.rs | 119 ++++ frontend/rust-lib/flowy-folder2/src/lib.rs | 13 + .../rust-lib/flowy-folder2/src/manager.rs | 614 ++++++++++++++++++ .../flowy-folder2/src/notification.rs | 72 ++ .../rust-lib/flowy-folder2/src/test_helper.rs | 50 ++ .../flowy-folder2/src/user_default.rs | 105 +++ .../rust-lib/flowy-folder2/src/view_ext.rs | 72 ++ .../tests/workspace/folder_test.rs | 273 ++++++++ .../flowy-folder2/tests/workspace/main.rs | 2 + .../flowy-folder2/tests/workspace/script.rs | 329 ++++++++++ frontend/rust-lib/flowy-net/Cargo.toml | 2 +- .../flowy-net/src/http_server/folder.rs | 457 ------------- .../rust-lib/flowy-net/src/http_server/mod.rs | 1 - .../flowy-net/src/local_server/server.rs | 161 +---- .../rust-lib/flowy-net/src/local_server/ws.rs | 4 +- .../flowy-revision/src/cache/reset.rs | 10 +- .../flowy-revision/src/conflict_resolve.rs | 6 - .../flowy-revision/src/rev_manager.rs | 7 - .../flowy-revision/src/rev_persistence.rs | 13 +- .../flowy-revision/src/rev_snapshot.rs | 3 - .../tests/revision_test/script.rs | 27 +- frontend/rust-lib/flowy-sqlite/src/schema.rs | 34 +- frontend/rust-lib/flowy-test/Cargo.toml | 2 +- .../rust-lib/flowy-test/src/event_builder.rs | 6 +- frontend/rust-lib/flowy-test/src/helper.rs | 43 +- frontend/rust-lib/flowy-user/Cargo.toml | 2 + .../flowy-user/src/entities/user_profile.rs | 15 +- .../user_handler.rs => event_handler.rs} | 41 +- frontend/rust-lib/flowy-user/src/event_map.rs | 16 +- .../flowy-user/src/handlers/auth_handler.rs | 37 -- .../rust-lib/flowy-user/src/handlers/mod.rs | 5 - frontend/rust-lib/flowy-user/src/lib.rs | 3 +- .../flowy-user/src/services/database.rs | 63 +- .../flowy-user/src/services/user_session.rs | 85 ++- frontend/rust-lib/flowy-user/src/uid.rs | 58 ++ .../tests/event/user_profile_test.rs | 12 +- frontend/scripts/makefile/tests.toml | 9 + shared-lib/flowy-client-ws/src/connection.rs | 4 +- shared-lib/flowy-client-ws/src/ws.rs | 2 +- shared-lib/user-model/src/lib.rs | 12 +- 198 files changed, 4595 insertions(+), 1736 deletions(-) delete mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/tests/TestApiButton.tsx create mode 100644 frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs create mode 100644 frontend/rust-lib/flowy-folder2/Cargo.toml create mode 100644 frontend/rust-lib/flowy-folder2/Flowy.toml create mode 100644 frontend/rust-lib/flowy-folder2/build.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/app.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/mod.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/trash/mod.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/trash/trash_id.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/view/mod.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_desc.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_id.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_name.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_thumbnail.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/mod.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_desc.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_id.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_name.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/trash.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/view.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/entities/workspace.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/event_handler.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/event_map.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/lib.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/manager.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/notification.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/test_helper.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/user_default.rs create mode 100644 frontend/rust-lib/flowy-folder2/src/view_ext.rs create mode 100644 frontend/rust-lib/flowy-folder2/tests/workspace/folder_test.rs create mode 100644 frontend/rust-lib/flowy-folder2/tests/workspace/main.rs create mode 100644 frontend/rust-lib/flowy-folder2/tests/workspace/script.rs delete mode 100644 frontend/rust-lib/flowy-net/src/http_server/folder.rs rename frontend/rust-lib/flowy-user/src/{handlers/user_handler.rs => event_handler.rs} (70%) delete mode 100644 frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs delete mode 100644 frontend/rust-lib/flowy-user/src/handlers/mod.rs create mode 100644 frontend/rust-lib/flowy-user/src/uid.rs diff --git a/frontend/appflowy_flutter/lib/core/folder_notification.dart b/frontend/appflowy_flutter/lib/core/folder_notification.dart index 4d147da88e..571561bbaa 100644 --- a/frontend/appflowy_flutter/lib/core/folder_notification.dart +++ b/frontend/appflowy_flutter/lib/core/folder_notification.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; import 'notification_helper.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart index 6cdbc964e4..dfff5279a2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart @@ -9,7 +9,7 @@ import 'package:appflowy_backend/protobuf/flowy-database/group_changeset.pb.dart import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:collection/collection.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart index 5ecaad6ef3..44896c0883 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart @@ -5,7 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pb.dar import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/group.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart index 61911b5318..d91cd68558 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart @@ -6,7 +6,7 @@ import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart index fe1702873a..c6d2922cb2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart @@ -3,7 +3,7 @@ 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/workspace/presentation/widgets/left_bar_item.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart index 24c30a0cd3..095ffab019 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/presentation/board_page.dart @@ -7,7 +7,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle import 'package:appflowy/plugins/database_view/application/row/row_cache.dart'; import 'package:appflowy/plugins/database_view/application/row/row_data_controller.dart'; import 'package:appflowy/plugins/database_view/widgets/row/row_detail.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart'; import 'package:appflowy_board/appflowy_board.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart index f0cfb43b48..147e7531cc 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart'; import 'package:calendar_view/calendar_view.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart index 1ddfb7a64f..9e29fc8d06 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart @@ -3,7 +3,7 @@ import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; import '../../util.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/presentation/calendar_page.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/presentation/calendar_page.dart index 988654a8ec..943af77ce4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/presentation/calendar_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/presentation/calendar_page.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database_view/calendar/application/calendar_bloc.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:calendar_view/calendar_view.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_bloc.dart index 7d73ab9b4a..01082746e3 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_bloc.dart @@ -4,7 +4,7 @@ import 'package:appflowy/plugins/database_view/application/row/row_service.dart' import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart index ba4bc2f628..213e74ebe2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart @@ -4,7 +4,7 @@ import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; import 'presentation/grid_page.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart index 2b8f9a060c..2971542529 100755 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart @@ -8,7 +8,7 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; import 'package:linked_scroll_controller/linked_scroll_controller.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart index ae47a120ca..b1eae868d7 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart @@ -8,9 +8,8 @@ import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pbserver.dart'; import 'package:appflowy_editor/appflowy_editor.dart' show EditorState, Document, Transaction, Node; -import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/log.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -49,8 +48,7 @@ class DocumentBloc extends Bloc { emit(state.copyWith(isDeleted: false)); }, deletePermanently: (DeletePermanently value) async { - final result = await _trashService - .deleteViews([Tuple2(view.id, TrashType.TrashView)]); + final result = await _trashService.deleteViews([view.id]); final newState = result.fold( (l) => state.copyWith(forceClose: true), (r) => state); diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart b/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart index 6597dfc3f1..88f4ead686 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart @@ -1,7 +1,7 @@ import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart index ddb4fe915d..abd53da58c 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart @@ -5,7 +5,7 @@ import 'package:appflowy/plugins/document/presentation/plugins/parsers/divider_n import 'package:appflowy/plugins/document/presentation/plugins/parsers/math_equation_node_parser.dart'; import 'package:appflowy/plugins/document/presentation/plugins/parsers/code_block_node_parser.dart'; import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/share_service.dart b/frontend/appflowy_flutter/lib/plugins/document/application/share_service.dart index cf07dc0054..b2939244b5 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/share_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/share_service.dart @@ -3,7 +3,7 @@ import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; class ShareService { Future> export( diff --git a/frontend/appflowy_flutter/lib/plugins/document/document.dart b/frontend/appflowy_flutter/lib/plugins/document/document.dart index 30a9aa688d..1a61742870 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/document.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/document.dart @@ -10,7 +10,7 @@ import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy/workspace/presentation/widgets/left_bar_item.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/document_page.dart b/frontend/appflowy_flutter/lib/plugins/document/document_page.dart index 8c87000722..b2c44f41f2 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/document_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/document_page.dart @@ -1,5 +1,5 @@ import 'package:appflowy/plugins/document/presentation/plugins/board/board_view_menu_item.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor_plugins/appflowy_editor_plugins.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart index 0df834c355..a80be87b9d 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/built_in_page_widget.dart @@ -3,7 +3,7 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/application/app/app_service.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -59,7 +59,7 @@ class _BuiltInPageWidgetState extends State { child: CircularProgressIndicator(), ); }, - future: AppBackendService().getView(appID, gridID), + future: AppBackendService().getChildView(appID, gridID), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart index 8d4afd917e..cb286d69ae 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart @@ -1,14 +1,13 @@ import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart'; import 'package:appflowy/plugins/document/presentation/plugins/grid/grid_node_widget.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; const String kAppID = 'app_id'; const String kViewID = 'view_id'; extension InsertPage on EditorState { - void insertPage(AppPB appPB, ViewPB viewPB) { + void insertPage(ViewPB appPB, ViewPB viewPB) { final selection = service.selectionService.currentSelection.value; final textNodes = service.selectionService.currentSelectedNodes.whereType(); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart index 46c8298b49..4a5c879fbf 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart @@ -1,6 +1,5 @@ import 'package:appflowy/workspace/application/app/app_service.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:dartz/dartz.dart' as dartz; import 'package:flowy_infra/image.dart'; @@ -50,8 +49,8 @@ void showLinkToPageMenu( editorState: editorState, layoutType: pageType, hintText: hintText, - onSelected: (appPB, viewPB) { - editorState.insertPage(appPB, viewPB); + onSelected: (viewPB, childViewPB) { + editorState.insertPage(viewPB, childViewPB); }, ), ), @@ -85,7 +84,7 @@ class LinkToPageMenu extends StatefulWidget { final EditorState editorState; final ViewLayoutTypePB layoutType; final String hintText; - final void Function(AppPB appPB, ViewPB viewPB) onSelected; + final void Function(ViewPB view, ViewPB childView) onSelected; @override State createState() => _LinkToPageMenuState(); @@ -118,11 +117,11 @@ class _LinkToPageMenuState extends State { } Widget _buildListWidget(BuildContext context) { - return FutureBuilder>>>( + return FutureBuilder>>>( builder: (context, snapshot) { if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) { - final apps = snapshot.data; + final views = snapshot.data; final children = [ Padding( padding: const EdgeInsets.symmetric(vertical: 4), @@ -133,18 +132,18 @@ class _LinkToPageMenuState extends State { ), ), ]; - if (apps != null && apps.isNotEmpty) { - for (final app in apps) { - if (app.value2.isNotEmpty) { + if (views != null && views.isNotEmpty) { + for (final view in views) { + if (view.value2.isNotEmpty) { children.add( Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: FlowyText.regular( - app.value1.name, + view.value1.name, ), ), ); - for (final value in app.value2) { + for (final value in view.value2) { children.add( FlowyButton( leftIcon: svgWidget( @@ -152,7 +151,7 @@ class _LinkToPageMenuState extends State { color: Theme.of(context).iconTheme.color, ), text: FlowyText.regular(value.name), - onTap: () => widget.onSelected(app.value1, value), + onTap: () => widget.onSelected(view.value1, value), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart index c81d394f7d..90bd0d68ec 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/plugins/base/link_to_page_widget.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart index b25fe52679..40f3c9ce86 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart @@ -1,4 +1,4 @@ -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/application/prelude.dart'; @@ -42,15 +42,14 @@ SelectionMenuItem boardViewMenuItem(DocumentBloc documentBloc) => return; } - final app = - (await service.readApp(appId: result.appId)).getLeftOrNull(); + final app = (await service.getView(result.viewId)).getLeftOrNull(); // We should show an error dialog. if (app == null) { return; } - final view = - (await service.getView(result.appId, result.id)).getLeftOrNull(); + final view = (await service.getChildView(result.viewId, result.id)) + .getLeftOrNull(); // As this. if (view == null) { return; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart index b79162027b..aaf976274e 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart @@ -1,6 +1,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/plugins/base/link_to_page_widget.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart index 2dc030d547..a3fa5fd8af 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart @@ -2,7 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/application/doc_bloc.dart'; import 'package:appflowy/plugins/document/presentation/plugins/base/insert_page_command.dart'; import 'package:appflowy/workspace/application/app/app_service.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; @@ -41,15 +41,14 @@ SelectionMenuItem gridViewMenuItem(DocumentBloc documentBloc) => return; } - final app = - (await service.readApp(appId: result.appId)).getLeftOrNull(); + final app = (await service.getView(result.viewId)).getLeftOrNull(); // We should show an error dialog. if (app == null) { return; } - final view = - (await service.getView(result.appId, result.id)).getLeftOrNull(); + final view = (await service.getChildView(result.viewId, result.id)) + .getLeftOrNull(); // As this. if (view == null) { return; diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_button.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_button.dart index 84e9b179cb..ffdd9a5f23 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/share/share_button.dart @@ -13,7 +13,7 @@ import 'package:file_picker/file_picker.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart index 2a744817e4..f653fbfe11 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart @@ -1,6 +1,6 @@ import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -31,8 +31,7 @@ class TrashBloc extends Bloc { final result = await _service.putback(e.trashId); await _handleResult(result, emit); }, delete: (e) async { - final result = - await _service.deleteViews([Tuple2(e.trash.id, e.trash.ty)]); + final result = await _service.deleteViews([e.trash.id]); await _handleResult(result, emit); }, deleteAll: (e) async { final result = await _service.deleteAll(); diff --git a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart index 5df20b27e9..bca3bd3f74 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart @@ -3,9 +3,9 @@ import 'dart:typed_data'; import 'package:appflowy/core/folder_notification.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; typedef TrashUpdatedCallback = void Function( @@ -19,7 +19,10 @@ class TrashListener { void start({TrashUpdatedCallback? trashUpdated}) { _trashUpdated = trashUpdated; - _parser = FolderNotificationParser(callback: _observableCallback); + _parser = FolderNotificationParser( + id: "trash", + callback: _observableCallback, + ); _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } diff --git a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart index 5b2e350435..29fb9f13c1 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart'; class TrashService { Future> readTrash() { @@ -15,12 +15,9 @@ class TrashService { return FolderEventPutbackTrash(id).send(); } - Future> deleteViews( - List> trashList) { - final items = trashList.map((trash) { - return TrashIdPB.create() - ..id = trash.value1 - ..ty = trash.value2; + Future> deleteViews(List trash) { + final items = trash.map((trash) { + return TrashIdPB.create()..id = trash; }); final ids = RepeatedTrashIdPB(items: items); diff --git a/frontend/appflowy_flutter/lib/plugins/trash/src/trash_cell.dart b/frontend/appflowy_flutter/lib/plugins/trash/src/trash_cell.dart index a46cca2a3b..01f33edbfd 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/src/trash_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/src/trash_cell.dart @@ -2,7 +2,7 @@ import 'package:flowy_infra/image.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/trash.pb.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:fixnum/fixnum.dart' as $fixnum; diff --git a/frontend/appflowy_flutter/lib/plugins/util.dart b/frontend/appflowy_flutter/lib/plugins/util.dart index f689511c44..f128b3ad99 100644 --- a/frontend/appflowy_flutter/lib/plugins/util.dart +++ b/frontend/appflowy_flutter/lib/plugins/util.dart @@ -2,7 +2,7 @@ import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/application/view/view_listener.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; class ViewPluginNotifier extends PluginNotifier> { diff --git a/frontend/appflowy_flutter/lib/startup/deps_resolver.dart b/frontend/appflowy_flutter/lib/startup/deps_resolver.dart index b8e219125e..8e0f4cbbc0 100644 --- a/frontend/appflowy_flutter/lib/startup/deps_resolver.dart +++ b/frontend/appflowy_flutter/lib/startup/deps_resolver.dart @@ -8,7 +8,6 @@ import 'package:appflowy/user/application/user_listener.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy/util/file_picker/file_picker_impl.dart'; import 'package:appflowy/util/file_picker/file_picker_service.dart'; -import 'package:appflowy/workspace/application/app/prelude.dart'; import 'package:appflowy/plugins/document/application/prelude.dart'; import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart'; import 'package:appflowy/workspace/application/user/prelude.dart'; @@ -22,8 +21,7 @@ import 'package:appflowy/user/presentation/router.dart'; import 'package:appflowy/plugins/trash/application/prelude.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy/workspace/presentation/home/menu/menu.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:get_it/get_it.dart'; @@ -122,11 +120,6 @@ void _resolveFolderDeps(GetIt getIt) { (user, _) => SettingsUserViewBloc(user), ); - // AppPB - getIt.registerFactoryParam( - (app, _) => AppBloc(app: app), - ); - // trash getIt.registerLazySingleton(() => TrashService()); getIt.registerLazySingleton(() => TrashListener()); diff --git a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart index 2a50dda5e0..87b0ef7c4b 100644 --- a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart @@ -3,7 +3,7 @@ library flowy_plugin; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/widgets.dart'; export "./src/sandbox.dart"; diff --git a/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart b/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart index 9507e9fd0c..994e018f21 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart @@ -36,10 +36,10 @@ Future appFlowyDocumentDirectory() async { switch (integrationEnv()) { case IntegrationMode.develop: Directory documentsDir = await getApplicationDocumentsDirectory(); - return Directory(path.join(documentsDir.path, 'flowy_dev')).create(); + return Directory(path.join(documentsDir.path, 'data_dev')).create(); case IntegrationMode.release: Directory documentsDir = await getApplicationDocumentsDirectory(); - return Directory(path.join(documentsDir.path, 'flowy')).create(); + return Directory(path.join(documentsDir.path, 'data')).create(); case IntegrationMode.test: return Directory(path.join(Directory.current.path, '.sandbox')); } diff --git a/frontend/appflowy_flutter/lib/user/application/user_listener.dart b/frontend/appflowy_flutter/lib/user/application/user_listener.dart index 8dc182a48b..b9bda5e042 100644 --- a/frontend/appflowy_flutter/lib/user/application/user_listener.dart +++ b/frontend/appflowy_flutter/lib/user/application/user_listener.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'package:appflowy/core/folder_notification.dart'; import 'package:appflowy/core/user_notification.dart'; import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'dart:typed_data'; import 'package:flowy_infra/notifier.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/notification.pb.dart' as user; @@ -119,13 +119,6 @@ class UserWorkspaceListener { ) { switch (ty) { case FolderNotification.DidCreateWorkspace: - case FolderNotification.DidDeleteWorkspace: - result.fold( - (payload) => _workspacesChangedNotifier?.value = - left(RepeatedWorkspacePB.fromBuffer(payload).items), - (error) => _workspacesChangedNotifier?.value = right(error), - ); - break; case FolderNotification.DidUpdateWorkspaceSetting: result.fold( (payload) => _settingChangedNotifier?.value = diff --git a/frontend/appflowy_flutter/lib/user/application/user_service.dart b/frontend/appflowy_flutter/lib/user/application/user_service.dart index 295c1c4f01..7edf49a4ee 100644 --- a/frontend/appflowy_flutter/lib/user/application/user_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/user_service.dart @@ -3,15 +3,16 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:fixnum/fixnum.dart'; class UserBackendService { UserBackendService({ required this.userId, }); - final String userId; + final Int64 userId; static Future> getCurrentUserProfile() { return UserEventGetUserProfile().send(); diff --git a/frontend/appflowy_flutter/lib/user/presentation/router.dart b/frontend/appflowy_flutter/lib/user/presentation/router.dart index 665b261b66..8e08a0ce11 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/router.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/router.dart @@ -10,7 +10,7 @@ import 'package:flowy_infra/time/duration.dart'; import 'package:flowy_infra_ui/widget/route/animation.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; -import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart'; import 'package:flutter/material.dart'; class AuthRouter { diff --git a/frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart index 84f9fa441f..3aefed7c6c 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/skip_log_in_screen.dart @@ -6,7 +6,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; 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-folder2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; diff --git a/frontend/appflowy_flutter/lib/user/presentation/welcome_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/welcome_screen.dart index 5e21d4c69d..78c23b2521 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/welcome_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/welcome_screen.dart @@ -5,7 +5,7 @@ import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart index df9d203974..6132d3870d 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/app/app_bloc.dart @@ -7,8 +7,7 @@ import 'package:appflowy/workspace/application/app/app_service.dart'; import 'package:appflowy/workspace/presentation/home/menu/menu.dart'; import 'package:expandable/expandable.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -21,10 +20,10 @@ class AppBloc extends Bloc { final AppBackendService appService; final AppListener appListener; - AppBloc({required AppPB app}) + AppBloc({required ViewPB view}) : appService = AppBackendService(), - appListener = AppListener(appId: app.id), - super(AppState.initial(app)) { + appListener = AppListener(viewId: view.id), + super(AppState.initial(view)) { on((event, emit) async { await event.map(initial: (e) async { _startListening(); @@ -41,10 +40,10 @@ class AppBloc extends Bloc { await _renameView(e, emit); }, appDidUpdate: (e) async { final latestCreatedView = state.latestCreatedView; - final views = e.app.belongings.items; + final views = e.app.belongings; AppState newState = state.copyWith( views: views, - app: e.app, + view: e.app, ); if (latestCreatedView != null) { final index = @@ -70,7 +69,7 @@ class AppBloc extends Bloc { Future _renameView(Rename e, Emitter emit) async { final result = - await appService.updateApp(appId: state.app.id, name: e.newName); + await appService.updateApp(appId: state.view.id, name: e.newName); result.fold( (l) => emit(state.copyWith(successOrFailure: left(unit))), (error) => emit(state.copyWith(successOrFailure: right(error))), @@ -79,7 +78,7 @@ class AppBloc extends Bloc { // Delete the current app Future _deleteApp(Emitter emit) async { - final result = await appService.delete(appId: state.app.id); + final result = await appService.delete(viewId: state.view.id); result.fold( (unit) => emit(state.copyWith(successOrFailure: left(unit))), (error) => emit(state.copyWith(successOrFailure: right(error))), @@ -96,7 +95,7 @@ class AppBloc extends Bloc { Future _createView(CreateView value, Emitter emit) async { final result = await appService.createView( - appId: state.app.id, + appId: state.view.id, name: value.name, desc: value.desc ?? "", layoutType: value.pluginBuilder.layoutType!, @@ -122,7 +121,7 @@ class AppBloc extends Bloc { } Future _loadViews(Emitter emit) async { - final viewsOrFailed = await appService.getViews(appId: state.app.id); + final viewsOrFailed = await appService.getViews(viewId: state.view.id); viewsOrFailed.fold( (views) => emit(state.copyWith(views: views)), (error) { @@ -150,34 +149,34 @@ class AppEvent with _$AppEvent { const factory AppEvent.delete() = DeleteApp; const factory AppEvent.deleteView(String viewId) = DeleteView; const factory AppEvent.rename(String newName) = Rename; - const factory AppEvent.appDidUpdate(AppPB app) = AppDidUpdate; + const factory AppEvent.appDidUpdate(ViewPB app) = AppDidUpdate; } @freezed class AppState with _$AppState { const factory AppState({ - required AppPB app, + required ViewPB view, required List views, ViewPB? latestCreatedView, required Either successOrFailure, }) = _AppState; - factory AppState.initial(AppPB app) => AppState( - app: app, - views: app.belongings.items, + factory AppState.initial(ViewPB view) => AppState( + view: view, + views: view.belongings, successOrFailure: left(unit), ); } class AppViewDataContext extends ChangeNotifier { - final String appId; + final String viewId; final ValueNotifier> _viewsNotifier = ValueNotifier([]); final ValueNotifier _selectedViewNotifier = ValueNotifier(null); VoidCallback? _menuSharedStateListener; ExpandableController expandController = ExpandableController(initialExpanded: false); - AppViewDataContext({required this.appId}) { + AppViewDataContext({required this.viewId}) { _setLatestView(getIt().latestOpenView); _menuSharedStateListener = getIt().addLatestViewListener((view) { diff --git a/frontend/appflowy_flutter/lib/workspace/application/app/app_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/app/app_listener.dart index 1186068c75..af3875b1ec 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/app/app_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/app/app_listener.dart @@ -5,12 +5,11 @@ import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; -typedef AppDidUpdateCallback = void Function(AppPB app); +typedef AppDidUpdateCallback = void Function(ViewPB app); typedef ViewsDidChangeCallback = void Function( Either, FlowyError> viewsOrFailed); @@ -18,15 +17,15 @@ class AppListener { StreamSubscription? _subscription; AppDidUpdateCallback? _updated; FolderNotificationParser? _parser; - String appId; + String viewId; AppListener({ - required this.appId, + required this.viewId, }); void start({AppDidUpdateCallback? onAppUpdated}) { _updated = onAppUpdated; - _parser = FolderNotificationParser(id: appId, callback: _handleCallback); + _parser = FolderNotificationParser(id: viewId, callback: _handleCallback); _subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable)); } @@ -34,11 +33,12 @@ class AppListener { void _handleCallback( FolderNotification ty, Either result) { switch (ty) { - case FolderNotification.DidUpdateApp: + case FolderNotification.DidUpdateView: + case FolderNotification.DidUpdateChildViews: if (_updated != null) { result.fold( (payload) { - final app = AppPB.fromBuffer(payload); + final app = ViewPB.fromBuffer(payload); _updated!(app); }, (error) => Log.error(error), diff --git a/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart b/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart index c54d2ad602..110c906afb 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart @@ -1,20 +1,13 @@ import 'dart:async'; import 'dart:convert'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; class AppBackendService { - Future> readApp({required String appId}) { - final payload = AppIdPB.create()..value = appId; - - return FolderEventReadApp(payload).send(); - } - Future> createView({ required String appId, required String name, @@ -51,20 +44,20 @@ class AppBackendService { return FolderEventCreateView(payload).send(); } - Future, FlowyError>> getViews({required String appId}) { - final payload = AppIdPB.create()..value = appId; + Future, FlowyError>> getViews({required String viewId}) { + final payload = ViewIdPB.create()..value = viewId; - return FolderEventReadApp(payload).send().then((result) { + return FolderEventReadView(payload).send().then((result) { return result.fold( - (app) => left(app.belongings.items), + (app) => left(app.belongings), (error) => right(error), ); }); } - Future> delete({required String appId}) { - final request = AppIdPB.create()..value = appId; - return FolderEventDeleteApp(request).send(); + Future> delete({required String viewId}) { + final request = RepeatedViewIdPB.create()..items.add(viewId); + return FolderEventDeleteView(request).send(); } Future> deleteView({required String viewId}) { @@ -72,14 +65,14 @@ class AppBackendService { return FolderEventDeleteView(request).send(); } - Future> updateApp( + Future> updateApp( {required String appId, String? name}) { - UpdateAppPayloadPB payload = UpdateAppPayloadPB.create()..appId = appId; + var payload = UpdateViewPayloadPB.create()..viewId = appId; if (name != null) { payload.name = name; } - return FolderEventUpdateApp(payload).send(); + return FolderEventUpdateView(payload).send(); } Future> moveView({ @@ -96,22 +89,22 @@ class AppBackendService { return FolderEventMoveItem(payload).send(); } - Future>>> fetchViews( + Future>>> fetchViews( ViewLayoutTypePB layoutType) async { - final result = >>[]; + final result = >>[]; return FolderEventReadCurrentWorkspace().send().then((value) async { final workspaces = value.getLeftOrNull(); if (workspaces != null) { - final apps = workspaces.workspace.apps.items; - for (var app in apps) { - final views = await getViews(appId: app.id).then( + final views = workspaces.workspace.views; + for (var view in views) { + final childViews = await getViews(viewId: view.id).then( (value) => value .getLeftOrNull>() ?.where((e) => e.layout == layoutType) .toList(), ); - if (views != null && views.isNotEmpty) { - result.add(Tuple2(app, views)); + if (childViews != null && childViews.isNotEmpty) { + result.add(Tuple2(view, childViews)); } } } @@ -120,14 +113,21 @@ class AppBackendService { } Future> getView( - String appID, String viewID, ) async { - final payload = AppIdPB.create()..value = appID; - return FolderEventReadApp(payload).send().then((result) { + final payload = ViewIdPB.create()..value = viewID; + return FolderEventReadView(payload).send(); + } + + Future> getChildView( + String viewID, + String childViewID, + ) async { + final payload = ViewIdPB.create()..value = viewID; + return FolderEventReadView(payload).send().then((result) { return result.fold( (app) => left( - app.belongings.items.firstWhere((e) => e.id == viewID), + app.belongings.firstWhere((e) => e.id == childViewID), ), (error) => right(error), ); diff --git a/frontend/appflowy_flutter/lib/workspace/application/home/home_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/home/home_bloc.dart index 9163710b96..53b7328122 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/home/home_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/home/home_bloc.dart @@ -3,8 +3,8 @@ import 'package:flowy_infra/time/duration.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart' +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart' show WorkspaceSettingPB; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart b/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart index 51c57ca576..dd1c19b2b7 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart @@ -1,14 +1,14 @@ import 'dart:async'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; class HomeService { - Future> readApp({required String appId}) { - final payload = AppIdPB.create()..value = appId; + Future> readApp({required String appId}) { + final payload = ViewIdPB.create()..value = appId; - return FolderEventReadApp(payload).send(); + return FolderEventReadView(payload).send(); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart index 44e8518760..d24ca6f8a4 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart @@ -1,7 +1,7 @@ import 'package:appflowy/user/application/user_listener.dart'; import 'package:appflowy/workspace/application/appearance.dart'; import 'package:appflowy/workspace/application/edit_panel/edit_context.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart' +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart' show WorkspaceSettingPB; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart index c687938652..54c126b221 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart @@ -2,11 +2,11 @@ import 'dart:async'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/application/workspace/workspace_listener.dart'; import 'package:appflowy/workspace/application/workspace/workspace_service.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -38,24 +38,35 @@ class MenuBloc extends Bloc { emit(state.copyWith(plugin: e.plugin)); }, createApp: (_CreateApp event) async { - await _performActionOnCreateApp(event, emit); + final result = await _workspaceService.createApp( + name: event.name, + desc: event.desc ?? "", + ); + result.fold( + (app) => {}, + (error) { + Log.error(error); + emit(state.copyWith(successOrFailure: right(error))); + }, + ); }, didReceiveApps: (e) async { emit(e.appsOrFail.fold( - (apps) => state.copyWith(apps: apps, successOrFailure: left(unit)), + (views) => + state.copyWith(views: views, successOrFailure: left(unit)), (err) => state.copyWith(successOrFailure: right(err)), )); }, moveApp: (_MoveApp value) { - if (state.apps.length > value.fromIndex) { - final app = state.apps[value.fromIndex]; + if (state.views.length > value.fromIndex) { + final view = state.views[value.fromIndex]; _workspaceService.moveApp( - appId: app.id, + appId: view.id, fromIndex: value.fromIndex, toIndex: value.toIndex); - final apps = List.from(state.apps); + final apps = List.from(state.views); apps.insert(value.toIndex, apps.removeAt(value.fromIndex)); - emit(state.copyWith(apps: apps)); + emit(state.copyWith(views: apps)); } }, ); @@ -68,24 +79,11 @@ class MenuBloc extends Bloc { return super.close(); } - Future _performActionOnCreateApp( - _CreateApp event, Emitter emit) async { - final result = await _workspaceService.createApp( - name: event.name, desc: event.desc ?? ""); - result.fold( - (app) => {}, - (error) { - Log.error(error); - emit(state.copyWith(successOrFailure: right(error))); - }, - ); - } - // ignore: unused_element Future _fetchApps(Emitter emit) async { final appsOrFail = await _workspaceService.getApps(); emit(appsOrFail.fold( - (apps) => state.copyWith(apps: apps), + (views) => state.copyWith(views: views), (error) { Log.error(error); return state.copyWith(successOrFailure: right(error)); @@ -93,7 +91,7 @@ class MenuBloc extends Bloc { )); } - void _handleAppsOrFail(Either, FlowyError> appsOrFail) { + void _handleAppsOrFail(Either, FlowyError> appsOrFail) { appsOrFail.fold( (apps) => add(MenuEvent.didReceiveApps(left(apps))), (error) => add(MenuEvent.didReceiveApps(right(error))), @@ -108,19 +106,19 @@ class MenuEvent with _$MenuEvent { const factory MenuEvent.createApp(String name, {String? desc}) = _CreateApp; const factory MenuEvent.moveApp(int fromIndex, int toIndex) = _MoveApp; const factory MenuEvent.didReceiveApps( - Either, FlowyError> appsOrFail) = _ReceiveApps; + Either, FlowyError> appsOrFail) = _ReceiveApps; } @freezed class MenuState with _$MenuState { const factory MenuState({ - required List apps, + required List views, required Either successOrFailure, required Plugin plugin, }) = _MenuState; factory MenuState.initial(WorkspacePB workspace) => MenuState( - apps: workspace.apps.items, + views: workspace.views, successOrFailure: left(unit), plugin: makePlugin(pluginType: PluginType.blank), ); diff --git a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart index f12627dca9..d6bb398d9c 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart @@ -1,7 +1,7 @@ import 'package:appflowy/user/application/user_listener.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart index fdf82a91a2..2f275f1fef 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_view_section_bloc.dart @@ -3,7 +3,7 @@ import 'dart:async'; import 'package:appflowy/workspace/application/app/app_bloc.dart'; import 'package:appflowy/workspace/application/app/app_service.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart index 04be1f61bf..5e75f744b5 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/settings_file_exporter_cubit.dart @@ -1,26 +1,26 @@ -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SettingsFileExportState { SettingsFileExportState({ - required this.apps, + required this.views, }) { initialize(); } - List apps; + List views; List expanded = []; List selectedApps = []; List> selectedItems = []; SettingsFileExportState copyWith({ - List? apps, + List? views, List? expanded, List? selectedApps, List>? selectedItems, }) { final state = SettingsFileExportState( - apps: apps ?? this.apps, + views: views ?? this.views, ); state.expanded = expanded ?? this.expanded; state.selectedApps = selectedApps ?? this.selectedApps; @@ -29,17 +29,17 @@ class SettingsFileExportState { } void initialize() { - expanded = apps.map((e) => true).toList(); - selectedApps = apps.map((e) => true).toList(); + expanded = views.map((e) => true).toList(); + selectedApps = views.map((e) => true).toList(); selectedItems = - apps.map((e) => e.belongings.items.map((e) => true).toList()).toList(); + views.map((e) => e.belongings.map((e) => true).toList()).toList(); } } class SettingsFileExporterCubit extends Cubit { SettingsFileExporterCubit({ - required List apps, - }) : super(SettingsFileExportState(apps: apps)); + required List views, + }) : super(SettingsFileExportState(views: views)); void selectOrDeselectItem(int outerIndex, int innerIndex) { final selectedItems = state.selectedItems; @@ -55,7 +55,7 @@ class SettingsFileExporterCubit extends Cubit { } Map> fetchSelectedPages() { - final apps = state.apps; + final apps = state.views; final selectedItems = state.selectedItems; Map> result = {}; for (var i = 0; i < selectedItems.length; i++) { @@ -63,7 +63,7 @@ class SettingsFileExporterCubit extends Cubit { final ids = []; for (var j = 0; j < selectedItem.length; j++) { if (selectedItem[j]) { - ids.add(apps[i].belongings.items[j].id); + ids.add(apps[i].belongings[j].id); } } if (ids.isNotEmpty) { diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart index 1951fd0a88..05bd1ca178 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart @@ -1,7 +1,7 @@ import 'package:appflowy/workspace/application/view/view_listener.dart'; import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.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 200ce23686..29173d7f0f 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -1,6 +1,6 @@ import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:flowy_infra/image.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; enum FlowyPlugin { diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart index 1af4a8e57b..38de59e4cc 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart @@ -3,9 +3,9 @@ import 'dart:typed_data'; import 'package:appflowy/core/folder_notification.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; import 'package:flowy_infra/notifier.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart index 7524a39e2c..7facfcec3f 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; class ViewService { diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/welcome_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/welcome_bloc.dart index aef0464cee..8700297a84 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/welcome_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/welcome_bloc.dart @@ -1,7 +1,7 @@ import 'package:appflowy/user/application/user_listener.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart index 73019c34e1..4346d1f226 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart @@ -1,16 +1,16 @@ import 'dart:async'; import 'dart:typed_data'; import 'package:appflowy/core/folder_notification.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/notification.pb.dart'; -typedef AppListNotifyValue = Either, FlowyError>; +typedef AppListNotifyValue = Either, FlowyError>; typedef WorkspaceNotifyValue = Either; class WorkspaceListener { @@ -55,10 +55,10 @@ class WorkspaceListener { (error) => _workspaceUpdatedNotifier?.value = right(error), ); break; - case FolderNotification.DidUpdateWorkspaceApps: + case FolderNotification.DidUpdateWorkspaceViews: result.fold( (payload) => _appsChangedNotifier?.value = - left(RepeatedAppPB.fromBuffer(payload).items), + left(RepeatedViewPB.fromBuffer(payload).items), (error) => _appsChangedNotifier?.value = right(error), ); break; diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart index 425154f353..533b839fc6 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart @@ -4,10 +4,14 @@ import 'package:dartz/dartz.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart' - show MoveFolderItemPayloadPB, MoveFolderItemType; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart' + show + CreateViewPayloadPB, + MoveFolderItemPayloadPB, + MoveFolderItemType, + ViewLayoutTypePB, + ViewPB; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; @@ -16,13 +20,15 @@ class WorkspaceService { WorkspaceService({ required this.workspaceId, }); - Future> createApp( + Future> createApp( {required String name, String? desc}) { - final payload = CreateAppPayloadPB.create() + final payload = CreateViewPayloadPB.create() + ..belongToId = workspaceId ..name = name - ..workspaceId = workspaceId - ..desc = desc ?? ""; - return FolderEventCreateApp(payload).send(); + ..desc = desc ?? "" + ..layout = ViewLayoutTypePB.Document; + + return FolderEventCreateView(payload).send(); } Future> getWorkspace() { @@ -44,7 +50,7 @@ class WorkspaceService { }); } - Future, FlowyError>> getApps() { + Future, FlowyError>> getApps() { final payload = WorkspaceIdPB.create()..value = workspaceId; return FolderEventReadWorkspaceApps(payload).send().then((result) { return result.fold( diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart index 57ca5182aa..02dce780a9 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart @@ -10,7 +10,7 @@ import 'package:appflowy/workspace/presentation/home/hotkeys.dart'; import 'package:appflowy/workspace/presentation/widgets/edit_panel/panel_animation.dart'; import 'package:appflowy/workspace/presentation/widgets/float_bubble/question_bubble.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; import 'package:flowy_infra_ui/style_widget/container.dart'; @@ -263,8 +263,8 @@ class HomeScreenStackAdaptor extends HomeStackDelegate { final homeService = HomeService(); homeService.readApp(appId: view.appId).then((result) { result.fold( - (appPB) { - final List views = appPB.belongings.items; + (parentView) { + final List views = parentView.belongings; if (views.isNotEmpty) { var lastView = views.last; if (index != null && index != 0 && views.length > index - 1) { 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 e73577d818..1511965942 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_stack.dart @@ -5,7 +5,7 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; import 'package:appflowy/workspace/presentation/home/navigation.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-folder2/view.pb.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart index c2161066c9..6137a49d7f 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/header.dart @@ -2,12 +2,12 @@ import 'dart:convert'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:expandable/expandable.dart'; import 'package:flowy_infra/icon_data.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:appflowy/workspace/application/app/app_bloc.dart'; @@ -19,7 +19,7 @@ import '../menu_app.dart'; import 'add_button.dart'; class MenuAppHeader extends StatelessWidget { - final AppPB app; + final ViewPB app; const MenuAppHeader( this.app, { Key? key, @@ -83,7 +83,7 @@ class MenuAppHeader extends StatelessWidget { case AppDisclosureAction.rename: NavigatorTextFieldDialog( title: LocaleKeys.menuAppHeader_renameDialog.tr(), - value: context.read().state.app.name, + value: context.read().state.view.name, confirm: (newValue) { context.read().add(AppEvent.rename(newValue)); }, @@ -166,8 +166,8 @@ class AppActionList extends StatelessWidget { onSecondaryTap: () { controller.show(); }, - child: BlocSelector( - selector: (state) => state.app, + child: BlocSelector( + selector: (state) => state.view, builder: (context, app) => FlowyText.medium( app.name, overflow: TextOverflow.ellipsis, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/menu_app.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/menu_app.dart index 653f67fa5a..cf48af34fe 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/menu_app.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/menu_app.dart @@ -1,6 +1,6 @@ import 'package:appflowy/workspace/presentation/home/menu/menu.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:expandable/expandable.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:appflowy/startup/startup.dart'; @@ -9,8 +9,8 @@ import 'package:provider/provider.dart'; import 'section/section.dart'; class MenuApp extends StatefulWidget { - final AppPB app; - const MenuApp(this.app, {Key? key}) : super(key: key); + final ViewPB view; + const MenuApp(this.view, {Key? key}) : super(key: key); @override State createState() => _MenuAppState(); @@ -21,7 +21,7 @@ class _MenuAppState extends State { @override void initState() { - viewDataContext = AppViewDataContext(appId: widget.app.id); + viewDataContext = AppViewDataContext(viewId: widget.view.id); super.initState(); } @@ -31,7 +31,7 @@ class _MenuAppState extends State { providers: [ BlocProvider( create: (context) { - final appBloc = getIt(param1: widget.app); + final appBloc = AppBloc(view: widget.view); appBloc.add(const AppEvent.initial()); return appBloc; }, @@ -86,7 +86,7 @@ class _MenuAppState extends State { iconPadding: EdgeInsets.zero, hasIcon: false, ), - header: MenuAppHeader(widget.app), + header: MenuAppHeader(widget.view), expanded: ViewSection(appViewData: viewDataContext), collapsed: const SizedBox(), ), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/section/item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/section/item.dart index e6d328d797..bbe1e607f6 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/section/item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/section/item.dart @@ -7,7 +7,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu.dart index 11cfa05042..b0be6b6be2 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/menu.dart @@ -8,8 +8,8 @@ import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; import 'package:appflowy/workspace/application/menu/menu_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; import 'package:easy_localization/easy_localization.dart'; @@ -112,7 +112,7 @@ class HomeMenu extends StatelessWidget { child: ScrollConfiguration( behavior: const ScrollBehavior().copyWith(scrollbars: false), child: BlocSelector>( - selector: (state) => state.apps + selector: (state) => state.views .map((app) => MenuApp(app, key: ValueKey(app.id))) .toList(), builder: (context, menuItems) { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart index 2b075d16fc..9d490d1b69 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart @@ -6,7 +6,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -73,9 +73,9 @@ class _FileExporterWidgetState extends State { snapshot.connectionState == ConnectionState.done) { final workspaces = snapshot.data?.getLeftOrNull(); if (workspaces != null) { - final apps = workspaces.workspace.apps.items; + final views = workspaces.workspace.views; return BlocProvider( - create: (_) => SettingsFileExporterCubit(apps: apps), + create: (_) => SettingsFileExporterCubit(views: views), child: const _ExpandedList(), ); } @@ -118,7 +118,7 @@ class _ExpandedListState extends State<_ExpandedList> { } List _buildChildren(BuildContext context) { - final apps = context.read().state.apps; + final apps = context.read().state.views; List children = []; for (var i = 0; i < apps.length; i++) { children.add(_buildExpandedItem(context, i)); @@ -128,14 +128,14 @@ class _ExpandedListState extends State<_ExpandedList> { Widget _buildExpandedItem(BuildContext context, int index) { final state = context.read().state; - final apps = state.apps; + final apps = state.views; final expanded = state.expanded; final selectedItems = state.selectedItems; final isExpaned = expanded[index] == true; List expandedChildren = []; if (isExpaned) { for (var i = 0; i < selectedItems[index].length; i++) { - final name = apps[index].belongings.items[i].name; + final name = apps[index].belongings[i].name; final checkbox = CheckboxListTile( value: selectedItems[index][i], onChanged: (value) { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/left_bar_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/left_bar_item.dart index e697262492..5bf6052516 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/left_bar_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/left_bar_item.dart @@ -1,7 +1,7 @@ import 'package:appflowy/workspace/application/view/view_listener.dart'; import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter/material.dart'; class ViewLeftBarItem extends StatefulWidget { 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 6e2829659e..a32fce93a9 100644 --- a/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart +++ b/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart @@ -15,7 +15,7 @@ import 'dart:typed_data'; import 'package:appflowy_backend/ffi.dart' as ffi; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_backend/protobuf/dart-ffi/protobuf.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database/protobuf.dart'; @@ -25,7 +25,7 @@ import 'dart:convert' show utf8; import '../protobuf/flowy-net/event_map.pb.dart'; import 'error.dart'; -part 'dart_event/flowy-folder/dart_event.dart'; +part 'dart_event/flowy-folder2/dart_event.dart'; part 'dart_event/flowy-net/dart_event.dart'; part 'dart_event/flowy-user/dart_event.dart'; part 'dart_event/flowy-database/dart_event.dart'; 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 668338bfb5..3ffe8cbf5b 100644 --- a/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart @@ -11,7 +11,7 @@ import 'package:appflowy/plugins/database_view/application/database_controller.d import 'package:appflowy/plugins/database_view/grid/application/row/row_bloc.dart'; import 'package:appflowy/workspace/application/app/app_service.dart'; import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pbenum.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import '../../util.dart'; diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart index af85cc8bf2..32a1c4f1ce 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart @@ -13,7 +13,7 @@ import 'package:appflowy/workspace/application/app/app_service.dart'; import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/setting_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:dartz/dartz.dart'; diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/app_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/app_bloc_test.dart index 69ef8eb1e4..878bf71d23 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/app_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/app_bloc_test.dart @@ -15,30 +15,30 @@ void main() { test('rename app test', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(const AppEvent.rename('Hello world')); await blocResponseFuture(); - assert(bloc.state.app.name == 'Hello world'); + expect(bloc.state.view.name, 'Hello world'); }); test('delete app test', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(const AppEvent.delete()); await blocResponseFuture(); final apps = await testContext.loadApps(); - assert(apps.where((element) => element.id == app.id).isEmpty); + expect(apps.where((element) => element.id == app.id).isEmpty, true); }); test('create documents in order', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("1", DocumentPluginBuilder())); @@ -55,7 +55,7 @@ void main() { test('reorder documents test', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("1", DocumentPluginBuilder())); @@ -66,7 +66,7 @@ void main() { await blocResponseFuture(); assert(bloc.state.views.length == 3); - final appViewData = AppViewDataContext(appId: app.id); + final appViewData = AppViewDataContext(viewId: app.id); appViewData.views = bloc.state.views; final viewSectionBloc = ViewSectionBloc( @@ -84,7 +84,7 @@ void main() { test('open latest view test', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); assert( bloc.state.latestCreatedView == null, @@ -108,7 +108,7 @@ void main() { test('open latest documents test', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("document 1", DocumentPluginBuilder())); @@ -135,7 +135,7 @@ void main() { test('open latest document test', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("document 1", DocumentPluginBuilder())); diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart index 978f168df6..f0862643ce 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart @@ -3,7 +3,7 @@ import 'package:appflowy/plugins/database_view/board/board.dart'; import 'package:appflowy/plugins/database_view/grid/grid.dart'; import 'package:appflowy/plugins/document/document.dart'; import 'package:appflowy/workspace/application/app/app_bloc.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../util.dart'; @@ -15,7 +15,7 @@ void main() { test('create a document', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("Test document", DocumentPluginBuilder())); @@ -28,7 +28,7 @@ void main() { test('create a grid', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("Test grid", GridPluginBuilder())); @@ -41,7 +41,7 @@ void main() { test('create a kanban', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("Test board", BoardPluginBuilder())); @@ -54,7 +54,7 @@ void main() { test('create a calendar', () async { final app = await testContext.createTestApp(); - final bloc = AppBloc(app: app)..add(const AppEvent.initial()); + final bloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); bloc.add(AppEvent.createView("Test calendar", CalendarPluginBuilder())); diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/home_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/home_bloc_test.dart index ef42b59fc0..3f79d9dc20 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/home_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/home_bloc_test.dart @@ -37,7 +37,7 @@ void main() { await blocResponseFuture(); final app = await testContext.createTestApp(); - final appBloc = AppBloc(app: app)..add(const AppEvent.initial()); + final appBloc = AppBloc(view: app)..add(const AppEvent.initial()); assert(appBloc.state.latestCreatedView == null); appBloc.add(AppEvent.createView("New document", DocumentPluginBuilder())); diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/menu_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/menu_bloc_test.dart index 252cbc9f4f..2f0e94f346 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/menu_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/menu_bloc_test.dart @@ -16,7 +16,7 @@ void main() { )..add(const MenuEvent.initial()); await blocResponseFuture(); - assert(menuBloc.state.apps.length == 1); + assert(menuBloc.state.views.length == 1); }); test('reorder apps', () async { @@ -35,8 +35,8 @@ void main() { menuBloc.add(const MenuEvent.moveApp(1, 3)); await blocResponseFuture(); - assert(menuBloc.state.apps[1].name == 'App 2'); - assert(menuBloc.state.apps[2].name == 'App 3'); - assert(menuBloc.state.apps[3].name == 'App 1'); + assert(menuBloc.state.views[1].name == 'App 2'); + assert(menuBloc.state.views[2].name == 'App 3'); + assert(menuBloc.state.views[3].name == 'App 1'); }); } diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/trash_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/trash_bloc_test.dart index da7d0159d3..03db7f34b0 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/trash_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/trash_bloc_test.dart @@ -1,14 +1,13 @@ import 'package:appflowy/plugins/document/document.dart'; import 'package:appflowy/plugins/trash/application/trash_bloc.dart'; import 'package:appflowy/workspace/application/app/app_bloc.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:flutter_test/flutter_test.dart'; import '../../util.dart'; class TrashTestContext { - late AppPB app; + late ViewPB view; late AppBloc appBloc; late List allViews; final AppFlowyUnitTest unitTest; @@ -16,8 +15,8 @@ class TrashTestContext { TrashTestContext(this.unitTest); Future initialize() async { - app = await unitTest.createTestApp(); - appBloc = AppBloc(app: app)..add(const AppEvent.initial()); + view = await unitTest.createTestApp(); + appBloc = AppBloc(view: view)..add(const AppEvent.initial()); await blocResponseFuture(); appBloc.add(AppEvent.createView( @@ -40,7 +39,7 @@ class TrashTestContext { ); await blocResponseFuture(); - allViews = [...appBloc.state.app.belongings.items]; + allViews = [...appBloc.state.view.belongings]; assert(allViews.length == 3, 'but receive ${allViews.length}'); } } @@ -65,17 +64,17 @@ void main() { await blocResponseFuture(millisecond: 200); // delete a view - final deletedView = context.appBloc.state.app.belongings.items[0]; + final deletedView = context.appBloc.state.view.belongings[0]; context.appBloc.add(AppEvent.deleteView(deletedView.id)); await blocResponseFuture(); - assert(context.appBloc.state.app.belongings.items.length == 2); + assert(context.appBloc.state.view.belongings.length == 2); assert(trashBloc.state.objects.length == 1); assert(trashBloc.state.objects.first.id == deletedView.id); // put back trashBloc.add(TrashEvent.putback(deletedView.id)); await blocResponseFuture(); - assert(context.appBloc.state.app.belongings.items.length == 3); + assert(context.appBloc.state.view.belongings.length == 3); assert(trashBloc.state.objects.isEmpty); // delete all views 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 cc4c5ec832..3009035607 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 @@ -13,7 +13,7 @@ void main() { test('rename view test', () async { final app = await testContext.createTestApp(); - final appBloc = AppBloc(app: app)..add(const AppEvent.initial()); + final appBloc = AppBloc(view: app)..add(const AppEvent.initial()); appBloc.add(AppEvent.createView( "Test document", DocumentPluginBuilder(), @@ -30,7 +30,7 @@ void main() { test('duplicate view test', () async { final app = await testContext.createTestApp(); - final appBloc = AppBloc(app: app)..add(const AppEvent.initial()); + final appBloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); appBloc.add(AppEvent.createView( @@ -51,7 +51,7 @@ void main() { test('delete view test', () async { final app = await testContext.createTestApp(); - final appBloc = AppBloc(app: app)..add(const AppEvent.initial()); + final appBloc = AppBloc(view: app)..add(const AppEvent.initial()); await blocResponseFuture(); appBloc.add(AppEvent.createView( diff --git a/frontend/appflowy_flutter/test/util.dart b/frontend/appflowy_flutter/test/util.dart index 93340ddb72..f31d90b84e 100644 --- a/frontend/appflowy_flutter/test/util.dart +++ b/frontend/appflowy_flutter/test/util.dart @@ -3,10 +3,10 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/auth_service.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy/workspace/application/workspace/workspace_service.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/uuid.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -81,7 +81,7 @@ class AppFlowyUnitTest { workspaceService = WorkspaceService(workspaceId: currentWorkspace.id); } - Future createTestApp() async { + Future createTestApp() async { final result = await workspaceService.createApp(name: "Test App"); return result.fold( (app) => app, @@ -89,7 +89,7 @@ class AppFlowyUnitTest { ); } - Future> loadApps() async { + Future> loadApps() async { final result = await workspaceService.getApps(); return result.fold( diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 406589203c..4d56fe6426 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "appflowy_tauri" @@ -123,7 +123,7 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -134,7 +134,7 @@ checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -274,7 +274,7 @@ dependencies = [ "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", "proc-macro2", - "syn", + "syn 1.0.109", ] [[package]] @@ -285,7 +285,7 @@ checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -296,7 +296,7 @@ checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -354,7 +354,7 @@ checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -460,9 +460,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", "js-sys", @@ -517,7 +517,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -561,6 +561,70 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "collab" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "anyhow", + "bytes", + "collab-persistence", + "lib0", + "parking_lot 0.12.1", + "serde", + "serde_json", + "thiserror", + "tracing", + "y-sync", + "yrs", +] + +[[package]] +name = "collab-derive" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "proc-macro2", + "quote", + "serde_json", + "syn 1.0.109", + "yrs", +] + +[[package]] +name = "collab-folder" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "anyhow", + "collab", + "collab-derive", + "collab-persistence", + "parking_lot 0.12.1", + "serde", + "serde_json", + "serde_repr", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "collab-persistence" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "bincode", + "chrono", + "lib0", + "serde", + "sled", + "smallvec", + "thiserror", + "tokio", + "yrs", +] + [[package]] name = "color_quant" version = "1.1.0" @@ -736,7 +800,7 @@ dependencies = [ "proc-macro2", "quote", "smallvec", - "syn", + "syn 1.0.109", ] [[package]] @@ -746,7 +810,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -756,7 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -789,7 +853,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.109", ] [[package]] @@ -806,7 +870,7 @@ checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -830,7 +894,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 1.0.109", ] [[package]] @@ -841,7 +905,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -854,7 +918,7 @@ dependencies = [ "hashbrown", "lock_api", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.6", ] [[package]] @@ -877,7 +941,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -890,7 +954,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn", + "syn 1.0.109", ] [[package]] @@ -918,7 +982,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1133,7 +1197,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1160,7 +1224,7 @@ dependencies = [ "folder-model", "lib-infra", "lib-ot", - "parking_lot", + "parking_lot 0.12.1", "revision-model", "serde", "serde_json", @@ -1178,7 +1242,7 @@ dependencies = [ "futures-util", "lib-infra", "lib-ws", - "parking_lot", + "parking_lot 0.12.1", "serde", "serde_repr", "thiserror", @@ -1204,7 +1268,7 @@ dependencies = [ "serde", "serde_json", "similar", - "syn", + "syn 1.0.109", "tera", "toml", "walkdir", @@ -1215,12 +1279,14 @@ name = "flowy-core" version = "0.1.0" dependencies = [ "bytes", + "collab-persistence", "database-model", "flowy-client-ws", "flowy-database", "flowy-document", "flowy-error", "flowy-folder", + "flowy-folder2", "flowy-net", "flowy-revision", "flowy-sqlite", @@ -1231,7 +1297,7 @@ dependencies = [ "lib-infra", "lib-log", "lib-ws", - "parking_lot", + "parking_lot 0.12.1", "revision-model", "serde", "serde_json", @@ -1271,7 +1337,7 @@ dependencies = [ "lib-infra", "lib-ot", "nanoid", - "parking_lot", + "parking_lot 0.12.1", "protobuf", "rayon", "regex", @@ -1299,7 +1365,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn", + "syn 1.0.109", "walkdir", ] @@ -1388,7 +1454,7 @@ dependencies = [ "lib-infra", "lib-ot", "log", - "parking_lot", + "parking_lot 0.12.1", "pin-project", "protobuf", "revision-model", @@ -1402,6 +1468,33 @@ dependencies = [ "ws-model", ] +[[package]] +name = "flowy-folder2" +version = "0.1.0" +dependencies = [ + "bytes", + "chrono", + "collab", + "collab-folder", + "collab-persistence", + "flowy-codegen", + "flowy-derive", + "flowy-document", + "flowy-error", + "flowy-notification", + "lazy_static", + "lib-dispatch", + "lib-infra", + "nanoid", + "parking_lot 0.12.1", + "protobuf", + "strum", + "strum_macros", + "tokio", + "tracing", + "unicode-segmentation", +] + [[package]] name = "flowy-net" version = "0.1.0" @@ -1419,7 +1512,7 @@ dependencies = [ "flowy-derive", "flowy-document", "flowy-error", - "flowy-folder", + "flowy-folder2", "flowy-server-sync", "flowy-sync", "flowy-user", @@ -1431,7 +1524,7 @@ dependencies = [ "lib-infra", "lib-ws", "nanoid", - "parking_lot", + "parking_lot 0.12.1", "protobuf", "reqwest", "revision-model", @@ -1536,7 +1629,7 @@ dependencies = [ "folder-model", "lib-infra", "lib-ot", - "parking_lot", + "parking_lot 0.12.1", "revision-model", "serde", "strum", @@ -1562,6 +1655,7 @@ name = "flowy-user" version = "0.1.0" dependencies = [ "bytes", + "collab-persistence", "diesel", "diesel_derives", "flowy-codegen", @@ -1574,7 +1668,7 @@ dependencies = [ "lib-infra", "log", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "protobuf", "serde", "serde_json", @@ -1625,6 +1719,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "futf" version = "0.1.5" @@ -1691,7 +1795,7 @@ checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1845,8 +1949,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1928,7 +2034,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2034,7 +2140,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2100,7 +2206,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2527,7 +2633,7 @@ dependencies = [ "futures-util", "lib-infra", "log", - "parking_lot", + "parking_lot 0.12.1", "pin-project", "protobuf", "serde", @@ -2540,6 +2646,17 @@ dependencies = [ "url", ] +[[package]] +name = "lib0" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf23122cb1c970b77ea6030eac5e328669415b65d2ab245c99bfb110f9d62dc" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "libc" version = "0.2.139" @@ -2716,7 +2833,7 @@ dependencies = [ "migrations_internals", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2892,7 +3009,7 @@ dependencies = [ "proc-macro-crate 1.2.1", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2977,7 +3094,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3040,6 +3157,17 @@ dependencies = [ "system-deps 6.0.3", ] +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -3047,7 +3175,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.6", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -3120,7 +3262,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3226,7 +3368,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3240,7 +3382,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3288,7 +3430,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3376,7 +3518,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -3399,9 +3541,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -3510,14 +3652,14 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -3529,7 +3671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" dependencies = [ "log", - "parking_lot", + "parking_lot 0.12.1", "scheduled-thread-pool", ] @@ -3784,7 +3926,7 @@ checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3891,7 +4033,7 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" dependencies = [ - "parking_lot", + "parking_lot 0.12.1", ] [[package]] @@ -3990,9 +4132,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.152" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" dependencies = [ "serde_derive", ] @@ -4010,20 +4152,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" dependencies = [ "itoa 1.0.5", "ryu", @@ -4038,7 +4180,7 @@ checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4072,7 +4214,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4094,7 +4236,7 @@ checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4170,6 +4312,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + [[package]] name = "slug" version = "0.1.4" @@ -4179,6 +4337,15 @@ dependencies = [ "deunicode", ] +[[package]] +name = "smallstr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f" +dependencies = [ + "smallvec", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -4252,7 +4419,7 @@ checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "phf_shared 0.10.0", "precomputed-hash", "serde", @@ -4291,7 +4458,7 @@ dependencies = [ "heck 0.3.3", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4305,6 +4472,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -4364,7 +4542,7 @@ dependencies = [ "ndk-sys", "objc", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "paste", "png", "raw-window-handle", @@ -4486,7 +4664,7 @@ dependencies = [ "heck 0.4.0", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "tauri-codegen", "tauri-utils", ] @@ -4633,22 +4811,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.13", ] [[package]] @@ -4736,7 +4914,7 @@ dependencies = [ "memchr", "mio", "num_cpus", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", @@ -4752,7 +4930,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4839,7 +5017,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -5220,7 +5398,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -5254,7 +5432,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5342,7 +5520,7 @@ checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -5432,7 +5610,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" dependencies = [ - "syn", + "syn 1.0.109", "windows-tokens", ] @@ -5662,6 +5840,17 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +[[package]] +name = "y-sync" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a143afe4dde83bc987ad3119228d0f107053a3da131a00738cb2d7f496641" +dependencies = [ + "lib0", + "thiserror", + "yrs", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -5670,3 +5859,17 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yrs" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2aef2bf89b4f7c003f9c73f1c8097427ca32e1d006443f3f607f11e79a797b" +dependencies = [ + "atomic_refcell", + "lib0", + "rand 0.7.3", + "smallstr", + "smallvec", + "thiserror", +] diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 04fccca1aa..b99aa67948 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -31,3 +31,10 @@ 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 = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } +collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } + + diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts index 21be5aa783..6cb486e35b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/auth.hooks.ts @@ -2,8 +2,8 @@ import { currentUserActions } from '../../stores/reducers/current-user/slice'; import { useAppDispatch, useAppSelector } from '../../stores/store'; import { UserProfilePB } from '../../../services/backend/events/flowy-user'; import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc'; -import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder'; -import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder/workspace'; +import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder2'; +import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace'; import { Log } from '../../utils/log'; export const useAuth = () => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts index 5c61a933ac..1d94beaf92 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts @@ -39,8 +39,8 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { void appObserver.subscribe({ onAppChanged: (change) => { if (change.ok) { - const app: AppPB = change.val; - const updatedPages: IPage[] = app.belongings.items.map((view) => ({ + const views = change.val; + const updatedPages: IPage[] = views.items.map((view) => ({ id: view.id, folderId: view.app_id, pageType: view.layout, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Workspace.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Workspace.hooks.ts index 5c1efcbc53..59d1231a7e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Workspace.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Workspace.hooks.ts @@ -6,11 +6,11 @@ import { UserBackendService } from '../../stores/effects/user/user_bd_svc'; import { useError } from '../error/Error.hooks'; export const useWorkspace = () => { - const appDispatch = useAppDispatch(); const currentUser = useAppSelector((state) => state.currentUser); - const error = useError(); - const userBackendService: UserBackendService = new UserBackendService(currentUser.id || ''); + const appDispatch = useAppDispatch(); + const error = useError(); + const userBackendService: UserBackendService = new UserBackendService(currentUser.id || 0); const loadWorkspaceItems = async () => { try { @@ -20,11 +20,11 @@ export const useWorkspace = () => { appDispatch(foldersActions.clearFolders()); appDispatch(pagesActions.clearPages()); - const apps = workspace.apps.items; + const apps = workspace.views; for (const app of apps) { appDispatch(foldersActions.addFolder({ id: app.id, title: app.name })); - const views = app.belongings.items; + const views = app.belongings; for (const view of views) { appDispatch(pagesActions.addPage({ folderId: app.id, id: view.id, pageType: view.layout, title: view.name })); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts index 7ab6cdd5ce..548ff6816b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts @@ -5,7 +5,7 @@ import { ViewPB, WorkspaceSettingPB, } from '../../../services/backend'; -import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder'; +import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder2'; import { AppBackendService } from '../../stores/effects/folder/app/app_bd_svc'; import { DatabaseController } from '../../stores/effects/database/database_controller'; import { RowInfo } from '../../stores/effects/database/row/row_cache'; @@ -31,7 +31,7 @@ import { SelectOptionBackendService } from '../../stores/effects/database/cell/s // Do not use it production code. Just for testing export async function createTestDatabaseView(layout: ViewLayoutTypePB): Promise { const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap()); - const app = workspaceSetting.workspace.apps.items[0]; + const app = workspaceSetting.workspace.views[0]; const appService = new AppBackendService(app.id); return await appService.createView({ name: 'New Grid', layoutType: layout }); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts index f05220df94..67ababa3b5 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts @@ -1,10 +1,10 @@ -import { ViewLayoutTypePB, WorkspaceSettingPB } from '../../../services/backend'; -import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder'; -import { AppBackendService } from '../../stores/effects/folder/app/app_bd_svc'; +import { ViewLayoutTypePB, WorkspaceSettingPB } from '@/services/backend'; +import { FolderEventReadCurrentWorkspace } from '@/services/backend/events/flowy-folder2'; +import { AppBackendService } from '$app/stores/effects/folder/app/app_bd_svc'; export async function createTestDocument() { const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap()); - const app = workspaceSetting.workspace.apps.items[0]; + const app = workspaceSetting.workspace.views[0]; const appService = new AppBackendService(app.id); return await appService.createView({ name: 'New Document', layoutType: ViewLayoutTypePB.Document }); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestApiButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestApiButton.tsx deleted file mode 100644 index 161e94d596..0000000000 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestApiButton.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { SignInPayloadPB } from '../../../services/backend/models/flowy-user/index'; -import { nanoid } from 'nanoid'; -import { UserNotificationListener } from '../user/application/notifications'; -import { - ColorStylePB, - CreateAppPayloadPB, - CreateWorkspacePayloadPB, - FolderEventCreateApp, - FolderEventCreateWorkspace, - FolderEventOpenWorkspace, - WorkspaceIdPB, -} from '../../../services/backend/events/flowy-folder'; -import { useEffect, useState } from 'react'; -import * as dependency_1 from '../../../services/backend/models/flowy-folder/app'; -import { UserEventGetUserSetting, UserEventSignIn } from '../../../services/backend/events/flowy-user'; - -const TestApiButton = () => { - const [workspaceId, setWorkspaceId] = useState(''); - const [appId, setAppId] = useState(''); - - useEffect(() => { - if (!workspaceId?.length) return; - void (async () => { - const openWorkspaceResult = await FolderEventOpenWorkspace( - WorkspaceIdPB.fromObject({ - value: workspaceId, - }) - ); - - if (openWorkspaceResult.ok) { - const pb = openWorkspaceResult.val; - console.log(pb.toObject()); - } else { - throw new Error('open workspace error'); - } - - const createAppResult = await FolderEventCreateApp( - CreateAppPayloadPB.fromObject({ - name: 'APP_1', - desc: 'Application One', - color_style: ColorStylePB.fromObject({ theme_color: 'light' }), - workspace_id: workspaceId, - }) - ); - if (createAppResult.ok) { - const pb = createAppResult.val; - const obj = pb.toObject(); - console.log(obj); - } else { - throw new Error('create app error'); - } - })(); - }, [workspaceId]); - - async function sendSignInEvent() { - const make_payload = () => - SignInPayloadPB.fromObject({ - email: nanoid(4) + '@gmail.com', - password: 'A!@123abc', - name: 'abc', - }); - - const listener = new UserNotificationListener({ - onUserSignIn: (userProfile) => { - console.log(userProfile); - }, - onProfileUpdate: (userProfile) => { - console.log(userProfile); - // stop listening the changes - void listener.stop(); - }, - }); - - await listener.start(); - - const signInResult = await UserEventSignIn(make_payload()); - if (signInResult.ok) { - const pb = signInResult.val; - console.log(pb.toObject()); - } else { - throw new Error('sign in error'); - } - - const getSettingsResult = await UserEventGetUserSetting(); - if (getSettingsResult.ok) { - const pb = getSettingsResult.val; - console.log(pb.toObject()); - } else { - throw new Error('get user settings error'); - } - - const createWorkspaceResult = await FolderEventCreateWorkspace( - CreateWorkspacePayloadPB.fromObject({ - name: 'WS_1', - desc: 'Workspace One', - }) - ); - - if (createWorkspaceResult.ok) { - const pb = createWorkspaceResult.val; - console.log(pb.toObject()); - const workspace: { - id?: string; - name?: string; - desc?: string; - apps?: ReturnType; - modified_time?: number; - create_time?: number; - } = pb.toObject(); - setWorkspaceId(workspace?.id || ''); - } else { - throw new Error('create workspace error'); - } - - /**/ - } - - return ( - <> -
- -
- - ); -}; - -export default TestApiButton; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts index bce7783ddc..8b41f96f1c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts @@ -23,7 +23,7 @@ import { CreateRowPayloadPB, ViewIdPB, } from '@/services/backend'; -import { FolderEventCloseView } from '@/services/backend/events/flowy-folder'; +import { FolderEventCloseView } from '@/services/backend/events/flowy-folder2'; /// A service that wraps the backend service export class DatabaseBackendService { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_bd_svc.ts index 095abcaa5b..c582b1f7d2 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/document/document_bd_svc.ts @@ -8,7 +8,7 @@ import { } from '@/services/backend'; import { DocumentEventApplyEdit, DocumentEventGetDocument } from '@/services/backend/events/flowy-document'; import { Result } from 'ts-results'; -import { FolderEventCloseView } from '@/services/backend/events/flowy-folder'; +import { FolderEventCloseView } from '@/services/backend/events/flowy-folder2'; export class DocumentBackendService { constructor(public readonly viewId: string) {} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts index 47c27c741d..53cd18680b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts @@ -1,21 +1,20 @@ import { FolderEventCreateView, - FolderEventDeleteApp, FolderEventDeleteView, FolderEventMoveItem, - FolderEventReadApp, - FolderEventUpdateApp, + FolderEventReadView, + FolderEventUpdateView, ViewLayoutTypePB, -} from '@/services/backend/events/flowy-folder'; +} from '@/services/backend/events/flowy-folder2'; import { - AppIdPB, - UpdateAppPayloadPB, CreateViewPayloadPB, RepeatedViewIdPB, ViewPB, MoveFolderItemPayloadPB, MoveFolderItemType, FlowyError, + ViewIdPB, + UpdateViewPayloadPB, } from '@/services/backend'; import { None, Result, Some } from 'ts-results'; @@ -23,8 +22,8 @@ export class AppBackendService { constructor(public readonly appId: string) {} getApp = () => { - const payload = AppIdPB.fromObject({ value: this.appId }); - return FolderEventReadApp(payload); + const payload = ViewIdPB.fromObject({ value: this.appId }); + return FolderEventReadView(payload); }; createView = async (params: { @@ -54,9 +53,9 @@ export class AppBackendService { }; getAllViews = (): Promise> => { - const payload = AppIdPB.fromObject({ value: this.appId }); - return FolderEventReadApp(payload).then((result) => { - return result.map((app) => app.belongings.items); + const payload = ViewIdPB.fromObject({ value: this.appId }); + return FolderEventReadView(payload).then((result) => { + return result.map((app) => app.belongings); }); }; @@ -75,16 +74,16 @@ export class AppBackendService { }; update = async (params: { name: string }) => { - const payload = UpdateAppPayloadPB.fromObject({ app_id: this.appId, name: params.name }); - const result = await FolderEventUpdateApp(payload); + const payload = UpdateViewPayloadPB.fromObject({ view_id: this.appId, name: params.name }); + const result = await FolderEventUpdateView(payload); if (!result.ok) { throw new Error(result.val.msg); } }; delete = async () => { - const payload = AppIdPB.fromObject({ value: this.appId }); - const result = await FolderEventDeleteApp(payload); + const payload = RepeatedViewIdPB.fromObject({ items: [this.appId] }); + const result = await FolderEventDeleteView(payload); if (!result.ok) { throw new Error(result.val.msg); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts index 6440cb37c0..d46ffdef6f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts @@ -1,12 +1,12 @@ import { Ok, Result } from 'ts-results'; -import { AppPB, FlowyError, FolderNotification } from '@/services/backend'; +import { AppPB, FlowyError, FolderNotification, RepeatedViewPB } from '@/services/backend'; import { ChangeNotifier } from '$app/utils/change_notifier'; import { FolderNotificationObserver } from '../notifications/observer'; -export type AppUpdateNotifyCallback = (value: Result) => void; +export type AppUpdateNotifyCallback = (value: Result) => void; export class AppObserver { - _appNotifier = new ChangeNotifier>(); + _appNotifier = new ChangeNotifier>(); _listener?: FolderNotificationObserver; constructor(public readonly appId: string) {} @@ -17,9 +17,9 @@ export class AppObserver { viewId: this.appId, parserHandler: (notification, result) => { switch (notification) { - case FolderNotification.DidUpdateWorkspaceApps: + case FolderNotification.DidUpdateWorkspaceViews: if (result.ok) { - this._appNotifier?.notify(Ok(AppPB.deserializeBinary(result.val))); + this._appNotifier?.notify(Ok(RepeatedViewPB.deserializeBinary(result.val))); } else { this._appNotifier?.notify(result); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_bd_svc.ts index f3fbd99829..ec98fb08ce 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_bd_svc.ts @@ -3,7 +3,7 @@ import { FolderEventDeleteView, FolderEventDuplicateView, FolderEventUpdateView, -} from '@/services/backend/events/flowy-folder'; +} from '@/services/backend/events/flowy-folder2'; export class ViewBackendService { constructor(public readonly viewId: string) {} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts index fec8269cc6..8dcfce6930 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts @@ -1,24 +1,31 @@ import { Err, Ok } from 'ts-results'; import { - FolderEventCreateApp, + FolderEventCreateView, FolderEventMoveItem, FolderEventReadWorkspaceApps, FolderEventReadWorkspaces, -} from '@/services/backend/events/flowy-folder'; -import { CreateAppPayloadPB, WorkspaceIdPB, FlowyError, MoveFolderItemPayloadPB } from '@/services/backend'; +} from '@/services/backend/events/flowy-folder2'; +import { + CreateViewPayloadPB, + FlowyError, + MoveFolderItemPayloadPB, + ViewLayoutTypePB, + WorkspaceIdPB, +} from '@/services/backend'; import assert from 'assert'; export class WorkspaceBackendService { constructor(public readonly workspaceId: string) {} createApp = async (params: { name: string; desc?: string }) => { - const payload = CreateAppPayloadPB.fromObject({ - workspace_id: this.workspaceId, + const payload = CreateViewPayloadPB.fromObject({ + belong_to_id: this.workspaceId, name: params.name, desc: params.desc || '', + layout: ViewLayoutTypePB.Document, }); - const result = await FolderEventCreateApp(payload); + const result = await FolderEventCreateView(payload); if (result.ok) { return result.val; } else { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts index 0b9efdab5a..e668fa06a1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts @@ -1,9 +1,17 @@ import { Ok, Result } from 'ts-results'; -import { AppPB, FolderNotification, RepeatedAppPB, WorkspacePB, FlowyError } from '@/services/backend'; +import { + AppPB, + FolderNotification, + RepeatedAppPB, + WorkspacePB, + FlowyError, + RepeatedViewPB, + ViewPB, +} from '@/services/backend'; import { ChangeNotifier } from '$app/utils/change_notifier'; import { FolderNotificationObserver } from '../notifications/observer'; -export type AppListNotifyValue = Result; +export type AppListNotifyValue = Result; export type AppListNotifyCallback = (value: AppListNotifyValue) => void; export type WorkspaceNotifyValue = Result; export type WorkspaceNotifyCallback = (value: WorkspaceNotifyValue) => void; @@ -33,9 +41,9 @@ export class WorkspaceObserver { this.workspaceNotifier?.notify(result); } break; - case FolderNotification.DidUpdateWorkspaceApps: + case FolderNotification.DidUpdateWorkspaceViews: if (result.ok) { - this.appListNotifier?.notify(Ok(RepeatedAppPB.deserializeBinary(result.val).items)); + this.appListNotifier?.notify(Ok(RepeatedViewPB.deserializeBinary(result.val).items)); } else { this.appListNotifier?.notify(result); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts index 2e80f34e54..7c9e50d3fc 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/user/user_bd_svc.ts @@ -21,10 +21,10 @@ import { FolderEventOpenWorkspace, FolderEventReadCurrentWorkspace, FolderEventReadWorkspaces, -} from '@/services/backend/events/flowy-folder'; +} from '@/services/backend/events/flowy-folder2'; export class UserBackendService { - constructor(public readonly userId: string) {} + constructor(public readonly userId: number) {} getUserProfile = () => { return UserEventGetUserProfile(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts index 4b5fbcb5ea..be68ddf6c9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts @@ -1,9 +1,9 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { nanoid } from 'nanoid'; -import { WorkspaceSettingPB } from '@/services/backend/models/flowy-folder/workspace'; +import { WorkspaceSettingPB } from '@/services/backend/models/flowy-folder2/workspace'; export interface ICurrentUser { - id?: string; + id?: number; displayName?: string; email?: string; token?: string; diff --git a/frontend/appflowy_tauri/src/services/backend/index.ts b/frontend/appflowy_tauri/src/services/backend/index.ts index d9b08aff40..af708e6c22 100644 --- a/frontend/appflowy_tauri/src/services/backend/index.ts +++ b/frontend/appflowy_tauri/src/services/backend/index.ts @@ -1,6 +1,6 @@ export * from "./models/flowy-user"; export * from "./models/flowy-document"; export * from "./models/flowy-database"; -export * from "./models/flowy-folder"; +export * from "./models/flowy-folder2"; export * from "./models/flowy-net"; export * from "./models/flowy-error"; diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 2052c1707c..3127146c89 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "arrayvec" @@ -102,7 +102,7 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -113,7 +113,7 @@ checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -298,7 +298,7 @@ dependencies = [ "borsh-schema-derive-internal", "proc-macro-crate", "proc-macro2", - "syn", + "syn 1.0.109", ] [[package]] @@ -309,7 +309,7 @@ checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -320,7 +320,7 @@ checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -369,7 +369,7 @@ checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -407,9 +407,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ "iana-time-zone", "js-sys", @@ -475,7 +475,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -488,6 +488,70 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "collab" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "anyhow", + "bytes", + "collab-persistence", + "lib0", + "parking_lot 0.12.1", + "serde", + "serde_json", + "thiserror", + "tracing", + "y-sync", + "yrs", +] + +[[package]] +name = "collab-derive" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "proc-macro2", + "quote", + "serde_json", + "syn 1.0.109", + "yrs", +] + +[[package]] +name = "collab-folder" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "anyhow", + "collab", + "collab-derive", + "collab-persistence", + "parking_lot 0.12.1", + "serde", + "serde_json", + "serde_repr", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "collab-persistence" +version = "0.1.0" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +dependencies = [ + "bincode", + "chrono", + "lib0", + "serde", + "sled", + "smallvec", + "thiserror", + "tokio", + "yrs", +] + [[package]] name = "color-eyre" version = "0.5.11" @@ -739,7 +803,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn", + "syn 1.0.109", ] [[package]] @@ -756,7 +820,7 @@ checksum = "39e61fda7e62115119469c7b3591fd913ecca96fb766cfd3f2e2502ab7bc87a5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -813,7 +877,7 @@ checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -826,7 +890,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 1.0.109", ] [[package]] @@ -854,7 +918,7 @@ checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1022,7 +1086,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1093,7 +1157,7 @@ dependencies = [ "serde", "serde_json", "similar", - "syn", + "syn 1.0.109", "tera", "toml", "walkdir", @@ -1104,6 +1168,7 @@ name = "flowy-core" version = "0.1.0" dependencies = [ "bytes", + "collab-persistence", "console-subscriber", "database-model", "flowy-client-ws", @@ -1111,6 +1176,7 @@ dependencies = [ "flowy-document", "flowy-error", "flowy-folder", + "flowy-folder2", "flowy-net", "flowy-revision", "flowy-sqlite", @@ -1192,7 +1258,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn", + "syn 1.0.109", "tokio", "trybuild", "walkdir", @@ -1307,6 +1373,35 @@ dependencies = [ "ws-model", ] +[[package]] +name = "flowy-folder2" +version = "0.1.0" +dependencies = [ + "bytes", + "chrono", + "collab", + "collab-folder", + "collab-persistence", + "flowy-codegen", + "flowy-derive", + "flowy-document", + "flowy-error", + "flowy-folder2", + "flowy-notification", + "flowy-test", + "lazy_static", + "lib-dispatch", + "lib-infra", + "nanoid", + "parking_lot 0.12.1", + "protobuf", + "strum", + "strum_macros", + "tokio", + "tracing", + "unicode-segmentation", +] + [[package]] name = "flowy-net" version = "0.1.0" @@ -1324,7 +1419,7 @@ dependencies = [ "flowy-derive", "flowy-document", "flowy-error", - "flowy-folder", + "flowy-folder2", "flowy-server-sync", "flowy-sync", "flowy-user", @@ -1478,7 +1573,7 @@ dependencies = [ "flowy-client-sync", "flowy-core", "flowy-document", - "flowy-folder", + "flowy-folder2", "flowy-net", "flowy-user", "futures", @@ -1503,6 +1598,7 @@ name = "flowy-user" version = "0.1.0" dependencies = [ "bytes", + "collab-persistence", "diesel", "diesel_derives", "flowy-codegen", @@ -1568,6 +1664,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "futures" version = "0.3.26" @@ -1624,7 +1730,7 @@ checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1657,6 +1763,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -1684,8 +1799,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -2166,6 +2283,17 @@ dependencies = [ "url", ] +[[package]] +name = "lib0" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3994538ae0215990b1c3df6dc45bb5afad77abce3a6ba3335512c5f5d9bfb1d4" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "libc" version = "0.2.139" @@ -2285,7 +2413,7 @@ dependencies = [ "migrations_internals", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2448,7 +2576,7 @@ checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2589,7 +2717,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2664,7 +2792,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2703,7 +2831,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2776,7 +2904,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -2799,9 +2927,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" dependencies = [ "unicode-ident", ] @@ -2826,7 +2954,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2942,7 +3070,7 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -2964,14 +3092,14 @@ checksum = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -3218,7 +3346,7 @@ checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3362,9 +3490,9 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.152" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" dependencies = [ "serde_derive", ] @@ -3392,20 +3520,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.8", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa 1.0.5", "ryu", @@ -3420,7 +3548,7 @@ checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3454,7 +3582,7 @@ checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3520,6 +3648,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + [[package]] name = "slug" version = "0.1.4" @@ -3529,6 +3673,15 @@ dependencies = [ "deunicode", ] +[[package]] +name = "smallstr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e922794d168678729ffc7e07182721a14219c65814e66e91b839a272fe5ae4f" +dependencies = [ + "smallvec", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -3566,7 +3719,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3580,6 +3733,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -3652,22 +3816,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.8", ] [[package]] @@ -3765,7 +3929,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -3940,7 +4104,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -4306,7 +4470,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -4340,7 +4504,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4504,6 +4668,17 @@ dependencies = [ "serde_repr", ] +[[package]] +name = "y-sync" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a143afe4dde83bc987ad3119228d0f107053a3da131a00738cb2d7f496641" +dependencies = [ + "lib0", + "thiserror", + "yrs", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -4512,3 +4687,17 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yrs" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2b23ac465bed6c0ffbb9fbd80ec808bd89b37b823a420b16917d1806d76d75" +dependencies = [ + "atomic_refcell", + "lib0", + "rand 0.7.3", + "smallstr", + "smallvec", + "thiserror", +] diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index 83a5e25bc0..a941760c75 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -8,7 +8,8 @@ members = [ "flowy-user", "flowy-test", "flowy-sqlite", - "flowy-folder", +# "flowy-folder", + "flowy-folder2", "flowy-notification", "flowy-document", "flowy-error", @@ -34,4 +35,10 @@ opt-level = 3 #strip = "debuginfo" ## For from-scratch builds, incremental adds an extra dependency-tracking overhead. It also significantly increases ## the amount of IO and the size of ./target, which make caching less effective. -incremental = false \ No newline at end of file +incremental = false + + +[patch.crates-io] +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } +collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 591f459963..608b145b2a 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -11,6 +11,7 @@ lib-log = { path = "../lib-log" } flowy-user = { path = "../flowy-user" } flowy-net = { path = "../flowy-net" } flowy-folder = { path = "../flowy-folder" } +flowy-folder2 = { path = "../flowy-folder2" } flowy-database = { path = "../flowy-database" } database-model = { path = "../../../shared-lib/database-model" } user-model = { path = "../../../shared-lib/user-model" } @@ -20,6 +21,7 @@ flowy-document = { path = "../flowy-document" } flowy-revision = { path = "../flowy-revision" } flowy-error = { path = "../flowy-error", features = ["adaptor_ws"] } flowy-task = { path = "../flowy-task" } +collab-persistence = { version = "0.1.0" } tracing = { version = "0.1", features = ["log"] } futures-core = { version = "0.3", default-features = false } @@ -45,6 +47,7 @@ dart = [ "flowy-user/dart", "flowy-net/dart", "flowy-folder/dart", + "flowy-folder2/dart", "flowy-database/dart", "flowy-document/dart", ] @@ -52,6 +55,7 @@ ts = [ "flowy-user/ts", "flowy-net/ts", "flowy-folder/ts", + "flowy-folder2/ts", "flowy-database/ts", "flowy-document/ts", ] diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/document_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/document_deps.rs index b08b99769e..90b0d34ff7 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/document_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/document_deps.rs @@ -61,7 +61,7 @@ impl DocumentUser for BlockUserImpl { Ok(doc_dir) } - fn user_id(&self) -> Result { + fn user_id(&self) -> Result { self.0.user_id() } diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs new file mode 100644 index 0000000000..e8d61e932a --- /dev/null +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs @@ -0,0 +1,258 @@ +use bytes::Bytes; +use collab_persistence::CollabKV; +use database_model::BuildDatabaseContext; +use flowy_database::entities::LayoutTypePB; +use flowy_database::manager::{create_new_database, link_existing_database, DatabaseManager}; +use flowy_database::util::{make_default_board, make_default_calendar, make_default_grid}; +use flowy_document::editor::make_transaction_from_document_content; +use flowy_document::DocumentManager; +use flowy_error::FlowyError; + +use flowy_folder2::manager::{Folder2Manager, FolderUser}; +use flowy_folder2::view_ext::{ViewDataProcessor, ViewDataProcessorMap}; +use flowy_folder2::ViewLayout; +use flowy_user::services::UserSession; +use lib_infra::future::FutureResult; +use revision_model::Revision; +use std::collections::HashMap; +use std::convert::TryFrom; +use std::sync::Arc; + +pub struct Folder2DepsResolver(); +impl Folder2DepsResolver { + pub async fn resolve( + user_session: Arc, + document_manager: &Arc, + database_manager: &Arc, + ) -> Arc { + let user: Arc = Arc::new(FolderUserImpl(user_session.clone())); + + let view_data_processor = + make_view_data_processor(document_manager.clone(), database_manager.clone()); + Arc::new( + Folder2Manager::new(user.clone(), view_data_processor) + .await + .unwrap(), + ) + } +} + +fn make_view_data_processor( + document_manager: Arc, + database_manager: Arc, +) -> ViewDataProcessorMap { + let mut map: HashMap> = HashMap::new(); + + let document_processor = Arc::new(DocumentViewDataProcessor(document_manager)); + map.insert(ViewLayout::Document, document_processor); + + let database_processor = Arc::new(DatabaseViewDataProcessor(database_manager)); + map.insert(ViewLayout::Board, database_processor.clone()); + map.insert(ViewLayout::Grid, database_processor.clone()); + map.insert(ViewLayout::Calendar, database_processor); + Arc::new(map) +} + +struct FolderUserImpl(Arc); +impl FolderUser for FolderUserImpl { + fn user_id(&self) -> Result { + self + .0 + .user_id() + .map_err(|e| FlowyError::internal().context(e)) + } + + fn token(&self) -> Result { + self + .0 + .token() + .map_err(|e| FlowyError::internal().context(e)) + } + + fn kv_db(&self) -> Result, FlowyError> { + self.0.get_kv_db() + } +} + +struct DocumentViewDataProcessor(Arc); +impl ViewDataProcessor for DocumentViewDataProcessor { + 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_document_editor(view_id).await?; + Ok(()) + }) + } + + fn get_view_data(&self, view_id: &str) -> FutureResult { + let manager = self.0.clone(); + let view_id = view_id.to_string(); + FutureResult::new(async move { + let editor = manager.open_document_editor(view_id).await?; + let document_data = Bytes::from(editor.duplicate().await?); + Ok(document_data) + }) + } + + fn create_view_with_build_in_data( + &self, + _user_id: i64, + view_id: &str, + _name: &str, + layout: ViewLayout, + _ext: HashMap, + ) -> FutureResult<(), FlowyError> { + debug_assert_eq!(layout, ViewLayout::Document); + let view_id = view_id.to_string(); + let manager = self.0.clone(); + let document_content = self.0.initial_document_content(); + FutureResult::new(async move { + let delta_data = Bytes::from(document_content); + let revision = Revision::initial_revision(&view_id, delta_data); + manager.create_document(view_id, vec![revision]).await?; + Ok(()) + }) + } + + fn create_view_with_custom_data( + &self, + _user_id: i64, + view_id: &str, + _name: &str, + data: Vec, + layout: ViewLayout, + _ext: HashMap, + ) -> FutureResult<(), FlowyError> { + debug_assert_eq!(layout, ViewLayout::Document); + let view_data = match String::from_utf8(data) { + Ok(content) => match make_transaction_from_document_content(&content) { + Ok(transaction) => transaction.to_bytes().unwrap_or_else(|_| vec![]), + Err(_) => vec![], + }, + Err(_) => vec![], + }; + + let revision = Revision::initial_revision(view_id, Bytes::from(view_data)); + let view_id = view_id.to_string(); + let manager = self.0.clone(); + + FutureResult::new(async move { + manager.create_document(view_id, vec![revision]).await?; + Ok(()) + }) + } +} + +struct DatabaseViewDataProcessor(Arc); +impl ViewDataProcessor for DatabaseViewDataProcessor { + fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError> { + let database_manager = self.0.clone(); + let view_id = view_id.to_string(); + FutureResult::new(async move { + database_manager.close_database_view(view_id).await?; + Ok(()) + }) + } + + fn get_view_data(&self, view_id: &str) -> FutureResult { + let database_manager = self.0.clone(); + let view_id = view_id.to_owned(); + FutureResult::new(async move { + let editor = database_manager.open_database_view(&view_id).await?; + let delta_bytes = editor.duplicate_database(&view_id).await?; + Ok(delta_bytes.into()) + }) + } + + /// Create a database view with build-in data. + /// If the ext contains the {"database_id": "xx"}, then it will link to + /// the existing database. The data of the database will be shared within + /// these references views. + fn create_view_with_build_in_data( + &self, + _user_id: i64, + view_id: &str, + name: &str, + layout: ViewLayout, + ext: HashMap, + ) -> FutureResult<(), FlowyError> { + let view_id = view_id.to_string(); + let name = name.to_string(); + let database_manager = self.0.clone(); + match DatabaseExtParams::from_map(ext).map(|params| params.database_id) { + None => { + let (build_context, layout) = match layout { + ViewLayout::Grid => (make_default_grid(), LayoutTypePB::Grid), + ViewLayout::Board => (make_default_board(), LayoutTypePB::Board), + ViewLayout::Calendar => (make_default_calendar(), LayoutTypePB::Calendar), + ViewLayout::Document => { + return FutureResult::new(async move { + Err(FlowyError::internal().context(format!("Can't handle {:?} layout type", layout))) + }); + }, + }; + FutureResult::new(async move { + create_new_database(&view_id, name, layout, database_manager, build_context).await + }) + }, + Some(database_id) => { + let layout = layout_type_from_view_layout(layout); + FutureResult::new(async move { + link_existing_database(&view_id, name, &database_id, layout, database_manager).await + }) + }, + } + } + + /// Create a database view with custom data. + /// If the ext contains the {"database_id": "xx"}, then it will link + /// to the existing database. The data of the database will be shared + /// within these references views. + fn create_view_with_custom_data( + &self, + _user_id: i64, + view_id: &str, + name: &str, + data: Vec, + layout: ViewLayout, + ext: HashMap, + ) -> FutureResult<(), FlowyError> { + let view_id = view_id.to_string(); + let database_manager = self.0.clone(); + let layout = layout_type_from_view_layout(layout); + let name = name.to_string(); + match DatabaseExtParams::from_map(ext).map(|params| params.database_id) { + None => FutureResult::new(async move { + let bytes = Bytes::from(data); + let build_context = BuildDatabaseContext::try_from(bytes)?; + let _ = create_new_database(&view_id, name, layout, database_manager, build_context).await; + Ok(()) + }), + Some(database_id) => FutureResult::new(async move { + link_existing_database(&view_id, name, &database_id, layout, database_manager).await + }), + } + } +} + +#[derive(Debug, serde::Deserialize)] +struct DatabaseExtParams { + database_id: String, +} + +impl DatabaseExtParams { + pub fn from_map(map: HashMap) -> Option { + let value = serde_json::to_value(map).ok()?; + serde_json::from_value::(value).ok() + } +} + +pub fn layout_type_from_view_layout(layout: ViewLayout) -> LayoutTypePB { + match layout { + ViewLayout::Grid => LayoutTypePB::Grid, + ViewLayout::Board => LayoutTypePB::Board, + ViewLayout::Calendar => LayoutTypePB::Calendar, + ViewLayout::Document => LayoutTypePB::Grid, + } +} diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/grid_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/grid_deps.rs index 63fdf4bcad..77f07ebde3 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/grid_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/grid_deps.rs @@ -46,7 +46,7 @@ impl DatabaseDBConnection for DatabaseDBConnectionImpl { struct GridUserImpl(Arc); impl DatabaseUser for GridUserImpl { - fn user_id(&self) -> Result { + fn user_id(&self) -> Result { self.0.user_id() } 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 6a270e4376..9620e97ff3 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/mod.rs @@ -1,10 +1,10 @@ mod document_deps; -mod folder_deps; +mod folder2_deps; mod grid_deps; mod user_deps; mod util; pub use document_deps::*; -pub use folder_deps::*; +pub use folder2_deps::*; pub use grid_deps::*; pub use user_deps::*; diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index c37efabad7..f614315b33 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -1,13 +1,15 @@ mod deps_resolve; pub mod module; use crate::deps_resolve::*; + use flowy_client_ws::{listen_on_websocket, FlowyWebSocketConnect, NetworkType}; +use flowy_database::entities::LayoutTypePB; use flowy_database::manager::DatabaseManager; use flowy_document::entities::DocumentVersionPB; use flowy_document::{DocumentConfig, DocumentManager}; use flowy_error::FlowyResult; -use flowy_folder::entities::{ViewDataFormatPB, ViewLayoutTypePB}; -use flowy_folder::{errors::FlowyError, manager::FolderManager}; +use flowy_folder::errors::FlowyError; +use flowy_folder2::manager::Folder2Manager; pub use flowy_net::get_client_server_configuration; use flowy_net::local_server::LocalServer; use flowy_net::ClientServerConfiguration; @@ -16,8 +18,6 @@ use flowy_user::event_map::UserStatusCallback; use flowy_user::services::{UserSession, UserSessionConfig}; use lib_dispatch::prelude::*; use lib_dispatch::runtime::tokio_default_runtime; - -use flowy_database::entities::LayoutTypePB; use lib_infra::future::{to_fut, Fut}; use module::make_plugins; pub use module::*; @@ -89,6 +89,8 @@ fn create_log_filter(level: String, with_crates: Vec) -> String { .collect::>(); filters.push(format!("flowy_core={}", level)); filters.push(format!("flowy_folder={}", level)); + filters.push(format!("flowy_folder2={}", level)); + filters.push(format!("collab_folder={}", level)); filters.push(format!("flowy_user={}", level)); filters.push(format!("flowy_document={}", level)); filters.push(format!("flowy_database={}", level)); @@ -106,7 +108,7 @@ fn create_log_filter(level: String, with_crates: Vec) -> String { filters.push(format!("dart_ffi={}", "info")); filters.push(format!("flowy_sqlite={}", "info")); - filters.push(format!("flowy_net={}", "info")); + filters.push(format!("flowy_net={}", level)); #[cfg(feature = "profiling")] filters.push(format!("tokio={}", level)); @@ -122,7 +124,7 @@ pub struct AppFlowyCore { pub config: AppFlowyCoreConfig, pub user_session: Arc, pub document_manager: Arc, - pub folder_manager: Arc, + pub folder_manager: Arc, pub database_manager: Arc, pub event_dispatcher: Arc, pub ws_conn: Arc, @@ -162,15 +164,9 @@ impl AppFlowyCore { ) .await; - let folder_manager = FolderDepsResolver::resolve( - local_server.clone(), - user_session.clone(), - &config.server_config, - &ws_conn, - &document_manager, - &database_manager, - ) - .await; + let folder_manager = + Folder2DepsResolver::resolve(user_session.clone(), &document_manager, &database_manager) + .await; if let Some(local_server) = local_server.as_ref() { local_server.run(); @@ -232,11 +228,11 @@ impl AppFlowyCore { fn _start_listening( event_dispatcher: &AFPluginDispatcher, ws_conn: &Arc, - folder_manager: &Arc, + folder_manager: &Arc, ) { let subscribe_network_type = ws_conn.subscribe_network_ty(); let folder_manager = folder_manager.clone(); - let cloned_folder_manager = folder_manager; + let _cloned_folder_manager = folder_manager; let ws_conn = ws_conn.clone(); event_dispatcher.spawn(async move { @@ -244,7 +240,7 @@ fn _start_listening( }); event_dispatcher.spawn(async move { - _listen_network_status(subscribe_network_type, cloned_folder_manager).await; + _listen_network_status(subscribe_network_type).await; }); } @@ -263,10 +259,7 @@ fn mk_local_server( } } -async fn _listen_network_status( - mut subscribe: broadcast::Receiver, - _core: Arc, -) { +async fn _listen_network_status(mut subscribe: broadcast::Receiver) { while let Ok(_new_type) = subscribe.recv().await { // core.network_state_changed(new_type); } @@ -301,41 +294,33 @@ fn mk_user_session( struct UserStatusListener { document_manager: Arc, - folder_manager: Arc, + folder_manager: Arc, database_manager: Arc, ws_conn: Arc, + #[allow(dead_code)] config: AppFlowyCoreConfig, } impl UserStatusListener { - async fn did_sign_in(&self, token: &str, user_id: &str) -> FlowyResult<()> { - self.folder_manager.initialize(user_id, token).await?; + async fn did_sign_in(&self, token: &str, user_id: i64) -> FlowyResult<()> { + self.folder_manager.initialize(user_id).await?; self.document_manager.initialize(user_id).await?; - let cloned_folder_manager = self.folder_manager.clone(); let get_views_fn = to_fut(async move { cloned_folder_manager - .get_current_workspace() + .get_current_workspace_views() .await - .map(|workspace| { - workspace - .apps - .items - .into_iter() - .flat_map(|app| app.belongings.items) - .flat_map(|view| match view.layout { - ViewLayoutTypePB::Grid | ViewLayoutTypePB::Board | ViewLayoutTypePB::Calendar => { - Some(( - view.id, - view.name, - layout_type_from_view_layout(view.layout), - )) - }, - _ => None, - }) - .collect::>() - }) .unwrap_or_default() + .into_iter() + .filter(|view| view.layout.is_database()) + .map(|view| { + ( + view.id, + view.name, + layout_type_from_view_layout(view.layout), + ) + }) + .collect::>() }); self .database_manager @@ -349,32 +334,28 @@ impl UserStatusListener { } async fn did_sign_up(&self, user_profile: &UserProfile) -> FlowyResult<()> { - let view_data_type = match self.config.document.version { - DocumentVersionPB::V0 => ViewDataFormatPB::DeltaFormat, - DocumentVersionPB::V1 => ViewDataFormatPB::NodeFormat, - }; self .folder_manager - .initialize_with_new_user(&user_profile.id, &user_profile.token, view_data_type) + .initialize_with_new_user(user_profile.id, &user_profile.token) .await?; self .document_manager - .initialize_with_new_user(&user_profile.id, &user_profile.token) + .initialize_with_new_user(user_profile.id, &user_profile.token) .await?; self .database_manager - .initialize_with_new_user(&user_profile.id, &user_profile.token) + .initialize_with_new_user(user_profile.id, &user_profile.token) .await?; self .ws_conn - .start(user_profile.token.clone(), user_profile.id.clone()) + .start(user_profile.token.clone(), user_profile.id) .await?; Ok(()) } - async fn did_expired(&self, _token: &str, user_id: &str) -> FlowyResult<()> { + async fn did_expired(&self, _token: &str, user_id: i64) -> FlowyResult<()> { self.folder_manager.clear(user_id).await; self.ws_conn.stop().await; Ok(()) @@ -386,11 +367,11 @@ struct UserStatusCallbackImpl { } impl UserStatusCallback for UserStatusCallbackImpl { - fn did_sign_in(&self, token: &str, user_id: &str) -> Fut> { + fn did_sign_in(&self, token: &str, user_id: i64) -> Fut> { let listener = self.listener.clone(); let token = token.to_owned(); let user_id = user_id.to_owned(); - to_fut(async move { listener.did_sign_in(&token, &user_id).await }) + to_fut(async move { listener.did_sign_in(&token, user_id).await }) } fn did_sign_up(&self, user_profile: &UserProfile) -> Fut> { @@ -399,10 +380,15 @@ impl UserStatusCallback for UserStatusCallbackImpl { to_fut(async move { listener.did_sign_up(&user_profile).await }) } - fn did_expired(&self, token: &str, user_id: &str) -> Fut> { + fn did_expired(&self, token: &str, user_id: i64) -> Fut> { let listener = self.listener.clone(); let token = token.to_owned(); let user_id = user_id.to_owned(); - to_fut(async move { listener.did_expired(&token, &user_id).await }) + to_fut(async move { listener.did_expired(&token, user_id).await }) + } + + fn will_migrated(&self, _token: &str, _old_user_id: &str, _user_id: i64) -> Fut> { + // Read the folder data + todo!() } } diff --git a/frontend/rust-lib/flowy-core/src/module.rs b/frontend/rust-lib/flowy-core/src/module.rs index d9a3d117bc..41cad63a3c 100644 --- a/frontend/rust-lib/flowy-core/src/module.rs +++ b/frontend/rust-lib/flowy-core/src/module.rs @@ -1,20 +1,21 @@ use flowy_client_ws::FlowyWebSocketConnect; use flowy_database::manager::DatabaseManager; use flowy_document::DocumentManager; -use flowy_folder::manager::FolderManager; + +use flowy_folder2::manager::Folder2Manager; use flowy_user::services::UserSession; use lib_dispatch::prelude::AFPlugin; use std::sync::Arc; pub fn make_plugins( ws_conn: &Arc, - folder_manager: &Arc, + folder_manager: &Arc, grid_manager: &Arc, user_session: &Arc, document_manager: &Arc, ) -> Vec { let user_plugin = flowy_user::event_map::init(user_session.clone()); - let folder_plugin = flowy_folder::event_map::init(folder_manager.clone()); + let folder_plugin = flowy_folder2::event_map::init(folder_manager.clone()); let network_plugin = flowy_net::event_map::init(ws_conn.clone()); let grid_plugin = flowy_database::event_map::init(grid_manager.clone()); let document_plugin = flowy_document::event_map::init(document_manager.clone()); diff --git a/frontend/rust-lib/flowy-database/src/manager.rs b/frontend/rust-lib/flowy-database/src/manager.rs index f4b30de956..860f748fbb 100644 --- a/frontend/rust-lib/flowy-database/src/manager.rs +++ b/frontend/rust-lib/flowy-database/src/manager.rs @@ -35,7 +35,7 @@ use std::sync::Arc; use tokio::sync::RwLock; pub trait DatabaseUser: Send + Sync { - fn user_id(&self) -> Result; + fn user_id(&self) -> Result; fn token(&self) -> Result; fn db_pool(&self) -> Result, FlowyError>; } @@ -75,13 +75,13 @@ impl DatabaseManager { } } - pub async fn initialize_with_new_user(&self, _user_id: &str, _token: &str) -> FlowyResult<()> { + pub async fn initialize_with_new_user(&self, _user_id: i64, _token: &str) -> FlowyResult<()> { Ok(()) } pub async fn initialize( &self, - user_id: &str, + user_id: i64, _token: &str, get_views_fn: Fut>, ) -> FlowyResult<()> { @@ -114,9 +114,8 @@ impl DatabaseManager { revisions: Vec, ) -> FlowyResult<()> { let view_id = view_id.as_ref(); - let user_id = self.database_user.user_id()?; let pool = self.database_user.db_pool()?; - let rev_manager = make_database_view_rev_manager(&user_id, pool, view_id).await?; + let rev_manager = make_database_view_rev_manager(pool, view_id).await?; rev_manager.reset_object(revisions).await?; Ok(()) } @@ -210,10 +209,8 @@ impl DatabaseManager { ) -> FlowyResult> { let user = self.database_user.clone(); let create_view_editor = |database_editor: Arc| async move { - let user_id = user.user_id()?; let (view_pad, view_rev_manager) = make_database_view_revision_pad(view_id, user).await?; DatabaseViewEditor::from_pad( - &user_id, database_editor.database_view_data.clone(), database_editor.cell_data_cache.clone(), view_rev_manager, @@ -275,7 +272,6 @@ impl DatabaseManager { .initialize::(Some(cloud)) .await?, )); - let user_id = user.user_id()?; let database_editor = DatabaseEditor::new( &database_id, user, @@ -288,7 +284,6 @@ impl DatabaseManager { .await?; let base_view_editor = DatabaseViewEditor::from_pad( - &user_id, database_editor.database_view_data.clone(), database_editor.cell_data_cache.clone(), base_view_rev_manager, @@ -306,13 +301,10 @@ impl DatabaseManager { database_id: &str, pool: Arc, ) -> FlowyResult>> { - let user_id = self.database_user.user_id()?; - // Create revision persistence - let disk_cache = SQLiteDatabaseRevisionPersistence::new(&user_id, pool.clone()); + let disk_cache = SQLiteDatabaseRevisionPersistence::new(pool.clone()); let configuration = RevisionPersistenceConfiguration::new(6, false); - let rev_persistence = - RevisionPersistence::new(&user_id, database_id, disk_cache, configuration); + let rev_persistence = RevisionPersistence::new(database_id, disk_cache, configuration); // Create snapshot persistence const DATABASE_SP_PREFIX: &str = "grid"; @@ -322,7 +314,6 @@ impl DatabaseManager { let rev_compress = DatabaseRevisionMergeable(); let rev_manager = RevisionManager::new( - &user_id, database_id, rev_persistence, rev_compress, diff --git a/frontend/rust-lib/flowy-database/src/services/database/block_editor.rs b/frontend/rust-lib/flowy-database/src/services/database/block_editor.rs index ffcadf1e2f..2df275a135 100644 --- a/frontend/rust-lib/flowy-database/src/services/database/block_editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database/block_editor.rs @@ -20,8 +20,6 @@ use std::sync::Arc; use tokio::sync::RwLock; pub struct DatabaseBlockEditor { - #[allow(dead_code)] - user_id: String, pub block_id: String, pad: Arc>, rev_manager: Arc>>, @@ -29,7 +27,6 @@ pub struct DatabaseBlockEditor { impl DatabaseBlockEditor { pub async fn new( - user_id: &str, token: &str, block_id: &str, mut rev_manager: RevisionManager>, @@ -42,10 +39,8 @@ impl DatabaseBlockEditor { .await?; let pad = Arc::new(RwLock::new(block_revision_pad)); let rev_manager = Arc::new(rev_manager); - let user_id = user_id.to_owned(); let block_id = block_id.to_owned(); Ok(Self { - user_id, block_id, pad, rev_manager, diff --git a/frontend/rust-lib/flowy-database/src/services/database/block_manager.rs b/frontend/rust-lib/flowy-database/src/services/database/block_manager.rs index 9d91ff7fd9..d98979c5ef 100644 --- a/frontend/rust-lib/flowy-database/src/services/database/block_manager.rs +++ b/frontend/rust-lib/flowy-database/src/services/database/block_manager.rs @@ -322,22 +322,19 @@ async fn make_database_block_editor( ) -> FlowyResult { tracing::trace!("Open block:{} editor", block_id); let token = user.token()?; - let user_id = user.user_id()?; let rev_manager = make_database_block_rev_manager(user, block_id)?; - DatabaseBlockEditor::new(&user_id, &token, block_id, rev_manager).await + DatabaseBlockEditor::new(&token, block_id, rev_manager).await } pub fn make_database_block_rev_manager( user: &Arc, block_id: &str, ) -> FlowyResult>> { - let user_id = user.user_id()?; - // Create revision persistence let pool = user.db_pool()?; - let disk_cache = SQLiteDatabaseBlockRevisionPersistence::new(&user_id, pool.clone()); + let disk_cache = SQLiteDatabaseBlockRevisionPersistence::new(pool.clone()); let configuration = RevisionPersistenceConfiguration::new(4, false); - let rev_persistence = RevisionPersistence::new(&user_id, block_id, disk_cache, configuration); + let rev_persistence = RevisionPersistence::new(block_id, disk_cache, configuration); // Create snapshot persistence const DATABASE_BLOCK_SP_PREFIX: &str = "grid_block"; @@ -347,7 +344,6 @@ pub fn make_database_block_rev_manager( let rev_compress = DatabaseBlockRevisionMergeable(); let rev_manager = RevisionManager::new( - &user_id, block_id, rev_persistence, rev_compress, diff --git a/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs index b0ca679bdd..8d5775d239 100644 --- a/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs @@ -888,11 +888,14 @@ impl DatabaseEditor { Ok(()) } - pub async fn duplicate_database(&self, _view_id: &str) -> FlowyResult { + pub async fn duplicate_database>( + &self, + _view_id: T, + ) -> FlowyResult { let database_pad = self.database_pad.read().await; // let database_view_data = self // .database_views - // .duplicate_database_view_setting(view_id) + // .duplicate_database_view(view_id.as_ref()) // .await?; let original_blocks = database_pad.get_block_meta_revs(); let (duplicated_fields, duplicated_blocks) = database_pad.duplicate_database_block_meta().await; diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs index 1d5449bd27..f2ed34e31e 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs @@ -76,7 +76,6 @@ pub trait DatabaseViewData: Send + Sync + 'static { } pub struct DatabaseViewEditor { - user_id: String, pub view_id: String, pad: Arc>, rev_manager: Arc>>, @@ -95,7 +94,6 @@ impl Drop for DatabaseViewEditor { impl DatabaseViewEditor { pub async fn from_pad( - user_id: &str, delegate: Arc, cell_data_cache: AtomicCellDataCache, rev_manager: RevisionManager>, @@ -108,7 +106,6 @@ impl DatabaseViewEditor { let view_rev_pad = Arc::new(RwLock::new(view_rev_pad)); let rev_manager = Arc::new(rev_manager); let group_controller = new_group_controller( - user_id.to_owned(), view_id.clone(), view_rev_pad.clone(), rev_manager.clone(), @@ -116,7 +113,6 @@ impl DatabaseViewEditor { ) .await?; - let user_id = user_id.to_owned(); let group_controller = Arc::new(RwLock::new(group_controller)); let filter_controller = make_filter_controller( &view_id, @@ -138,7 +134,6 @@ impl DatabaseViewEditor { .await; Ok(Self { pad: view_rev_pad, - user_id, view_id, rev_manager, delegate, @@ -151,7 +146,6 @@ impl DatabaseViewEditor { #[tracing::instrument(level = "trace", skip_all, err)] pub async fn new( - user_id: &str, token: &str, view_id: String, delegate: Arc, @@ -176,14 +170,7 @@ impl DatabaseViewEditor { }, }; - Self::from_pad( - user_id, - delegate, - cell_data_cache, - rev_manager, - view_rev_pad, - ) - .await + Self::from_pad(delegate, cell_data_cache, rev_manager, view_rev_pad).await } #[tracing::instrument(name = "close database view editor", level = "trace", skip_all)] @@ -795,7 +782,6 @@ impl DatabaseViewEditor { view_editor_delegate: self.delegate.clone(), }; let new_group_controller = new_group_controller_with_field_rev( - self.user_id.clone(), self.view_id.clone(), self.pad.clone(), self.rev_manager.clone(), @@ -973,7 +959,7 @@ impl DatabaseViewEditor { match f(&mut write_guard)? { None => {}, Some(change) => { - apply_change(&self.user_id, self.rev_manager.clone(), change).await?; + apply_change(self.rev_manager.clone(), change).await?; }, } Ok(()) @@ -1066,7 +1052,6 @@ pub(crate) async fn get_cells_for_field_in_rows( } async fn new_group_controller( - user_id: String, view_id: String, view_rev_pad: Arc>, rev_manager: Arc>>, @@ -1092,7 +1077,6 @@ async fn new_group_controller( .unwrap_or_else(|| find_grouping_field(&field_revs, &layout).unwrap()); new_group_controller_with_field_rev( - user_id, view_id, view_rev_pad, rev_manager, @@ -1106,7 +1090,6 @@ async fn new_group_controller( /// Returns a [GroupController] /// async fn new_group_controller_with_field_rev( - user_id: String, view_id: String, view_rev_pad: Arc>, rev_manager: Arc>>, @@ -1115,7 +1098,6 @@ async fn new_group_controller_with_field_rev( configuration_reader: GroupConfigurationReaderImpl, ) -> FlowyResult> { let configuration_writer = GroupConfigurationWriterImpl { - user_id, rev_manager, view_pad: view_rev_pad, }; diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs index 993b5835e3..9307e4d954 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs @@ -313,15 +313,12 @@ impl DatabaseViews { } async fn make_view_editor(&self, view_id: &str) -> FlowyResult { - let user_id = self.user.user_id()?; let pool = self.user.db_pool()?; - let rev_manager = make_database_view_rev_manager(&user_id, pool, view_id).await?; - let user_id = self.user.user_id()?; + let rev_manager = make_database_view_rev_manager(pool, view_id).await?; let token = self.user.token()?; let view_id = view_id.to_owned(); DatabaseViewEditor::new( - &user_id, &token, view_id, self.delegate.clone(), @@ -340,9 +337,8 @@ pub async fn make_database_view_revision_pad( DatabaseViewRevisionPad, RevisionManager>, )> { - let user_id = user.user_id()?; let pool = user.db_pool()?; - let mut rev_manager = make_database_view_rev_manager(&user_id, pool, view_id).await?; + let mut rev_manager = make_database_view_rev_manager(pool, view_id).await?; let view_rev_pad = rev_manager .initialize::(None) .await?; @@ -350,14 +346,13 @@ pub async fn make_database_view_revision_pad( } pub async fn make_database_view_rev_manager( - user_id: &str, pool: Arc, view_id: &str, ) -> FlowyResult>> { // Create revision persistence - let disk_cache = SQLiteDatabaseViewRevisionPersistence::new(user_id, pool.clone()); + let disk_cache = SQLiteDatabaseViewRevisionPersistence::new(pool.clone()); let configuration = RevisionPersistenceConfiguration::new(2, false); - let rev_persistence = RevisionPersistence::new(user_id, view_id, disk_cache, configuration); + let rev_persistence = RevisionPersistence::new(view_id, disk_cache, configuration); // Create snapshot persistence const DATABASE_VIEW_SP_PREFIX: &str = "grid_view"; @@ -367,7 +362,6 @@ pub async fn make_database_view_rev_manager( let rev_compress = DatabaseViewRevisionMergeable(); Ok(RevisionManager::new( - user_id, view_id, rev_persistence, rev_compress, diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/trait_impl.rs b/frontend/rust-lib/flowy-database/src/services/database_view/trait_impl.rs index 4efcfc4c8a..e9372646a7 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/trait_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/trait_impl.rs @@ -97,7 +97,6 @@ impl GroupConfigurationReader for GroupConfigurationReaderImpl { } pub(crate) struct GroupConfigurationWriterImpl { - pub(crate) user_id: String, pub(crate) rev_manager: Arc>>, pub(crate) view_pad: Arc>, } @@ -109,7 +108,6 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { field_type: FieldTypeRevision, group_configuration: GroupConfigurationRevision, ) -> Fut> { - let user_id = self.user_id.clone(); let rev_manager = self.rev_manager.clone(); let view_pad = self.view_pad.clone(); let field_id = field_id.to_owned(); @@ -121,7 +119,7 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { .insert_or_update_group_configuration(&field_id, &field_type, group_configuration)?; if let Some(changeset) = changeset { - apply_change(&user_id, rev_manager, changeset).await?; + apply_change(rev_manager, changeset).await?; } Ok(()) }) @@ -129,7 +127,6 @@ impl GroupConfigurationWriter for GroupConfigurationWriterImpl { } pub(crate) async fn apply_change( - _user_id: &str, rev_manager: Arc>>, change: DatabaseViewRevisionChangeset, ) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_migration.rs b/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_migration.rs index 2c351e7327..754d397bcb 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_migration.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_migration.rs @@ -17,13 +17,13 @@ use revision_model::Revision; use std::sync::Arc; const V1_MIGRATION: &str = "DATABASE_V1_MIGRATION"; -pub fn is_database_rev_migrated(user_id: &str) -> bool { - let key = migration_flag_key(&user_id, V1_MIGRATION); +pub fn is_database_rev_migrated(user_id: i64) -> bool { + let key = migration_flag_key(user_id, V1_MIGRATION); KV::get_bool(&key) } pub(crate) async fn migration_database_rev_struct( - user_id: &str, + user_id: i64, databases: &Vec, pool: Arc, ) -> FlowyResult<()> { @@ -35,16 +35,16 @@ pub(crate) async fn migration_database_rev_struct( let object = DatabaseRevisionResettable { database_id: database.view_id.clone(), }; - let disk_cache = SQLiteDatabaseRevisionPersistence::new(&user_id, pool.clone()); - let reset = RevisionStructReset::new(&user_id, object, Arc::new(disk_cache)); + let disk_cache = SQLiteDatabaseRevisionPersistence::new(pool.clone()); + let reset = RevisionStructReset::new(object, Arc::new(disk_cache)); reset.run().await?; } - let key = migration_flag_key(&user_id, V1_MIGRATION); + let key = migration_flag_key(user_id, V1_MIGRATION); KV::set_bool(&key, true); Ok(()) } -fn migration_flag_key(user_id: &str, version: &str) -> String { +fn migration_flag_key(user_id: i64, version: &str) -> String { md5(format!("{}{}", user_id, version,)) } diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_view_migration.rs b/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_view_migration.rs index 5479a34649..2964db9392 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_view_migration.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/migration/database_view_migration.rs @@ -22,13 +22,13 @@ use std::sync::Arc; const DATABASE_VIEW_MIGRATE: &str = "database_view_migrate"; -pub fn is_database_view_migrated(user_id: &str) -> bool { +pub fn is_database_view_migrated(user_id: i64) -> bool { let key = md5(format!("{}{}", user_id, DATABASE_VIEW_MIGRATE)); KV::get_bool(&key) } pub(crate) async fn migrate_database_view( - user_id: &str, + user_id: i64, database_refs: Arc, migrated_databases: &Vec, pool: Arc, @@ -77,8 +77,7 @@ pub(crate) async fn migrate_database_view( let database_view_ops = make_database_view_operations(&database_view_rev); let database_view_bytes = database_view_ops.json_bytes(); let revision = Revision::initial_revision(&database_view_id, database_view_bytes); - let rev_manager = - make_database_view_rev_manager(user_id, pool.clone(), &database_view_id).await?; + let rev_manager = make_database_view_rev_manager(pool.clone(), &database_view_id).await?; rev_manager.reset_object(vec![revision]).await?; } @@ -87,8 +86,8 @@ pub(crate) async fn migrate_database_view( let object = DatabaseViewRevisionResettable { database_view_id: database.view_id.clone(), }; - let disk_cache = SQLiteDatabaseViewRevisionPersistence::new(user_id, pool.clone()); - let reset = RevisionStructReset::new(user_id, object, Arc::new(disk_cache)); + let disk_cache = SQLiteDatabaseViewRevisionPersistence::new(pool.clone()); + let reset = RevisionStructReset::new(object, Arc::new(disk_cache)); reset.run().await?; } diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs b/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs index 7be1d5f27b..b0719c928c 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs @@ -30,7 +30,7 @@ impl DatabaseMigration { pub async fn run( &self, - user_id: &str, + user_id: i64, get_views_fn: Fut>, ) -> FlowyResult<()> { let pool = self.user.db_pool()?; diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs index fadaec2ff9..12b11d459f 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs @@ -13,7 +13,6 @@ use revision_model::{Revision, RevisionRange}; use std::sync::Arc; pub struct SQLiteDatabaseBlockRevisionPersistence { - user_id: String, pub(crate) pool: Arc, } @@ -36,7 +35,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = DatabaseBlockMetaRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DatabaseBlockMetaRevisionSql::read(object_id, rev_ids, &conn)?; Ok(records) } @@ -46,8 +45,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi range: &RevisionRange, ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - let revisions = - DatabaseBlockMetaRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + let revisions = DatabaseBlockMetaRevisionSql::read_with_range(object_id, range.clone(), conn)?; Ok(revisions) } @@ -88,11 +86,8 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi } impl SQLiteDatabaseBlockRevisionPersistence { - pub fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } + pub fn new(pool: Arc) -> Self { + Self { pool } } } @@ -143,7 +138,6 @@ impl DatabaseBlockMetaRevisionSql { } fn read( - user_id: &str, object_id: &str, rev_ids: Option>, conn: &SqliteConnection, @@ -159,14 +153,13 @@ impl DatabaseBlockMetaRevisionSql { .load::(conn)?; let records = rows .into_iter() - .map(|row| mk_revision_record_from_table(user_id, row)) + .map(mk_revision_record_from_table) .collect::>(); Ok(records) } fn read_with_range( - user_id: &str, object_id: &str, range: RevisionRange, conn: &SqliteConnection, @@ -180,7 +173,7 @@ impl DatabaseBlockMetaRevisionSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_record_from_table(user_id, table)) + .map(mk_revision_record_from_table) .collect::>(); Ok(revisions) } @@ -239,7 +232,7 @@ impl std::default::Default for GridBlockRevisionState { } } -fn mk_revision_record_from_table(_user_id: &str, table: GridBlockRevisionTable) -> SyncRecord { +fn mk_revision_record_from_table(table: GridBlockRevisionTable) -> SyncRecord { let md5 = md5(&table.data); let revision = Revision::new( &table.object_id, diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs index 7a84e02f32..e555327396 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs @@ -13,7 +13,6 @@ use revision_model::{Revision, RevisionRange}; use std::sync::Arc; pub struct SQLiteDatabaseRevisionPersistence { - user_id: String, pub(crate) pool: Arc, } @@ -36,7 +35,7 @@ impl RevisionDiskCache> for SQLiteDatabaseRevisionPersistenc rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = DatabaseRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DatabaseRevisionSql::read(object_id, rev_ids, &conn)?; Ok(records) } @@ -46,8 +45,7 @@ impl RevisionDiskCache> for SQLiteDatabaseRevisionPersistenc range: &RevisionRange, ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - let revisions = - DatabaseRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + let revisions = DatabaseRevisionSql::read_with_range(object_id, range.clone(), conn)?; Ok(revisions) } @@ -88,11 +86,8 @@ impl RevisionDiskCache> for SQLiteDatabaseRevisionPersistenc } impl SQLiteDatabaseRevisionPersistence { - pub fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } + pub fn new(pool: Arc) -> Self { + Self { pool } } } @@ -142,7 +137,6 @@ impl DatabaseRevisionSql { } fn read( - user_id: &str, object_id: &str, rev_ids: Option>, conn: &SqliteConnection, @@ -158,14 +152,13 @@ impl DatabaseRevisionSql { .load::(conn)?; let records = rows .into_iter() - .map(|row| mk_revision_record_from_table(user_id, row)) + .map(mk_revision_record_from_table) .collect::>(); Ok(records) } fn read_with_range( - user_id: &str, object_id: &str, range: RevisionRange, conn: &SqliteConnection, @@ -179,7 +172,7 @@ impl DatabaseRevisionSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_record_from_table(user_id, table)) + .map(mk_revision_record_from_table) .collect::>(); Ok(revisions) } @@ -239,7 +232,7 @@ impl std::default::Default for DatabaseRevisionState { } } -fn mk_revision_record_from_table(_user_id: &str, table: DatabaseRevisionTable) -> SyncRecord { +fn mk_revision_record_from_table(table: DatabaseRevisionTable) -> SyncRecord { let md5 = md5(&table.data); let revision = Revision::new( &table.object_id, diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs index d6f4340f7e..6e19d1cbd4 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs @@ -13,16 +13,12 @@ use revision_model::{Revision, RevisionRange}; use std::sync::Arc; pub struct SQLiteDatabaseViewRevisionPersistence { - user_id: String, pub(crate) pool: Arc, } impl SQLiteDatabaseViewRevisionPersistence { - pub fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } + pub fn new(pool: Arc) -> Self { + Self { pool } } } @@ -45,7 +41,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = DatabaseViewRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DatabaseViewRevisionSql::read(object_id, rev_ids, &conn)?; Ok(records) } @@ -55,8 +51,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis range: &RevisionRange, ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - let revisions = - DatabaseViewRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + let revisions = DatabaseViewRevisionSql::read_with_range(object_id, range.clone(), conn)?; Ok(revisions) } @@ -142,7 +137,6 @@ impl DatabaseViewRevisionSql { } fn read( - user_id: &str, object_id: &str, rev_ids: Option>, conn: &SqliteConnection, @@ -158,14 +152,13 @@ impl DatabaseViewRevisionSql { .load::(conn)?; let records = rows .into_iter() - .map(|row| mk_revision_record_from_table(user_id, row)) + .map(mk_revision_record_from_table) .collect::>(); Ok(records) } fn read_with_range( - user_id: &str, object_id: &str, range: RevisionRange, conn: &SqliteConnection, @@ -179,7 +172,7 @@ impl DatabaseViewRevisionSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_record_from_table(user_id, table)) + .map(mk_revision_record_from_table) .collect::>(); Ok(revisions) } @@ -239,7 +232,7 @@ impl std::default::Default for DatabaseViewRevisionState { } } -fn mk_revision_record_from_table(_user_id: &str, table: DatabaseViewRevisionTable) -> SyncRecord { +fn mk_revision_record_from_table(table: DatabaseViewRevisionTable) -> SyncRecord { let md5 = md5(&table.data); let revision = Revision::new( &table.object_id, diff --git a/frontend/rust-lib/flowy-database/tests/database/database_editor.rs b/frontend/rust-lib/flowy-database/tests/database/database_editor.rs index f3d0635531..ff0ebf925e 100644 --- a/frontend/rust-lib/flowy-database/tests/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database/tests/database/database_editor.rs @@ -60,16 +60,16 @@ impl DatabaseEditorTest { let editor = sdk .database_manager - .open_database_view(&test.view.id) + .open_database_view(&test.child_view.id) .await .unwrap(); let field_revs = editor.get_field_revs(None).await.unwrap(); let block_meta_revs = editor.get_block_meta_revs().await.unwrap(); - let row_pbs = editor.get_all_row_revs(&test.view.id).await.unwrap(); + let row_pbs = editor.get_all_row_revs(&test.child_view.id).await.unwrap(); assert_eq!(block_meta_revs.len(), 1); - let view_id = test.view.id; - let app_id = test.app.id; + let view_id = test.child_view.id; + let app_id = test.parent_view.id; Self { sdk, app_id, diff --git a/frontend/rust-lib/flowy-document/src/manager.rs b/frontend/rust-lib/flowy-document/src/manager.rs index d63b7173df..060819f120 100644 --- a/frontend/rust-lib/flowy-document/src/manager.rs +++ b/frontend/rust-lib/flowy-document/src/manager.rs @@ -31,7 +31,7 @@ use ws_model::ws_revision::ServerRevisionWSData; pub trait DocumentUser: Send + Sync { fn user_dir(&self) -> Result; - fn user_id(&self) -> Result; + fn user_id(&self) -> Result; fn token(&self) -> Result; } @@ -113,13 +113,13 @@ impl DocumentManager { /// Called immediately after the application launched with the user sign in/sign up. #[tracing::instrument(level = "trace", skip_all, err)] - pub async fn initialize(&self, user_id: &str) -> FlowyResult<()> { + pub async fn initialize(&self, user_id: i64) -> FlowyResult<()> { self.persistence.initialize(user_id)?; listen_ws_state_changed(self.rev_web_socket.clone(), self.editor_map.clone()); Ok(()) } - pub async fn initialize_with_new_user(&self, _user_id: &str, _token: &str) -> FlowyResult<()> { + pub async fn initialize_with_new_user(&self, _user_id: i64, _token: &str) -> FlowyResult<()> { Ok(()) } @@ -283,13 +283,11 @@ impl DocumentManager { doc_id: &str, pool: Arc, ) -> Result>, FlowyError> { - let user_id = self.user.user_id()?; - let disk_cache = SQLiteDocumentRevisionPersistence::new(&user_id, pool.clone()); + let disk_cache = SQLiteDocumentRevisionPersistence::new(pool.clone()); let configuration = RevisionPersistenceConfiguration::new(200, true); - let rev_persistence = RevisionPersistence::new(&user_id, doc_id, disk_cache, configuration); + let rev_persistence = RevisionPersistence::new(doc_id, disk_cache, configuration); let snapshot_persistence = SQLiteDocumentRevisionSnapshotPersistence::new(doc_id, pool); Ok(RevisionManager::new( - &user_id, doc_id, rev_persistence, DocumentRevisionMergeable(), @@ -302,12 +300,10 @@ impl DocumentManager { doc_id: &str, pool: Arc, ) -> Result>, FlowyError> { - let user_id = self.user.user_id()?; - let disk_cache = SQLiteDeltaDocumentRevisionPersistence::new(&user_id, pool); + let disk_cache = SQLiteDeltaDocumentRevisionPersistence::new(pool); let configuration = RevisionPersistenceConfiguration::new(100, true); - let rev_persistence = RevisionPersistence::new(&user_id, doc_id, disk_cache, configuration); + let rev_persistence = RevisionPersistence::new(doc_id, disk_cache, configuration); Ok(RevisionManager::new( - &user_id, doc_id, rev_persistence, DeltaDocumentRevisionMergeable(), diff --git a/frontend/rust-lib/flowy-document/src/old_editor/editor.rs b/frontend/rust-lib/flowy-document/src/old_editor/editor.rs index 998d7f4bd3..59082cbca3 100644 --- a/frontend/rust-lib/flowy-document/src/old_editor/editor.rs +++ b/frontend/rust-lib/flowy-document/src/old_editor/editor.rs @@ -57,7 +57,6 @@ impl DeltaDocumentEditor { #[cfg(feature = "sync")] let ws_manager = crate::old_editor::web_socket::make_document_ws_manager( doc_id.clone(), - user_id.clone(), edit_cmd_tx.clone(), rev_manager.clone(), rev_web_socket, diff --git a/frontend/rust-lib/flowy-document/src/old_editor/web_socket.rs b/frontend/rust-lib/flowy-document/src/old_editor/web_socket.rs index c3a682ebc9..bd1c3fa7c6 100644 --- a/frontend/rust-lib/flowy-document/src/old_editor/web_socket.rs +++ b/frontend/rust-lib/flowy-document/src/old_editor/web_socket.rs @@ -45,19 +45,14 @@ pub type DocumentConflictController = #[allow(dead_code)] pub(crate) async fn make_document_ws_manager( doc_id: String, - user_id: String, edit_cmd_tx: EditorCommandSender, rev_manager: Arc>>, rev_web_socket: Arc, ) -> Arc { let ws_data_provider = Arc::new(WSDataProvider::new(&doc_id, Arc::new(rev_manager.clone()))); let resolver = Arc::new(DocumentConflictResolver { edit_cmd_tx }); - let conflict_controller = DocumentConflictController::new( - &user_id, - resolver, - Arc::new(ws_data_provider.clone()), - rev_manager, - ); + let conflict_controller = + DocumentConflictController::new(resolver, Arc::new(ws_data_provider.clone()), rev_manager); let ws_data_stream = Arc::new(DocumentRevisionWSDataStream::new(conflict_controller)); let ws_data_sink = Arc::new(DocumentWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(TEXT_BLOCK_SYNC_INTERVAL_IN_MILLIS); @@ -69,16 +64,12 @@ pub(crate) async fn make_document_ws_manager( ws_data_stream, ping_duration, )); - listen_document_ws_state(&user_id, &doc_id, ws_manager.scribe_state()); + listen_document_ws_state(&doc_id, ws_manager.scribe_state()); ws_manager } #[allow(dead_code)] -fn listen_document_ws_state( - _user_id: &str, - _doc_id: &str, - mut subscriber: broadcast::Receiver, -) { +fn listen_document_ws_state(_doc_id: &str, mut subscriber: broadcast::Receiver) { tokio::spawn(async move { while let Ok(state) = subscriber.recv().await { match state { diff --git a/frontend/rust-lib/flowy-document/src/services/migration.rs b/frontend/rust-lib/flowy-document/src/services/migration.rs index 2ea9bea1dc..abc49fea82 100644 --- a/frontend/rust-lib/flowy-document/src/services/migration.rs +++ b/frontend/rust-lib/flowy-document/src/services/migration.rs @@ -12,26 +12,26 @@ use std::sync::Arc; const V1_MIGRATION: &str = "DOCUMENT_V1_MIGRATION"; pub(crate) struct DocumentMigration { - user_id: String, + user_id: i64, database: Arc, } impl DocumentMigration { - pub fn new(user_id: &str, database: Arc) -> Self { + pub fn new(user_id: i64, database: Arc) -> Self { let user_id = user_id.to_owned(); Self { user_id, database } } pub fn run_v1_migration(&self) -> FlowyResult<()> { - let key = migration_flag_key(&self.user_id, V1_MIGRATION); + let key = migration_flag_key(self.user_id, V1_MIGRATION); if KV::get_bool(&key) { return Ok(()); } let pool = self.database.db_pool()?; let conn = &*pool.get()?; - let disk_cache = SQLiteDocumentRevisionPersistence::new(&self.user_id, pool); - let documents = DeltaRevisionSql::read_all_documents(&self.user_id, conn)?; + let disk_cache = SQLiteDocumentRevisionPersistence::new(pool); + let documents = DeltaRevisionSql::read_all_documents(conn)?; tracing::debug!("[Migration]: try migrate {} documents", documents.len()); for revisions in documents { if revisions.is_empty() { @@ -71,6 +71,6 @@ impl DocumentMigration { Ok(()) } } -fn migration_flag_key(user_id: &str, version: &str) -> String { +fn migration_flag_key(user_id: i64, version: &str) -> String { md5(format!("{}{}", user_id, version,)) } diff --git a/frontend/rust-lib/flowy-document/src/services/persistence/mod.rs b/frontend/rust-lib/flowy-document/src/services/persistence/mod.rs index a48b838193..e985c47480 100644 --- a/frontend/rust-lib/flowy-document/src/services/persistence/mod.rs +++ b/frontend/rust-lib/flowy-document/src/services/persistence/mod.rs @@ -16,7 +16,7 @@ impl DocumentPersistence { } #[tracing::instrument(level = "trace", skip_all, err)] - pub fn initialize(&self, user_id: &str) -> FlowyResult<()> { + pub fn initialize(&self, user_id: i64) -> FlowyResult<()> { let migration = DocumentMigration::new(user_id, self.database.clone()); if let Err(e) = migration.run_v1_migration() { tracing::error!("[Document Migration]: run v1 migration failed: {:?}", e); diff --git a/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v0.rs b/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v0.rs index ded4fbd160..ab59cf10c0 100644 --- a/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v0.rs +++ b/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v0.rs @@ -14,7 +14,6 @@ use std::collections::HashMap; use std::sync::Arc; pub struct SQLiteDeltaDocumentRevisionPersistence { - user_id: String, pub(crate) pool: Arc, } @@ -37,7 +36,7 @@ impl RevisionDiskCache> for SQLiteDeltaDocumentRevisionPersi rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = DeltaRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DeltaRevisionSql::read(object_id, rev_ids, &conn)?; Ok(records) } @@ -47,8 +46,7 @@ impl RevisionDiskCache> for SQLiteDeltaDocumentRevisionPersi range: &RevisionRange, ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - let revisions = - DeltaRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + let revisions = DeltaRevisionSql::read_with_range(object_id, range.clone(), conn)?; Ok(revisions) } @@ -89,11 +87,8 @@ impl RevisionDiskCache> for SQLiteDeltaDocumentRevisionPersi } impl SQLiteDeltaDocumentRevisionPersistence { - pub fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } + pub fn new(pool: Arc) -> Self { + Self { pool } } } @@ -143,7 +138,6 @@ impl DeltaRevisionSql { } fn read( - user_id: &str, object_id: &str, rev_ids: Option>, conn: &SqliteConnection, @@ -157,14 +151,13 @@ impl DeltaRevisionSql { let rows = sql.order(dsl::rev_id.asc()).load::(conn)?; let records = rows .into_iter() - .map(|row| mk_revision_record_from_table(user_id, row)) + .map(mk_revision_record_from_table) .collect::>(); Ok(records) } fn read_with_range( - user_id: &str, object_id: &str, range: RevisionRange, conn: &SqliteConnection, @@ -178,7 +171,7 @@ impl DeltaRevisionSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_record_from_table(user_id, table)) + .map(mk_revision_record_from_table) .collect::>(); Ok(revisions) } @@ -205,10 +198,7 @@ impl DeltaRevisionSql { Ok(()) } - pub fn read_all_documents( - user_id: &str, - conn: &SqliteConnection, - ) -> Result>, FlowyError> { + pub fn read_all_documents(conn: &SqliteConnection) -> Result>, FlowyError> { let rev_tables = dsl::rev_table .order(dsl::rev_id.asc()) .load::(conn)?; @@ -224,7 +214,7 @@ impl DeltaRevisionSql { let revisions = rev_tables .into_iter() .map(|table| { - let record = mk_revision_record_from_table(user_id, table); + let record = mk_revision_record_from_table(table); record.revision }) .collect::>(); @@ -263,7 +253,7 @@ impl std::default::Default for TextRevisionState { } } -fn mk_revision_record_from_table(_user_id: &str, table: RevisionTable) -> SyncRecord { +fn mk_revision_record_from_table(table: RevisionTable) -> SyncRecord { let md5 = md5(&table.data); let revision = Revision::new( &table.doc_id, diff --git a/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v1.rs b/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v1.rs index 569fada510..bab2ca95b7 100644 --- a/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v1.rs +++ b/frontend/rust-lib/flowy-document/src/services/persistence/rev_sqlite/document_rev_sqlite_v1.rs @@ -13,7 +13,6 @@ use revision_model::{Revision, RevisionRange}; use std::sync::Arc; pub struct SQLiteDocumentRevisionPersistence { - user_id: String, pub(crate) pool: Arc, } @@ -36,7 +35,7 @@ impl RevisionDiskCache> for SQLiteDocumentRevisionPersistenc rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = DocumentRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DocumentRevisionSql::read(object_id, rev_ids, &conn)?; Ok(records) } @@ -46,8 +45,7 @@ impl RevisionDiskCache> for SQLiteDocumentRevisionPersistenc range: &RevisionRange, ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - let revisions = - DocumentRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + let revisions = DocumentRevisionSql::read_with_range(object_id, range.clone(), conn)?; Ok(revisions) } @@ -88,11 +86,8 @@ impl RevisionDiskCache> for SQLiteDocumentRevisionPersistenc } impl SQLiteDocumentRevisionPersistence { - pub fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } + pub fn new(pool: Arc) -> Self { + Self { pool } } } @@ -141,7 +136,6 @@ impl DocumentRevisionSql { } fn read( - user_id: &str, object_id: &str, rev_ids: Option>, conn: &SqliteConnection, @@ -157,14 +151,13 @@ impl DocumentRevisionSql { .load::(conn)?; let records = rows .into_iter() - .map(|row| mk_revision_record_from_table(user_id, row)) + .map(mk_revision_record_from_table) .collect::>(); Ok(records) } fn read_with_range( - user_id: &str, object_id: &str, range: RevisionRange, conn: &SqliteConnection, @@ -178,7 +171,7 @@ impl DocumentRevisionSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_record_from_table(user_id, table)) + .map(mk_revision_record_from_table) .collect::>(); Ok(revisions) } @@ -233,7 +226,7 @@ impl std::default::Default for DocumentRevisionState { } } -fn mk_revision_record_from_table(_user_id: &str, table: DocumentRevisionTable) -> SyncRecord { +fn mk_revision_record_from_table(table: DocumentRevisionTable) -> SyncRecord { let md5 = md5(&table.data); let revision = Revision::new( &table.document_id, diff --git a/frontend/rust-lib/flowy-document/tests/new_document/script.rs b/frontend/rust-lib/flowy-document/tests/new_document/script.rs index d3ae48d64b..26736f5b23 100644 --- a/frontend/rust-lib/flowy-document/tests/new_document/script.rs +++ b/frontend/rust-lib/flowy-document/tests/new_document/script.rs @@ -48,7 +48,7 @@ impl DocumentEditorTest { let test = ViewTest::new_document_view(&sdk).await; let document_editor = sdk .document_manager - .open_document_editor(&test.view.id) + .open_document_editor(&test.child_view.id) .await .unwrap(); let editor = match document_editor diff --git a/frontend/rust-lib/flowy-document/tests/old_document/script.rs b/frontend/rust-lib/flowy-document/tests/old_document/script.rs index 49f94e019d..0fd94aa8b8 100644 --- a/frontend/rust-lib/flowy-document/tests/old_document/script.rs +++ b/frontend/rust-lib/flowy-document/tests/old_document/script.rs @@ -51,7 +51,6 @@ impl DeltaDocumentEditorTest { async fn run_script(&mut self, script: EditorScript) { let rev_manager = self.editor.rev_manager(); let cache = rev_manager.revision_cache().await; - let _user_id = self.sdk.user_session.user_id().unwrap(); match script { EditorScript::InsertText(s, offset) => { diff --git a/frontend/rust-lib/flowy-folder/build.rs b/frontend/rust-lib/flowy-folder/build.rs index 06388d2a02..d17034a7e8 100644 --- a/frontend/rust-lib/flowy-folder/build.rs +++ b/frontend/rust-lib/flowy-folder/build.rs @@ -2,9 +2,9 @@ fn main() { let crate_name = env!("CARGO_PKG_NAME"); flowy_codegen::protobuf_file::gen(crate_name); - #[cfg(feature = "dart")] - flowy_codegen::dart_event::gen(crate_name); - - #[cfg(feature = "ts")] - flowy_codegen::ts_event::gen(crate_name); + // #[cfg(feature = "dart")] + // flowy_codegen::dart_event::gen(crate_name); + // + // #[cfg(feature = "ts")] + // flowy_codegen::ts_event::gen(crate_name); } diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index 088688ee26..2b7a76fe2e 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -1,6 +1,10 @@ use crate::entities::view::ViewDataFormatPB; use crate::entities::{ViewLayoutTypePB, ViewPB, WorkspacePB}; use crate::services::folder_editor::FolderRevisionMergeable; +use crate::services::persistence::rev_sqlite::{ + SQLiteFolderRevisionPersistence, SQLiteFolderRevisionSnapshotPersistence, +}; +use crate::services::{clear_current_workspace, get_current_workspace}; use crate::{ entities::workspace::RepeatedWorkspacePB, errors::FlowyResult, @@ -12,6 +16,7 @@ use crate::{ }, }; use bytes::Bytes; +use flowy_client_sync::client_folder::FolderPad; use flowy_document::editor::initial_read_me; use flowy_error::FlowyError; use flowy_revision::{ @@ -20,12 +25,6 @@ use flowy_revision::{ use folder_model::user_default; use lazy_static::lazy_static; use lib_infra::future::FutureResult; - -use crate::services::persistence::rev_sqlite::{ - SQLiteFolderRevisionPersistence, SQLiteFolderRevisionSnapshotPersistence, -}; -use crate::services::{clear_current_workspace, get_current_workspace}; -use flowy_client_sync::client_folder::FolderPad; use std::convert::TryFrom; use std::{collections::HashMap, fmt::Formatter, sync::Arc}; use tokio::sync::RwLock as TokioRwLock; @@ -84,10 +83,7 @@ impl FolderManager { if let Ok(user_id) = user.user_id() { // Reset the flag if the folder manager gets initialized, otherwise, // the folder_editor will not be initialized after flutter hot reload. - INIT_FOLDER_FLAG - .write() - .await - .insert(user_id.to_owned(), false); + INIT_FOLDER_FLAG.write().await.insert(user_id, false); } let folder_editor = Arc::new(TokioRwLock::new(None)); @@ -176,9 +172,9 @@ impl FolderManager { let pool = self.persistence.db_pool()?; let object_id = folder_id.as_ref(); - let disk_cache = SQLiteFolderRevisionPersistence::new(user_id, pool.clone()); + let disk_cache = SQLiteFolderRevisionPersistence::new(pool.clone()); let configuration = RevisionPersistenceConfiguration::new(200, false); - let rev_persistence = RevisionPersistence::new(user_id, object_id, disk_cache, configuration); + let rev_persistence = RevisionPersistence::new(object_id, disk_cache, configuration); let rev_compactor = FolderRevisionMergeable(); const FOLDER_SP_PREFIX: &str = "folder"; @@ -186,21 +182,14 @@ impl FolderManager { let snapshot_persistence = SQLiteFolderRevisionSnapshotPersistence::new(&snapshot_object_id, pool); let rev_manager = RevisionManager::new( - user_id, folder_id.as_ref(), rev_persistence, rev_compactor, snapshot_persistence, ); - let folder_editor = FolderEditor::new( - user_id, - &folder_id, - token, - rev_manager, - self.web_socket.clone(), - ) - .await?; + let folder_editor = + FolderEditor::new(&folder_id, token, rev_manager, self.web_socket.clone()).await?; *self.folder_editor.write().await = Some(Arc::new(folder_editor)); self.app_controller.initialize()?; diff --git a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs index eeb322d762..e52742c665 100644 --- a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs +++ b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs @@ -17,8 +17,6 @@ use std::sync::Arc; use ws_model::ws_revision::ServerRevisionWSData; pub struct FolderEditor { - #[allow(dead_code)] - user_id: String, #[allow(dead_code)] folder_id: FolderId, pub(crate) folder: Arc>, @@ -30,7 +28,6 @@ pub struct FolderEditor { impl FolderEditor { #[allow(unused_variables)] pub async fn new( - user_id: &str, folder_id: &FolderId, token: &str, mut rev_manager: RevisionManager>, @@ -48,7 +45,6 @@ impl FolderEditor { #[cfg(feature = "sync")] let ws_manager = crate::services::web_socket::make_folder_ws_manager( - user_id, folder_id.as_ref(), rev_manager.clone(), web_socket, @@ -56,10 +52,8 @@ impl FolderEditor { ) .await; - let user_id = user_id.to_owned(); let folder_id = folder_id.to_owned(); Ok(Self { - user_id, folder_id, folder, rev_manager, @@ -108,7 +102,7 @@ impl FolderEditor { } } -struct FolderRevisionSerde(); +pub struct FolderRevisionSerde(); impl RevisionObjectDeserializer for FolderRevisionSerde { type Output = FolderPad; diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs index 7498e8dbec..a56495532b 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/migration.rs @@ -112,8 +112,8 @@ impl FolderMigration { }; let pool = self.database.db_pool()?; - let disk_cache = SQLiteFolderRevisionPersistence::new(&self.user_id, pool); - let reset = RevisionStructReset::new(&self.user_id, object, Arc::new(disk_cache)); + let disk_cache = SQLiteFolderRevisionPersistence::new(pool); + let reset = RevisionStructReset::new(object, Arc::new(disk_cache)); reset.run().await } } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs index d46ec12951..9b03d00e01 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs @@ -144,8 +144,8 @@ impl FolderPersistence { } pub fn make_folder_revision_disk_cache( - user_id: &str, + _user_id: &str, pool: Arc, ) -> Arc, Error = FlowyError>> { - Arc::new(SQLiteFolderRevisionPersistence::new(user_id, pool)) + Arc::new(SQLiteFolderRevisionPersistence::new(pool)) } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs index de32507c4e..79a693eb1d 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs @@ -13,7 +13,6 @@ use revision_model::{Revision, RevisionRange}; use std::sync::Arc; pub struct SQLiteFolderRevisionPersistence { - user_id: String, pub(crate) pool: Arc, } @@ -36,7 +35,7 @@ impl RevisionDiskCache> for SQLiteFolderRevisionPersistence rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = FolderRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = FolderRevisionSql::read(object_id, rev_ids, &conn)?; Ok(records) } @@ -46,8 +45,7 @@ impl RevisionDiskCache> for SQLiteFolderRevisionPersistence range: &RevisionRange, ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - let revisions = - FolderRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + let revisions = FolderRevisionSql::read_with_range(object_id, range.clone(), conn)?; Ok(revisions) } @@ -88,11 +86,8 @@ impl RevisionDiskCache> for SQLiteFolderRevisionPersistence } impl SQLiteFolderRevisionPersistence { - pub fn new(user_id: &str, pool: Arc) -> Self { - Self { - user_id: user_id.to_owned(), - pool, - } + pub fn new(pool: Arc) -> Self { + Self { pool } } } @@ -145,7 +140,6 @@ impl FolderRevisionSql { } fn read( - user_id: &str, object_id: &str, rev_ids: Option>, conn: &SqliteConnection, @@ -159,14 +153,13 @@ impl FolderRevisionSql { let rows = sql.order(dsl::rev_id.asc()).load::(conn)?; let records = rows .into_iter() - .map(|row| mk_revision_record_from_table(user_id, row)) + .map(mk_revision_record_from_table) .collect::>(); Ok(records) } fn read_with_range( - user_id: &str, object_id: &str, range: RevisionRange, conn: &SqliteConnection, @@ -180,7 +173,7 @@ impl FolderRevisionSql { let revisions = rev_tables .into_iter() - .map(|table| mk_revision_record_from_table(user_id, table)) + .map(mk_revision_record_from_table) .collect::>(); Ok(revisions) } @@ -241,7 +234,7 @@ impl std::default::Default for TextRevisionState { } } -fn mk_revision_record_from_table(_user_id: &str, table: RevisionTable) -> SyncRecord { +fn mk_revision_record_from_table(table: RevisionTable) -> SyncRecord { let md5 = md5(&table.data); let revision = Revision::new( &table.doc_id, diff --git a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs index 6a4eb4a463..0337fa0a57 100644 --- a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs +++ b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs @@ -39,7 +39,6 @@ pub type FolderConflictController = #[allow(dead_code)] pub(crate) async fn make_folder_ws_manager( - user_id: &str, folder_id: &str, rev_manager: Arc>>, web_socket: Arc, @@ -50,12 +49,8 @@ pub(crate) async fn make_folder_ws_manager( Arc::new(rev_manager.clone()), )); let resolver = Arc::new(FolderConflictResolver { folder_pad }); - let conflict_controller = FolderConflictController::new( - user_id, - resolver, - Arc::new(ws_data_provider.clone()), - rev_manager, - ); + let conflict_controller = + FolderConflictController::new(resolver, Arc::new(ws_data_provider.clone()), rev_manager); let ws_data_stream = Arc::new(FolderRevisionWSDataStream::new(conflict_controller)); let ws_data_sink = Arc::new(FolderWSDataSink(ws_data_provider)); let ping_duration = Duration::from_millis(FOLDER_SYNC_INTERVAL_IN_MILLIS); diff --git a/frontend/rust-lib/flowy-folder/tests/workspace/main.rs b/frontend/rust-lib/flowy-folder/tests/workspace/main.rs index ff48b349e1..7a47dda24d 100644 --- a/frontend/rust-lib/flowy-folder/tests/workspace/main.rs +++ b/frontend/rust-lib/flowy-folder/tests/workspace/main.rs @@ -1,2 +1,2 @@ -mod folder_test; -mod script; +// mod folder_test; +// mod script; diff --git a/frontend/rust-lib/flowy-folder2/Cargo.toml b/frontend/rust-lib/flowy-folder2/Cargo.toml new file mode 100644 index 0000000000..f12f3d3613 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "flowy-folder2" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +collab = { version = "0.1.0" } +collab-folder = { version = "0.1.0" } +collab-persistence = { version = "0.1.0" } + +flowy-derive = { path = "../flowy-derive" } +flowy-notification = { path = "../flowy-notification" } +parking_lot = "0.12.1" +unicode-segmentation = "1.10" +tracing = { version = "0.1", features = ["log"] } +flowy-error = { path = "../flowy-error", features = ["adaptor_dispatch"]} +lib-dispatch = { path = "../lib-dispatch" } +bytes = { version = "1.4" } +lib-infra = { path = "../../../shared-lib/lib-infra" } +tokio = { version = "1.26", features = ["full"] } +nanoid = "0.4.0" +lazy_static = "1.4.0" +chrono = { version = "0.4.24"} +strum = "0.21" +strum_macros = "0.21" +protobuf = {version = "2.28.0"} +flowy-document = { path = "../flowy-document" } + +[dev-dependencies] +flowy-folder2 = { path = "../flowy-folder2"} +flowy-test = { path = "../flowy-test" } + +[build-dependencies] +flowy-codegen = { path = "../flowy-codegen"} + +[features] +dart = ["flowy-codegen/dart", "flowy-notification/dart"] +ts = ["flowy-codegen/ts", "flowy-notification/ts"] +test_helper = [] \ No newline at end of file diff --git a/frontend/rust-lib/flowy-folder2/Flowy.toml b/frontend/rust-lib/flowy-folder2/Flowy.toml new file mode 100644 index 0000000000..0ae861cf30 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/Flowy.toml @@ -0,0 +1,3 @@ +# Check out the FlowyConfig (located in flowy_toml.rs) for more details. +proto_input = ["src/entities", "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-folder2/build.rs b/frontend/rust-lib/flowy-folder2/build.rs new file mode 100644 index 0000000000..06388d2a02 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/build.rs @@ -0,0 +1,10 @@ +fn main() { + let crate_name = env!("CARGO_PKG_NAME"); + flowy_codegen::protobuf_file::gen(crate_name); + + #[cfg(feature = "dart")] + flowy_codegen::dart_event::gen(crate_name); + + #[cfg(feature = "ts")] + flowy_codegen::ts_event::gen(crate_name); +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/app.rs b/frontend/rust-lib/flowy-folder2/src/entities/app.rs new file mode 100644 index 0000000000..ffff29eab4 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/app.rs @@ -0,0 +1,183 @@ +use crate::entities::parser::app::{AppColorStyle, AppIdentify, AppName}; +use crate::entities::parser::workspace::WorkspaceIdentify; +use crate::entities::RepeatedViewPB; + +use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use std::convert::TryInto; + +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct AppPB { + #[pb(index = 1)] + pub id: String, + + #[pb(index = 2)] + pub workspace_id: String, + + #[pb(index = 3)] + pub name: String, + + #[pb(index = 4)] + pub belongings: RepeatedViewPB, + + #[pb(index = 5)] + pub create_time: i64, +} + +#[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)] +pub struct RepeatedAppPB { + #[pb(index = 1)] + pub items: Vec, +} + +#[derive(ProtoBuf, Default)] +pub struct CreateAppPayloadPB { + #[pb(index = 1)] + pub workspace_id: String, + + #[pb(index = 2)] + pub name: String, + + #[pb(index = 3)] + pub desc: String, + + #[pb(index = 4)] + pub color_style: ColorStylePB, +} + +#[derive(ProtoBuf, Default, Debug, Clone)] +pub struct ColorStylePB { + #[pb(index = 1)] + pub theme_color: String, +} + +#[derive(Debug)] +pub struct CreateAppParams { + pub workspace_id: String, + pub name: String, + pub desc: String, + pub color_style: ColorStylePB, +} + +impl TryInto for CreateAppPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let name = AppName::parse(self.name)?; + let id = WorkspaceIdentify::parse(self.workspace_id)?; + let color_style = AppColorStyle::parse(self.color_style.theme_color.clone())?; + + Ok(CreateAppParams { + workspace_id: id.0, + name: name.0, + desc: self.desc, + color_style: color_style.into(), + }) + } +} + +impl std::convert::From for ColorStylePB { + fn from(data: AppColorStyle) -> Self { + ColorStylePB { + theme_color: data.theme_color, + } + } +} + +#[derive(ProtoBuf, Default, Clone, Debug)] +pub struct AppIdPB { + #[pb(index = 1)] + pub value: String, +} + +impl AppIdPB { + pub fn new(app_id: &str) -> Self { + Self { + value: app_id.to_string(), + } + } +} + +#[derive(ProtoBuf, Default)] +pub struct UpdateAppPayloadPB { + #[pb(index = 1)] + pub app_id: String, + + #[pb(index = 2, one_of)] + pub name: Option, + + #[pb(index = 3, one_of)] + pub desc: Option, + + #[pb(index = 4, one_of)] + pub color_style: Option, + + #[pb(index = 5, one_of)] + pub is_trash: Option, +} + +#[derive(Debug, Clone)] +pub struct UpdateAppParams { + pub app_id: String, + + pub name: Option, + + pub desc: Option, + + pub color_style: Option, + + pub is_trash: Option, +} + +impl UpdateAppParams { + pub fn new(app_id: &str) -> Self { + Self { + app_id: app_id.to_string(), + name: None, + desc: None, + color_style: None, + is_trash: None, + } + } + + pub fn name(mut self, name: &str) -> Self { + self.name = Some(name.to_string()); + self + } + + pub fn desc(mut self, desc: &str) -> Self { + self.desc = Some(desc.to_string()); + self + } + + pub fn trash(mut self) -> Self { + self.is_trash = Some(true); + self + } +} + +impl TryInto for UpdateAppPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let app_id = AppIdentify::parse(self.app_id)?.0; + + let name = match self.name { + None => None, + Some(name) => Some(AppName::parse(name)?.0), + }; + + let color_style = match self.color_style { + None => None, + Some(color_style) => Some(AppColorStyle::parse(color_style.theme_color)?.into()), + }; + + Ok(UpdateAppParams { + app_id, + name, + desc: self.desc, + color_style, + is_trash: self.is_trash, + }) + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/mod.rs new file mode 100644 index 0000000000..d5370f0786 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/mod.rs @@ -0,0 +1,10 @@ +pub mod app; +mod parser; +pub mod trash; +pub mod view; +pub mod workspace; + +pub use app::*; +pub use trash::*; +pub use view::*; +pub use workspace::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs new file mode 100644 index 0000000000..b98b809f3d --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs @@ -0,0 +1,13 @@ +use flowy_error::ErrorCode; + +#[derive(Debug)] +pub struct AppColorStyle { + pub theme_color: String, +} + +impl AppColorStyle { + pub fn parse(theme_color: String) -> Result { + // TODO: verify the color style format + Ok(AppColorStyle { theme_color }) + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs new file mode 100644 index 0000000000..24cc2dcab8 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs @@ -0,0 +1,20 @@ +use unicode_segmentation::UnicodeSegmentation; +#[derive(Debug)] +pub struct AppDesc(pub String); + +impl AppDesc { + #[allow(dead_code)] + pub fn parse(s: String) -> Result { + if s.graphemes(true).count() > 1024 { + return Err("Workspace description too long".to_string()); + } + + Ok(Self(s)) + } +} + +impl AsRef for AppDesc { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs new file mode 100644 index 0000000000..2311001089 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs @@ -0,0 +1,20 @@ +use flowy_error::ErrorCode; + +#[derive(Debug)] +pub struct AppIdentify(pub String); + +impl AppIdentify { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(ErrorCode::AppIdInvalid); + } + + Ok(Self(s)) + } +} + +impl AsRef for AppIdentify { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs new file mode 100644 index 0000000000..f14670c650 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs @@ -0,0 +1,20 @@ +use flowy_error::ErrorCode; + +#[derive(Debug)] +pub struct AppName(pub String); + +impl AppName { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(ErrorCode::AppNameInvalid); + } + + Ok(Self(s)) + } +} + +impl AsRef for AppName { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs new file mode 100644 index 0000000000..fcf6f4bd3f --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs @@ -0,0 +1,9 @@ +mod app_color_style; +mod app_desc; +mod app_id; +mod app_name; + +pub use app_color_style::*; +pub use app_desc::*; +pub use app_id::*; +pub use app_name::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs new file mode 100644 index 0000000000..3ee0f4b591 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs @@ -0,0 +1,4 @@ +pub mod app; +pub mod trash; +pub mod view; +pub mod workspace; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/trash/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/trash/mod.rs new file mode 100644 index 0000000000..ddb6a3b91e --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/trash/mod.rs @@ -0,0 +1,3 @@ +mod trash_id; + +pub use trash_id::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/trash/trash_id.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/trash/trash_id.rs new file mode 100644 index 0000000000..3b6a4c4f6d --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/trash/trash_id.rs @@ -0,0 +1,34 @@ +#[derive(Debug)] +pub struct TrashIdentify(pub String); + +impl TrashIdentify { + #[allow(dead_code)] + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err("Trash id can not be empty or whitespace".to_string()); + } + + Ok(Self(s)) + } +} + +impl AsRef for TrashIdentify { + fn as_ref(&self) -> &str { + &self.0 + } +} + +#[derive(Debug)] +pub struct TrashIds(pub Vec); + +impl TrashIds { + #[allow(dead_code)] + pub fn parse(ids: Vec) -> Result { + let mut trash_ids = vec![]; + for id in ids { + let id = TrashIdentify::parse(id)?; + trash_ids.push(id.0); + } + Ok(Self(trash_ids)) + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/view/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/mod.rs new file mode 100644 index 0000000000..399cc44c45 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/mod.rs @@ -0,0 +1,9 @@ +mod view_desc; +mod view_id; +mod view_name; +mod view_thumbnail; + +pub use view_desc::*; +pub use view_id::*; +pub use view_name::*; +pub use view_thumbnail::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_desc.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_desc.rs new file mode 100644 index 0000000000..f88eb6ebff --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_desc.rs @@ -0,0 +1,21 @@ +use flowy_error::ErrorCode; +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct ViewDesc(pub String); + +impl ViewDesc { + pub fn parse(s: String) -> Result { + if s.graphemes(true).count() > 1000 { + return Err(ErrorCode::ViewDescTooLong); + } + + Ok(Self(s)) + } +} + +impl AsRef for ViewDesc { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_id.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_id.rs new file mode 100644 index 0000000000..c19d9d0ac0 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_id.rs @@ -0,0 +1,20 @@ +use flowy_error::ErrorCode; + +#[derive(Debug)] +pub struct ViewIdentify(pub String); + +impl ViewIdentify { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(ErrorCode::ViewIdIsInvalid); + } + + Ok(Self(s)) + } +} + +impl AsRef for ViewIdentify { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_name.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_name.rs new file mode 100644 index 0000000000..df1861e820 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_name.rs @@ -0,0 +1,25 @@ +use flowy_error::ErrorCode; +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct ViewName(pub String); + +impl ViewName { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(ErrorCode::ViewNameInvalid); + } + + if s.graphemes(true).count() > 256 { + return Err(ErrorCode::ViewNameTooLong); + } + + Ok(Self(s)) + } +} + +impl AsRef for ViewName { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_thumbnail.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_thumbnail.rs new file mode 100644 index 0000000000..c538da8212 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/view/view_thumbnail.rs @@ -0,0 +1,21 @@ +use flowy_error::ErrorCode; + +#[derive(Debug)] +pub struct ViewThumbnail(pub String); + +impl ViewThumbnail { + pub fn parse(s: String) -> Result { + // if s.trim().is_empty() { + // return Err(format!("View thumbnail can not be empty or whitespace")); + // } + // TODO: verify the thumbnail url is valid or not + + Ok(Self(s)) + } +} + +impl AsRef for ViewThumbnail { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/mod.rs new file mode 100644 index 0000000000..876ba10858 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/mod.rs @@ -0,0 +1,7 @@ +mod workspace_desc; +mod workspace_id; +mod workspace_name; + +pub use workspace_desc::*; +pub use workspace_id::*; +pub use workspace_name::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_desc.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_desc.rs new file mode 100644 index 0000000000..f523592b86 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_desc.rs @@ -0,0 +1,21 @@ +use flowy_error::ErrorCode; +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct WorkspaceDesc(pub String); + +impl WorkspaceDesc { + pub fn parse(s: String) -> Result { + if s.graphemes(true).count() > 1024 { + return Err(ErrorCode::WorkspaceNameTooLong); + } + + Ok(Self(s)) + } +} + +impl AsRef for WorkspaceDesc { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_id.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_id.rs new file mode 100644 index 0000000000..b3ce24c6c9 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_id.rs @@ -0,0 +1,20 @@ +use flowy_error::ErrorCode; + +#[derive(Debug)] +pub struct WorkspaceIdentify(pub String); + +impl WorkspaceIdentify { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(ErrorCode::WorkspaceIdInvalid); + } + + Ok(Self(s)) + } +} + +impl AsRef for WorkspaceIdentify { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_name.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_name.rs new file mode 100644 index 0000000000..95e292668a --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/workspace/workspace_name.rs @@ -0,0 +1,25 @@ +use flowy_error::ErrorCode; +use unicode_segmentation::UnicodeSegmentation; + +#[derive(Debug)] +pub struct WorkspaceName(pub String); + +impl WorkspaceName { + pub fn parse(s: String) -> Result { + if s.trim().is_empty() { + return Err(ErrorCode::WorkspaceNameInvalid); + } + + if s.graphemes(true).count() > 256 { + return Err(ErrorCode::WorkspaceNameTooLong); + } + + Ok(Self(s)) + } +} + +impl AsRef for WorkspaceName { + fn as_ref(&self) -> &str { + &self.0 + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/trash.rs b/frontend/rust-lib/flowy-folder2/src/entities/trash.rs new file mode 100644 index 0000000000..b1158dbe07 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/trash.rs @@ -0,0 +1,73 @@ +use collab_folder::core::TrashInfo; +use flowy_derive::ProtoBuf; + +#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)] +pub struct TrashPB { + #[pb(index = 1)] + pub id: String, + + #[pb(index = 2)] + pub name: String, + + #[pb(index = 3)] + pub modified_time: i64, + + #[pb(index = 4)] + pub create_time: i64, +} + +impl std::convert::From for TrashPB { + fn from(trash_info: TrashInfo) -> Self { + TrashPB { + id: trash_info.id, + name: trash_info.name, + modified_time: trash_info.created_at, + create_time: trash_info.created_at, + } + } +} + +impl std::convert::From for TrashInfo { + fn from(trash: TrashPB) -> Self { + TrashInfo { + id: trash.id, + name: trash.name, + created_at: trash.create_time, + } + } +} +#[derive(PartialEq, Eq, Debug, Default, ProtoBuf, Clone)] +pub struct RepeatedTrashPB { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::convert::From> for RepeatedTrashPB { + fn from(trash_revs: Vec) -> Self { + let items: Vec = trash_revs + .into_iter() + .map(|trash_rev| trash_rev.into()) + .collect(); + RepeatedTrashPB { items } + } +} + +#[derive(PartialEq, Eq, ProtoBuf, Default, Debug, Clone)] +pub struct TrashIdPB { + #[pb(index = 1)] + pub id: String, +} + +impl std::convert::From<&TrashInfo> for TrashIdPB { + fn from(trash_info: &TrashInfo) -> Self { + TrashIdPB { + id: trash_info.id.clone(), + } + } +} + +#[derive(PartialEq, Eq, ProtoBuf, Default, Debug, Clone)] +pub struct RepeatedTrashIdPB { + #[pb(index = 1)] + pub items: Vec, +} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/view.rs b/frontend/rust-lib/flowy-folder2/src/entities/view.rs new file mode 100644 index 0000000000..f952fd65e5 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/view.rs @@ -0,0 +1,349 @@ +use crate::entities::parser::{ + app::AppIdentify, + view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail}, +}; +use crate::view_ext::gen_view_id; +use collab_folder::core::{View, ViewLayout}; +use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; +use flowy_error::ErrorCode; +use std::collections::HashMap; +use std::convert::TryInto; +use std::ops::{Deref, DerefMut}; + +#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] +pub struct ViewPB { + #[pb(index = 1)] + pub id: String, + + #[pb(index = 2)] + pub app_id: String, + + #[pb(index = 3)] + pub name: String, + + #[pb(index = 4)] + pub create_time: i64, + + #[pb(index = 5)] + pub belongings: Vec, + + #[pb(index = 6)] + pub layout: ViewLayoutTypePB, +} + +impl std::convert::From for ViewPB { + fn from(view: View) -> Self { + ViewPB { + id: view.id, + app_id: view.bid, + name: view.name, + create_time: view.created_at, + belongings: Default::default(), + layout: view.layout.into(), + } + } +} + +#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] +pub enum ViewLayoutTypePB { + Document = 0, + Grid = 3, + Board = 4, + Calendar = 5, +} + +impl std::default::Default for ViewLayoutTypePB { + fn default() -> Self { + ViewLayoutTypePB::Grid + } +} + +impl std::convert::From for ViewLayoutTypePB { + fn from(rev: ViewLayout) -> Self { + match rev { + ViewLayout::Grid => ViewLayoutTypePB::Grid, + ViewLayout::Board => ViewLayoutTypePB::Board, + ViewLayout::Document => ViewLayoutTypePB::Document, + ViewLayout::Calendar => ViewLayoutTypePB::Calendar, + } + } +} + +#[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)] +pub struct RepeatedViewPB { + #[pb(index = 1)] + pub items: Vec, +} + +impl std::convert::From> for RepeatedViewPB { + fn from(views: Vec) -> Self { + let items = views + .into_iter() + .map(|value| value.into()) + .collect::>(); + RepeatedViewPB { items } + } +} + +impl Deref for RepeatedViewPB { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.items + } +} + +impl DerefMut for RepeatedViewPB { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.items + } +} + +#[derive(Default, ProtoBuf)] +pub struct RepeatedViewIdPB { + #[pb(index = 1)] + pub items: Vec, +} + +#[derive(Default, ProtoBuf)] +pub struct CreateViewPayloadPB { + #[pb(index = 1)] + pub belong_to_id: String, + + #[pb(index = 2)] + pub name: String, + + #[pb(index = 3)] + pub desc: String, + + #[pb(index = 4, one_of)] + pub thumbnail: Option, + + #[pb(index = 5)] + pub layout: ViewLayoutTypePB, + + #[pb(index = 6)] + pub initial_data: Vec, + + #[pb(index = 7)] + pub ext: HashMap, +} + +#[derive(Debug, Clone)] +pub struct CreateViewParams { + pub belong_to_id: String, + pub name: String, + pub desc: String, + pub layout: ViewLayoutTypePB, + pub view_id: String, + pub initial_data: Vec, + pub ext: HashMap, +} + +impl TryInto for CreateViewPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let name = ViewName::parse(self.name)?.0; + let belong_to_id = AppIdentify::parse(self.belong_to_id)?.0; + let view_id = gen_view_id(); + + Ok(CreateViewParams { + belong_to_id, + name, + desc: self.desc, + layout: self.layout, + view_id, + initial_data: self.initial_data, + ext: self.ext, + }) + } +} + +#[derive(Default, ProtoBuf, Clone, Debug)] +pub struct ViewIdPB { + #[pb(index = 1)] + pub value: String, +} + +impl std::convert::From<&str> for ViewIdPB { + fn from(value: &str) -> Self { + ViewIdPB { + value: value.to_string(), + } + } +} + +#[derive(Default, ProtoBuf, Clone, Debug)] +pub struct DeletedViewPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2, one_of)] + pub index: Option, +} + +impl std::ops::Deref for ViewIdPB { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.value + } +} + +#[derive(Default, ProtoBuf)] +pub struct UpdateViewPayloadPB { + #[pb(index = 1)] + pub view_id: String, + + #[pb(index = 2, one_of)] + pub name: Option, + + #[pb(index = 3, one_of)] + pub desc: Option, + + #[pb(index = 4, one_of)] + pub thumbnail: Option, +} + +#[derive(Clone, Debug)] +pub struct UpdateViewParams { + pub view_id: String, + pub name: Option, + pub desc: Option, + pub thumbnail: Option, +} + +impl TryInto for UpdateViewPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let view_id = ViewIdentify::parse(self.view_id)?.0; + + let name = match self.name { + None => None, + Some(name) => Some(ViewName::parse(name)?.0), + }; + + let desc = match self.desc { + None => None, + Some(desc) => Some(ViewDesc::parse(desc)?.0), + }; + + let thumbnail = match self.thumbnail { + None => None, + Some(thumbnail) => Some(ViewThumbnail::parse(thumbnail)?.0), + }; + + Ok(UpdateViewParams { + view_id, + name, + desc, + thumbnail, + }) + } +} + +#[derive(ProtoBuf_Enum)] +pub enum MoveFolderItemType { + MoveApp = 0, + MoveView = 1, +} + +impl std::default::Default for MoveFolderItemType { + fn default() -> Self { + MoveFolderItemType::MoveApp + } +} + +#[derive(Default, ProtoBuf)] +pub struct MoveFolderItemPayloadPB { + #[pb(index = 1)] + pub item_id: String, + + #[pb(index = 2)] + pub from: i32, + + #[pb(index = 3)] + pub to: i32, + + #[pb(index = 4)] + pub ty: MoveFolderItemType, +} + +pub struct MoveViewParams { + pub item_id: String, + pub from: usize, + pub to: usize, + pub ty: MoveFolderItemType, +} + +impl TryInto for MoveFolderItemPayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let view_id = ViewIdentify::parse(self.item_id)?.0; + Ok(MoveViewParams { + item_id: view_id, + from: self.from as usize, + to: self.to as usize, + ty: self.ty, + }) + } +} + +// impl<'de> Deserialize<'de> for ViewDataType { +// fn deserialize(deserializer: D) -> Result>::Error> +// where +// D: Deserializer<'de>, +// { +// struct ViewTypeVisitor(); +// +// impl<'de> Visitor<'de> for ViewTypeVisitor { +// type Value = ViewDataType; +// fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { +// formatter.write_str("RichText, PlainText") +// } +// +// fn visit_u8(self, v: u8) -> Result +// where +// E: de::Error, +// { +// let data_type; +// match v { +// 0 => { +// data_type = ViewDataType::RichText; +// } +// 1 => { +// data_type = ViewDataType::PlainText; +// } +// _ => { +// return Err(de::Error::invalid_value(Unexpected::Unsigned(v as u64), &self)); +// } +// } +// Ok(data_type) +// } +// +// fn visit_str(self, s: &str) -> Result +// where +// E: de::Error, +// { +// let data_type; +// match s { +// "Doc" | "RichText" => { +// // Rename ViewDataType::Doc to ViewDataType::RichText, So we need to migrate the ViewType manually. +// data_type = ViewDataType::RichText; +// } +// "PlainText" => { +// data_type = ViewDataType::PlainText; +// } +// unknown => { +// return Err(de::Error::invalid_value(Unexpected::Str(unknown), &self)); +// } +// } +// Ok(data_type) +// } +// } +// deserializer.deserialize_any(ViewTypeVisitor()) +// } +// } diff --git a/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs b/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs new file mode 100644 index 0000000000..f0c027377e --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs @@ -0,0 +1,141 @@ +use crate::{ + entities::parser::workspace::{WorkspaceDesc, WorkspaceIdentify, WorkspaceName}, + entities::view::ViewPB, +}; +use collab_folder::core::Workspace; +use flowy_derive::ProtoBuf; +use flowy_error::ErrorCode; +use std::convert::TryInto; + +#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)] +pub struct WorkspacePB { + #[pb(index = 1)] + pub id: String, + + #[pb(index = 2)] + pub name: String, + + #[pb(index = 3)] + pub views: Vec, + + #[pb(index = 4)] + pub create_time: i64, +} + +impl std::convert::From for WorkspacePB { + fn from(workspace: Workspace) -> Self { + WorkspacePB { + id: workspace.id, + name: workspace.name, + views: Default::default(), + create_time: workspace.created_at, + } + } +} + +#[derive(PartialEq, Eq, Debug, Default, ProtoBuf)] +pub struct RepeatedWorkspacePB { + #[pb(index = 1)] + pub items: Vec, +} + +impl From> for RepeatedWorkspacePB { + fn from(workspaces: Vec) -> Self { + Self { + items: workspaces + .into_iter() + .map(|workspace| workspace.into()) + .collect::>(), + } + } +} + +#[derive(ProtoBuf, Default)] +pub struct CreateWorkspacePayloadPB { + #[pb(index = 1)] + pub name: String, + + #[pb(index = 2)] + pub desc: String, +} + +#[derive(Clone, Debug)] +pub struct CreateWorkspaceParams { + pub name: String, + pub desc: String, +} + +impl TryInto for CreateWorkspacePayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let name = WorkspaceName::parse(self.name)?; + let desc = WorkspaceDesc::parse(self.desc)?; + + Ok(CreateWorkspaceParams { + name: name.0, + desc: desc.0, + }) + } +} + +// Read all workspaces if the workspace_id is None +#[derive(Clone, ProtoBuf, Default, Debug)] +pub struct WorkspaceIdPB { + #[pb(index = 1, one_of)] + pub value: Option, +} + +impl WorkspaceIdPB { + pub fn new(workspace_id: Option) -> Self { + Self { + value: workspace_id, + } + } +} + +#[derive(Default, ProtoBuf, Clone)] +pub struct WorkspaceSettingPB { + #[pb(index = 1)] + pub workspace: WorkspacePB, + + #[pb(index = 2, one_of)] + pub latest_view: Option, +} + +#[derive(ProtoBuf, Default)] +pub struct UpdateWorkspacePayloadPB { + #[pb(index = 1)] + pub id: String, + + #[pb(index = 2, one_of)] + pub name: Option, + + #[pb(index = 3, one_of)] + pub desc: Option, +} + +#[derive(Clone, Debug)] +pub struct UpdateWorkspaceParams { + pub id: String, + pub name: Option, + pub desc: Option, +} + +impl TryInto for UpdateWorkspacePayloadPB { + type Error = ErrorCode; + + fn try_into(self) -> Result { + let name = match self.name { + None => None, + Some(name) => Some(WorkspaceName::parse(name)?.0), + }; + let id = WorkspaceIdentify::parse(self.id)?; + + Ok(UpdateWorkspaceParams { + id: id.0, + name, + desc: self.desc, + }) + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/event_handler.rs b/frontend/rust-lib/flowy-folder2/src/event_handler.rs new file mode 100644 index 0000000000..38bc761964 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/event_handler.rs @@ -0,0 +1,201 @@ +use crate::entities::{ + CreateViewParams, CreateViewPayloadPB, CreateWorkspaceParams, CreateWorkspacePayloadPB, + MoveFolderItemPayloadPB, MoveViewParams, RepeatedTrashIdPB, RepeatedTrashPB, RepeatedViewIdPB, + RepeatedViewPB, RepeatedWorkspacePB, TrashIdPB, UpdateViewParams, UpdateViewPayloadPB, ViewIdPB, + ViewPB, WorkspaceIdPB, WorkspacePB, WorkspaceSettingPB, +}; +use crate::manager::Folder2Manager; + +use flowy_error::FlowyError; +use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult}; +use std::sync::Arc; + +#[tracing::instrument(level = "debug", skip(data, folder), err)] +pub(crate) async fn create_workspace_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> DataResult { + let params: CreateWorkspaceParams = data.into_inner().try_into()?; + let workspace = folder.create_workspace(params).await?; + data_result_ok(workspace.into()) +} + +#[tracing::instrument(level = "debug", skip(folder), err)] +pub(crate) async fn read_workspace_apps_handler( + folder: AFPluginState>, +) -> DataResult { + let child_views = folder.get_current_workspace_views().await?; + let repeated_view: RepeatedViewPB = child_views.into(); + data_result_ok(repeated_view) +} + +#[tracing::instrument(level = "debug", skip(data, folder), err)] +pub(crate) async fn open_workspace_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> DataResult { + let params: WorkspaceIdPB = data.into_inner(); + match params.value { + None => Err(FlowyError::workspace_id().context("workspace id should not be empty")), + Some(workspace_id) => { + let workspace = folder.open_workspace(&workspace_id).await?; + let workspace_pb: WorkspacePB = workspace.into(); + data_result_ok(workspace_pb) + }, + } +} + +#[tracing::instrument(level = "debug", skip(data, folder), err)] +pub(crate) async fn read_workspaces_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> DataResult { + let params: WorkspaceIdPB = data.into_inner(); + let workspaces = match params.value { + None => folder.get_all_workspaces().await, + Some(workspace_id) => folder + .get_workspace(&workspace_id) + .await + .map(|workspace| vec![workspace]) + .unwrap_or_default(), + }; + + data_result_ok(workspaces.into()) +} + +#[tracing::instrument(level = "debug", skip(folder), err)] +pub async fn read_cur_workspace_setting_handler( + folder: AFPluginState>, +) -> DataResult { + let workspace: WorkspacePB = folder.get_current_workspace().await?.into(); + let latest_view: Option = folder.get_current_view().await; + data_result_ok(WorkspaceSettingPB { + workspace, + latest_view, + }) +} + +pub(crate) async fn create_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> DataResult { + let params: CreateViewParams = data.into_inner().try_into()?; + let view = folder.create_view_with_params(params).await?; + let _ = folder.set_current_view(&view.id).await; + data_result_ok(view.into()) +} + +pub(crate) async fn read_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> DataResult { + let view_id: ViewIdPB = data.into_inner(); + let view_pb = folder.get_view(&view_id.value).await?; + data_result_ok(view_pb) +} + +#[tracing::instrument(level = "debug", skip(data, folder), err)] +pub(crate) async fn update_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let params: UpdateViewParams = data.into_inner().try_into()?; + let _ = folder.update_view_with_params(params).await?; + Ok(()) +} + +pub(crate) async fn delete_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let params: RepeatedViewIdPB = data.into_inner(); + for view_id in ¶ms.items { + let _ = folder.move_view_to_trash(view_id).await; + } + Ok(()) +} + +pub(crate) async fn set_latest_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let view_id: ViewIdPB = data.into_inner(); + let _ = folder.set_current_view(&view_id.value).await; + Ok(()) +} + +pub(crate) async fn close_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let view_id: ViewIdPB = data.into_inner(); + let _ = folder.close_view(&view_id.value).await; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip_all, err)] +pub(crate) async fn move_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let params: MoveViewParams = data.into_inner().try_into()?; + folder + .move_view(¶ms.item_id, params.from, params.to) + .await?; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(data, folder), err)] +pub(crate) async fn duplicate_view_handler( + data: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let view: ViewPB = data.into_inner(); + folder.duplicate_view(&view.id).await?; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(folder), err)] +pub(crate) async fn read_trash_handler( + folder: AFPluginState>, +) -> DataResult { + let trash = folder.get_all_trash().await; + data_result_ok(trash.into()) +} + +#[tracing::instrument(level = "debug", skip(identifier, folder), err)] +pub(crate) async fn putback_trash_handler( + identifier: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + folder.restore_trash(&identifier.id).await; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(identifiers, folder), err)] +pub(crate) async fn delete_trash_handler( + identifiers: AFPluginData, + folder: AFPluginState>, +) -> Result<(), FlowyError> { + let trash_ids = identifiers.into_inner().items; + for trash_id in trash_ids { + folder.delete_trash(&trash_id.id).await; + } + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(folder), err)] +pub(crate) async fn restore_all_trash_handler( + folder: AFPluginState>, +) -> Result<(), FlowyError> { + folder.restore_all_trash().await; + Ok(()) +} + +#[tracing::instrument(level = "debug", skip(folder), err)] +pub(crate) async fn delete_all_trash_handler( + folder: AFPluginState>, +) -> Result<(), FlowyError> { + folder.delete_all_trash().await; + Ok(()) +} diff --git a/frontend/rust-lib/flowy-folder2/src/event_map.rs b/frontend/rust-lib/flowy-folder2/src/event_map.rs new file mode 100644 index 0000000000..ee72436baf --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/event_map.rs @@ -0,0 +1,119 @@ +use crate::event_handler::*; +use crate::manager::Folder2Manager; +use flowy_derive::{Flowy_Event, ProtoBuf_Enum}; + +use lib_dispatch::prelude::*; +use std::sync::Arc; +use strum_macros::Display; + +pub fn init(folder: Arc) -> AFPlugin { + AFPlugin::new().name("Flowy-Folder").state(folder) + // Workspace + .event(FolderEvent::CreateWorkspace, create_workspace_handler) + .event( + FolderEvent::ReadCurrentWorkspace, + read_cur_workspace_setting_handler, + ) + .event(FolderEvent::ReadWorkspaces, read_workspaces_handler) + .event(FolderEvent::OpenWorkspace, open_workspace_handler) + .event(FolderEvent::ReadWorkspaceApps, read_workspace_apps_handler) + // View + .event(FolderEvent::CreateView, create_view_handler) + .event(FolderEvent::ReadView, read_view_handler) + .event(FolderEvent::UpdateView, update_view_handler) + .event(FolderEvent::DeleteView, delete_view_handler) + .event(FolderEvent::DuplicateView, duplicate_view_handler) + .event(FolderEvent::SetLatestView, set_latest_view_handler) + .event(FolderEvent::CloseView, close_view_handler) + .event(FolderEvent::MoveItem, move_view_handler) + // Trash + .event(FolderEvent::ReadTrash, read_trash_handler) + .event(FolderEvent::PutbackTrash, putback_trash_handler) + .event(FolderEvent::DeleteTrash, delete_trash_handler) + .event(FolderEvent::RestoreAllTrash, restore_all_trash_handler) + .event(FolderEvent::DeleteAllTrash, delete_all_trash_handler) +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] +#[event_err = "FlowyError"] +pub enum FolderEvent { + /// Create a new workspace + #[event(input = "CreateWorkspacePayloadPB", output = "WorkspacePB")] + CreateWorkspace = 0, + + /// Read the current opening workspace + #[event(output = "WorkspaceSettingPB")] + ReadCurrentWorkspace = 1, + + /// Open the workspace and mark it as the current workspace + #[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")] + ReadWorkspaces = 2, + + /// Delete the workspace + #[event(input = "WorkspaceIdPB")] + DeleteWorkspace = 3, + + /// Open the workspace and mark it as the current workspace + #[event(input = "WorkspaceIdPB", output = "WorkspacePB")] + OpenWorkspace = 4, + + /// Return a list of apps that belong to this workspace + #[event(input = "WorkspaceIdPB", output = "RepeatedViewPB")] + ReadWorkspaceApps = 5, + + /// Create a new view in the corresponding app + #[event(input = "CreateViewPayloadPB", output = "ViewPB")] + CreateView = 201, + + /// Return the view info + #[event(input = "ViewIdPB", output = "ViewPB")] + ReadView = 202, + + /// Update the view's properties including the name,description, etc. + #[event(input = "UpdateViewPayloadPB", output = "ViewPB")] + UpdateView = 203, + + /// Move the view to the trash folder + #[event(input = "RepeatedViewIdPB")] + DeleteView = 204, + + /// Duplicate the view + #[event(input = "ViewPB")] + DuplicateView = 205, + + /// Close and release the resources that are used by this view. + /// It should get called when the 'View' page get destroy + #[event(input = "ViewIdPB")] + CloseView = 206, + + #[event()] + CopyLink = 220, + + /// Set the current visiting view + #[event(input = "ViewIdPB")] + SetLatestView = 221, + + /// Move the view or app to another place + #[event(input = "MoveFolderItemPayloadPB")] + MoveItem = 230, + + /// Read the trash that was deleted by the user + #[event(output = "RepeatedTrashPB")] + ReadTrash = 300, + + /// Put back the trash to the origin folder + #[event(input = "TrashIdPB")] + PutbackTrash = 301, + + /// Delete the trash from the disk + #[event(input = "RepeatedTrashIdPB")] + DeleteTrash = 302, + + /// Put back all the trash to its original folder + #[event()] + RestoreAllTrash = 303, + + /// Delete all the trash from the disk + #[event()] + DeleteAllTrash = 304, +} diff --git a/frontend/rust-lib/flowy-folder2/src/lib.rs b/frontend/rust-lib/flowy-folder2/src/lib.rs new file mode 100644 index 0000000000..244caa9ab4 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/lib.rs @@ -0,0 +1,13 @@ +pub mod entities; +pub mod event_handler; +pub mod event_map; +pub mod manager; +mod notification; +pub mod protobuf; +mod user_default; +pub mod view_ext; + +#[cfg(feature = "test_helper")] +mod test_helper; + +pub use collab_folder::core::ViewLayout; diff --git a/frontend/rust-lib/flowy-folder2/src/manager.rs b/frontend/rust-lib/flowy-folder2/src/manager.rs new file mode 100644 index 0000000000..396c74cca2 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/manager.rs @@ -0,0 +1,614 @@ +use crate::entities::{ + CreateViewParams, CreateWorkspaceParams, RepeatedTrashPB, RepeatedViewPB, RepeatedWorkspacePB, + UpdateViewParams, ViewPB, +}; +use crate::notification::{ + send_notification, send_workspace_notification, send_workspace_setting_notification, + FolderNotification, +}; +use crate::user_default::{gen_workspace_id, DefaultFolderBuilder}; +use crate::view_ext::{ + gen_view_id, view_from_create_view_params, ViewDataProcessor, ViewDataProcessorMap, +}; +use collab::plugin_impl::disk::CollabDiskPlugin; +use collab::preclude::CollabBuilder; +use collab_folder::core::{ + Folder as InnerFolder, FolderContext, TrashChange, TrashChangeReceiver, TrashInfo, TrashRecord, + View, ViewChange, ViewChangeReceiver, ViewLayout, Workspace, +}; +use collab_persistence::CollabKV; +use flowy_error::{FlowyError, FlowyResult}; +use lib_infra::util::timestamp; +use parking_lot::Mutex; +use std::collections::{HashMap, HashSet}; +use std::ops::Deref; +use std::sync::Arc; +use tracing::{event, Level}; + +pub trait FolderUser: Send + Sync { + fn user_id(&self) -> Result; + fn token(&self) -> Result; + fn kv_db(&self) -> Result, FlowyError>; +} + +pub struct Folder2Manager { + folder: Folder, + user: Arc, + view_processors: ViewDataProcessorMap, +} + +unsafe impl Send for Folder2Manager {} +unsafe impl Sync for Folder2Manager {} + +impl Folder2Manager { + pub async fn new( + user: Arc, + view_processors: ViewDataProcessorMap, + ) -> FlowyResult { + // let folder = make_user_folder(user.clone())?; + let folder = Folder::default(); + let manager = Self { + user, + folder, + view_processors, + }; + + Ok(manager) + } + + pub async fn get_current_workspace(&self) -> FlowyResult { + match self.with_folder(None, |folder| folder.get_current_workspace()) { + None => Err(FlowyError::record_not_found().context("Can not find the workspace")), + Some(workspace) => Ok(workspace), + } + } + + pub async fn get_current_workspace_views(&self) -> FlowyResult> { + let views = self.with_folder(vec![], |folder| { + let trash_ids = folder + .trash + .get_all_trash() + .into_iter() + .map(|trash| trash.id) + .collect::>(); + + let mut views = folder.get_views_belong_to_current_workspace(); + views.retain(|view| !trash_ids.contains(&view.id)); + views + }); + + Ok(views) + } + + pub async fn get_workspace_views( + &self, + workspace_id: &str, + filter: F, + ) -> FlowyResult> + where + F: Fn(&ViewLayout) -> bool, + { + Ok(self.with_folder(vec![], |folder| { + folder + .views + .get_views_belong_to(workspace_id) + .into_iter() + .filter(|view| filter(&view.layout)) + .collect::>() + })) + } + + /// Called immediately after the application launched with the user sign in/sign up. + #[tracing::instrument(level = "trace", skip(self), err)] + pub async fn initialize(&self, user_id: i64) -> FlowyResult<()> { + if let Ok(uid) = self.user.user_id() { + let folder_id = FolderId::new(uid); + let mut collab = CollabBuilder::new(uid, folder_id).build(); + if let Ok(kv_db) = self.user.kv_db() { + let disk_plugin = Arc::new( + CollabDiskPlugin::new(uid, kv_db).map_err(|err| FlowyError::internal().context(err))?, + ); + collab.add_plugin(disk_plugin); + collab.initial(); + } + + let (view_tx, view_rx) = tokio::sync::broadcast::channel(100); + let (trash_tx, trash_rx) = tokio::sync::broadcast::channel(100); + let folder_context = FolderContext { + view_change_tx: Some(view_tx), + trash_change_tx: Some(trash_tx), + }; + *self.folder.lock() = Some(InnerFolder::create(collab, folder_context)); + listen_on_trash_change(trash_rx, self.folder.clone()); + listen_on_view_change(view_rx, self.folder.clone()); + } + + Ok(()) + } + + pub async fn initialize_with_new_user(&self, user_id: i64, token: &str) -> FlowyResult<()> { + self.initialize(user_id).await?; + let (folder_data, workspace_pb) = + DefaultFolderBuilder::build(self.user.user_id()?, &self.view_processors).await; + self.with_folder((), |folder| { + folder.create_with_data(folder_data); + }); + + send_notification(token, FolderNotification::DidCreateWorkspace) + .payload(RepeatedWorkspacePB { + items: vec![workspace_pb], + }) + .send(); + Ok(()) + } + + /// Called when the current user logout + /// + pub async fn clear(&self, _user_id: i64) { + todo!() + } + + pub async fn create_workspace(&self, params: CreateWorkspaceParams) -> FlowyResult { + let workspace = Workspace { + id: gen_workspace_id(), + name: params.name, + belongings: Default::default(), + created_at: timestamp(), + }; + + self.with_folder((), |folder| { + folder.workspaces.create_workspace(workspace.clone()); + folder.set_current_workspace(&workspace.id); + }); + + let repeated_workspace = RepeatedWorkspacePB { + items: vec![workspace.clone().into()], + }; + send_workspace_notification(FolderNotification::DidCreateWorkspace, repeated_workspace); + Ok(workspace) + } + + pub async fn open_workspace(&self, workspace_id: &str) -> FlowyResult { + self.with_folder(Err(FlowyError::internal()), |folder| { + let workspace = folder + .workspaces + .get_workspace(workspace_id) + .ok_or_else(|| { + FlowyError::record_not_found().context("Can't open not existing workspace") + })?; + folder.set_current_workspace(workspace_id); + Ok::(workspace) + }) + } + + pub async fn get_workspace(&self, workspace_id: &str) -> Option { + self.with_folder(None, |folder| folder.workspaces.get_workspace(workspace_id)) + } + + fn with_folder(&self, default_value: Output, f: F) -> Output + where + F: FnOnce(&InnerFolder) -> Output, + { + let folder = self.folder.lock(); + match &*folder { + None => default_value, + Some(folder) => f(folder), + } + } + + pub async fn get_all_workspaces(&self) -> Vec { + self.with_folder(vec![], |folder| folder.workspaces.get_all_workspaces()) + } + + pub async fn create_view_with_params(&self, params: CreateViewParams) -> FlowyResult { + let view_layout: ViewLayout = params.layout.clone().into(); + let processor = self.get_data_processor(&view_layout)?; + let user_id = self.user.user_id()?; + let ext = params.ext.clone(); + match params.initial_data.is_empty() { + true => { + tracing::trace!("Create view with build-in data"); + processor + .create_view_with_build_in_data( + user_id, + ¶ms.view_id, + ¶ms.name, + view_layout.clone(), + ext, + ) + .await?; + }, + false => { + tracing::trace!("Create view with view data"); + processor + .create_view_with_custom_data( + user_id, + ¶ms.view_id, + ¶ms.name, + params.initial_data.clone(), + view_layout.clone(), + ext, + ) + .await?; + }, + } + let view = view_from_create_view_params(params, view_layout); + self.with_folder((), |folder| { + folder.insert_view(view.clone()); + }); + + notify_parent_view_did_change(self.folder.clone(), vec![view.bid.clone()]); + Ok(view) + } + + #[tracing::instrument(level = "debug", skip(self), err)] + pub(crate) async fn close_view(&self, view_id: &str) -> Result<(), FlowyError> { + let view = self + .with_folder(None, |folder| folder.views.get_view(view_id)) + .ok_or_else(|| { + FlowyError::record_not_found().context("Can't find the view when closing the view") + })?; + let processor = self.get_data_processor(&view.layout)?; + processor.close_view(view_id).await?; + Ok(()) + } + + pub async fn create_view_data( + &self, + view_id: &str, + name: &str, + view_layout: ViewLayout, + data: Vec, + ) -> FlowyResult<()> { + let user_id = self.user.user_id()?; + let processor = self.get_data_processor(&view_layout)?; + processor + .create_view_with_custom_data( + user_id, + view_id, + name, + data, + view_layout, + HashMap::default(), + ) + .await?; + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self, view_id), err)] + pub async fn get_view(&self, view_id: &str) -> FlowyResult { + let view_id = view_id.to_string(); + let folder = self.folder.lock(); + let folder = folder.as_ref().ok_or_else(folder_not_init_error)?; + let trash_ids = folder + .trash + .get_all_trash() + .into_iter() + .map(|trash| trash.id) + .collect::>(); + + if trash_ids.contains(&view_id) { + return Err(FlowyError::record_not_found()); + } + + match folder.views.get_view(&view_id) { + None => Err(FlowyError::record_not_found()), + Some(mut view) => { + view.belongings.retain(|b| !trash_ids.contains(&b.id)); + let mut view_pb: ViewPB = view.into(); + view_pb.belongings = folder + .views + .get_views_belong_to(&view_pb.id) + .into_iter() + .filter(|view| !trash_ids.contains(&view.id)) + .map(|view| view.into()) + .collect::>(); + Ok(view_pb) + }, + } + } + + #[tracing::instrument(level = "debug", skip(self, view_id), err)] + pub async fn delete_view(&self, view_id: &str) -> FlowyResult<()> { + self.with_folder((), |folder| folder.views.delete_views(vec![view_id])); + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self), err)] + pub async fn move_view_to_trash(&self, view_id: &str) -> FlowyResult<()> { + self.with_folder((), |folder| { + folder.trash.add_trash(vec![TrashRecord { + id: view_id.to_string(), + created_at: timestamp(), + }]); + + if let Some(view) = folder.get_current_view() { + if view == view_id { + folder.set_current_view(""); + } + } + }); + + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self), err)] + pub async fn move_view(&self, view_id: &str, from: usize, to: usize) -> FlowyResult<()> { + let view = self.with_folder(None, |folder| { + folder.move_view(view_id, from as u32, to as u32) + }); + + match view { + None => tracing::error!("Couldn't find the view. It should not be empty"), + Some(view) => { + notify_parent_view_did_change(self.folder.clone(), vec![view.bid]); + }, + } + Ok(()) + } + + #[tracing::instrument(level = "debug", skip(self, bid), err)] + pub async fn get_views_belong_to(&self, bid: &str) -> FlowyResult> { + let views = self.with_folder(vec![], |folder| folder.views.get_views_belong_to(bid)); + Ok(views) + } + + #[tracing::instrument(level = "trace", skip(self), err)] + pub async fn update_view_with_params(&self, params: UpdateViewParams) -> FlowyResult { + let view = self + .folder + .lock() + .as_ref() + .ok_or_else(folder_not_init_error)? + .views + .update_view(¶ms.view_id, |update| { + update + .set_name_if_not_none(params.name) + .set_desc_if_not_none(params.desc) + .done() + }); + + match view { + None => Err(FlowyError::record_not_found()), + Some(view) => { + let view_pb: ViewPB = view.clone().into(); + send_notification(&view.id, FolderNotification::DidUpdateView) + .payload(view_pb) + .send(); + + notify_parent_view_did_change(self.folder.clone(), vec![view.bid.clone()]); + Ok(view) + }, + } + } + + #[tracing::instrument(level = "debug", skip(self), err)] + pub(crate) async fn duplicate_view(&self, view_id: &str) -> Result<(), FlowyError> { + let view = self + .with_folder(None, |folder| folder.views.get_view(view_id)) + .ok_or_else(|| FlowyError::record_not_found().context("Can't duplicate the view"))?; + + let processor = self.get_data_processor(&view.layout)?; + let view_data = processor.get_view_data(&view.id).await?; + let mut ext = HashMap::new(); + if let Some(database_id) = view.database_id { + ext.insert("database_id".to_string(), database_id); + } + let duplicate_params = CreateViewParams { + belong_to_id: view.bid.clone(), + name: format!("{} (copy)", &view.name), + desc: view.desc, + layout: view.layout.into(), + initial_data: view_data.to_vec(), + view_id: gen_view_id(), + ext, + }; + + let _ = self.create_view_with_params(duplicate_params).await?; + Ok(()) + } + + #[tracing::instrument(level = "trace", skip(self), err)] + pub(crate) async fn set_current_view(&self, view_id: &str) -> Result<(), FlowyError> { + let folder = self.folder.lock(); + let folder = folder.as_ref().ok_or_else(folder_not_init_error)?; + folder.set_current_view(view_id); + + let workspace = folder.get_current_workspace(); + let view = folder + .get_current_view() + .and_then(|view_id| folder.views.get_view(&view_id)); + send_workspace_setting_notification(workspace, view); + Ok(()) + } + + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn get_current_view(&self) -> Option { + let view_id = self.with_folder(None, |folder| folder.get_current_view())?; + self.get_view(&view_id).await.ok() + } + + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn get_all_trash(&self) -> Vec { + self.with_folder(vec![], |folder| folder.trash.get_all_trash()) + } + + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn restore_all_trash(&self) { + self.with_folder((), |folder| { + folder.trash.clear(); + }); + + send_notification("trash", FolderNotification::DidUpdateTrash) + .payload(RepeatedTrashPB { items: vec![] }) + .send(); + } + + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn restore_trash(&self, trash_id: &str) { + self.with_folder((), |folder| { + folder.trash.delete_trash(vec![trash_id]); + }); + } + + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn delete_trash(&self, trash_id: &str) { + self.with_folder((), |folder| { + folder.trash.delete_trash(vec![trash_id]); + folder.views.delete_views(vec![trash_id]); + }) + } + + #[tracing::instrument(level = "trace", skip(self))] + pub(crate) async fn delete_all_trash(&self) { + self.with_folder((), |folder| { + let trash = folder.trash.get_all_trash(); + folder.trash.clear(); + folder.views.delete_views(trash); + }); + + send_notification("trash", FolderNotification::DidUpdateTrash) + .payload(RepeatedTrashPB { items: vec![] }) + .send(); + } + + fn get_data_processor( + &self, + view_layout: &ViewLayout, + ) -> FlowyResult> { + match self.view_processors.get(view_layout) { + None => Err(FlowyError::internal().context(format!( + "Get data processor failed. Unknown layout type: {:?}", + view_layout + ))), + Some(processor) => Ok(processor.clone()), + } + } +} + +/// Listen on the [ViewChange] after create/delete/update events happened +fn listen_on_view_change(mut rx: ViewChangeReceiver, folder: Folder) { + tokio::spawn(async move { + while let Ok(value) = rx.recv().await { + match value { + ViewChange::DidCreateView { view } => { + notify_parent_view_did_change(folder.clone(), vec![view.bid]); + }, + ViewChange::DidDeleteView { views: _ } => {}, + ViewChange::DidUpdate { view } => { + notify_parent_view_did_change(folder.clone(), vec![view.bid]); + }, + }; + } + }); +} + +/// Listen on the [TrashChange]s and notify the frontend some views were changed. +fn listen_on_trash_change(mut rx: TrashChangeReceiver, folder: Folder) { + tokio::spawn(async move { + while let Ok(value) = rx.recv().await { + let mut unique_ids = HashSet::new(); + tracing::trace!("Did receive trash change: {:?}", value); + let ids = match value { + TrashChange::DidCreateTrash { ids } => ids, + TrashChange::DidDeleteTrash { ids } => ids, + }; + + if let Some(folder) = folder.lock().as_ref() { + let views = folder.views.get_views(&ids); + for view in views { + unique_ids.insert(view.bid); + } + + let repeated_trash: RepeatedTrashPB = folder.trash.get_all_trash().into(); + send_notification("trash", FolderNotification::DidUpdateTrash) + .payload(repeated_trash) + .send(); + } + + let parent_view_ids = unique_ids.into_iter().collect(); + notify_parent_view_did_change(folder.clone(), parent_view_ids); + } + }); +} + +#[tracing::instrument(level = "debug", skip(folder, parent_view_ids))] +fn notify_parent_view_did_change>( + folder: Folder, + parent_view_ids: Vec, +) -> Option<()> { + let folder = folder.lock(); + let folder = folder.as_ref()?; + let workspace_id = folder.get_current_workspace_id()?; + let trash_ids = folder + .trash + .get_all_trash() + .into_iter() + .map(|trash| trash.id) + .collect::>(); + + for parent_view_id in parent_view_ids { + let parent_view_id = parent_view_id.as_ref(); + + // if the view's bid is equal to workspace id. Then it will fetch the current + // workspace views. Because the the workspace is not a view stored in the views map. + if parent_view_id == workspace_id { + let mut child_views = folder.get_views_belong_to_current_workspace(); + child_views.retain(|view| !trash_ids.contains(&view.id)); + let repeated_view: RepeatedViewPB = child_views.into(); + send_notification(&workspace_id, FolderNotification::DidUpdateWorkspaceViews) + .payload(repeated_view) + .send(); + } else { + // Parent view can contain a list of child views. Currently, only get the first level + // child views. + let parent_view = folder.views.get_view(parent_view_id)?; + let mut child_views = folder.views.get_views_belong_to(parent_view_id); + child_views.retain(|view| !trash_ids.contains(&view.id)); + event!(Level::DEBUG, child_views_count = child_views.len()); + + // Post the notification + let mut parent_view_pb: ViewPB = parent_view.into(); + parent_view_pb.belongings = child_views + .into_iter() + .map(|child_view| child_view.into()) + .collect::>(); + send_notification(parent_view_id, FolderNotification::DidUpdateChildViews) + .payload(parent_view_pb) + .send(); + } + } + + None +} + +fn folder_not_init_error() -> FlowyError { + FlowyError::internal().context("Folder not initialized") +} + +#[derive(Clone)] +pub struct FolderId(String); +impl FolderId { + pub fn new(uid: i64) -> Self { + Self(format!("{}:folder", uid)) + } +} + +impl AsRef for FolderId { + fn as_ref(&self) -> &str { + &self.0 + } +} +#[derive(Clone, Default)] +pub struct Folder(Arc>>); + +impl Deref for Folder { + type Target = Arc>>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +unsafe impl Sync for Folder {} + +unsafe impl Send for Folder {} diff --git a/frontend/rust-lib/flowy-folder2/src/notification.rs b/frontend/rust-lib/flowy-folder2/src/notification.rs new file mode 100644 index 0000000000..5599b68d2f --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/notification.rs @@ -0,0 +1,72 @@ +use crate::entities::{ViewPB, WorkspacePB, WorkspaceSettingPB}; +use collab_folder::core::{View, Workspace}; +use flowy_derive::ProtoBuf_Enum; +use flowy_notification::NotificationBuilder; +use lib_dispatch::prelude::ToBytes; + +const OBSERVABLE_CATEGORY: &str = "Workspace"; + +#[derive(ProtoBuf_Enum, Debug)] +pub(crate) enum FolderNotification { + Unknown = 0, + /// Trigger after creating a workspace + DidCreateWorkspace = 1, + // /// Trigger after updating a workspace + DidUpdateWorkspace = 2, + + DidUpdateWorkspaceViews = 3, + /// Trigger when the settings of the workspace are changed. The changes including the latest visiting view, etc + DidUpdateWorkspaceSetting = 4, + + DidUpdateView = 29, + /// Trigger when the properties including rename,update description of the view are changed + DidUpdateChildViews = 30, + /// Trigger after deleting the view + DidDeleteView = 31, + /// Trigger when restore the view from trash + DidRestoreView = 32, + /// Trigger after moving the view to trash + DidMoveViewToTrash = 33, + /// Trigger when the number of trash is changed + DidUpdateTrash = 34, +} + +impl std::default::Default for FolderNotification { + fn default() -> Self { + FolderNotification::Unknown + } +} + +impl std::convert::From for i32 { + fn from(notification: FolderNotification) -> Self { + notification as i32 + } +} + +#[tracing::instrument(level = "trace")] +pub(crate) fn send_notification(id: &str, ty: FolderNotification) -> NotificationBuilder { + NotificationBuilder::new(id, ty, OBSERVABLE_CATEGORY) +} + +/// The [CURRENT_WORKSPACE] represents as the current workspace that opened by the +/// user. Only one workspace can be opened at a time. +const CURRENT_WORKSPACE: &str = "current-workspace"; +pub(crate) fn send_workspace_notification(ty: FolderNotification, payload: T) { + send_notification(CURRENT_WORKSPACE, ty) + .payload(payload) + .send(); +} + +pub(crate) fn send_workspace_setting_notification( + current_workspace: Option, + current_view: Option, +) -> Option<()> { + let workspace: WorkspacePB = current_workspace?.into(); + let latest_view = current_view.map(ViewPB::from); + let setting = WorkspaceSettingPB { + workspace, + latest_view, + }; + send_workspace_notification(FolderNotification::DidUpdateWorkspaceSetting, setting); + None +} diff --git a/frontend/rust-lib/flowy-folder2/src/test_helper.rs b/frontend/rust-lib/flowy-folder2/src/test_helper.rs new file mode 100644 index 0000000000..f6a243336a --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/test_helper.rs @@ -0,0 +1,50 @@ +use crate::entities::{CreateViewParams, ViewLayoutTypePB}; +use crate::manager::Folder2Manager; +use crate::view_ext::gen_view_id; +use std::collections::HashMap; + +#[cfg(feature = "test_helper")] +impl Folder2Manager { + pub async fn create_test_grid_view( + &self, + app_id: &str, + name: &str, + ext: HashMap, + ) -> String { + self + .create_test_view(app_id, name, ViewLayoutTypePB::Grid, ext) + .await + } + + pub async fn create_test_board_view( + &self, + app_id: &str, + name: &str, + ext: HashMap, + ) -> String { + self + .create_test_view(app_id, name, ViewLayoutTypePB::Board, ext) + .await + } + + async fn create_test_view( + &self, + app_id: &str, + name: &str, + layout: ViewLayoutTypePB, + ext: HashMap, + ) -> String { + let view_id = gen_view_id(); + let params = CreateViewParams { + belong_to_id: app_id.to_string(), + name: name.to_string(), + desc: "".to_string(), + layout, + view_id: view_id.clone(), + initial_data: vec![], + ext, + }; + self.create_view_with_params(params).await.unwrap(); + view_id + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/user_default.rs b/frontend/rust-lib/flowy-folder2/src/user_default.rs new file mode 100644 index 0000000000..879a91ea32 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/user_default.rs @@ -0,0 +1,105 @@ +use crate::entities::{ViewPB, WorkspacePB}; + +use crate::view_ext::{gen_view_id, ViewDataProcessorMap}; +use chrono::Utc; +use collab_folder::core::{Belonging, Belongings, FolderData, View, ViewLayout, Workspace}; +use flowy_document::editor::initial_read_me; +use nanoid::nanoid; +use std::collections::HashMap; + +pub struct DefaultFolderBuilder(); +impl DefaultFolderBuilder { + pub async fn build( + uid: i64, + view_processors: &ViewDataProcessorMap, + ) -> (FolderData, WorkspacePB) { + let time = Utc::now().timestamp(); + let workspace_id = gen_workspace_id(); + let view_id = gen_view_id(); + let child_view_id = gen_view_id(); + + let child_view_layout = ViewLayout::Document; + let child_view = View { + id: child_view_id.clone(), + bid: view_id.clone(), + name: "Read me".to_string(), + desc: "".to_string(), + belongings: Default::default(), + created_at: time, + layout: child_view_layout.clone(), + database_id: None, + }; + + // create the document + let data = initial_read_me().into_bytes(); + let processor = view_processors.get(&child_view_layout).unwrap(); + processor + .create_view_with_custom_data( + uid, + &child_view.id, + &child_view.name, + data, + child_view_layout.clone(), + HashMap::default(), + ) + .await + .unwrap(); + + let view = View { + id: view_id, + bid: workspace_id.clone(), + name: "⭐️ Getting started".to_string(), + desc: "".to_string(), + belongings: Belongings::new(vec![Belonging { + id: child_view.id.clone(), + name: child_view.name.clone(), + }]), + created_at: time, + layout: ViewLayout::Document, + database_id: None, + }; + + let workspace = Workspace { + id: workspace_id, + name: "Workspace".to_string(), + belongings: Belongings::new(vec![Belonging { + id: view.id.clone(), + name: view.name.clone(), + }]), + created_at: time, + }; + + let workspace_pb = workspace_pb_from_workspace(&workspace, &view, &child_view); + + ( + FolderData { + current_workspace: workspace.id.clone(), + current_view: child_view_id, + workspaces: vec![workspace], + views: vec![view, child_view], + }, + workspace_pb, + ) + } +} + +pub fn gen_workspace_id() -> String { + nanoid!(10) +} + +fn workspace_pb_from_workspace( + workspace: &Workspace, + view: &View, + child_view: &View, +) -> WorkspacePB { + let child_view_pb: ViewPB = child_view.clone().into(); + let mut view_pb: ViewPB = view.clone().into(); + view_pb.belongings.push(child_view_pb); + + WorkspacePB { + id: workspace.id.clone(), + name: workspace.name.clone(), + views: vec![view_pb], + create_time: workspace.created_at, + } +} diff --git a/frontend/rust-lib/flowy-folder2/src/view_ext.rs b/frontend/rust-lib/flowy-folder2/src/view_ext.rs new file mode 100644 index 0000000000..fa371840d7 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/src/view_ext.rs @@ -0,0 +1,72 @@ +use crate::entities::{CreateViewParams, ViewLayoutTypePB}; +use bytes::Bytes; +use collab_folder::core::{View, ViewLayout}; +use flowy_error::FlowyError; +use lib_infra::future::FutureResult; +use lib_infra::util::timestamp; +use nanoid::nanoid; +use std::collections::HashMap; +use std::sync::Arc; + +pub trait ViewDataProcessor { + /// Closes the view and releases the resources that this view has in + /// the backend + fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError>; + + /// Gets the data of the this view. + /// For example, the data can be used to duplicate the view. + fn get_view_data(&self, view_id: &str) -> FutureResult; + + /// Create a view with the pre-defined data. + /// For example, the initial data of the grid/calendar/kanban board when + /// you create a new view. + fn create_view_with_build_in_data( + &self, + user_id: i64, + view_id: &str, + name: &str, + layout: ViewLayout, + ext: HashMap, + ) -> FutureResult<(), FlowyError>; + + /// Create a view with custom data + fn create_view_with_custom_data( + &self, + user_id: i64, + view_id: &str, + name: &str, + data: Vec, + layout: ViewLayout, + ext: HashMap, + ) -> FutureResult<(), FlowyError>; +} + +pub type ViewDataProcessorMap = Arc>>; + +impl From for ViewLayout { + fn from(pb: ViewLayoutTypePB) -> Self { + match pb { + ViewLayoutTypePB::Document => ViewLayout::Document, + ViewLayoutTypePB::Grid => ViewLayout::Grid, + ViewLayoutTypePB::Board => ViewLayout::Board, + ViewLayoutTypePB::Calendar => ViewLayout::Calendar, + } + } +} + +pub fn view_from_create_view_params(params: CreateViewParams, layout: ViewLayout) -> View { + let time = timestamp(); + View { + id: params.view_id, + bid: params.belong_to_id, + name: params.name, + desc: params.desc, + belongings: Default::default(), + created_at: time, + layout, + database_id: None, + } +} +pub fn gen_view_id() -> String { + format!("v:{}", nanoid!(10)) +} diff --git a/frontend/rust-lib/flowy-folder2/tests/workspace/folder_test.rs b/frontend/rust-lib/flowy-folder2/tests/workspace/folder_test.rs new file mode 100644 index 0000000000..1171f34132 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/tests/workspace/folder_test.rs @@ -0,0 +1,273 @@ +use crate::script::{invalid_workspace_name_test_case, FolderScript::*, FolderTest}; +use collab_folder::core::ViewLayout; +use flowy_folder2::entities::CreateWorkspacePayloadPB; +use flowy_test::{event_builder::*, FlowySDKTest}; + +#[tokio::test] +async fn workspace_read_all() { + let mut test = FolderTest::new().await; + test.run_scripts(vec![ReadAllWorkspaces]).await; + assert!(!test.all_workspace.is_empty()); +} + +#[tokio::test] +async fn workspace_create() { + let mut test = FolderTest::new().await; + let name = "My new workspace".to_owned(); + let desc = "Daily routines".to_owned(); + test + .run_scripts(vec![CreateWorkspace { + name: name.clone(), + desc: desc.clone(), + }]) + .await; + + let workspace = test.workspace.clone(); + assert_eq!(workspace.name, name); + + test + .run_scripts(vec![ + ReadWorkspace(Some(workspace.id.clone())), + AssertWorkspace(workspace), + ]) + .await; +} + +#[tokio::test] +async fn workspace_read() { + let mut test = FolderTest::new().await; + let workspace = test.workspace.clone(); + + test + .run_scripts(vec![ + ReadWorkspace(Some(workspace.id.clone())), + AssertWorkspace(workspace), + ]) + .await; +} + +#[tokio::test] +async fn workspace_create_with_apps() { + let mut test = FolderTest::new().await; + test + .run_scripts(vec![CreateApp { + name: "App".to_string(), + desc: "App description".to_string(), + }]) + .await; + + let app = test.parent_view.clone(); + test.run_scripts(vec![RefreshRootView(app.id)]).await; +} + +#[tokio::test] +async fn workspace_create_with_invalid_name() { + for (name, code) in invalid_workspace_name_test_case() { + let sdk = FlowySDKTest::default(); + let request = CreateWorkspacePayloadPB { + name, + desc: "".to_owned(), + }; + assert_eq!( + Folder2EventBuilder::new(sdk) + .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace) + .payload(request) + .async_send() + .await + .error() + .code, + code.value() + ) + } +} + +#[tokio::test] +#[should_panic] +async fn app_delete() { + let mut test = FolderTest::new().await; + let app = test.parent_view.clone(); + test + .run_scripts(vec![DeleteRootView, RefreshRootView(app.id)]) + .await; +} + +#[tokio::test] +async fn app_delete_then_restore() { + let mut test = FolderTest::new().await; + test + .run_scripts(vec![RefreshRootView(test.parent_view.id.clone())]) + .await; + + let parent_view = test.parent_view.clone(); + test + .run_scripts(vec![ + DeleteRootView, + RestoreAppFromTrash, + RefreshRootView(parent_view.id.clone()), + AssertRootView(parent_view), + ]) + .await; +} + +#[tokio::test] +async fn app_update() { + let mut test = FolderTest::new().await; + let app = test.parent_view.clone(); + let new_name = "😁 hell world".to_owned(); + assert_ne!(app.name, new_name); + + test + .run_scripts(vec![ + UpdateRootView { + name: Some(new_name.clone()), + desc: None, + }, + RefreshRootView(app.id), + ]) + .await; + assert_eq!(test.parent_view.name, new_name); +} + +#[tokio::test] +async fn app_create_with_view() { + let mut test = FolderTest::new().await; + let mut app = test.parent_view.clone(); + test + .run_scripts(vec![ + CreateView { + name: "View A".to_owned(), + desc: "View A description".to_owned(), + layout: ViewLayout::Document, + }, + CreateView { + name: "Grid".to_owned(), + desc: "Grid description".to_owned(), + layout: ViewLayout::Grid, + }, + RefreshRootView(app.id), + ]) + .await; + + app = test.parent_view.clone(); + assert_eq!(app.belongings.len(), 3); + assert_eq!(app.belongings[1].name, "View A"); + assert_eq!(app.belongings[2].name, "Grid") +} + +#[tokio::test] +async fn view_update() { + let mut test = FolderTest::new().await; + let view = test.child_view.clone(); + let new_name = "😁 123".to_owned(); + assert_ne!(view.name, new_name); + + test + .run_scripts(vec![ + UpdateView { + name: Some(new_name.clone()), + desc: None, + }, + ReadView(view.id), + ]) + .await; + assert_eq!(test.child_view.name, new_name); +} + +#[tokio::test] +#[should_panic] +async fn view_delete() { + let mut test = FolderTest::new().await; + let view = test.child_view.clone(); + test.run_scripts(vec![DeleteView, ReadView(view.id)]).await; +} + +#[tokio::test] +async fn view_delete_then_restore() { + let mut test = FolderTest::new().await; + let view = test.child_view.clone(); + test + .run_scripts(vec![ + DeleteView, + RestoreViewFromTrash, + ReadView(view.id.clone()), + AssertView(view), + ]) + .await; +} + +#[tokio::test] +async fn view_delete_all() { + let mut test = FolderTest::new().await; + let parent_view = test.parent_view.clone(); + test + .run_scripts(vec![ + CreateView { + name: "View A".to_owned(), + desc: "View A description".to_owned(), + layout: ViewLayout::Document, + }, + CreateView { + name: "Grid".to_owned(), + desc: "Grid description".to_owned(), + layout: ViewLayout::Grid, + }, + RefreshRootView(parent_view.id.clone()), + ]) + .await; + + assert_eq!( + test.parent_view.belongings.len(), + 3, + "num of belongings should be 3" + ); + let view_ids = test + .parent_view + .belongings + .iter() + .map(|view| view.id.clone()) + .collect::>(); + test + .run_scripts(vec![ + DeleteViews(view_ids), + RefreshRootView(parent_view.id), + ReadTrash, + ]) + .await; + + assert_eq!(test.parent_view.belongings.len(), 0); + assert_eq!(test.trash.len(), 3); +} + +#[tokio::test] +async fn view_delete_all_permanent() { + let mut test = FolderTest::new().await; + let app = test.parent_view.clone(); + test + .run_scripts(vec![ + CreateView { + name: "View A".to_owned(), + desc: "View A description".to_owned(), + layout: ViewLayout::Document, + }, + RefreshRootView(app.id.clone()), + ]) + .await; + + let view_ids = test + .parent_view + .belongings + .iter() + .map(|view| view.id.clone()) + .collect::>(); + test + .run_scripts(vec![ + DeleteViews(view_ids), + RefreshRootView(app.id), + DeleteAllTrash, + ReadTrash, + ]) + .await; + + assert_eq!(test.parent_view.belongings.len(), 0); + assert_eq!(test.trash.len(), 0); +} diff --git a/frontend/rust-lib/flowy-folder2/tests/workspace/main.rs b/frontend/rust-lib/flowy-folder2/tests/workspace/main.rs new file mode 100644 index 0000000000..ff48b349e1 --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/tests/workspace/main.rs @@ -0,0 +1,2 @@ +mod folder_test; +mod script; diff --git a/frontend/rust-lib/flowy-folder2/tests/workspace/script.rs b/frontend/rust-lib/flowy-folder2/tests/workspace/script.rs new file mode 100644 index 0000000000..aadc7d2fcf --- /dev/null +++ b/frontend/rust-lib/flowy-folder2/tests/workspace/script.rs @@ -0,0 +1,329 @@ +use collab_folder::core::ViewLayout; +use flowy_error::ErrorCode; +use flowy_folder2::entities::*; +use flowy_folder2::event_map::FolderEvent::*; +use flowy_test::event_builder::Folder2EventBuilder; +use flowy_test::FlowySDKTest; + +pub enum FolderScript { + // Workspace + ReadAllWorkspaces, + CreateWorkspace { + name: String, + desc: String, + }, + AssertWorkspace(WorkspacePB), + ReadWorkspace(Option), + + // App + CreateApp { + name: String, + desc: String, + }, + AssertRootView(ViewPB), + RefreshRootView(String), + UpdateRootView { + name: Option, + desc: Option, + }, + DeleteRootView, + + // View + CreateView { + name: String, + desc: String, + layout: ViewLayout, + }, + AssertView(ViewPB), + ReadView(String), + UpdateView { + name: Option, + desc: Option, + }, + DeleteView, + DeleteViews(Vec), + + // Trash + RestoreAppFromTrash, + RestoreViewFromTrash, + ReadTrash, + DeleteAllTrash, +} + +pub struct FolderTest { + pub sdk: FlowySDKTest, + pub all_workspace: Vec, + pub workspace: WorkspacePB, + pub parent_view: ViewPB, + pub child_view: ViewPB, + pub trash: Vec, +} + +impl FolderTest { + pub async fn new() -> Self { + let sdk = FlowySDKTest::default(); + let _ = sdk.init_user().await; + let workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await; + let parent_view = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await; + let view = create_view( + &sdk, + &parent_view.id, + "Folder View", + "Folder test view", + ViewLayout::Document, + ) + .await; + Self { + sdk, + all_workspace: vec![], + workspace, + parent_view, + child_view: view, + trash: vec![], + } + } + + pub async fn run_scripts(&mut self, scripts: Vec) { + for script in scripts { + self.run_script(script).await; + } + } + + pub async fn run_script(&mut self, script: FolderScript) { + let sdk = &self.sdk; + match script { + FolderScript::ReadAllWorkspaces => { + let all_workspace = read_workspace(sdk, None).await; + self.all_workspace = all_workspace; + }, + FolderScript::CreateWorkspace { name, desc } => { + let workspace = create_workspace(sdk, &name, &desc).await; + self.workspace = workspace; + }, + FolderScript::AssertWorkspace(workspace) => { + assert_eq!(self.workspace, workspace, "Workspace not equal"); + }, + FolderScript::ReadWorkspace(workspace_id) => { + let workspace = read_workspace(sdk, workspace_id).await.pop().unwrap(); + self.workspace = workspace; + }, + FolderScript::CreateApp { name, desc } => { + let app = create_app(sdk, &self.workspace.id, &name, &desc).await; + self.parent_view = app; + }, + FolderScript::AssertRootView(app) => { + assert_eq!(self.parent_view, app, "App not equal"); + }, + FolderScript::RefreshRootView(app_id) => { + let app = read_view(sdk, &app_id).await; + self.parent_view = app; + }, + FolderScript::UpdateRootView { name, desc } => { + update_view(sdk, &self.parent_view.id, name, desc).await; + }, + FolderScript::DeleteRootView => { + delete_view(sdk, vec![self.parent_view.id.clone()]).await; + }, + + FolderScript::CreateView { name, desc, layout } => { + let view = create_view(sdk, &self.parent_view.id, &name, &desc, layout).await; + self.child_view = view; + }, + FolderScript::AssertView(view) => { + assert_eq!(self.child_view, view, "View not equal"); + }, + FolderScript::ReadView(view_id) => { + let view = read_view(sdk, &view_id).await; + self.child_view = view; + }, + FolderScript::UpdateView { name, desc } => { + update_view(sdk, &self.child_view.id, name, desc).await; + }, + FolderScript::DeleteView => { + delete_view(sdk, vec![self.child_view.id.clone()]).await; + }, + FolderScript::DeleteViews(view_ids) => { + delete_view(sdk, view_ids).await; + }, + FolderScript::RestoreAppFromTrash => { + restore_app_from_trash(sdk, &self.parent_view.id).await; + }, + FolderScript::RestoreViewFromTrash => { + restore_view_from_trash(sdk, &self.child_view.id).await; + }, + FolderScript::ReadTrash => { + let trash = read_trash(sdk).await; + self.trash = trash.items; + }, + FolderScript::DeleteAllTrash => { + delete_all_trash(sdk).await; + self.trash = vec![]; + }, + } + } +} + +pub fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> { + vec![ + ("".to_owned(), ErrorCode::WorkspaceNameInvalid), + ("1234".repeat(100), ErrorCode::WorkspaceNameTooLong), + ] +} + +pub async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> WorkspacePB { + let request = CreateWorkspacePayloadPB { + name: name.to_owned(), + desc: desc.to_owned(), + }; + + Folder2EventBuilder::new(sdk.clone()) + .event(CreateWorkspace) + .payload(request) + .async_send() + .await + .parse::() +} + +pub async fn read_workspace(sdk: &FlowySDKTest, workspace_id: Option) -> Vec { + let request = WorkspaceIdPB { + value: workspace_id, + }; + let repeated_workspace = Folder2EventBuilder::new(sdk.clone()) + .event(ReadWorkspaces) + .payload(request.clone()) + .async_send() + .await + .parse::(); + + let workspaces; + if let Some(workspace_id) = &request.value { + workspaces = repeated_workspace + .items + .into_iter() + .filter(|workspace| &workspace.id == workspace_id) + .collect::>(); + debug_assert_eq!(workspaces.len(), 1); + } else { + workspaces = repeated_workspace.items; + } + + workspaces +} + +pub async fn create_app(sdk: &FlowySDKTest, workspace_id: &str, name: &str, desc: &str) -> ViewPB { + let create_view_request = CreateViewPayloadPB { + belong_to_id: workspace_id.to_owned(), + name: name.to_string(), + desc: desc.to_string(), + thumbnail: None, + layout: ViewLayout::Document.into(), + initial_data: vec![], + ext: Default::default(), + }; + + Folder2EventBuilder::new(sdk.clone()) + .event(CreateView) + .payload(create_view_request) + .async_send() + .await + .parse::() +} + +pub async fn create_view( + sdk: &FlowySDKTest, + app_id: &str, + name: &str, + desc: &str, + layout: ViewLayout, +) -> ViewPB { + let request = CreateViewPayloadPB { + belong_to_id: app_id.to_string(), + name: name.to_string(), + desc: desc.to_string(), + thumbnail: None, + layout: layout.into(), + initial_data: vec![], + ext: Default::default(), + }; + Folder2EventBuilder::new(sdk.clone()) + .event(CreateView) + .payload(request) + .async_send() + .await + .parse::() +} + +pub async fn read_view(sdk: &FlowySDKTest, view_id: &str) -> ViewPB { + let view_id: ViewIdPB = view_id.into(); + Folder2EventBuilder::new(sdk.clone()) + .event(ReadView) + .payload(view_id) + .async_send() + .await + .parse::() +} + +pub async fn update_view( + sdk: &FlowySDKTest, + view_id: &str, + name: Option, + desc: Option, +) { + let request = UpdateViewPayloadPB { + view_id: view_id.to_string(), + name, + desc, + thumbnail: None, + }; + Folder2EventBuilder::new(sdk.clone()) + .event(UpdateView) + .payload(request) + .async_send() + .await; +} + +pub async fn delete_view(sdk: &FlowySDKTest, view_ids: Vec) { + let request = RepeatedViewIdPB { items: view_ids }; + Folder2EventBuilder::new(sdk.clone()) + .event(DeleteView) + .payload(request) + .async_send() + .await; +} + +pub async fn read_trash(sdk: &FlowySDKTest) -> RepeatedTrashPB { + Folder2EventBuilder::new(sdk.clone()) + .event(ReadTrash) + .async_send() + .await + .parse::() +} + +pub async fn restore_app_from_trash(sdk: &FlowySDKTest, app_id: &str) { + let id = TrashIdPB { + id: app_id.to_owned(), + }; + Folder2EventBuilder::new(sdk.clone()) + .event(PutbackTrash) + .payload(id) + .async_send() + .await; +} + +pub async fn restore_view_from_trash(sdk: &FlowySDKTest, view_id: &str) { + let id = TrashIdPB { + id: view_id.to_owned(), + }; + Folder2EventBuilder::new(sdk.clone()) + .event(PutbackTrash) + .payload(id) + .async_send() + .await; +} + +pub async fn delete_all_trash(sdk: &FlowySDKTest) { + Folder2EventBuilder::new(sdk.clone()) + .event(DeleteAllTrash) + .async_send() + .await; +} diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml index addea337b0..a7bc4f23af 100644 --- a/frontend/rust-lib/flowy-net/Cargo.toml +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -19,7 +19,7 @@ flowy-client-ws = { path = "../../../shared-lib/flowy-client-ws"} flowy-client-network-config= { path = "../../../shared-lib/flowy-client-network-config"} flowy-sync = { path = "../../../shared-lib/flowy-sync"} user-model = { path = "../../../shared-lib/user-model"} -flowy-folder = { path = "../flowy-folder" } +flowy-folder2 = { path = "../flowy-folder2" } flowy-user = { path = "../flowy-user" } flowy-document = { path = "../flowy-document" } lazy_static = "1.4.0" diff --git a/frontend/rust-lib/flowy-net/src/http_server/folder.rs b/frontend/rust-lib/flowy-net/src/http_server/folder.rs deleted file mode 100644 index 4694136444..0000000000 --- a/frontend/rust-lib/flowy-net/src/http_server/folder.rs +++ /dev/null @@ -1,457 +0,0 @@ -use crate::request::{HttpRequestBuilder, ResponseMiddleware}; -use crate::response::HttpResponse; -use flowy_client_network_config::ClientServerConfiguration; -use flowy_error::FlowyError; -use flowy_folder::entities::{ - trash::RepeatedTrashIdPB, - view::{CreateViewParams, RepeatedViewIdPB, UpdateViewParams, ViewIdPB}, - workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdPB}, - {AppIdPB, CreateAppParams, UpdateAppParams}, -}; -use flowy_folder::event_map::FolderCouldServiceV1; -use folder_model::{AppRevision, TrashRevision, ViewRevision, WorkspaceRevision}; -use lazy_static::lazy_static; -use lib_infra::future::FutureResult; -use std::sync::Arc; -use tokio::sync::broadcast; - -pub struct FolderHttpCloudService { - config: ClientServerConfiguration, -} - -impl FolderHttpCloudService { - pub fn new(config: ClientServerConfiguration) -> FolderHttpCloudService { - Self { config } - } -} - -impl FolderCouldServiceV1 for FolderHttpCloudService { - fn init(&self) {} - - fn create_workspace( - &self, - token: &str, - params: CreateWorkspaceParams, - ) -> FutureResult { - let token = token.to_owned(); - let url = self.config.workspace_url(); - FutureResult::new(async move { - let workspace = create_workspace_request(&token, params, &url).await?; - Ok(workspace) - }) - } - - fn read_workspace( - &self, - token: &str, - params: WorkspaceIdPB, - ) -> FutureResult, FlowyError> { - let token = token.to_owned(); - let url = self.config.workspace_url(); - FutureResult::new(async move { - let workspace_revs = read_workspaces_request(&token, params, &url).await?; - Ok(workspace_revs) - }) - } - - fn update_workspace( - &self, - token: &str, - params: UpdateWorkspaceParams, - ) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.workspace_url(); - FutureResult::new(async move { - update_workspace_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn delete_workspace(&self, token: &str, params: WorkspaceIdPB) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.workspace_url(); - FutureResult::new(async move { - delete_workspace_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn create_view( - &self, - token: &str, - params: CreateViewParams, - ) -> FutureResult { - let token = token.to_owned(); - let url = self.config.view_url(); - FutureResult::new(async move { - let view = create_view_request(&token, params, &url).await?; - Ok(view) - }) - } - - fn read_view( - &self, - token: &str, - params: ViewIdPB, - ) -> FutureResult, FlowyError> { - let token = token.to_owned(); - let url = self.config.view_url(); - FutureResult::new(async move { - let view_rev = read_view_request(&token, params, &url).await?; - Ok(view_rev) - }) - } - - fn delete_view(&self, token: &str, params: RepeatedViewIdPB) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.view_url(); - FutureResult::new(async move { - delete_view_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn update_view(&self, token: &str, params: UpdateViewParams) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.view_url(); - FutureResult::new(async move { - update_view_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn create_app( - &self, - token: &str, - params: CreateAppParams, - ) -> FutureResult { - let token = token.to_owned(); - let url = self.config.app_url(); - FutureResult::new(async move { - let app = create_app_request(&token, params, &url).await?; - Ok(app) - }) - } - - fn read_app( - &self, - token: &str, - params: AppIdPB, - ) -> FutureResult, FlowyError> { - let token = token.to_owned(); - let url = self.config.app_url(); - FutureResult::new(async move { - let app_rev = read_app_request(&token, params, &url).await?; - Ok(app_rev) - }) - } - - fn update_app(&self, token: &str, params: UpdateAppParams) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.app_url(); - FutureResult::new(async move { - update_app_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn delete_app(&self, token: &str, params: AppIdPB) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.app_url(); - FutureResult::new(async move { - delete_app_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn create_trash(&self, token: &str, params: RepeatedTrashIdPB) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.trash_url(); - FutureResult::new(async move { - create_trash_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn delete_trash(&self, token: &str, params: RepeatedTrashIdPB) -> FutureResult<(), FlowyError> { - let token = token.to_owned(); - let url = self.config.trash_url(); - FutureResult::new(async move { - delete_trash_request(&token, params, &url).await?; - Ok(()) - }) - } - - fn read_trash(&self, token: &str) -> FutureResult, FlowyError> { - let token = token.to_owned(); - let url = self.config.trash_url(); - FutureResult::new(async move { - let repeated_trash = read_trash_request(&token, &url).await?; - Ok(repeated_trash) - }) - } -} - -#[allow(dead_code)] -fn request_builder() -> HttpRequestBuilder { - HttpRequestBuilder::new().middleware(MIDDLEWARE.clone()) -} - -pub async fn create_workspace_request( - _token: &str, - _params: CreateWorkspaceParams, - _url: &str, -) -> Result { - // let workspace = request_builder() - // .post(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .response() - // .await?; - // Ok(workspace) - unimplemented!() -} - -pub async fn read_workspaces_request( - _token: &str, - _params: WorkspaceIdPB, - _url: &str, -) -> Result, FlowyError> { - // let repeated_workspace = request_builder() - // .get(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .response::() - // .await?; - // - // Ok(repeated_workspace) - unimplemented!() -} - -pub async fn update_workspace_request( - _token: &str, - _params: UpdateWorkspaceParams, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .patch(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -pub async fn delete_workspace_request( - _token: &str, - _params: WorkspaceIdPB, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .delete(url) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -// App -pub async fn create_app_request( - _token: &str, - _params: CreateAppParams, - _url: &str, -) -> Result { - // let app = request_builder() - // .post(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .response() - // .await?; - // Ok(app) - unimplemented!() -} - -pub async fn read_app_request( - _token: &str, - _params: AppIdPB, - _url: &str, -) -> Result, FlowyError> { - // let app = request_builder() - // .get(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .option_response() - // .await?; - // Ok(app) - - unimplemented!() -} - -pub async fn update_app_request( - _token: &str, - _params: UpdateAppParams, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .patch(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -pub async fn delete_app_request( - _token: &str, - _params: AppIdPB, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .delete(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -// View -pub async fn create_view_request( - _token: &str, - _params: CreateViewParams, - _url: &str, -) -> Result { - // let view = request_builder() - // .post(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .response() - // .await?; - // Ok(view) - unimplemented!() -} - -pub async fn read_view_request( - _token: &str, - _params: ViewIdPB, - _url: &str, -) -> Result, FlowyError> { - // let view = request_builder() - // .get(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .option_response() - // .await?; - // - // Ok(view) - unimplemented!() -} - -pub async fn update_view_request( - _token: &str, - _params: UpdateViewParams, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .patch(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -pub async fn delete_view_request( - _token: &str, - _params: RepeatedViewIdPB, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .delete(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -pub async fn create_trash_request( - _token: &str, - _params: RepeatedTrashIdPB, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .post(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -pub async fn delete_trash_request( - _token: &str, - _params: RepeatedTrashIdPB, - _url: &str, -) -> Result<(), FlowyError> { - // let _ = request_builder() - // .delete(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .protobuf(params)? - // .send() - // .await?; - Ok(()) -} - -pub async fn read_trash_request( - _token: &str, - _url: &str, -) -> Result, FlowyError> { - // let repeated_trash = request_builder() - // .get(&url.to_owned()) - // .header(HEADER_TOKEN, token) - // .response::() - // .await?; - // Ok(repeated_trash) - unimplemented!() -} - -lazy_static! { - static ref MIDDLEWARE: Arc = Arc::new(FolderResponseMiddleware::new()); -} - -pub struct FolderResponseMiddleware { - invalid_token_sender: broadcast::Sender, -} - -impl FolderResponseMiddleware { - fn new() -> Self { - let (sender, _) = broadcast::channel(10); - FolderResponseMiddleware { - invalid_token_sender: sender, - } - } - - #[allow(dead_code)] - fn invalid_token_subscribe(&self) -> broadcast::Receiver { - self.invalid_token_sender.subscribe() - } -} - -impl ResponseMiddleware for FolderResponseMiddleware { - fn receive_response(&self, token: &Option, response: &HttpResponse) { - if let Some(error) = &response.error { - if error.is_unauthorized() { - tracing::error!("user is unauthorized"); - match token { - None => {}, - Some(token) => match self.invalid_token_sender.send(token.clone()) { - Ok(_) => {}, - Err(e) => tracing::error!("{:?}", e), - }, - } - } - } - } -} diff --git a/frontend/rust-lib/flowy-net/src/http_server/mod.rs b/frontend/rust-lib/flowy-net/src/http_server/mod.rs index 53fd3bdead..a7b831d704 100644 --- a/frontend/rust-lib/flowy-net/src/http_server/mod.rs +++ b/frontend/rust-lib/flowy-net/src/http_server/mod.rs @@ -1,3 +1,2 @@ pub mod document; -pub mod folder; pub mod user; diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 78fe79a663..c124567de9 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -7,26 +7,19 @@ use document_model::document::{ use flowy_client_sync::errors::SyncError; use flowy_document::DocumentCloudService; use flowy_error::{internal_error, FlowyError}; -use flowy_folder::entities::{ - app::{AppIdPB, CreateAppParams, UpdateAppParams}, - trash::RepeatedTrashIdPB, - view::{CreateViewParams, RepeatedViewIdPB, UpdateViewParams, ViewIdPB}, - workspace::{CreateWorkspaceParams, UpdateWorkspaceParams, WorkspaceIdPB}, -}; -use flowy_folder::event_map::FolderCouldServiceV1; use flowy_server_sync::server_document::ServerDocumentManager; use flowy_server_sync::server_folder::ServerFolderManager; use flowy_sync::{RevisionSyncResponse, RevisionUser}; use flowy_user::entities::UserProfilePB; use flowy_user::event_map::UserCloudService; -use folder_model::{ - gen_app_id, gen_workspace_id, AppRevision, TrashRevision, ViewRevision, WorkspaceRevision, -}; + +use flowy_user::uid::UserIDGenerator; use futures_util::stream::StreamExt; -use lib_infra::{future::FutureResult, util::timestamp}; +use lib_infra::future::FutureResult; use lib_ws::{WSChannel, WebSocketRawMessage}; -use nanoid::nanoid; -use parking_lot::RwLock; + +use lazy_static::lazy_static; +use parking_lot::{Mutex, RwLock}; use std::{ convert::{TryFrom, TryInto}, fmt::Debug, @@ -35,6 +28,9 @@ use std::{ use tokio::sync::{broadcast, mpsc, mpsc::UnboundedSender}; use user_model::*; use ws_model::ws_revision::{ClientRevisionWSData, ClientRevisionWSDataType}; +lazy_static! { + static ref ID_GEN: Mutex = Mutex::new(UserIDGenerator::new(1)); +} pub struct LocalServer { doc_manager: Arc, @@ -53,7 +49,6 @@ impl LocalServer { let doc_manager = Arc::new(ServerDocumentManager::new(persistence.clone())); let folder_manager = Arc::new(ServerFolderManager::new(persistence)); let stop_tx = RwLock::new(None); - LocalServer { doc_manager, folder_manager, @@ -271,151 +266,27 @@ impl RevisionUser for LocalRevisionUser { } } -impl FolderCouldServiceV1 for LocalServer { - fn init(&self) {} - - fn create_workspace( - &self, - _token: &str, - params: CreateWorkspaceParams, - ) -> FutureResult { - let time = timestamp(); - let workspace = WorkspaceRevision { - id: gen_workspace_id(), - name: params.name, - desc: params.desc, - apps: vec![], - modified_time: time, - create_time: time, - }; - - FutureResult::new(async { Ok(workspace) }) - } - - fn read_workspace( - &self, - _token: &str, - _params: WorkspaceIdPB, - ) -> FutureResult, FlowyError> { - FutureResult::new(async { Ok(vec![]) }) - } - - fn update_workspace( - &self, - _token: &str, - _params: UpdateWorkspaceParams, - ) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn delete_workspace(&self, _token: &str, _params: WorkspaceIdPB) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn create_view( - &self, - _token: &str, - params: CreateViewParams, - ) -> FutureResult { - let time = timestamp(); - let view = ViewRevision::new( - params.view_id, - params.belong_to_id, - params.name, - params.desc, - params.data_format.into(), - params.layout.into(), - time, - time, - ); - FutureResult::new(async { Ok(view) }) - } - - fn read_view( - &self, - _token: &str, - _params: ViewIdPB, - ) -> FutureResult, FlowyError> { - FutureResult::new(async { Ok(None) }) - } - - fn delete_view(&self, _token: &str, _params: RepeatedViewIdPB) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn update_view(&self, _token: &str, _params: UpdateViewParams) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn create_app( - &self, - _token: &str, - params: CreateAppParams, - ) -> FutureResult { - let time = timestamp(); - let app = AppRevision { - id: gen_app_id(), - workspace_id: params.workspace_id, - name: params.name, - desc: params.desc, - belongings: vec![], - version: 0, - modified_time: time, - create_time: time, - }; - FutureResult::new(async { Ok(app) }) - } - - fn read_app( - &self, - _token: &str, - _params: AppIdPB, - ) -> FutureResult, FlowyError> { - FutureResult::new(async { Ok(None) }) - } - - fn update_app(&self, _token: &str, _params: UpdateAppParams) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn delete_app(&self, _token: &str, _params: AppIdPB) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn create_trash(&self, _token: &str, _params: RepeatedTrashIdPB) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn delete_trash(&self, _token: &str, _params: RepeatedTrashIdPB) -> FutureResult<(), FlowyError> { - FutureResult::new(async { Ok(()) }) - } - - fn read_trash(&self, _token: &str) -> FutureResult, FlowyError> { - FutureResult::new(async { Ok(vec![]) }) - } -} - impl UserCloudService for LocalServer { fn sign_up(&self, params: SignUpParams) -> FutureResult { - let uid = nanoid!(20); + let uid = ID_GEN.lock().next_id(); FutureResult::new(async move { Ok(SignUpResponse { - user_id: uid.clone(), + user_id: uid, name: params.name, email: params.email, - token: uid, + token: "".to_string(), }) }) } fn sign_in(&self, params: SignInParams) -> FutureResult { - let user_id = nanoid!(20); - FutureResult::new(async { + let uid = ID_GEN.lock().next_id(); + FutureResult::new(async move { Ok(SignInResponse { - user_id: user_id.clone(), + user_id: uid, name: params.name, email: params.email, - token: user_id, + token: "".to_string(), }) }) } diff --git a/frontend/rust-lib/flowy-net/src/local_server/ws.rs b/frontend/rust-lib/flowy-net/src/local_server/ws.rs index 733a2632c0..c02778061d 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/ws.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/ws.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use tokio::sync::{broadcast, broadcast::Receiver, mpsc::UnboundedReceiver}; pub struct LocalWebSocket { - user_id: Arc>>, + user_id: Arc>>, receivers: Arc>>, state_sender: broadcast::Sender, server_ws_receiver: RwLock>>, @@ -53,7 +53,7 @@ impl FlowyRawWebSocket for LocalWebSocket { FutureResult::new(async { Ok(()) }) } - fn start_connect(&self, _addr: String, user_id: String) -> FutureResult<(), WSErrorCode> { + fn start_connect(&self, _addr: String, user_id: i64) -> FutureResult<(), WSErrorCode> { *self.user_id.write() = Some(user_id); FutureResult::new(async { Ok(()) }) } diff --git a/frontend/rust-lib/flowy-revision/src/cache/reset.rs b/frontend/rust-lib/flowy-revision/src/cache/reset.rs index ba29870ec3..b6179e7022 100644 --- a/frontend/rust-lib/flowy-revision/src/cache/reset.rs +++ b/frontend/rust-lib/flowy-revision/src/cache/reset.rs @@ -22,7 +22,6 @@ pub trait RevisionResettable { } pub struct RevisionStructReset { - user_id: String, target: T, disk_cache: Arc>, } @@ -32,13 +31,8 @@ where T: RevisionResettable, C: 'static, { - pub fn new( - user_id: &str, - object: T, - disk_cache: Arc>, - ) -> Self { + pub fn new(object: T, disk_cache: Arc>) -> Self { Self { - user_id: user_id.to_owned(), target: object, disk_cache, } @@ -67,14 +61,12 @@ where async fn reset_object(&self) -> FlowyResult<()> { let configuration = RevisionPersistenceConfiguration::new(2, false); let rev_persistence = Arc::new(RevisionPersistence::from_disk_cache( - &self.user_id, self.target.target_id(), self.disk_cache.clone(), configuration, )); let revisions = RevisionLoader { object_id: self.target.target_id().to_owned(), - user_id: self.user_id.clone(), cloud: None, rev_persistence, } diff --git a/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs b/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs index 4d1c182078..83442ed351 100644 --- a/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs +++ b/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs @@ -40,7 +40,6 @@ pub struct ConflictController where Operations: Send + Sync, { - user_id: String, resolver: Arc + Send + Sync>, rev_sink: Arc, rev_manager: Arc>, @@ -52,14 +51,11 @@ where Connection: 'static, { pub fn new( - user_id: &str, resolver: Arc + Send + Sync>, rev_sink: Arc, rev_manager: Arc>, ) -> Self { - let user_id = user_id.to_owned(); Self { - user_id, resolver, rev_sink, rev_manager, @@ -135,7 +131,6 @@ where self.rev_manager.add_remote_revision(revision).await?; } let (client_revision, server_revision) = make_client_and_server_revision( - &self.user_id, &self.rev_manager, client_operations, Some(server_operations), @@ -152,7 +147,6 @@ where } fn make_client_and_server_revision( - _user_id: &str, rev_manager: &Arc>, client_operations: Operations, server_operations: Option, diff --git a/frontend/rust-lib/flowy-revision/src/rev_manager.rs b/frontend/rust-lib/flowy-revision/src/rev_manager.rs index c0722e4a6c..b9438aaa43 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_manager.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_manager.rs @@ -52,7 +52,6 @@ pub trait RevisionObjectSerializer: Send + Sync { pub trait RevisionMergeable: Send + Sync { fn merge_revisions( &self, - _user_id: &str, object_id: &str, mut revisions: Vec, ) -> FlowyResult { @@ -77,7 +76,6 @@ pub trait RevisionMergeable: Send + Sync { pub struct RevisionManager { pub object_id: String, - user_id: String, rev_id_counter: Arc, rev_persistence: Arc>, rev_snapshot: Arc>, @@ -89,7 +87,6 @@ pub struct RevisionManager { impl RevisionManager { pub fn new( - user_id: &str, object_id: &str, rev_persistence: RevisionPersistence, rev_compress: Compress, @@ -103,7 +100,6 @@ impl RevisionManager { let rev_compress = Arc::new(rev_compress); let rev_persistence = Arc::new(rev_persistence); let rev_snapshot = RevisionSnapshotController::new( - user_id, object_id, snapshot_persistence, rev_id_counter.clone(), @@ -121,7 +117,6 @@ impl RevisionManager { tokio::spawn(queue.run()); Self { object_id: object_id.to_string(), - user_id: user_id.to_owned(), rev_id_counter, rev_persistence, rev_snapshot: Arc::new(rev_snapshot), @@ -219,7 +214,6 @@ impl RevisionManager { pub async fn load_revisions(&self) -> FlowyResult> { let revisions = RevisionLoader { object_id: self.object_id.clone(), - user_id: self.user_id.clone(), cloud: None, rev_persistence: self.rev_persistence.clone(), } @@ -357,7 +351,6 @@ impl RevisionManager { pub struct RevisionLoader { pub object_id: String, - pub user_id: String, pub cloud: Option>, pub rev_persistence: Arc>, } diff --git a/frontend/rust-lib/flowy-revision/src/rev_persistence.rs b/frontend/rust-lib/flowy-revision/src/rev_persistence.rs index 21ba5c2f47..59c0b1209b 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_persistence.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_persistence.rs @@ -53,7 +53,6 @@ impl std::default::Default for RevisionPersistenceConfiguration { /// The generic parameter, `Connection`, represents as the disk backend's connection. /// If the backend is SQLite, then the Connect will be SQLiteConnect. pub struct RevisionPersistence { - user_id: String, object_id: String, disk_cache: Arc>, memory_cache: Arc, @@ -66,7 +65,6 @@ where Connection: 'static, { pub fn new( - user_id: &str, object_id: &str, disk_cache: C, configuration: RevisionPersistenceConfiguration, @@ -76,24 +74,21 @@ where { let disk_cache = Arc::new(disk_cache) as Arc>; - Self::from_disk_cache(user_id, object_id, disk_cache, configuration) + Self::from_disk_cache(object_id, disk_cache, configuration) } pub fn from_disk_cache( - user_id: &str, object_id: &str, disk_cache: Arc>, configuration: RevisionPersistenceConfiguration, ) -> RevisionPersistence { let object_id = object_id.to_owned(); - let user_id = user_id.to_owned(); let sync_seq = RwLock::new(DeferSyncSequence::new()); let memory_cache = Arc::new(RevisionMemoryCache::new( &object_id, Arc::new(disk_cache.clone()), )); Self { - user_id, object_id, disk_cache, memory_cache, @@ -130,8 +125,7 @@ where let rev_ids = range.to_rev_ids(); debug_assert_eq!(range.len() as usize, revisions.len()); // compact multiple revisions into one - let merged_revision = - rev_compress.merge_revisions(&self.user_id, &self.object_id, revisions)?; + let merged_revision = rev_compress.merge_revisions(&self.object_id, revisions)?; tracing::Span::current().record("rev_id", merged_revision.rev_id); let record = SyncRecord { @@ -193,8 +187,7 @@ where revisions.push(new_revision); // compact multiple revisions into one - let merged_revision = - rev_compress.merge_revisions(&self.user_id, &self.object_id, revisions)?; + let merged_revision = rev_compress.merge_revisions(&self.object_id, revisions)?; let new_rev_id = merged_revision.rev_id; tracing::Span::current().record("rev_id", merged_revision.rev_id); sync_seq.recv(new_rev_id)?; diff --git a/frontend/rust-lib/flowy-revision/src/rev_snapshot.rs b/frontend/rust-lib/flowy-revision/src/rev_snapshot.rs index a6079295be..6a316d58f2 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_snapshot.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_snapshot.rs @@ -28,7 +28,6 @@ pub trait RevisionSnapshotDataGenerator: Send + Sync { const AUTO_GEN_SNAPSHOT_PER_10_REVISION: i64 = 10; pub struct RevisionSnapshotController { - user_id: String, object_id: String, rev_snapshot_persistence: Arc, rev_snapshot_data: Option>, @@ -43,7 +42,6 @@ where Connection: 'static, { pub fn new( - user_id: &str, object_id: &str, disk_cache: D, rev_id_counter: Arc, @@ -55,7 +53,6 @@ where { let rev_snapshot_persistence = Arc::new(disk_cache); Self { - user_id: user_id.to_string(), object_id: object_id.to_string(), rev_snapshot_persistence, rev_id_counter, diff --git a/frontend/rust-lib/flowy-revision/tests/revision_test/script.rs b/frontend/rust-lib/flowy-revision/tests/revision_test/script.rs index ec285a0cc6..22824b88c9 100644 --- a/frontend/rust-lib/flowy-revision/tests/revision_test/script.rs +++ b/frontend/rust-lib/flowy-revision/tests/revision_test/script.rs @@ -28,7 +28,6 @@ pub enum RevisionScript { } pub struct RevisionTest { - user_id: String, object_id: String, configuration: RevisionPersistenceConfiguration, rev_manager: Arc>, @@ -40,22 +39,18 @@ impl RevisionTest { } pub async fn new_with_configuration(max_merge_len: i64) -> Self { - let user_id = nanoid!(10); let object_id = nanoid!(6); let configuration = RevisionPersistenceConfiguration::new(max_merge_len as usize, false); let disk_cache = RevisionDiskCacheMock::new(vec![]); - let persistence = - RevisionPersistence::new(&user_id, &object_id, disk_cache, configuration.clone()); + let persistence = RevisionPersistence::new(&object_id, disk_cache, configuration.clone()); let compress = RevisionMergeableMock {}; let snapshot = RevisionSnapshotMock {}; - let mut rev_manager = - RevisionManager::new(&user_id, &object_id, persistence, compress, snapshot); + let mut rev_manager = RevisionManager::new(&object_id, persistence, compress, snapshot); rev_manager .initialize::(None) .await .unwrap(); Self { - user_id, object_id, configuration, rev_manager: Arc::new(rev_manager), @@ -66,28 +61,18 @@ impl RevisionTest { let records = old_test.rev_manager.get_all_revision_records().unwrap(); let disk_cache = RevisionDiskCacheMock::new(records); let configuration = old_test.configuration; - let persistence = RevisionPersistence::new( - &old_test.user_id, - &old_test.object_id, - disk_cache, - configuration.clone(), - ); + let persistence = + RevisionPersistence::new(&old_test.object_id, disk_cache, configuration.clone()); let compress = RevisionMergeableMock {}; let snapshot = RevisionSnapshotMock {}; - let mut rev_manager = RevisionManager::new( - &old_test.user_id, - &old_test.object_id, - persistence, - compress, - snapshot, - ); + let mut rev_manager = + RevisionManager::new(&old_test.object_id, persistence, compress, snapshot); rev_manager .initialize::(None) .await .unwrap(); Self { - user_id: old_test.user_id, object_id: old_test.object_id, configuration, rev_manager: Arc::new(rev_manager), diff --git a/frontend/rust-lib/flowy-sqlite/src/schema.rs b/frontend/rust-lib/flowy-sqlite/src/schema.rs index 5b70cf9164..643c6cabd6 100644 --- a/frontend/rust-lib/flowy-sqlite/src/schema.rs +++ b/frontend/rust-lib/flowy-sqlite/src/schema.rs @@ -189,21 +189,21 @@ diesel::table! { } diesel::allow_tables_to_appear_in_same_query!( - app_table, - database_refs, - document_rev_snapshot, - document_rev_table, - folder_rev_snapshot, - grid_block_index_table, - grid_meta_rev_table, - grid_rev_snapshot, - grid_rev_table, - grid_view_rev_table, - kv_table, - rev_snapshot, - rev_table, - trash_table, - user_table, - view_table, - workspace_table, + app_table, + database_refs, + document_rev_snapshot, + document_rev_table, + folder_rev_snapshot, + grid_block_index_table, + grid_meta_rev_table, + grid_rev_snapshot, + grid_rev_table, + grid_view_rev_table, + kv_table, + rev_snapshot, + rev_table, + trash_table, + user_table, + view_table, + workspace_table, ); diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index 2e137f48c8..4f454a925c 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" flowy-core = { path = "../flowy-core" } flowy-user = { path = "../flowy-user"} flowy-net = { path = "../flowy-net"} -flowy-folder = { path = "../flowy-folder", features = ["flowy_unit_test"] } +flowy-folder2 = { path = "../flowy-folder2", features = ["test_helper"] } flowy-document= { path = "../flowy-document" } lib-dispatch = { path = "../lib-dispatch" } diff --git a/frontend/rust-lib/flowy-test/src/event_builder.rs b/frontend/rust-lib/flowy-test/src/event_builder.rs index f6083838a2..764f6d087a 100644 --- a/frontend/rust-lib/flowy-test/src/event_builder.rs +++ b/frontend/rust-lib/flowy-test/src/event_builder.rs @@ -12,8 +12,8 @@ use std::{ sync::Arc, }; -pub type FolderEventBuilder = EventBuilder; -impl FolderEventBuilder { +pub type Folder2EventBuilder = EventBuilder; +impl Folder2EventBuilder { pub fn new(sdk: FlowySDKTest) -> Self { EventBuilder::test(TestContext::new(sdk)) } @@ -22,7 +22,7 @@ impl FolderEventBuilder { } } -pub type UserModuleEventBuilder = FolderEventBuilder; +pub type UserModuleEventBuilder = Folder2EventBuilder; #[derive(Clone)] pub struct EventBuilder { diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index dc275549fa..cd6a10f22c 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -1,13 +1,9 @@ use crate::prelude::*; -use flowy_folder::entities::WorkspaceIdPB; -use flowy_folder::{ - entities::{ - app::*, - view::*, - workspace::{CreateWorkspacePayloadPB, WorkspacePB}, - }, - event_map::FolderEvent::{CreateWorkspace, OpenWorkspace, *}, +use flowy_folder2::entities::{ + CreateViewPayloadPB, CreateWorkspacePayloadPB, ViewLayoutTypePB, ViewPB, WorkspaceIdPB, + WorkspacePB, }; +use flowy_folder2::event_map::FolderEvent::{CreateView, CreateWorkspace, OpenWorkspace}; use flowy_user::{ entities::{SignInPayloadPB, SignUpPayloadPB, UserProfilePB}, errors::FlowyError, @@ -19,8 +15,8 @@ use std::{fs, path::PathBuf, sync::Arc}; pub struct ViewTest { pub sdk: FlowySDKTest, pub workspace: WorkspacePB, - pub app: AppPB, - pub view: ViewPB, + pub parent_view: ViewPB, + pub child_view: ViewPB, } impl ViewTest { @@ -33,8 +29,8 @@ impl ViewTest { Self { sdk: sdk.clone(), workspace, - app, - view, + parent_view: app, + child_view: view, } } @@ -61,7 +57,7 @@ async fn create_workspace(sdk: &FlowySDKTest, name: &str, desc: &str) -> Workspa desc: desc.to_owned(), }; - FolderEventBuilder::new(sdk.clone()) + Folder2EventBuilder::new(sdk.clone()) .event(CreateWorkspace) .payload(request) .async_send() @@ -73,27 +69,30 @@ async fn open_workspace(sdk: &FlowySDKTest, workspace_id: &str) { let payload = WorkspaceIdPB { value: Some(workspace_id.to_owned()), }; - let _ = FolderEventBuilder::new(sdk.clone()) + let _ = Folder2EventBuilder::new(sdk.clone()) .event(OpenWorkspace) .payload(payload) .async_send() .await; } -async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &str) -> AppPB { - let create_app_request = CreateAppPayloadPB { - workspace_id: workspace_id.to_owned(), +async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &str) -> ViewPB { + let create_app_request = CreateViewPayloadPB { + belong_to_id: workspace_id.to_owned(), name: name.to_string(), desc: desc.to_string(), - color_style: Default::default(), + thumbnail: None, + layout: ViewLayoutTypePB::Document, + initial_data: vec![], + ext: Default::default(), }; - FolderEventBuilder::new(sdk.clone()) - .event(CreateApp) + Folder2EventBuilder::new(sdk.clone()) + .event(CreateView) .payload(create_app_request) .async_send() .await - .parse::() + .parse::() } async fn create_view( @@ -112,7 +111,7 @@ async fn create_view( ext: Default::default(), }; - FolderEventBuilder::new(sdk.clone()) + Folder2EventBuilder::new(sdk.clone()) .event(CreateView) .payload(payload) .async_send() diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index c87205d909..bcbf59f605 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -13,6 +13,8 @@ user-model = { path = "../../../shared-lib/user-model" } lib-infra = { path = "../../../shared-lib/lib-infra" } flowy-notification = { path = "../flowy-notification" } lib-dispatch = { path = "../lib-dispatch" } +collab-persistence = { version = "0.1.0" } + tracing = { version = "0.1", features = ["log"] } bytes = "1.4" diff --git a/frontend/rust-lib/flowy-user/src/entities/user_profile.rs b/frontend/rust-lib/flowy-user/src/entities/user_profile.rs index 5e17b7df30..04f6562681 100644 --- a/frontend/rust-lib/flowy-user/src/entities/user_profile.rs +++ b/frontend/rust-lib/flowy-user/src/entities/user_profile.rs @@ -2,8 +2,7 @@ use crate::errors::ErrorCode; use flowy_derive::ProtoBuf; use std::convert::TryInto; use user_model::{ - UpdateUserProfileParams, UserEmail, UserIcon, UserId, UserName, UserOpenaiKey, UserPassword, - UserProfile, + UpdateUserProfileParams, UserEmail, UserIcon, UserName, UserOpenaiKey, UserPassword, UserProfile, }; #[derive(Default, ProtoBuf)] @@ -21,7 +20,7 @@ pub struct UserSettingPB { #[derive(ProtoBuf, Default, Debug, PartialEq, Eq, Clone)] pub struct UserProfilePB { #[pb(index = 1)] - pub id: String, + pub id: i64, #[pb(index = 2)] pub email: String, @@ -55,7 +54,7 @@ impl std::convert::From for UserProfilePB { #[derive(ProtoBuf, Default)] pub struct UpdateUserProfilePayloadPB { #[pb(index = 1)] - pub id: String, + pub id: i64, #[pb(index = 2, one_of)] pub name: Option, @@ -74,9 +73,9 @@ pub struct UpdateUserProfilePayloadPB { } impl UpdateUserProfilePayloadPB { - pub fn new(id: &str) -> Self { + pub fn new(id: i64) -> Self { Self { - id: id.to_owned(), + id, ..Default::default() } } @@ -111,8 +110,6 @@ impl TryInto for UpdateUserProfilePayloadPB { type Error = ErrorCode; fn try_into(self) -> Result { - let id = UserId::parse(self.id)?.0; - let name = match self.name { None => None, Some(name) => Some(UserName::parse(name)?.0), @@ -139,7 +136,7 @@ impl TryInto for UpdateUserProfilePayloadPB { }; Ok(UpdateUserProfileParams { - id, + id: self.id, name, email, password, diff --git a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs b/frontend/rust-lib/flowy-user/src/event_handler.rs similarity index 70% rename from frontend/rust-lib/flowy-user/src/handlers/user_handler.rs rename to frontend/rust-lib/flowy-user/src/event_handler.rs index 143cef84be..edf9aebd1e 100644 --- a/frontend/rust-lib/flowy-user/src/handlers/user_handler.rs +++ b/frontend/rust-lib/flowy-user/src/event_handler.rs @@ -1,12 +1,41 @@ -use crate::entities::{ - AppearanceSettingsPB, UpdateUserProfilePayloadPB, UserProfilePB, UserSettingPB, - APPEARANCE_DEFAULT_THEME, -}; -use crate::{errors::FlowyError, services::UserSession}; +use crate::entities::*; +use crate::services::UserSession; +use flowy_error::FlowyError; use flowy_sqlite::kv::KV; use lib_dispatch::prelude::*; use std::{convert::TryInto, sync::Arc}; -use user_model::UpdateUserProfileParams; +use user_model::{SignInParams, SignUpParams, UpdateUserProfileParams}; + +// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html +#[tracing::instrument(level = "debug", name = "sign_in", skip(data, session), fields(email = %data.email), err)] +pub async fn sign_in( + data: AFPluginData, + session: AFPluginState>, +) -> DataResult { + let params: SignInParams = data.into_inner().try_into()?; + let user_profile: UserProfilePB = session.sign_in(params).await?.into(); + data_result_ok(user_profile) +} + +#[tracing::instrument( + level = "debug", + name = "sign_up", + skip(data, session), + fields( + email = %data.email, + name = %data.name, + ), + err +)] +pub async fn sign_up( + data: AFPluginData, + session: AFPluginState>, +) -> DataResult { + let params: SignUpParams = data.into_inner().try_into()?; + let user_profile: UserProfilePB = session.sign_up(params).await?.into(); + + data_result_ok(user_profile) +} #[tracing::instrument(level = "debug", skip(session))] pub async fn init_user_handler(session: AFPluginState>) -> Result<(), FlowyError> { diff --git a/frontend/rust-lib/flowy-user/src/event_map.rs b/frontend/rust-lib/flowy-user/src/event_map.rs index 11a7aa83ba..7981a5e89c 100644 --- a/frontend/rust-lib/flowy-user/src/event_map.rs +++ b/frontend/rust-lib/flowy-user/src/event_map.rs @@ -1,9 +1,12 @@ use crate::entities::UserProfilePB; -use crate::{errors::FlowyError, handlers::*, services::UserSession}; +use crate::event_handler::*; +use crate::{errors::FlowyError, services::UserSession}; +use flowy_derive::{Flowy_Event, ProtoBuf_Enum}; +use flowy_error::FlowyResult; use lib_dispatch::prelude::*; - use lib_infra::future::{Fut, FutureResult}; use std::sync::Arc; +use strum_macros::Display; use user_model::{ SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile, }; @@ -25,9 +28,10 @@ pub fn init(user_session: Arc) -> AFPlugin { } pub trait UserStatusCallback: Send + Sync + 'static { - fn did_sign_in(&self, token: &str, user_id: &str) -> Fut>; + fn did_sign_in(&self, token: &str, user_id: i64) -> Fut>; fn did_sign_up(&self, user_profile: &UserProfile) -> Fut>; - fn did_expired(&self, token: &str, user_id: &str) -> Fut>; + fn did_expired(&self, token: &str, user_id: i64) -> Fut>; + fn will_migrated(&self, token: &str, old_user_id: &str, user_id: i64) -> Fut>; } pub trait UserCloudService: Send + Sync { @@ -43,10 +47,6 @@ pub trait UserCloudService: Send + Sync { fn ws_addr(&self) -> String; } -use flowy_derive::{Flowy_Event, ProtoBuf_Enum}; -use flowy_error::FlowyResult; -use strum_macros::Display; - #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)] #[event_err = "FlowyError"] pub enum UserEvent { diff --git a/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs b/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs deleted file mode 100644 index fc994fa004..0000000000 --- a/frontend/rust-lib/flowy-user/src/handlers/auth_handler.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::entities::*; -use crate::services::UserSession; -use flowy_error::FlowyError; -use lib_dispatch::prelude::*; -use std::{convert::TryInto, sync::Arc}; -use user_model::{SignInParams, SignUpParams}; - -// tracing instrument 👉🏻 https://docs.rs/tracing/0.1.26/tracing/attr.instrument.html -#[tracing::instrument(level = "debug", name = "sign_in", skip(data, session), fields(email = %data.email), err)] -pub async fn sign_in( - data: AFPluginData, - session: AFPluginState>, -) -> DataResult { - let params: SignInParams = data.into_inner().try_into()?; - let user_profile: UserProfilePB = session.sign_in(params).await?.into(); - data_result_ok(user_profile) -} - -#[tracing::instrument( - level = "debug", - name = "sign_up", - skip(data, session), - fields( - email = %data.email, - name = %data.name, - ), - err -)] -pub async fn sign_up( - data: AFPluginData, - session: AFPluginState>, -) -> DataResult { - let params: SignUpParams = data.into_inner().try_into()?; - let user_profile: UserProfilePB = session.sign_up(params).await?.into(); - - data_result_ok(user_profile) -} diff --git a/frontend/rust-lib/flowy-user/src/handlers/mod.rs b/frontend/rust-lib/flowy-user/src/handlers/mod.rs deleted file mode 100644 index b220539145..0000000000 --- a/frontend/rust-lib/flowy-user/src/handlers/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod auth_handler; -mod user_handler; - -pub use auth_handler::*; -pub use user_handler::*; diff --git a/frontend/rust-lib/flowy-user/src/lib.rs b/frontend/rust-lib/flowy-user/src/lib.rs index 5156668ae1..e53ce14814 100644 --- a/frontend/rust-lib/flowy-user/src/lib.rs +++ b/frontend/rust-lib/flowy-user/src/lib.rs @@ -1,9 +1,10 @@ pub mod entities; +mod event_handler; pub mod event_map; -mod handlers; mod notification; pub mod protobuf; pub mod services; +pub mod uid; // mod sql_tables; #[macro_use] diff --git a/frontend/rust-lib/flowy-user/src/services/database.rs b/frontend/rust-lib/flowy-user/src/services/database.rs index d54fe4aa94..f4df3cd2d1 100644 --- a/frontend/rust-lib/flowy-user/src/services/database.rs +++ b/frontend/rust-lib/flowy-user/src/services/database.rs @@ -1,4 +1,5 @@ -use flowy_error::{ErrorCode, FlowyError}; +use collab_persistence::CollabKV; +use flowy_error::FlowyError; use flowy_sqlite::ConnectionPool; use flowy_sqlite::{schema::user_table, DBConnection, Database}; use lazy_static::lazy_static; @@ -18,25 +19,21 @@ impl UserDB { } } - fn open_user_db_if_need(&self, user_id: &str) -> Result, FlowyError> { - if user_id.is_empty() { - return Err(ErrorCode::UserIdIsEmpty.into()); - } - - if let Some(database) = DB_MAP.read().get(user_id) { + fn open_user_db_if_need(&self, user_id: i64) -> Result, FlowyError> { + if let Some(database) = DB_MAP.read().get(&user_id) { return Ok(database.get_pool()); } let mut write_guard = DB_MAP.write(); // The Write guard acquire exclusive access that will guarantee the user db only initialize once. - match write_guard.get(user_id) { + match write_guard.get(&user_id) { None => {}, Some(database) => return Ok(database.get_pool()), } let mut dir = PathBuf::new(); dir.push(&self.db_dir); - dir.push(user_id); + dir.push(user_id.to_string()); let dir = dir.to_str().unwrap().to_owned(); tracing::trace!("open user db {} at path: {}", user_id, dir); @@ -50,29 +47,59 @@ impl UserDB { Ok(pool) } - pub(crate) fn close_user_db(&self, user_id: &str) -> Result<(), FlowyError> { + fn open_kv_db_if_need(&self, user_id: i64) -> Result, FlowyError> { + if let Some(kv) = KVDB_MAP.read().get(&user_id) { + return Ok(kv.clone()); + } + + let mut write_guard = KVDB_MAP.write(); + // The Write guard acquire exclusive access that will guarantee the user db only initialize once. + match write_guard.get(&user_id) { + None => {}, + Some(kv) => return Ok(kv.clone()), + } + + let mut dir = PathBuf::new(); + dir.push(&self.db_dir); + dir.push(user_id.to_string()); + + tracing::trace!("open kv db {} at path: {:?}", user_id, dir); + let kv_db = CollabKV::open(dir).map_err(|err| FlowyError::internal().context(err))?; + let kv_db = Arc::new(kv_db); + write_guard.insert(user_id.to_owned(), kv_db.clone()); + drop(write_guard); + Ok(kv_db) + } + + pub(crate) fn close_user_db(&self, user_id: i64) -> Result<(), FlowyError> { match DB_MAP.try_write_for(Duration::from_millis(300)) { None => Err(FlowyError::internal().context("Acquire write lock to close user db failed")), Some(mut write_guard) => { - write_guard.remove(user_id); + write_guard.remove(&user_id); Ok(()) }, } } - pub(crate) fn get_connection(&self, user_id: &str) -> Result { + pub(crate) fn get_connection(&self, user_id: i64) -> Result { let conn = self.get_pool(user_id)?.get()?; Ok(conn) } - pub(crate) fn get_pool(&self, user_id: &str) -> Result, FlowyError> { + pub(crate) fn get_pool(&self, user_id: i64) -> Result, FlowyError> { let pool = self.open_user_db_if_need(user_id)?; Ok(pool) } + + pub(crate) fn get_kv_db(&self, user_id: i64) -> Result, FlowyError> { + let kv_db = self.open_kv_db_if_need(user_id)?; + Ok(kv_db) + } } lazy_static! { - static ref DB_MAP: RwLock> = RwLock::new(HashMap::new()); + static ref DB_MAP: RwLock> = RwLock::new(HashMap::new()); + static ref KVDB_MAP: RwLock>> = RwLock::new(HashMap::new()); } #[derive(Clone, Default, Queryable, Identifiable, Insertable)] @@ -108,20 +135,20 @@ impl UserTable { impl std::convert::From for UserTable { fn from(resp: SignUpResponse) -> Self { - UserTable::new(resp.user_id, resp.name, resp.email, resp.token) + UserTable::new(resp.user_id.to_string(), resp.name, resp.email, resp.token) } } impl std::convert::From for UserTable { fn from(resp: SignInResponse) -> Self { - UserTable::new(resp.user_id, resp.name, resp.email, resp.token) + UserTable::new(resp.user_id.to_string(), resp.name, resp.email, resp.token) } } impl std::convert::From for UserProfile { fn from(table: UserTable) -> Self { UserProfile { - id: table.id, + id: table.id.parse::().unwrap_or(0), email: table.email, name: table.name, token: table.token, @@ -145,7 +172,7 @@ pub struct UserTableChangeset { impl UserTableChangeset { pub fn new(params: UpdateUserProfileParams) -> Self { UserTableChangeset { - id: params.id, + id: params.id.to_string(), workspace: None, name: params.name, email: params.email, diff --git a/frontend/rust-lib/flowy-user/src/services/user_session.rs b/frontend/rust-lib/flowy-user/src/services/user_session.rs index f9ec7ca80c..4abbd2b594 100644 --- a/frontend/rust-lib/flowy-user/src/services/user_session.rs +++ b/frontend/rust-lib/flowy-user/src/services/user_session.rs @@ -1,11 +1,13 @@ use crate::entities::{UserProfilePB, UserSettingPB}; use crate::event_map::UserStatusCallback; + use crate::{ errors::{ErrorCode, FlowyError}, event_map::UserCloudService, notification::*, services::database::{UserDB, UserTable, UserTableChangeset}, }; +use collab_persistence::CollabKV; use flowy_sqlite::ConnectionPool; use flowy_sqlite::{ kv::KV, @@ -13,6 +15,7 @@ use flowy_sqlite::{ schema::{user_table, user_table::dsl}, DBConnection, ExpressionMethods, UserDatabaseConnection, }; + use serde::{Deserialize, Serialize}; use std::sync::Arc; use tokio::sync::RwLock; @@ -20,6 +23,9 @@ use user_model::{ SignInParams, SignInResponse, SignUpParams, SignUpResponse, UpdateUserProfileParams, UserProfile, }; +// lazy_static! { +// static ref ID_GEN: Mutex = Mutex::new(UserIDGenerator::new(1)); +// } pub struct UserSessionConfig { root_dir: String, @@ -59,9 +65,45 @@ impl UserSession { } pub async fn init(&self, user_status_callback: C) { + // if let Some(old_session) = self.get_old_session() { + // let uid = ID_GEN.lock().next_id(); + // let _ = user_status_callback + // .will_migrated(&old_session.token, &old_session.user_id, uid) + // .await; + // + // let new_session = Session { + // user_id: uid, + // token: old_session.token.clone(), + // email: old_session.email.clone(), + // name: old_session.name.clone(), + // }; + // self.set_session(Some(new_session)).unwrap(); + // + // if let Ok(db) = self.db_connection() { + // // Update db + // let _ = db.immediate_transaction(|| { + // // get the user data + // let mut user = dsl::user_table + // .filter(user_table::id.eq(&old_session.user_id)) + // .first::(&*db)?; + // + // // delete the existing row + // let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&old_session.user_id))) + // .execute(&*db)?; + // + // // insert new row + // user.id = uid.to_string(); + // let _ = diesel::insert_into(user_table::table) + // .values(user) + // .execute(&*db)?; + // Ok::<(), FlowyError>(()) + // }); + // } + // } + if let Ok(session) = self.get_session() { let _ = user_status_callback - .did_sign_in(&session.token, &session.user_id) + .did_sign_in(&session.token, session.user_id) .await; } *self.user_status_callback.write().await = Some(Arc::new(user_status_callback)); @@ -69,7 +111,7 @@ impl UserSession { pub fn db_connection(&self) -> Result { let user_id = self.get_session()?.user_id; - self.database.get_connection(&user_id) + self.database.get_connection(user_id) } // The caller will be not 'Sync' before of the return value, @@ -80,7 +122,12 @@ impl UserSession { // let conn: PooledConnection = pool.get()?; pub fn db_pool(&self) -> Result, FlowyError> { let user_id = self.get_session()?.user_id; - self.database.get_pool(&user_id) + self.database.get_pool(user_id) + } + + pub fn get_kv_db(&self) -> Result, FlowyError> { + let user_id = self.get_session()?.user_id; + self.database.get_kv_db(user_id) } #[tracing::instrument(level = "debug", skip(self))] @@ -106,7 +153,7 @@ impl UserSession { .await .as_ref() .unwrap() - .did_sign_in(&user_profile.token, &user_profile.id) + .did_sign_in(&user_profile.token, user_profile.id) .await; send_sign_in_notification() .payload::(user_profile.clone().into()) @@ -140,9 +187,10 @@ impl UserSession { #[tracing::instrument(level = "debug", skip(self))] pub async fn sign_out(&self) -> Result<(), FlowyError> { let session = self.get_session()?; - let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))) + let uid = session.user_id.to_string(); + let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&uid))) .execute(&*(self.db_connection()?))?; - self.database.close_user_db(&session.user_id)?; + self.database.close_user_db(session.user_id)?; self.set_session(None)?; let _ = self .user_status_callback @@ -150,7 +198,7 @@ impl UserSession { .await .as_ref() .unwrap() - .did_expired(&session.token, &session.user_id) + .did_expired(&session.token, session.user_id) .await; self.sign_out_on_server(&session.token).await?; @@ -181,7 +229,7 @@ impl UserSession { pub async fn check_user(&self) -> Result { let (user_id, token) = self.get_session()?.into_part(); - + let user_id = user_id.to_string(); let user = dsl::user_table .filter(user_table::id.eq(&user_id)) .first::(&*(self.db_connection()?))?; @@ -192,6 +240,7 @@ impl UserSession { pub async fn get_user_profile(&self) -> Result { let (user_id, token) = self.get_session()?.into_part(); + let user_id = user_id.to_string(); let user = dsl::user_table .filter(user_table::id.eq(&user_id)) .first::(&*(self.db_connection()?))?; @@ -212,7 +261,7 @@ impl UserSession { Ok(user_setting) } - pub fn user_id(&self) -> Result { + pub fn user_id(&self) -> Result { Ok(self.get_session()?.user_id) } @@ -288,6 +337,11 @@ impl UserSession { } } + // fn get_old_session(&self) -> Option { + // let s = KV::get_str(&self.config.session_cache_key)?; + // serde_json::from_str::(&s).ok() + // } + fn is_user_login(&self, email: &str) -> bool { match self.get_session() { Ok(session) => session.email == email, @@ -315,7 +369,7 @@ impl UserDatabaseConnection for UserSession { #[derive(Debug, Clone, Default, Serialize, Deserialize)] struct Session { - user_id: String, + user_id: i64, token: String, email: String, #[serde(default)] @@ -345,7 +399,7 @@ impl std::convert::From for Session { } impl Session { - pub fn into_part(self) -> (String, String) { + pub fn into_part(self) -> (i64, String) { (self.user_id, self.token) } } @@ -372,3 +426,12 @@ impl std::convert::From for String { } } } + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +struct OldSession { + user_id: String, + token: String, + email: String, + #[serde(default)] + name: String, +} diff --git a/frontend/rust-lib/flowy-user/src/uid.rs b/frontend/rust-lib/flowy-user/src/uid.rs new file mode 100644 index 0000000000..a39252e379 --- /dev/null +++ b/frontend/rust-lib/flowy-user/src/uid.rs @@ -0,0 +1,58 @@ +use std::time::SystemTime; + +const EPOCH: u64 = 1637806706000; +const NODE_ID_BITS: u64 = 10; +const SEQUENCE_BITS: u64 = 12; +const NODE_ID_SHIFT: u64 = SEQUENCE_BITS; +const TIMESTAMP_SHIFT: u64 = NODE_ID_BITS + SEQUENCE_BITS; +const SEQUENCE_MASK: u64 = (1 << SEQUENCE_BITS) - 1; + +pub struct UserIDGenerator { + node_id: u64, + sequence: u64, + last_timestamp: u64, +} + +impl UserIDGenerator { + pub fn new(node_id: u64) -> UserIDGenerator { + UserIDGenerator { + node_id, + sequence: 0, + last_timestamp: 0, + } + } + + pub fn next_id(&mut self) -> i64 { + let timestamp = self.timestamp(); + if timestamp < self.last_timestamp { + panic!("Clock moved backwards!"); + } + + if timestamp == self.last_timestamp { + self.sequence = (self.sequence + 1) & SEQUENCE_MASK; + if self.sequence == 0 { + self.wait_next_millis(); + } + } else { + self.sequence = 0; + } + + self.last_timestamp = timestamp; + let id = (timestamp - EPOCH) << TIMESTAMP_SHIFT | self.node_id << NODE_ID_SHIFT | self.sequence; + id as i64 + } + + fn wait_next_millis(&self) { + let mut timestamp = self.timestamp(); + while timestamp == self.last_timestamp { + timestamp = self.timestamp(); + } + } + + fn timestamp(&self) -> u64 { + SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .expect("Clock moved backwards!") + .as_millis() as u64 + } +} diff --git a/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs b/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs index ebaf06016d..3878cbb464 100644 --- a/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs +++ b/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs @@ -33,7 +33,7 @@ async fn user_update_with_name() { let sdk = FlowySDKTest::default(); let user = sdk.init_user().await; let new_name = "hello_world".to_owned(); - let request = UpdateUserProfilePayloadPB::new(&user.id).name(&new_name); + let request = UpdateUserProfilePayloadPB::new(user.id).name(&new_name); let _ = UserModuleEventBuilder::new(sdk.clone()) .event(UpdateUserProfile) .payload(request) @@ -53,7 +53,7 @@ async fn user_update_with_email() { let sdk = FlowySDKTest::default(); let user = sdk.init_user().await; let new_email = format!("{}@gmail.com", nanoid!(6)); - let request = UpdateUserProfilePayloadPB::new(&user.id).email(&new_email); + let request = UpdateUserProfilePayloadPB::new(user.id).email(&new_email); let _ = UserModuleEventBuilder::new(sdk.clone()) .event(UpdateUserProfile) .payload(request) @@ -72,7 +72,7 @@ async fn user_update_with_password() { let sdk = FlowySDKTest::default(); let user = sdk.init_user().await; let new_password = "H123world!".to_owned(); - let request = UpdateUserProfilePayloadPB::new(&user.id).password(&new_password); + let request = UpdateUserProfilePayloadPB::new(user.id).password(&new_password); let _ = UserModuleEventBuilder::new(sdk.clone()) .event(UpdateUserProfile) @@ -86,7 +86,7 @@ async fn user_update_with_invalid_email() { let test = FlowySDKTest::default(); let user = test.init_user().await; for email in invalid_email_test_case() { - let request = UpdateUserProfilePayloadPB::new(&user.id).email(&email); + let request = UpdateUserProfilePayloadPB::new(user.id).email(&email); assert_eq!( UserModuleEventBuilder::new(test.clone()) .event(UpdateUserProfile) @@ -104,7 +104,7 @@ async fn user_update_with_invalid_password() { let test = FlowySDKTest::default(); let user = test.init_user().await; for password in invalid_password_test_case() { - let request = UpdateUserProfilePayloadPB::new(&user.id).password(&password); + let request = UpdateUserProfilePayloadPB::new(user.id).password(&password); UserModuleEventBuilder::new(test.clone()) .event(UpdateUserProfile) @@ -118,7 +118,7 @@ async fn user_update_with_invalid_password() { async fn user_update_with_invalid_name() { let test = FlowySDKTest::default(); let user = test.init_user().await; - let request = UpdateUserProfilePayloadPB::new(&user.id).name(""); + let request = UpdateUserProfilePayloadPB::new(user.id).name(""); UserModuleEventBuilder::new(test.clone()) .event(UpdateUserProfile) .payload(request) diff --git a/frontend/scripts/makefile/tests.toml b/frontend/scripts/makefile/tests.toml index 3f85eaa75e..30831ec2b6 100644 --- a/frontend/scripts/makefile/tests.toml +++ b/frontend/scripts/makefile/tests.toml @@ -1,4 +1,13 @@ +#RUST_LOG="debug" flutter test -j, --concurrency=1 'path to the file' --name 'test case name' +[tasks.flutter_test] +description = "Run flutter test with single case in single file. Input: cargo make flutter_test 'path to the file' --name 'test case name'" +script = ''' +cd appflowy_flutter +RUST_LOG="debug" flutter test -j, --concurrency=1 "${@}" +''' +script_runner = "@shell" + [tasks.dart_unit_test] script = ''' cargo make --profile test-macos run_dart_unit_test diff --git a/shared-lib/flowy-client-ws/src/connection.rs b/shared-lib/flowy-client-ws/src/connection.rs index 87f2abcc1a..ff547a87b3 100644 --- a/shared-lib/flowy-client-ws/src/connection.rs +++ b/shared-lib/flowy-client-ws/src/connection.rs @@ -17,7 +17,7 @@ pub enum WSErrorCode { pub trait FlowyRawWebSocket: Send + Sync { fn initialize(&self) -> FutureResult<(), WSErrorCode>; - fn start_connect(&self, addr: String, user_id: String) -> FutureResult<(), WSErrorCode>; + fn start_connect(&self, addr: String, user_id: i64) -> FutureResult<(), WSErrorCode>; fn stop_connect(&self) -> FutureResult<(), WSErrorCode>; fn subscribe_connect_state(&self) -> BoxFuture>; fn reconnect(&self, count: usize) -> FutureResult<(), WSErrorCode>; @@ -87,7 +87,7 @@ impl FlowyWebSocketConnect { } } - pub async fn start(&self, token: String, user_id: String) -> Result<(), WSErrorCode> { + pub async fn start(&self, token: String, user_id: i64) -> Result<(), WSErrorCode> { let addr = format!("{}/{}", self.addr, &token); self.inner.stop_connect().await?; self.inner.start_connect(addr, user_id).await?; diff --git a/shared-lib/flowy-client-ws/src/ws.rs b/shared-lib/flowy-client-ws/src/ws.rs index 149b6da821..93ad852f7a 100644 --- a/shared-lib/flowy-client-ws/src/ws.rs +++ b/shared-lib/flowy-client-ws/src/ws.rs @@ -12,7 +12,7 @@ impl FlowyRawWebSocket for Arc { FutureResult::new(async { Ok(()) }) } - fn start_connect(&self, addr: String, _user_id: String) -> FutureResult<(), WSErrorCode> { + fn start_connect(&self, addr: String, _user_id: i64) -> FutureResult<(), WSErrorCode> { let cloned_ws = self.clone(); FutureResult::new(async move { cloned_ws.start(addr).await.map_err(internal_error)?; diff --git a/shared-lib/user-model/src/lib.rs b/shared-lib/user-model/src/lib.rs index 6856c7c971..4d4645c910 100644 --- a/shared-lib/user-model/src/lib.rs +++ b/shared-lib/user-model/src/lib.rs @@ -14,7 +14,7 @@ pub struct SignInParams { #[derive(Debug, Default, Serialize, Deserialize, Clone)] pub struct SignInResponse { - pub user_id: String, + pub user_id: i64, pub name: String, pub email: String, pub token: String, @@ -29,7 +29,7 @@ pub struct SignUpParams { #[derive(Serialize, Deserialize, Debug, Default, Clone)] pub struct SignUpResponse { - pub user_id: String, + pub user_id: i64, pub name: String, pub email: String, pub token: String, @@ -37,7 +37,7 @@ pub struct SignUpResponse { #[derive(Serialize, Deserialize, Default, Debug, Clone)] pub struct UserProfile { - pub id: String, + pub id: i64, pub email: String, pub name: String, pub token: String, @@ -47,7 +47,7 @@ pub struct UserProfile { #[derive(Serialize, Deserialize, Default, Clone, Debug)] pub struct UpdateUserProfileParams { - pub id: String, + pub id: i64, pub name: Option, pub email: Option, pub password: Option, @@ -56,9 +56,9 @@ pub struct UpdateUserProfileParams { } impl UpdateUserProfileParams { - pub fn new(user_id: &str) -> Self { + pub fn new(id: i64) -> Self { Self { - id: user_id.to_owned(), + id, name: None, email: None, password: None, From 231fd3829872fd11a6d6116560865aaea5f51eab Mon Sep 17 00:00:00 2001 From: Yijing Huang Date: Mon, 3 Apr 2023 23:48:56 -0500 Subject: [PATCH 3/7] chore: update to Flutter 3.7.5 (#2000) * chore: upgrade appflowy_editor_plugins and flowy_infra * feat(appflowy_flutter): upgrade dependence and delete unused import files * fix(appflowy_flutter): fix SvgPicture upgrade issue update color to colorFilter: apply mask color when the color is not null * feat(appflowy_editor): updateflutter_svg version * chore: flutter analyze * chore: update to 3.7.5 in github action * chore: update to 3.7.5 in github action(integration test) * chore: update appflowy_editor to 0.1.2 * chore: delete appflowy_editor_test.yml under appflowy * chore: update the flutter version in github action * docs: update flutter badge image * chore: update flutter version in scripts * chore: update appflowy editor to the latest release * chore: fix flutter analyze * chore: update integration_test.yml --------- Co-authored-by: Lucas.Xu Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com> --- .github/workflows/flutter_ci.yaml | 2 +- .github/workflows/integration_test.yml | 33 +- .github/workflows/release.yml | 2 +- .github/workflows/rust_ci.yaml | 2 +- .github/workflows/rust_coverage.yml | 2 +- frontend/appflowy_flutter/README.md | 16 +- .../field/field_action_sheet_bloc.dart | 6 - .../application/field/field_editor_bloc.dart | 9 +- .../field/type_option/date_bloc.dart | 6 - .../type_option/edit_select_option_bloc.dart | 6 - .../field/type_option/number_bloc.dart | 6 - .../field/type_option/number_format_bloc.dart | 6 - .../select_option_type_option_bloc.dart | 5 - .../application/setting/setting_bloc.dart | 6 - .../toolbar/board_setting_bloc.dart | 6 - .../application/calendar_setting_bloc.dart | 2 - .../select_option_filter_list_bloc.dart | 7 - .../grid/application/grid_header_bloc.dart | 5 - .../row/row_action_sheet_bloc.dart | 6 - .../plugins/base/link_to_page_widget.dart | 2 +- .../menu/app/header/import/import_panel.dart | 6 +- frontend/appflowy_flutter/macos/Podfile | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 11 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../packages/appflowy_backend/pubspec.yaml | 4 +- .../appflowy_editor/lib/appflowy_editor.dart | 1 - .../lib/src/infra/flowy_svg.dart | 3 +- .../packages/appflowy_editor/pubspec.yaml | 2 +- .../lib/src/emoji_picker/emoji_menu_item.dart | 2 +- .../lib/src/infra/svg.dart | 3 +- .../appflowy_editor_plugins/pubspec.yaml | 18 +- .../appflowy_popover/lib/src/mask.dart | 2 +- .../packages/flowy_infra/lib/image.dart | 14 +- .../packages/flowy_infra/pubspec.yaml | 4 +- .../flowy_infra_ui/lib/flowy_infra_ui.dart | 1 - frontend/appflowy_flutter/pubspec.lock | 703 +++++++++++------- frontend/appflowy_flutter/pubspec.yaml | 15 +- .../scripts/install_dev_env/install_linux.sh | 12 +- .../scripts/install_dev_env/install_macos.sh | 12 +- .../install_dev_env/install_windows.sh | 12 +- 40 files changed, 537 insertions(+), 427 deletions(-) diff --git a/.github/workflows/flutter_ci.yaml b/.github/workflows/flutter_ci.yaml index fafb78558e..842608e5ec 100644 --- a/.github/workflows/flutter_ci.yaml +++ b/.github/workflows/flutter_ci.yaml @@ -16,7 +16,7 @@ on: - "frontend/**" env: - FLUTTER_VERSION: "3.3.9" + FLUTTER_VERSION: "3.7.5" RUST_TOOLCHAIN: "1.65" jobs: diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 96ad941a26..084018f747 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -35,7 +35,7 @@ jobs: - uses: subosito/flutter-action@v2 with: channel: "stable" - flutter-version: "3.3.9" + flutter-version: "3.7.5" cache: true - name: Cache Cargo @@ -56,15 +56,16 @@ jobs: - name: Setup Environment run: | + cargo install --force cargo-make + cargo install --force duckscript_cli if [ "$RUNNER_OS" == "Linux" ]; then sudo wget -qO /etc/apt/trusted.gpg.d/dart_linux_signing_key.asc https://dl-ssl.google.com/linux/linux_signing_key.pub sudo wget -qO /etc/apt/sources.list.d/dart_stable.list https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list sudo apt-get update - sudo apt-get install -y dart curl build-essential libsqlite3-dev libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev + sudo apt-get install -y dart curl build-essential libssl-dev clang cmake ninja-build pkg-config libgtk-3-dev sudo apt-get install keybinder-3.0 elif [ "$RUNNER_OS" == "Windows" ]; then vcpkg integrate install - cargo install --force duckscript_cli elif [ "$RUNNER_OS" == "macOS" ]; then echo 'do nothing' fi @@ -77,17 +78,6 @@ jobs: cargo install cargo-make cargo make appflowy-flutter-deps-tools - - name: Build Test lib - working-directory: frontend - run: | - if [ "$RUNNER_OS" == "Linux" ]; then - cargo make --profile production-linux-x86_64 appflowy - elif [ "$RUNNER_OS" == "macOS" ]; then - cargo make --profile production-mac-x86_64 appflowy - elif [ "$RUNNER_OS" == "Windows" ]; then - cargo make --profile production-windows-x86 appflowy - fi - - name: Config Flutter run: | if [ "$RUNNER_OS" == "Linux" ]; then @@ -99,12 +89,17 @@ jobs: fi shell: bash - - name: Flutter Code Generation - working-directory: frontend/appflowy_flutter + - name: Build Test lib + working-directory: frontend run: | - flutter packages pub get - flutter packages pub run easy_localization:generate -f keys -o locale_keys.g.dart -S assets/translations -s en.json - flutter packages pub run build_runner build --delete-conflicting-outputs + if [ "$RUNNER_OS" == "Linux" ]; then + cargo make --profile development-linux-x86_64 appflowy-dev + elif [ "$RUNNER_OS" == "macOS" ]; then + cargo make --profile development-mac-x86_64 appflowy-dev + elif [ "$RUNNER_OS" == "Windows" ]; then + cargo make --profile development-windows-x86 appflowy-dev + fi + shell: bash - name: Run AppFlowy tests working-directory: frontend/appflowy_flutter diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e784801bca..c971bb30ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: - '*' env: - FLUTTER_VERSION: "3.3.9" + FLUTTER_VERSION: "3.7.5" RUST_TOOLCHAIN: "1.65" jobs: diff --git a/.github/workflows/rust_ci.yaml b/.github/workflows/rust_ci.yaml index 0991dd0dcb..33b08bbde7 100644 --- a/.github/workflows/rust_ci.yaml +++ b/.github/workflows/rust_ci.yaml @@ -20,7 +20,7 @@ on: env: CARGO_TERM_COLOR: always RUST_TOOLCHAIN: "1.65" - FLUTTER_VERSION: "3.3.9" + FLUTTER_VERSION: "3.7.5" jobs: test-on-ubuntu: diff --git a/.github/workflows/rust_coverage.yml b/.github/workflows/rust_coverage.yml index 5e5c741b0d..be9d09bb4d 100644 --- a/.github/workflows/rust_coverage.yml +++ b/.github/workflows/rust_coverage.yml @@ -11,7 +11,7 @@ on: env: CARGO_TERM_COLOR: always - FLUTTER_VERSION: "3.3.9" + FLUTTER_VERSION: "3.7.5" RUST_TOOLCHAIN: "1.65" jobs: diff --git a/frontend/appflowy_flutter/README.md b/frontend/appflowy_flutter/README.md index 74e4f803a3..3c1ac42d93 100644 --- a/frontend/appflowy_flutter/README.md +++ b/frontend/appflowy_flutter/README.md @@ -1,6 +1,6 @@

AppFlowy_Flutter

- +
@@ -9,13 +9,16 @@ This Repository contains the codebase for the frontend of the application, currently we use Flutter as our frontend framework. ### Platforms Supported Using Flutter 💻 + - Linux - macOS - Windows -> We later expect to extend support to Android and iOS devices using Flutter. + > We later expect to extend support to Android and iOS devices using Flutter. ### Am I Eligible to Contribute? + Yes! You are eligible to contribute, check out the ways in which you can [contribute to AppFlowy](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy). Some of the ways in which you can contribute are: + - Non-Coding Contributions - Documentation - Feature Requests and Feedbacks @@ -23,26 +26,27 @@ Yes! You are eligible to contribute, check out the ways in which you can [contri - Improve Translations - Coding Contributions - To contribute to `AppFlowy_Flutter` codebase specifically (coding contribution) we suggest you to have basic knowledge of Flutter. In case you are new to Flutter, we may suggest you to learn the basics and then try to contribute, get started with Flutter [here](https://flutter.dev/docs/get-started/codelab). ### What OS Should I Use for Development? + We support all OS for Development i.e Linux, macOS and Windows. However, most of us promote macOS and Linux over Windows. We have detailed [docs](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/environment-setup) on How to Setup `AppFlowy_Flutter` in your local system in each OS. - ### Getting Started ❇ + We have a detailed documentation, on how to [get started](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/contributing-to-appflowy) with the project, and make your first contribution. However, we do have some specific picks for you. + - [Code Architecture](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/frontend/codemap) - [Making Your First PR](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/submitting-your-first-pull-request) - [The Style Guide](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/style-guides) - [How to run/debug the application](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/launcher-and-tasks) - ### Need Help? + - New to GitHub? Follow [these](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/setting-up-your-repositories) steps to get started - Stuck Somewhere? Join the [Discord](https://discord.gg/9Q2xaN37tV) Group and we are there to help you! - diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_action_sheet_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_action_sheet_bloc.dart index 354bafbf1f..493f971177 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_action_sheet_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_action_sheet_bloc.dart @@ -2,7 +2,6 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'field_service.dart'; part 'field_action_sheet_bloc.freezed.dart'; @@ -64,11 +63,6 @@ class FieldActionSheetBloc }, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_editor_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_editor_bloc.dart index 8ec40c1c93..491d266b7d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_editor_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/field_editor_bloc.dart @@ -1,6 +1,5 @@ import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'dart:async'; import 'package:dartz/dartz.dart'; import 'field_service.dart'; import 'type_option/type_option_context.dart'; @@ -17,8 +16,7 @@ class FieldEditorBloc extends Bloc { required String fieldName, required bool isGroupField, required IFieldTypeOptionLoader loader, - }) : dataController = - TypeOptionController(viewId: viewId, loader: loader), + }) : dataController = TypeOptionController(viewId: viewId, loader: loader), super(FieldEditorState.initial(viewId, fieldName, isGroupField)) { on( (event, emit) async { @@ -63,11 +61,6 @@ class FieldEditorBloc extends Bloc { }, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/date_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/date_bloc.dart index 03eef86736..6762e0d7d3 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/date_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/date_bloc.dart @@ -2,7 +2,6 @@ import 'package:appflowy_backend/protobuf/flowy-database/date_type_option.pb.dar import 'package:appflowy_backend/protobuf/flowy-database/date_type_option_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'package:protobuf/protobuf.dart'; import 'type_option_context.dart'; @@ -52,11 +51,6 @@ class DateTypeOptionBloc } }); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart index 063be6be32..873daaeabe 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart @@ -1,7 +1,6 @@ import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'package:protobuf/protobuf.dart'; import 'package:dartz/dartz.dart'; part 'edit_select_option_bloc.freezed.dart'; @@ -27,11 +26,6 @@ class EditSelectOptionBloc ); } - @override - Future close() async { - return super.close(); - } - SelectOptionPB _updateColor(SelectOptionColorPB color) { state.option.freeze(); return state.option.rebuild((option) { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_bloc.dart index a66b5a88ca..b8e924819f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_bloc.dart @@ -2,7 +2,6 @@ import 'package:appflowy_backend/protobuf/flowy-database/format.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-database/number_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'package:protobuf/protobuf.dart'; import 'type_option_context.dart'; @@ -29,11 +28,6 @@ class NumberTypeOptionBloc typeOption.format = format; }); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_format_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_format_bloc.dart index 4936f69900..4145e90aff 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_format_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/number_format_bloc.dart @@ -1,7 +1,6 @@ import 'package:appflowy_backend/protobuf/flowy-database/format.pbenum.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; part 'number_format_bloc.freezed.dart'; class NumberFormatBloc extends Bloc { @@ -21,11 +20,6 @@ class NumberFormatBloc extends Bloc { }, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart index 5c608b474f..75c472f96d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart @@ -49,11 +49,6 @@ class SelectOptionTypeOptionBloc }, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_bloc.dart index 9857a2871a..8c59036f56 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/setting/setting_bloc.dart @@ -1,6 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'package:dartz/dartz.dart'; part 'setting_bloc.freezed.dart'; @@ -18,11 +17,6 @@ class DatabaseSettingBloc }, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/toolbar/board_setting_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/toolbar/board_setting_bloc.dart index 739d9ee141..e64072db56 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/toolbar/board_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/toolbar/board_setting_bloc.dart @@ -1,6 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'package:dartz/dartz.dart'; part 'board_setting_bloc.freezed.dart'; @@ -17,11 +16,6 @@ class BoardSettingBloc extends Bloc { }, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_setting_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_setting_bloc.dart index 1ebc97d90a..074836236f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_setting_bloc.dart @@ -23,8 +23,6 @@ class CalendarSettingBloc }); } - @override - Future close() async => super.close(); } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart index 9ff924c449..cd95541905 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/filter/select_option_filter_list_bloc.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/choicechip/select_option/select_option_loader.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart'; @@ -63,11 +61,6 @@ class SelectOptionFilterListBloc ); } - @override - Future close() async { - return super.close(); - } - void _updateSelectOptions({ String? predicate, Set? selectedOptionIds, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_header_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_header_bloc.dart index 7d212a80e0..92486a699b 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_header_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/grid_header_bloc.dart @@ -61,11 +61,6 @@ class GridHeaderBloc extends Bloc { listenWhen: () => !isClosed, ); } - - @override - Future close() async { - return super.close(); - } } @freezed diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/row/row_action_sheet_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/row/row_action_sheet_bloc.dart index 1ff5529ad9..aab8875a4c 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/row/row_action_sheet_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/application/row/row_action_sheet_bloc.dart @@ -2,7 +2,6 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; -import 'dart:async'; import 'package:dartz/dartz.dart'; import '../../../application/row/row_cache.dart'; @@ -34,11 +33,6 @@ class RowActionSheetBloc ); } - @override - Future close() async { - return super.close(); - } - void logResult(Either result) { result.fold((l) => null, (err) => Log.error(err)); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart index 19c21739cc..d59d679141 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart @@ -59,7 +59,7 @@ void showLinkToPageMenu( ); }); - Overlay.of(context)?.insert(_linkToPageMenu!); + Overlay.of(context).insert(_linkToPageMenu!); editorState.service.selectionService.currentSelection .addListener(dismissLinkToPageMenu); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_panel.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_panel.dart index f1996af8f8..540e0d8b1d 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_panel.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/header/import/import_panel.dart @@ -45,7 +45,7 @@ enum _ImportType { case _ImportType.markdownOrText: return 'Text & Markdown'; default: - assert(false, 'Unsupported Type ${this}'); + assert(false, 'Unsupported Type $this'); return ''; } } @@ -55,7 +55,7 @@ enum _ImportType { case _ImportType.markdownOrText: return svgWidget('editor/documents'); default: - assert(false, 'Unsupported Type ${this}'); + assert(false, 'Unsupported Type $this'); return null; } } @@ -65,7 +65,7 @@ enum _ImportType { case _ImportType.markdownOrText: return ['md', 'txt']; default: - assert(false, 'Unsupported Type ${this}'); + assert(false, 'Unsupported Type $this'); return []; } } diff --git a/frontend/appflowy_flutter/macos/Podfile b/frontend/appflowy_flutter/macos/Podfile index e806f574bd..7d7672e61f 100644 --- a/frontend/appflowy_flutter/macos/Podfile +++ b/frontend/appflowy_flutter/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.11' +platform :osx, '10.14' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/frontend/appflowy_flutter/macos/Runner.xcodeproj/project.pbxproj b/frontend/appflowy_flutter/macos/Runner.xcodeproj/project.pbxproj index 5634f236ea..7e9dfada08 100644 --- a/frontend/appflowy_flutter/macos/Runner.xcodeproj/project.pbxproj +++ b/frontend/appflowy_flutter/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -202,7 +202,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -255,6 +255,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -403,7 +404,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; STRIP_STYLE = "non-global"; @@ -489,7 +490,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -537,7 +538,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.11; + MACOSX_DEPLOYMENT_TARGET = 10.14; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; STRIP_STYLE = "non-global"; diff --git a/frontend/appflowy_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/frontend/appflowy_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 60b6e605fe..656a4d8b2a 100644 --- a/frontend/appflowy_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/frontend/appflowy_flutter/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ =2.18.0 <3.0.0" - flutter: ">=3.3.0" + sdk: ">=2.19.0 <3.0.0" + flutter: ">=3.7.0" dependencies: flutter: sdk: flutter - appflowy_editor: - path: ../appflowy_editor - flowy_infra: + appflowy_editor: ^0.1.4 + flowy_infra: path: ../flowy_infra flowy_infra_ui: path: ../flowy_infra_ui - appflowy_popover: + appflowy_popover: path: ../appflowy_popover - flutter_math_fork: ^0.6.3+1 + flutter_math_fork: + git: + url: https://github.com/LucasXu0/flutter_math_fork.git + ref: master highlight: ^0.7.0 shared_preferences: ^2.0.15 - flutter_svg: ^1.1.1+1 + flutter_svg: ^2.0.2 provider: ^6.0.3 dev_dependencies: diff --git a/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/mask.dart b/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/mask.dart index 4a79a1731f..d63e486a1e 100644 --- a/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/mask.dart +++ b/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/mask.dart @@ -17,7 +17,7 @@ class RootOverlayEntry { bool asBarrier, ) { _entries[newState] = OverlayEntryContext(entry, newState, asBarrier); - Overlay.of(context)?.insert(entry); + Overlay.of(context).insert(entry); } bool contains(PopoverState oldState) { diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/image.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/image.dart index 577e3c182a..0566f207e9 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/image.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/image.dart @@ -1,6 +1,6 @@ +import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:flutter/material.dart'; /// For icon that needs to change color when it is on hovered /// @@ -29,9 +29,17 @@ Widget svgWidget(String name, {Size? size, Color? color}) { if (size != null) { return SizedBox.fromSize( size: size, - child: SvgPicture.asset('assets/images/$name.svg', color: color), + child: SvgPicture.asset( + 'assets/images/$name.svg', + colorFilter: + color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null, + ), ); } else { - return SvgPicture.asset('assets/images/$name.svg', color: color); + return SvgPicture.asset( + 'assets/images/$name.svg', + colorFilter: + color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null, + ); } } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/pubspec.yaml b/frontend/appflowy_flutter/packages/flowy_infra/pubspec.yaml index a361184dbe..4686b7cd00 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/pubspec.yaml +++ b/frontend/appflowy_flutter/packages/flowy_infra/pubspec.yaml @@ -13,12 +13,12 @@ dependencies: time: '>=2.0.0' uuid: ">=2.2.2" textstyle_extensions: '2.0.0-nullsafety' - flutter_svg: ^1.1.1 + flutter_svg: ^2.0.2 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.1 + flutter_lints: ^2.0.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart index adb43b4837..7c830775c8 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/flowy_infra_ui.dart @@ -18,5 +18,4 @@ export 'style_widget/icon_button.dart'; export 'style_widget/scrolling/styled_scroll_bar.dart'; export '/widget/spacing.dart'; export 'style_widget/scrolling/styled_list.dart'; -export 'style_widget/button.dart'; export 'style_widget/color_picker.dart'; diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index f6e21acf11..c785f0285f 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -5,21 +5,24 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8" + url: "https://pub.dev" source: hosted version: "47.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80" + url: "https://pub.dev" source: hosted version: "4.7.0" animations: dependency: transitive description: name: animations - url: "https://pub.dartlang.org" + sha256: fe8a6bdca435f718bb1dc8a11661b2c22504c6da40ef934cee8327ed77934164 + url: "https://pub.dev" source: hosted version: "2.0.7" appflowy_backend: @@ -41,10 +44,11 @@ packages: appflowy_editor: dependency: "direct main" description: - path: "packages/appflowy_editor" - relative: true - source: path - version: "0.0.9" + name: appflowy_editor + sha256: "2f28ff3ef62bfb02f13e10931fa8c091aa9f804934dfbf5d3d0af0acaf06a240" + url: "https://pub.dev" + source: hosted + version: "0.1.4" appflowy_editor_plugins: dependency: "direct main" description: @@ -63,364 +67,384 @@ packages: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: "80e5141fafcb3361653ce308776cfd7d45e6e9fbb429e14eec571382c0c5fecb" + url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.2" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: "4cab82a83ffef80b262ddedf47a0a8e56ee6fbf7fe21e6e768b02792034dd440" + url: "https://pub.dev" source: hosted version: "2.4.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" bloc: dependency: "direct main" description: name: bloc - url: "https://pub.dartlang.org" + sha256: "658a5ae59edcf1e58aac98b000a71c762ad8f46f1394c34a52050cafb3e11a80" + url: "https://pub.dev" source: hosted version: "8.1.1" bloc_test: dependency: "direct dev" description: name: bloc_test - url: "https://pub.dartlang.org" + sha256: ffbb60c17ee3d8e3784cb78071088e353199057233665541e8ac6cd438dca8ad + url: "https://pub.dev" source: hosted version: "9.1.1" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" source: hosted version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "6bc5544ea6ce4428266e7ea680e945c68806c4aae2da0eb5e9ccf38df8d6acbf" + url: "https://pub.dev" source: hosted version: "3.1.1" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6" + url: "https://pub.dev" source: hosted version: "2.0.10" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: "93f05c041932674be039b0a2323d6cf57e5f2bbf884a3c0382f9e53fc45ebace" + url: "https://pub.dev" source: hosted version: "2.3.0" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" source: hosted version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: "169565c8ad06adb760c3645bf71f00bff161b00002cace266cad42c5d22a7725" + url: "https://pub.dev" source: hosted version: "8.4.4" calendar_view: dependency: "direct main" description: name: calendar_view - url: "https://pub.dartlang.org" + sha256: "7f2c460d38cda782e0852ca7706086c24f6e9407a9f0cfcdef034fb81e6d9f3e" + url: "https://pub.dev" source: hosted version: "1.0.2" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" charcode: dependency: "direct main" description: name: charcode - url: "https://pub.dartlang.org" + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" source: hosted version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted version: "2.0.2" clipboard: dependency: "direct main" description: name: clipboard - url: "https://pub.dartlang.org" + sha256: "2ec38f0e59878008ceca0ab122e4bfde98847f88ef0f83331362ba4521f565a9" + url: "https://pub.dev" source: hosted version: "0.1.3" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" source: hosted version: "4.4.0" collection: dependency: "direct main" description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" connectivity_plus: dependency: "direct main" description: name: connectivity_plus - url: "https://pub.dartlang.org" + sha256: "8875e8ed511a49f030e313656154e4bbbcef18d68dfd32eb853fac10bce48e96" + url: "https://pub.dev" source: hosted - version: "2.3.9" - connectivity_plus_linux: - dependency: transitive - description: - name: connectivity_plus_linux - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - connectivity_plus_macos: - dependency: transitive - description: - name: connectivity_plus_macos - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.6" + version: "3.0.3" connectivity_plus_platform_interface: dependency: "direct main" description: name: connectivity_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + url: "https://pub.dev" source: hosted version: "1.2.4" - connectivity_plus_web: - dependency: transitive - description: - name: connectivity_plus_web - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.5" - connectivity_plus_windows: - dependency: transitive - description: - name: connectivity_plus_windows - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.2" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted version: "3.1.1" coverage: dependency: transitive description: name: coverage - url: "https://pub.dartlang.org" + sha256: "525ac94733f9ce82507a050bfd62ad89eb1dcbc56308e1e2e17ab11abeee4a75" + url: "https://pub.dev" source: hosted version: "1.5.0" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" csslib: dependency: transitive description: name: csslib - url: "https://pub.dartlang.org" + sha256: b36c7f7e24c0bdf1bf9a3da461c837d1de64b9f8beb190c9011d8c72a3dfd745 + url: "https://pub.dev" source: hosted version: "0.17.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4" + url: "https://pub.dev" source: hosted version: "2.2.4" dartz: dependency: "direct main" description: name: dartz - url: "https://pub.dartlang.org" + sha256: e6acf34ad2e31b1eb00948692468c30ab48ac8250e0f0df661e29f12dd252168 + url: "https://pub.dev" source: hosted version: "0.10.1" dbus: dependency: transitive description: name: dbus - url: "https://pub.dartlang.org" + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" + url: "https://pub.dev" source: hosted - version: "0.7.4" + version: "0.7.8" device_info_plus: dependency: "direct main" description: name: device_info_plus - url: "https://pub.dartlang.org" + sha256: b809c4ed5f7fcdb325ccc70b80ad934677dc4e2aa414bf46859a42bfdfafcbb6 + url: "https://pub.dev" source: hosted - version: "3.2.4" + version: "4.1.3" device_info_plus_linux: dependency: transitive description: name: device_info_plus_linux - url: "https://pub.dartlang.org" + sha256: "77a8b3c4af06bc46507f89304d9f49dfc64b4ae004b994532ed23b34adeae4b3" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.0.0" device_info_plus_macos: dependency: transitive description: name: device_info_plus_macos - url: "https://pub.dartlang.org" + sha256: "37961762fbd46d3620c7b69ca606671014db55fc1b7a11e696fd90ed2e8fe03d" + url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "3.0.0" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: "83fdba24fcf6846d3b10f10dfdc8b6c6d7ada5f8ed21d62ea2909c2dfa043773" + url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "3.0.0" device_info_plus_web: dependency: transitive description: name: device_info_plus_web - url: "https://pub.dartlang.org" + sha256: "5890f6094df108181c7a29720bc23d0fd6159f17d82787fac093d1fefcaf6325" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "3.0.0" device_info_plus_windows: dependency: transitive description: name: device_info_plus_windows - url: "https://pub.dartlang.org" + sha256: "23a2874af0e23ee6e3a2a0ebcecec3a9da13241f2cb93a93a44c8764df123dd7" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "4.1.0" diff_match_patch: dependency: transitive description: name: diff_match_patch - url: "https://pub.dartlang.org" + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" + url: "https://pub.dev" source: hosted version: "0.4.1" easy_localization: dependency: "direct main" description: name: easy_localization - url: "https://pub.dartlang.org" + sha256: "6a2e99fa0bfe5765bf4c6ca9b137d5de2c75593007178c5e4cd2ae985f870080" + url: "https://pub.dev" source: hosted version: "3.0.1" easy_logger: dependency: transitive description: name: easy_logger - url: "https://pub.dartlang.org" + sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 + url: "https://pub.dev" source: hosted version: "0.0.2" equatable: dependency: "direct main" description: name: equatable - url: "https://pub.dartlang.org" + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" source: hosted version: "2.0.5" expandable: dependency: "direct main" description: name: expandable - url: "https://pub.dartlang.org" + sha256: "9604d612d4d1146dafa96c6d8eec9c2ff0994658d6d09fed720ab788c7f5afc2" + url: "https://pub.dev" source: hosted version: "5.0.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted - version: "6.1.2" + version: "6.1.4" file_picker: dependency: "direct main" description: name: file_picker - url: "https://pub.dartlang.org" + sha256: aeeb811e81c3831124fb9dc1077e42d3837de401f4762dd371cb108e9c9fb2a4 + url: "https://pub.dev" source: hosted - version: "4.6.1" + version: "5.0.0" fixnum: dependency: "direct main" description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + url: "https://pub.dev" source: hosted version: "1.0.1" flowy_infra: @@ -460,16 +484,18 @@ packages: dependency: "direct main" description: name: flutter_bloc - url: "https://pub.dartlang.org" + sha256: "434951eea948dbe87f737b674281465f610b8259c16c097b8163ce138749a775" + url: "https://pub.dev" source: hosted version: "8.1.2" flutter_colorpicker: dependency: "direct main" description: name: flutter_colorpicker - url: "https://pub.dartlang.org" + sha256: "458a6ed8ea480eb16ff892aedb4b7092b2804affd7e046591fb03127e8d8ef8b" + url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "1.0.3" flutter_driver: dependency: transitive description: flutter @@ -479,7 +505,8 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_localizations: @@ -490,24 +517,28 @@ packages: flutter_math_fork: dependency: transitive description: - name: flutter_math_fork - url: "https://pub.dartlang.org" - source: hosted + path: "." + ref: master + resolved-ref: "77cab5696e756e1e18e26b2a6239c1083f60d6b9" + url: "https://github.com/LucasXu0/flutter_math_fork.git" + source: git version: "0.6.3+1" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: "60fc7b78455b94e6de2333d2f95196d32cf5c22f4b0b0520a628804cb463503b" + url: "https://pub.dev" source: hosted version: "2.0.9" flutter_svg: dependency: transitive description: name: flutter_svg - url: "https://pub.dartlang.org" + sha256: "12006889e2987c549c4c1ec1a5ba4ec4b24d34d2469ee5f9476c926dcecff266" + url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "2.0.4" flutter_test: dependency: "direct dev" description: flutter @@ -522,28 +553,32 @@ packages: dependency: "direct main" description: name: fluttertoast - url: "https://pub.dartlang.org" + sha256: "7cc92eabe01e3f1babe1571c5560b135dfc762a34e41e9056881e2196b178ec1" + url: "https://pub.dev" source: hosted version: "8.2.1" freezed: dependency: "direct dev" description: name: freezed - url: "https://pub.dartlang.org" + sha256: "4179d41127bc7a67dc3f58ceec1d22f1cdf10470653cb86eda2a63f81b4920c7" + url: "https://pub.dev" source: hosted version: "2.2.0" freezed_annotation: dependency: "direct main" description: name: freezed_annotation - url: "https://pub.dartlang.org" + sha256: aeac15850ef1b38ee368d4c53ba9a847e900bb2c53a4db3f6881cbb3cb684338 + url: "https://pub.dev" source: hosted version: "2.2.0" frontend_server_client: dependency: transitive description: name: frontend_server_client - url: "https://pub.dartlang.org" + sha256: "4f4a162323c86ffc1245765cfe138872b8f069deb42f7dbb36115fa27f31469b" + url: "https://pub.dev" source: hosted version: "2.1.3" fuchsia_remote_debug_protocol: @@ -555,70 +590,80 @@ packages: dependency: "direct main" description: name: get_it - url: "https://pub.dartlang.org" + sha256: "290fde3a86072e4b37dbb03c07bec6126f0ecc28dad403c12ffe2e5a2d751ab7" + url: "https://pub.dev" source: hosted version: "7.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: c51b4fdfee4d281f49b8c957f1add91b815473597f76bcf07377987f66a55729 + url: "https://pub.dev" source: hosted version: "2.1.0" google_fonts: dependency: "direct main" description: name: google_fonts - url: "https://pub.dartlang.org" + sha256: "927573f2e8a8d65c17931e21918ad0ab0666b1b636537de7c4932bdb487b190f" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "4.0.3" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: f9e130f3259f52d26f0cfc0e964513796dafed572fa52e45d2f8d6ca14db39b2 + url: "https://pub.dev" source: hosted version: "2.2.0" highlight: dependency: transitive description: name: highlight - url: "https://pub.dartlang.org" + sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21" + url: "https://pub.dev" source: hosted version: "0.7.0" hotkey_manager: dependency: "direct main" description: name: hotkey_manager - url: "https://pub.dartlang.org" + sha256: "39b352b6dabb806fd53122d6c95ded1174df882d2db01eedc31cc046f8cc7b6c" + url: "https://pub.dev" source: hosted version: "0.1.7" html: dependency: transitive description: name: html - url: "https://pub.dartlang.org" + sha256: d9793e10dbe0e6c364f4c59bf3e01fb33a9b2a674bc7a1081693dba0614b6269 + url: "https://pub.dev" source: hosted version: "0.15.2" http: dependency: "direct main" description: name: http - url: "https://pub.dartlang.org" + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" source: hosted version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted version: "4.0.2" integration_test: @@ -630,497 +675,560 @@ packages: dependency: "direct main" description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" intl_utils: dependency: transitive description: name: intl_utils - url: "https://pub.dartlang.org" + sha256: "856baa08d4735ee3476901827d52671c1a2b6f9ccb8b848d73bc5b8dd28b21e5" + url: "https://pub.dev" source: hosted version: "2.7.0" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted version: "1.0.4" isolates: dependency: transitive description: name: isolates - url: "https://pub.dartlang.org" + sha256: ce89e4141b27b877326d3715be2dceac7a7ba89f3229785816d2d318a75ddf28 + url: "https://pub.dev" source: hosted version: "3.0.3+8" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" json_annotation: dependency: "direct main" description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: "3520fa844009431b5d4491a5a778603520cdc399ab3406332dcc50f93547258c" + url: "https://pub.dev" source: hosted version: "4.7.0" json_serializable: dependency: "direct dev" description: name: json_serializable - url: "https://pub.dartlang.org" + sha256: f3c2c18a7889580f71926f30c1937727c8c7d4f3a435f8f5e8b0ddd25253ef5d + url: "https://pub.dev" source: hosted version: "6.5.4" linked_scroll_controller: dependency: "direct main" description: name: linked_scroll_controller - url: "https://pub.dartlang.org" + sha256: e6020062bcf4ffc907ee7fd090fa971e65d8dfaac3c62baf601a3ced0b37986a + url: "https://pub.dev" source: hosted version: "0.2.0" lint: dependency: transitive description: name: lint - url: "https://pub.dartlang.org" + sha256: "4a539aa34ec5721a2c7574ae2ca0336738ea4adc2a34887d54b7596310b33c85" + url: "https://pub.dev" source: hosted version: "1.10.0" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + url: "https://pub.dev" source: hosted version: "2.0.1" loading_indicator: dependency: transitive description: name: loading_indicator - url: "https://pub.dartlang.org" + sha256: "5cb15810fc3d8872230d086b4810d9f9bbcd6e7d208a38f7cd6bc81fb2650e4b" + url: "https://pub.dev" source: hosted version: "3.1.0" logger: dependency: transitive description: name: logger - url: "https://pub.dartlang.org" + sha256: "5076f09225f91dc49289a4ccb92df2eeea9ea01cf7c26d49b3a1f04c6a49eec1" + url: "https://pub.dev" source: hosted version: "1.3.0" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted version: "1.1.1" markdown: dependency: transitive description: name: markdown - url: "https://pub.dartlang.org" + sha256: b3c60dee8c2af50ad0e6e90cceba98e47718a6ee0a7a6772c77846a0cc21f78b + url: "https://pub.dev" source: hosted - version: "6.0.1" + version: "7.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted version: "1.0.4" mocktail: dependency: transitive description: name: mocktail - url: "https://pub.dartlang.org" + sha256: "80a996cd9a69284b3dc521ce185ffe9150cde69767c2d3a0720147d93c0cef53" + url: "https://pub.dev" source: hosted version: "0.3.0" nested: dependency: transitive description: name: nested - url: "https://pub.dartlang.org" + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted version: "1.0.0" nm: dependency: transitive description: name: nm - url: "https://pub.dartlang.org" + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" source: hosted version: "0.5.0" node_preamble: dependency: transitive description: name: node_preamble - url: "https://pub.dartlang.org" + sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + url: "https://pub.dev" source: hosted version: "2.0.2" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted version: "2.1.0" package_info_plus: dependency: "direct main" description: name: package_info_plus - url: "https://pub.dartlang.org" + sha256: f62d7253edc197fe3c88d7c2ddab82d68f555e778d55390ccc3537eca8e8d637 + url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.4.3+1" package_info_plus_linux: dependency: transitive description: name: package_info_plus_linux - url: "https://pub.dartlang.org" + sha256: "04b575f44233d30edbb80a94e57cad9107aada334fc02aabb42b6becd13c43fc" + url: "https://pub.dev" source: hosted version: "1.0.5" package_info_plus_macos: dependency: transitive description: name: package_info_plus_macos - url: "https://pub.dartlang.org" + sha256: a2ad8b4acf4cd479d4a0afa5a74ea3f5b1c7563b77e52cc32b3ee6956d5482a6 + url: "https://pub.dev" source: hosted version: "1.3.0" package_info_plus_platform_interface: dependency: transitive description: name: package_info_plus_platform_interface - url: "https://pub.dartlang.org" + sha256: f7a0c8f1e7e981bc65f8b64137a53fd3c195b18d429fba960babc59a5a1c7ae8 + url: "https://pub.dev" source: hosted version: "1.0.2" package_info_plus_web: dependency: transitive description: name: package_info_plus_web - url: "https://pub.dartlang.org" + sha256: f0829327eb534789e0a16ccac8936a80beed4e2401c4d3a74f3f39094a822d3b + url: "https://pub.dev" source: hosted version: "1.0.6" package_info_plus_windows: dependency: transitive description: name: package_info_plus_windows - url: "https://pub.dartlang.org" + sha256: "79524f11c42dd9078b96d797b3cf79c0a2883a50c4920dc43da8562c115089bc" + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "2.1.0" path: dependency: "direct main" description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" - path_drawing: - dependency: transitive - description: - name: path_drawing - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" path_parsing: dependency: transitive description: name: path_parsing - url: "https://pub.dartlang.org" + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" source: hosted version: "1.0.1" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: dcea5feb97d8abf90cab9e9030b497fb7c3cbf26b7a1fe9e3ef7dcb0a1ddec95 + url: "https://pub.dev" source: hosted version: "2.0.14" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: a776c088d671b27f6e3aa8881d64b87b3e80201c64e8869b811325de7a76c15e + url: "https://pub.dev" source: hosted version: "2.0.24" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - url: "https://pub.dartlang.org" + sha256: "62a68e7e1c6c459f9289859e2fae58290c981ce21d1697faf54910fe1faa4c74" + url: "https://pub.dev" source: hosted version: "2.2.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: "2e32f1640f07caef0d3cb993680f181c79e54a3827b997d5ee221490d131fbd9" + url: "https://pub.dev" source: hosted version: "2.1.10" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: f0abc8ebd7253741f05488b4813d936b4d07c6bae3e86148a09e342ee4b08e76 + url: "https://pub.dev" source: hosted version: "2.0.6" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 + url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.1.5" percent_indicator: dependency: "direct main" description: name: percent_indicator - url: "https://pub.dartlang.org" + sha256: cec41f67181fbd5322aa68b355621d1a4eea827426b8eeb613f6cbe195ff7b4a + url: "https://pub.dev" source: hosted version: "4.2.3" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a + url: "https://pub.dev" source: hosted version: "2.1.4" pool: dependency: transitive description: name: pool - url: "https://pub.dartlang.org" + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted version: "1.5.1" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" protobuf: dependency: "direct main" description: name: protobuf - url: "https://pub.dartlang.org" + sha256: "467c7ccf3fee0272d5cb84bf20debc509f9a4f69ce06e5f7a8b749d7e6962085" + url: "https://pub.dev" source: hosted version: "2.0.0" provider: dependency: "direct main" description: name: provider - url: "https://pub.dartlang.org" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" source: hosted version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "307de764d305289ff24ad257ad5c5793ce56d04947599ad68b3baa124105fc17" + url: "https://pub.dev" source: hosted version: "2.1.3" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: "75f6614d6dde2dc68948dffbaa4fe5dae32cd700eb9fb763fe11dfb45a3c4d0a" + url: "https://pub.dev" source: hosted version: "1.2.1" reorderables: dependency: "direct main" description: name: reorderables - url: "https://pub.dartlang.org" + sha256: "004a886e4878df1ee27321831c838bc1c976311f4ca6a74ce7d561e506540a77" + url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" rich_clipboard: dependency: transitive description: name: rich_clipboard - url: "https://pub.dartlang.org" + sha256: "48bfc84a0d3eeec5692b3afd0277aa658a7c95d1dbda72bb623188fba6a8e253" + url: "https://pub.dev" source: hosted version: "1.0.1" rich_clipboard_android: dependency: transitive description: name: rich_clipboard_android - url: "https://pub.dartlang.org" + sha256: "1388bad7748791818aa5b822df2f3449fff34785b266fa6ca4cbc7cd24342871" + url: "https://pub.dev" source: hosted version: "1.0.0" rich_clipboard_ios: dependency: transitive description: name: rich_clipboard_ios - url: "https://pub.dartlang.org" + sha256: "9d6bc037463b1b24cb14ae35ee9d7530bd6b2bdb15b30909fb47a1af01bf3233" + url: "https://pub.dev" source: hosted version: "1.0.0" rich_clipboard_linux: dependency: transitive description: name: rich_clipboard_linux - url: "https://pub.dartlang.org" + sha256: "0d0ab273afd60cb7314d01fdf3994fa01be2be79528f448241d9d70ea19b3db9" + url: "https://pub.dev" source: hosted version: "1.0.1" rich_clipboard_macos: dependency: transitive description: name: rich_clipboard_macos - url: "https://pub.dartlang.org" + sha256: "1aeb409e267576baaced347549e42dabc59895b10b2e09dabd9f753f469deb3e" + url: "https://pub.dev" source: hosted version: "1.0.1" rich_clipboard_platform_interface: dependency: transitive description: name: rich_clipboard_platform_interface - url: "https://pub.dartlang.org" + sha256: a1cbf255719cd4e340d33eca02b619d9ffb9cb571f1905e80b9345d4266e893d + url: "https://pub.dev" source: hosted version: "1.0.0" rich_clipboard_web: dependency: transitive description: name: rich_clipboard_web - url: "https://pub.dartlang.org" + sha256: c1dd2b75b8ce83fed0027828900bbfd5c33c0f8ff22efb266931db5aa7acffa0 + url: "https://pub.dev" source: hosted version: "1.0.2" rich_clipboard_windows: dependency: transitive description: name: rich_clipboard_windows - url: "https://pub.dartlang.org" + sha256: "03decfbd9bf6c50c663f8c4a0db14063e2a4d9ad5dd053fdb72875aa8bc4fd1b" + url: "https://pub.dev" source: hosted version: "1.0.2" screen_retriever: dependency: transitive description: name: screen_retriever - url: "https://pub.dartlang.org" + sha256: "4931f226ca158123ccd765325e9fbf360bfed0af9b460a10f960f9bb13d58323" + url: "https://pub.dev" source: hosted version: "0.1.6" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "5949029e70abe87f75cfe59d17bf5c397619c4b74a099b10116baeb34786fad9" + url: "https://pub.dev" source: hosted version: "2.0.20" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "955e9736a12ba776bdd261cf030232b30eadfcd9c79b32a3250dd4a494e8c8f7" + url: "https://pub.dev" source: hosted version: "2.0.17" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - url: "https://pub.dartlang.org" + sha256: "2b55c18636a4edc529fa5cd44c03d3f3100c00513f518c5127c951978efcccd0" + url: "https://pub.dev" source: hosted version: "2.1.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: f8ea038aa6da37090093974ebdcf4397010605fd2ff65c37a66f9d28394cb874 + url: "https://pub.dev" source: hosted version: "2.1.5" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: da9431745ede5ece47bc26d5d73a9d3c6936ef6945c101a5aca46f62e52c1cf3 + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" source: hosted version: "2.0.6" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "5eaf05ae77658d3521d0e993ede1af962d4b326cd2153d312df716dc250f00c9" + url: "https://pub.dev" source: hosted version: "2.1.5" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: c24a96135a2ccd62c64b69315a14adc5c3419df63b4d7c05832a346fdb73682c + url: "https://pub.dev" source: hosted version: "1.4.0" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler - url: "https://pub.dartlang.org" + sha256: aef74dc9195746a384843102142ab65b6a4735bb3beea791e63527b88cc83306 + url: "https://pub.dev" source: hosted version: "3.0.1" shelf_static: dependency: transitive description: name: shelf_static - url: "https://pub.dartlang.org" + sha256: e792b76b96a36d4a41b819da593aff4bdd413576b3ba6150df5d8d9996d2e74c + url: "https://pub.dev" source: hosted version: "1.1.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: a988c0e8d8ffbdb8a28aa7ec8e449c260f3deb808781fe1284d22c5bba7156e8 + url: "https://pub.dev" source: hosted version: "1.0.3" simple_gesture_detector: dependency: transitive description: name: simple_gesture_detector - url: "https://pub.dartlang.org" + sha256: "86d08f85f1f58583b7b4b941d989f48ea6ce08c1724a1d10954a277c2ec36592" + url: "https://pub.dev" source: hosted version: "0.2.0" sized_context: dependency: "direct main" description: name: sized_context - url: "https://pub.dartlang.org" + sha256: "4da0ecbb6a58afc3f51ba1984dc25eef6ee0e8176f8923b686c96ee1cfba23ac" + url: "https://pub.dev" source: hosted version: "1.0.0+4" sky_engine: @@ -1132,303 +1240,370 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d" + url: "https://pub.dev" source: hosted version: "1.2.6" source_helper: dependency: transitive description: name: source_helper - url: "https://pub.dartlang.org" + sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f" + url: "https://pub.dev" source: hosted version: "1.3.3" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace - url: "https://pub.dartlang.org" + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" + url: "https://pub.dev" source: hosted version: "2.1.1" source_maps: dependency: transitive description: name: source_maps - url: "https://pub.dartlang.org" + sha256: "490098075234dcedb83c5d949b4c93dad5e6b7702748de000be2b57b8e6b2427" + url: "https://pub.dev" source: hosted version: "0.10.12" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" styled_widget: dependency: "direct main" description: name: styled_widget - url: "https://pub.dartlang.org" + sha256: a22407bb8e7450ad62e24232d8e02a12c399644d3144b6df742dc641e3f955ef + url: "https://pub.dev" source: hosted version: "0.3.1+2" sync_http: dependency: transitive description: name: sync_http - url: "https://pub.dartlang.org" + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.dev" source: hosted version: "0.3.1" table_calendar: dependency: "direct main" description: name: table_calendar - url: "https://pub.dartlang.org" + sha256: "7f1270313c0cdb245b583ed8518982c01d4a7e95869b3c30abcbae3b642c45d0" + url: "https://pub.dev" source: hosted version: "3.0.8" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test: dependency: transitive description: name: test - url: "https://pub.dartlang.org" + sha256: a5fcd2d25eeadbb6589e80198a47d6a464ba3e2049da473943b8af9797900c2d + url: "https://pub.dev" source: hosted - version: "1.21.4" + version: "1.22.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" test_core: dependency: transitive description: name: test_core - url: "https://pub.dartlang.org" + sha256: "0ef9755ec6d746951ba0aabe62f874b707690b5ede0fecc818b138fcc9b14888" + url: "https://pub.dev" source: hosted - version: "0.4.16" + version: "0.4.20" textfield_tags: dependency: "direct main" description: name: textfield_tags - url: "https://pub.dartlang.org" + sha256: c1d215f481e7e8da5c79719825e595db4f829bf1ad3fce4c7ce43d340aa72683 + url: "https://pub.dev" source: hosted version: "2.0.2" textstyle_extensions: dependency: "direct main" description: name: textstyle_extensions - url: "https://pub.dartlang.org" + sha256: b0538352844fb4d1d0eea82f7bc6b96e4dae03a3a071247e4dcc85ec627b2c6c + url: "https://pub.dev" source: hosted version: "2.0.0-nullsafety" time: dependency: "direct main" description: name: time - url: "https://pub.dartlang.org" + sha256: "83427e11d9072e038364a5e4da559e85869b227cf699a541be0da74f14140124" + url: "https://pub.dev" source: hosted version: "2.1.3" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted version: "1.0.1" tuple: dependency: "direct main" description: name: tuple - url: "https://pub.dartlang.org" + sha256: "0ea99cd2f9352b2586583ab2ce6489d1f95a5f6de6fb9492faaf97ae2060f0aa" + url: "https://pub.dev" source: hosted version: "2.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" universal_platform: dependency: transitive description: name: universal_platform - url: "https://pub.dartlang.org" + sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc + url: "https://pub.dev" source: hosted version: "1.0.0+1" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: e8f2efc804810c0f2f5b485f49e7942179f56eabcfe81dce3387fec4bb55876b + url: "https://pub.dev" source: hosted version: "6.1.10" url_launcher_android: dependency: transitive description: name: url_launcher_android - url: "https://pub.dartlang.org" + sha256: "3e2f6dfd2c7d9cd123296cab8ef66cfc2c1a13f5845f42c7a0f365690a8a7dd1" + url: "https://pub.dev" source: hosted version: "6.0.26" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - url: "https://pub.dartlang.org" + sha256: "0a5af0aefdd8cf820dd739886efb1637f1f24489900204f50984634c07a54815" + url: "https://pub.dev" source: hosted version: "6.1.3" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: "318c42cba924e18180c029be69caf0a1a710191b9ec49bb42b5998fdcccee3cc" + url: "https://pub.dev" source: hosted version: "3.0.4" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: "41988b55570df53b3dd2a7fc90c76756a963de6a8c5f8e113330cb35992e2094" + url: "https://pub.dev" source: hosted version: "3.0.4" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "4eae912628763eb48fc214522e58e942fd16ce195407dbf45638239523c759a6" + url: "https://pub.dev" source: hosted version: "2.1.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "44d79408ce9f07052095ef1f9a693c258d6373dc3944249374e30eff7219ccb0" + url: "https://pub.dev" source: hosted version: "2.0.16" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: b6217370f8eb1fd85c8890c539f5a639a01ab209a36db82c921ebeacefc7a615 + url: "https://pub.dev" source: hosted version: "3.0.5" uuid: dependency: transitive description: name: uuid - url: "https://pub.dartlang.org" + sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + url: "https://pub.dev" source: hosted version: "3.0.7" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "4cf8e60dbe4d3a693d37dff11255a172594c0793da542183cbfe7fe978ae4aaa" + url: "https://pub.dev" + source: hosted + version: "1.1.4" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "278ad5f816f58b1967396d1f78ced470e3e58c9fe4b27010102c0a595c764468" + url: "https://pub.dev" + source: hosted + version: "1.1.4" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "0bf61ad56e6fd6688a2865d3ceaea396bc6a0a90ea0d7ad5049b1b76c09d6163" + url: "https://pub.dev" + source: hosted + version: "1.1.4" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" vm_service: dependency: transitive description: name: vm_service - url: "https://pub.dartlang.org" + sha256: e7fb6c2282f7631712b69c19d1bff82f3767eea33a2321c14fa59ad67ea391c7 + url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "9.4.0" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted version: "1.0.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + url: "https://pub.dev" source: hosted version: "2.3.0" webdriver: dependency: transitive description: name: webdriver - url: "https://pub.dartlang.org" + sha256: ef67178f0cc7e32c1494645b11639dd1335f1d18814aa8435113a92e9ef9d841 + url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol - url: "https://pub.dartlang.org" + sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d" + url: "https://pub.dev" source: hosted version: "1.2.0" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "6b75ac2ddd42f5c226fdaf4498a2b04071c06f1f2b8f7ab1c3f77cc7f2285ff1" + url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "2.7.0" window_manager: dependency: "direct main" description: name: window_manager - url: "https://pub.dartlang.org" + sha256: "5bdd29dc5f1f3185fc90696373a571d77968e03e5e820fb1ecdbdade3f5d8fff" + url: "https://pub.dev" source: hosted version: "0.3.1" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + url: "https://pub.dev" source: hosted version: "1.0.0" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: ac0e3f4bf00ba2708c33fbabbbe766300e509f8c82dbd4ab6525039813f7e2fb + url: "https://pub.dev" source: hosted version: "6.1.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted version: "3.1.1" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + dart: ">=2.19.0 <3.0.0" + flutter: ">=3.7.0" diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 05d84a4d4c..801a062534 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 0.1.2 environment: - sdk: ">=2.18.0 <3.0.0" + sdk: ">=2.19.0 <3.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -42,8 +42,7 @@ dependencies: git: url: https://github.com/AppFlowy-IO/appflowy-board.git ref: a183c57 - appflowy_editor: - path: packages/appflowy_editor + appflowy_editor: ^0.1.4 appflowy_popover: path: packages/appflowy_popover @@ -60,22 +59,22 @@ dependencies: sized_context: ^1.0.0+1 styled_widget: "^0.3.1" expandable: ^5.0.1 - flutter_colorpicker: ^0.6.0 + flutter_colorpicker: ^1.0.3 package_info_plus: ^1.3.0 url_launcher: ^6.0.2 # file_picker: ^4.2.1 clipboard: ^0.1.3 - connectivity_plus: ^2.3.6+1 + connectivity_plus: ^3.0.3 connectivity_plus_platform_interface: ^1.2.2 easy_localization: ^3.0.0 textfield_tags: ^2.0.2 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 - device_info_plus: ^3.2.1 + device_info_plus: ^4.0.0 fluttertoast: ^8.0.9 table_calendar: ^3.0.5 - reorderables: ^0.5.1 + reorderables: ^0.6.0 linked_scroll_controller: ^0.2.0 hotkey_manager: ^0.1.7 fixnum: ^1.0.1 @@ -86,7 +85,7 @@ dependencies: bloc: ^8.1.0 textstyle_extensions: "2.0.0-nullsafety" shared_preferences: ^2.0.15 - google_fonts: ^3.0.1 + google_fonts: ^4.0.3 file_picker: <=5.0.0 percent_indicator: ^4.0.1 appflowy_editor_plugins: diff --git a/frontend/scripts/install_dev_env/install_linux.sh b/frontend/scripts/install_dev_env/install_linux.sh index bb1b3fd775..513aa4a957 100755 --- a/frontend/scripts/install_dev_env/install_linux.sh +++ b/frontend/scripts/install_dev_env/install_linux.sh @@ -38,9 +38,9 @@ fi printMessage "Setting up Flutter" # Get the current Flutter version FLUTTER_VERSION=$(flutter --version | grep -oP 'Flutter \K\S+') -# Check if the current version is 3.3.10 -if [ "$FLUTTER_VERSION" = "3.3.10" ]; then - echo "Flutter version is already 3.3.10" +# Check if the current version is 3.7.5 +if [ "$FLUTTER_VERSION" = "3.7.5" ]; then + echo "Flutter version is already 3.7.5" else # Get the path to the Flutter SDK FLUTTER_PATH=$(which flutter) @@ -49,12 +49,12 @@ else current_dir=$(pwd) cd $FLUTTER_PATH - # Use git to checkout version 3.3.10 of Flutter - git checkout 3.3.10 + # Use git to checkout version 3.7.5 of Flutter + git checkout 3.7.5 # Get back to current working directory cd "$current_dir" - echo "Switched to Flutter version 3.3.10" + echo "Switched to Flutter version 3.7.5" fi # Enable linux desktop diff --git a/frontend/scripts/install_dev_env/install_macos.sh b/frontend/scripts/install_dev_env/install_macos.sh index 0efb416d6f..91e8e603e4 100755 --- a/frontend/scripts/install_dev_env/install_macos.sh +++ b/frontend/scripts/install_dev_env/install_macos.sh @@ -41,9 +41,9 @@ printMessage "Setting up Flutter" # Get the current Flutter version FLUTTER_VERSION=$(flutter --version | grep -oE 'Flutter [^ ]+' | grep -oE '[^ ]+$') -# Check if the current version is 3.3.10 -if [ "$FLUTTER_VERSION" = "3.3.10" ]; then - echo "Flutter version is already 3.3.10" +# Check if the current version is 3.7.5 +if [ "$FLUTTER_VERSION" = "3.7.5" ]; then + echo "Flutter version is already 3.7.5" else # Get the path to the Flutter SDK FLUTTER_PATH=$(which flutter) @@ -52,12 +52,12 @@ else current_dir=$(pwd) cd $FLUTTER_PATH - # Use git to checkout version 3.3.10 of Flutter - git checkout 3.3.10 + # Use git to checkout version 3.7.5 of Flutter + git checkout 3.7.5 # Get back to current working directory cd "$current_dir" - echo "Switched to Flutter version 3.3.10" + echo "Switched to Flutter version 3.7.5" fi # Enable linux desktop diff --git a/frontend/scripts/install_dev_env/install_windows.sh b/frontend/scripts/install_dev_env/install_windows.sh index e29f574350..ac413738cb 100644 --- a/frontend/scripts/install_dev_env/install_windows.sh +++ b/frontend/scripts/install_dev_env/install_windows.sh @@ -48,9 +48,9 @@ fi printMessage "Setting up Flutter" # Get the current Flutter version FLUTTER_VERSION=$(flutter --version | grep -oP 'Flutter \K\S+') -# Check if the current version is 3.3.10 -if [ "$FLUTTER_VERSION" = "3.3.10" ]; then - echo "Flutter version is already 3.3.10" +# Check if the current version is 3.7.5 +if [ "$FLUTTER_VERSION" = "3.7.5" ]; then + echo "Flutter version is already 3.7.5" else # Get the path to the Flutter SDK FLUTTER_PATH=$(which flutter) @@ -59,12 +59,12 @@ else current_dir=$(pwd) cd $FLUTTER_PATH - # Use git to checkout version 3.3.10 of Flutter - git checkout 3.3.10 + # Use git to checkout version 3.7.5 of Flutter + git checkout 3.7.5 # Get back to current working directory cd "$current_dir" - echo "Switched to Flutter version 3.3.10" + echo "Switched to Flutter version 3.7.5" fi # Add pub cache and cargo to PATH From e2009c063bf896ef63408ff9520aefe6ea1b3b08 Mon Sep 17 00:00:00 2001 From: Alex Wallen Date: Mon, 3 Apr 2023 18:50:22 -1000 Subject: [PATCH 4/7] feat: Create a "view" for all database references in a document (#2083) * feat: add archive for compression * feat: add service to manage zipped work spaces * feat: export service in barrel file * feat: ignore .ephemeral directory * feat: add first compressed workspace file * fix: directory path was wrong * feat: add a somewhat useful test * fix: move to same file (delete later) * fix: use script path vs. working directory for CI * fix: read from asset bundle instead of file system * fix: workaround to run integration in multiple files on desktop (flutter/flutter#101031 * feat: remove .ephemeral from .gitignore, no longer created * feat: document test changes * fix: lucas suggestion * feat: mark assets as excluded in pubspec.yaml * feat: add class for build utilities * feat: add script runner for release builds * feat: add build script as task in flowy project * fix: typo in pubspec.yaml * chore: use constants for exclude tag * feat: add appversion as argument to build tool * feat: use dart script in release.yml * chore: remove task * fix: careless error Co-authored-by: Mihir <84044317+squidrye@users.noreply.github.com> * feat: add translations for view of * fix: typo in getAllDatabase * feat: add view of database * fix: remove unused import * fix: use effective dart typing * fix: insertPage marked as async, should return future * fix: Remove multi-line string * fix: ref can be null * fix: unused imports caused analyzer to fail * feat: also fix. Add empty document as option and change name to _name * chore: move referenced database tests to empty document test file * feat: add test utilities * feat: add new integration test on an empty document * feat: register test in runner * fix: missing reference in insert_page_command * fix: analyzer errors --------- Co-authored-by: Mihir <84044317+squidrye@users.noreply.github.com> --- .github/workflows/integration_test.yml | 7 +- .github/workflows/release.yml | 30 +- frontend/.vscode/tasks.json | 446 +++++++++--------- frontend/appflowy_flutter/.gitignore | 4 +- .../assets/test/workspaces/board.zip | Bin 0 -> 9394 bytes .../assets/test/workspaces/empty_document.zip | Bin 0 -> 7906 bytes .../assets/translations/en.json | 6 +- .../integration_test/board_test.dart | 43 ++ .../integration_test/empty_document_test.dart | 120 +++++ .../integration_test/runner.dart | 19 + .../integration_test/switch_folder_test.dart | 135 ------ .../integration_test/util/data.dart | 66 +++ .../integration_test/util/keyboard.dart | 12 + .../integration_test/util/util.dart | 1 + .../application/database_service.dart | 2 +- .../plugins/base/insert_page_command.dart | 50 +- frontend/appflowy_flutter/pubspec.yaml | 31 +- .../flutter_release_build/build_flowy.dart | 28 ++ .../scripts/flutter_release_build/tool.dart | 115 +++++ 19 files changed, 714 insertions(+), 401 deletions(-) create mode 100644 frontend/appflowy_flutter/assets/test/workspaces/board.zip create mode 100644 frontend/appflowy_flutter/assets/test/workspaces/empty_document.zip create mode 100644 frontend/appflowy_flutter/integration_test/board_test.dart create mode 100644 frontend/appflowy_flutter/integration_test/empty_document_test.dart create mode 100644 frontend/appflowy_flutter/integration_test/runner.dart create mode 100644 frontend/appflowy_flutter/integration_test/util/data.dart create mode 100644 frontend/appflowy_flutter/integration_test/util/keyboard.dart create mode 100644 frontend/scripts/flutter_release_build/build_flowy.dart create mode 100644 frontend/scripts/flutter_release_build/tool.dart diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 084018f747..76aed8da9b 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -105,11 +105,11 @@ jobs: working-directory: frontend/appflowy_flutter run: | if [ "$RUNNER_OS" == "Linux" ]; then - flutter test integration_test -d Linux --coverage + flutter test integration_test/runner.dart -d Linux --coverage elif [ "$RUNNER_OS" == "macOS" ]; then - flutter test integration_test -d macOS --coverage + flutter test integration_test/runner.dart -d macOS --coverage elif [ "$RUNNER_OS" == "Windows" ]; then - flutter test integration_test -d Windows --coverage + flutter test integration_test/runner.dart -d Windows --coverage fi shell: bash @@ -120,4 +120,3 @@ jobs: # env_vars: ${{ matrix.os }} # fail_ci_if_error: true # verbose: true - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c971bb30ac..88e40585f4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: release on: push: tags: - - '*' + - "*" env: FLUTTER_VERSION: "3.7.5" @@ -136,7 +136,11 @@ jobs: fail-fast: false matrix: job: - - { target: x86_64-apple-darwin, os: macos-10.15, extra-build-args: "" } + - { + target: x86_64-apple-darwin, + os: macos-10.15, + extra-build-args: "", + } steps: - name: Checkout source code uses: actions/checkout@v3 @@ -172,7 +176,7 @@ jobs: working-directory: frontend run: | flutter config --enable-macos-desktop - cargo make --env APP_VERSION=${{ github.ref_name }} --profile production-mac-x86_64 appflowy + dart ./scripts/flutter_release_build/build_flowy.dart . ${{ github.ref_name }} - name: Create macOS dmg run: | @@ -225,9 +229,21 @@ jobs: fail-fast: false matrix: job: - - { arch: x86_64, target: x86_64-unknown-linux-gnu, os: ubuntu-20.04, extra-build-args: "", flutter_profile: production-linux-x86_64 } + - { + arch: x86_64, + target: x86_64-unknown-linux-gnu, + os: ubuntu-20.04, + extra-build-args: "", + flutter_profile: production-linux-x86_64, + } # - { arch: aarch64, target: aarch64-unknown-linux-gnu, os: ubuntu-20.04, extra-build-args: "", flutter_profile: production-linux-aarch64 } - - { arch: x86_64, target: x86_64-unknown-linux-gnu, os: ubuntu-18.04, extra-build-args: "", flutter_profile: production-linux-x86_64} + - { + arch: x86_64, + target: x86_64-unknown-linux-gnu, + os: ubuntu-18.04, + extra-build-args: "", + flutter_profile: production-linux-x86_64, + } steps: - name: Checkout source code uses: actions/checkout@v3 @@ -275,7 +291,7 @@ jobs: working-directory: frontend run: | flutter config --enable-linux-desktop - cargo make --env APP_VERSION=${{ github.ref_name }} --profile ${{ matrix.job.flutter_profile}} appflowy + dart ./scripts/flutter_release_build/build_flowy.dart . ${{ github.ref_name }} - name: Archive Assert working-directory: ${{ env.LINUX_APP_RELEASE_PATH }} @@ -361,4 +377,4 @@ jobs: - name: Notify Discord run: | curl -H "Content-Type: application/json" -d '{"username": "release@appflowy", "content": "🎉 AppFlowy ${{ github.ref_name }} is available. https://github.com/AppFlowy-IO/AppFlowy/releases/tag/'${{ github.ref_name }}'"}' "https://discord.com/api/webhooks/${{ secrets.DISCORD }}" - shell: bash \ No newline at end of file + shell: bash diff --git a/frontend/.vscode/tasks.json b/frontend/.vscode/tasks.json index 227a5cbfba..4f8a52c95c 100644 --- a/frontend/.vscode/tasks.json +++ b/frontend/.vscode/tasks.json @@ -1,223 +1,225 @@ { - "version": "2.0.0", - // https://code.visualstudio.com/docs/editor/tasks - // https://gist.github.com/deadalusai/9e13e36d61ec7fb72148 - // ${workspaceRoot}: the root folder of the team - // ${file}: the current opened file - // ${fileBasename}: the current opened file's basename - // ${fileDirname}: the current opened file's dirname - // ${fileExtname}: the current opened file's extension - // ${cwd}: the current working directory of the spawned process - "tasks": [ - { - "label": "AF: Clean + Rebuild All", - "type": "shell", - "dependsOrder": "sequence", - "dependsOn": [ - "AF: Dart Clean", - "AF: Flutter Clean", - "AF: Build Appflowy Core", - "AF: Flutter Pub Get", - "AF: Flutter Package Get", - "AF: Generate Language Files", - "AF: Generate Freezed Files" - ], - "presentation": { - "reveal": "always", - "panel": "new" - } - }, - { - "label": "AF: Clean + Rebuild All (Android)", - "type": "shell", - "dependsOrder": "sequence", - "dependsOn": [ - "AF: Dart Clean", - "AF: Flutter Clean", - "AF: Build Appflowy Core_for_android", - "AF: Flutter Pub Get", - "AF: Flutter Package Get", - "AF: Generate Language Files", - "AF: Generate Freezed Files" - ], - "presentation": { - "reveal": "always", - "panel": "new" - } - }, - { - "label": "AF: Build Appflowy Core_for_android", - "type": "shell", - "command": "cargo make --profile development-android appflowy-core-dev-android", - "group": "build", - "options": { - "cwd": "${workspaceFolder}" - } - }, - { - "label": "AF: Build Appflowy Core", - "type": "shell", - "windows": { - "command": "cargo make --profile development-windows-x86 appflowy-core-dev" - }, - "linux": { - "command": "cargo make --profile \"development-linux-$(uname -m)\" appflowy-core-dev" - }, - "osx": { - "command": "cargo make --profile \"development-mac-$(uname -m)\" appflowy-core-dev" - }, - "group": "build", - "options": { - "cwd": "${workspaceFolder}" - } - }, - { - "label": "AF: Code Gen", - "type": "shell", - "dependsOrder": "sequence", - "dependsOn": [ - "AF: Flutter Clean", - "AF: Flutter Pub Get", - "AF: Flutter Package Get", - "AF: Generate Language Files", - "AF: Generate Freezed Files" - ], - "group": { - "kind": "build", - "isDefault": true - }, - "presentation": { - "reveal": "always", - "panel": "new" - } - }, - { - "label": "AF: Flutter Clean", - "type": "shell", - "command": "flutter clean", - "options": { - "cwd": "${workspaceFolder}/appflowy_flutter" - } - }, - { - "label": "AF: Flutter Pub Get", - "type": "shell", - "command": "flutter pub get", - "options": { - "cwd": "${workspaceFolder}/appflowy_flutter" - } - }, - { - "label": "AF: Flutter Package Get", - "type": "shell", - "command": "flutter packages pub get", - "options": { - "cwd": "${workspaceFolder}/appflowy_flutter" - } - }, - { - "label": "AF: Generate Freezed Files", - "type": "shell", - "command": "flutter pub run build_runner build --delete-conflicting-outputs", - "options": { - "cwd": "${workspaceFolder}/appflowy_flutter" - } - }, - { - "label": "AF: Generate Language Files", - "type": "shell", - "command": "sh ./scripts/generate_language_files.sh", - "windows": { - "options": { - "shell": { - "executable": "cmd.exe", - "args": [ - "/d", - "/c", - ".\\scripts\\generate_language_files.cmd" - ] - } - } - }, - "group": "build", - "options": { - "cwd": "${workspaceFolder}" - } - }, - { - "label": "AF: Flutter Clean", - "type": "shell", - "command": "cargo make flutter_clean", - "group": "build", - "options": { - "cwd": "${workspaceFolder}" - } - }, - { - "label": "AF: flutter build aar", - "type": "flutter", - "command": "flutter", - "args": [ - "build", - "aar" - ], - "group": "build", - "problemMatcher": [], - "detail": "appflowy_flutter" - }, - { - "label": "AF: Tauri UI Dev", - "type": "shell", - "isBackground": true, - "command": "yarn", - "args": ["dev"], - "options": { - "cwd": "${workspaceFolder}/appflowy_tauri" - } - }, - { - "label": "AF: Tauri UI Build", - "type": "shell", - "command": "npm run build", - "options": { - "cwd": "${workspaceFolder}/appflowy_tauri" - } - }, - { - "label": "AF: Tauri Dev", - "type": "shell", - "command": "npm run tauri:dev", - "options": { - "cwd": "${workspaceFolder}/appflowy_tauri" - } - }, - { - "label": "AF: Tauri Clean", - "type": "shell", - "command": "cargo make tauri_clean", - "options": { - "cwd": "${workspaceFolder}" - } - }, - { - "label": "AF: Tauri Clean + Dev", - "type": "shell", - "dependsOrder": "sequence", - "dependsOn": [ - "AF: Tauri Clean", - "AF: Tauri UI Dev" - ], - "options": { - "cwd": "${workspaceFolder}" - } - }, - { - "label": "AF: Tauri ESLint", - "type": "shell", - "command": "npx eslint --fix src", - "options": { - "cwd": "${workspaceFolder}/appflowy_tauri" - } - }, - ] -} \ No newline at end of file + "version": "2.0.0", + // https://code.visualstudio.com/docs/editor/tasks + // https://gist.github.com/deadalusai/9e13e36d61ec7fb72148 + // ${workspaceRoot}: the root folder of the team + // ${file}: the current opened file + // ${fileBasename}: the current opened file's basename + // ${fileDirname}: the current opened file's dirname + // ${fileExtname}: the current opened file's extension + // ${cwd}: the current working directory of the spawned process + "tasks": [ + { + "label": "AF: Clean + Rebuild All", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "AF: Dart Clean", + "AF: Flutter Clean", + "AF: Build Appflowy Core", + "AF: Flutter Pub Get", + "AF: Flutter Package Get", + "AF: Generate Language Files", + "AF: Generate Freezed Files" + ], + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "AF: Clean + Rebuild All (Android)", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "AF: Dart Clean", + "AF: Flutter Clean", + "AF: Build Appflowy Core_for_android", + "AF: Flutter Pub Get", + "AF: Flutter Package Get", + "AF: Generate Language Files", + "AF: Generate Freezed Files" + ], + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "AF: Build Appflowy Core_for_android", + "type": "shell", + "command": "cargo make --profile development-android appflowy-core-dev-android", + "group": "build", + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + "label": "AF: Build Appflowy Core", + "type": "shell", + "windows": { + "command": "cargo make --profile development-windows-x86 appflowy-core-dev" + }, + "linux": { + "command": "cargo make --profile \"development-linux-$(uname -m)\" appflowy-core-dev" + }, + "osx": { + "command": "cargo make --profile \"development-mac-$(uname -m)\" appflowy-core-dev" + }, + "group": "build", + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + "label": "AF: Code Gen", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "AF: Flutter Clean", + "AF: Flutter Pub Get", + "AF: Flutter Package Get", + "AF: Generate Language Files", + "AF: Generate Freezed Files" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "new" + } + }, + { + "label": "AF: Flutter Clean", + "type": "shell", + "command": "flutter clean", + "options": { + "cwd": "${workspaceFolder}/appflowy_flutter" + } + }, + { + "label": "AF: Flutter Pub Get", + "type": "shell", + "command": "flutter pub get", + "options": { + "cwd": "${workspaceFolder}/appflowy_flutter" + } + }, + { + "label": "AF: Flutter Package Get", + "type": "shell", + "command": "flutter packages pub get", + "options": { + "cwd": "${workspaceFolder}/appflowy_flutter" + } + }, + { + "label": "AF: Generate Freezed Files", + "type": "shell", + "command": "flutter pub run build_runner build --delete-conflicting-outputs", + "options": { + "cwd": "${workspaceFolder}/appflowy_flutter" + } + }, + { + "label": "AF: Generate Language Files", + "type": "shell", + "command": "sh ./scripts/generate_language_files.sh", + "windows": { + "options": { + "shell": { + "executable": "cmd.exe", + "args": [ + "/d", + "/c", + ".\\scripts\\generate_language_files.cmd" + ] + } + } + }, + "group": "build", + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + "label": "AF: Flutter Clean", + "type": "shell", + "command": "cargo make flutter_clean", + "group": "build", + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + "label": "AF: flutter build aar", + "type": "flutter", + "command": "flutter", + "args": [ + "build", + "aar" + ], + "group": "build", + "problemMatcher": [], + "detail": "appflowy_flutter" + }, + { + "label": "AF: Tauri UI Dev", + "type": "shell", + "isBackground": true, + "command": "yarn", + "args": [ + "dev" + ], + "options": { + "cwd": "${workspaceFolder}/appflowy_tauri" + } + }, + { + "label": "AF: Tauri UI Build", + "type": "shell", + "command": "npm run build", + "options": { + "cwd": "${workspaceFolder}/appflowy_tauri" + } + }, + { + "label": "AF: Tauri Dev", + "type": "shell", + "command": "npm run tauri:dev", + "options": { + "cwd": "${workspaceFolder}/appflowy_tauri" + } + }, + { + "label": "AF: Tauri Clean", + "type": "shell", + "command": "cargo make tauri_clean", + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + "label": "AF: Tauri Clean + Dev", + "type": "shell", + "dependsOrder": "sequence", + "dependsOn": [ + "AF: Tauri Clean", + "AF: Tauri UI Dev" + ], + "options": { + "cwd": "${workspaceFolder}" + } + }, + { + "label": "AF: Tauri ESLint", + "type": "shell", + "command": "npx eslint --fix src", + "options": { + "cwd": "${workspaceFolder}/appflowy_tauri" + } + }, + ] +} diff --git a/frontend/appflowy_flutter/.gitignore b/frontend/appflowy_flutter/.gitignore index e77b1c9f0f..82c35e91cd 100644 --- a/frontend/appflowy_flutter/.gitignore +++ b/frontend/appflowy_flutter/.gitignore @@ -40,7 +40,7 @@ lib/generated_plugin_registrant.dart lib/generated/ # Freezed generated files -*.g.dart +*.g.dart *.freezed.dart # Symbolication related @@ -67,4 +67,4 @@ windows/flutter/dart_ffi/ **/**/*.so **/**/Brewfile.lock.json **/.sandbox -**/.vscode/ \ No newline at end of file +**/.vscode/ diff --git a/frontend/appflowy_flutter/assets/test/workspaces/board.zip b/frontend/appflowy_flutter/assets/test/workspaces/board.zip new file mode 100644 index 0000000000000000000000000000000000000000..1a8f6b0dd4c00ccad1154addbfc8829cae953731 GIT binary patch literal 9394 zcmb_?WmFtnw=Eb0t+ET#2mqs~Qv+z96$)&)ibO2-@T5`DX&EE!{E zn_JJ;<73apeKO7WFmu{$`k8hN!#LhQFk{>wpikQ3LLth)P30?5GNm>tQW+$HaY_ut%&OCkP z{v?lLNYh*{AIcQ?h6()+_2gAbUG6clk^yy!&xd};mXAyqAVNR5Sv2O~W0ATg$qK>` z;fSBz;bLwGzIVOg(jirAi0uF-UDffvTs<5%C6LKF z-NBmbntqL6=E8xWeUEj~+>07(nZ-Y#N!=@ORL9gRF1Qxl_mK zW%7kt?`!M^kj98_IJF3f<8Ai1=4JP(f-GYn%cMEjwT5t8@C#paR$rO75x9;}IbXw$ zs6$$#$(s)}wURv&HCLhf&Yh}}=_`ES>wZ}#qhO9;Qk4TU#!=0Z6Umg`tvn!W^t8nU zB<8IN(oGmrb=1ugYf_k#8T2?!PJ_r$d0reFjFZe5Dxosc|GP4w^bOCud1L{DIFGbS zRjTaF_ldzu2Jr>Iykbz#ljYSXv#^9hmnJ7rvYT^Qir=ROA@VG^$+3Pfr+tI~-Hqmo z!s}G;Sq|vVP}!7CO}#xeRzg_2ic+~uTME#d6Pc1voAcP;uuEDHZ=h;PkXy`~vjrd8 zcJ#?bW+~niC0AhlPR9v5AF%uUVNxDog+)yry#el36r%ZDq~=v*duo~CAgU)blos!y zkLWr3iqg5e2cX5Z6g&^DY4a(Movi0j@p=u_v0BP>YuT{IFb4@P*Z36=tNJSTVf9yvb<#!QjN&VSKh=Fnh`9{3 z{fO;Id=C3yyY$Cvu68C11Idtp|Cefj`YizR$>sob-Xf|a*el&}0`9bTi28 zi`0(sc2j|&z59uXpwaF|c!JvPSC|%5H5toxgK!4zg;8!qyt+3q>j5@RH|HT>FApY7;bmMpy^^FyH&kJ^ zQ`Z1x!g4`!3 zW;kWDF61^zp*1v{&RlJ7*aOSFv}mA!9Bp4!!nV4Hpjor{t5F8)lmDt|E-Qm-8Cd`L zRi|d&a&!AFV8bF67bYHV)S4`E3W1mZvm(I3x$C&7J{N(%8{zZWzbb--s4kPShJul! zy``wBiKc_1sf;q?Uxsh~)3ENf^Wb~@XA8j>aPg)L9#V? zeap2C*c)eRgbZO8AU%Q7rsn={!ni*`dsp{0KXDyr+lAb9>Se?|&GB^;$<@%sLsRa= zdGLK}o^?YDkfDJ;4{v1}cF=MW8X-xZx9Htv0#ugw<&DSLTzE|-;d&8hLFVDaoh)Un z2&Uv>Pt{L$oLLnVD9r59N{TdL&F5r2ShIX++a+`ayD;*Db?ugOOjD|`WX)xQm>gusU2-vd zRC2eBZGnS*=}@b9b61`9+5Fpir9s-?5&r&S=H>-m>o!(<2^s`WV@ref{Kkg9+&_y6 zN39fD9b0ChUnRyP8B;G=#^W`C_gy&{%Ux6TAkISr04T%hIHu|oC;#wVQS<26ZPcp8 z)1HNmPGs|Gu7y1wADyi`M{_@H9gFHcx+QPBM?rReka2CuUu%9R&9w;yvqf)|e*cr-rG9UB>! zR#lwjc-6dpIbAz^uzY;ZtX3i~S0mYwqO`nMt5FLO@U^X!h|PYH+Y1uCL$VPqSL~B& z`sidXJgGXr2|!Dg$;$JlcP!G9FYHFi|BV7YOasj#_Zk`2s z61$|{JPk?$me*B0mNCKRE&0~hNBkF&<5y3p(IwjxwQk^{y#9z;bZFD}ELo|%i6b!n z4oNYhv~+P4MQuC{xfXu#`q>M`sGj_K(vomGBm}?dvQrhn0{3twkM!+N!|1t2b#}Xb zMa```OMk24ZZyJG8^(kbPqGB!a6d6{e1KS~_>bTYz2<=hVRM=o?YePr#O|g8fv$+1 zC<1y>f<630JlaEb$P@o#_l5N+&@I?g?*z{WB5-r~%jZ`qS{LFl;?oC{mw#iH90KE5 zN|Y%%c91`5)XyhEnVo#X^qsJt_k>7t;eM0`QFw?l#WrlAlNngDn(!iYL{pcP?ctg) zb5u=vvBNqH!r4>u&4KMv@0a65z#fceWWGuqE-qrgj9BbR#CNe00lI*U2&BRMpRn%GcdmDx z&AzvY%Z-1!!(0@&S^oS7EdSY3+=jl1QQvR80pa1Ze)7rbNxFJ70qi2`7L+ke82M}v zJTM#LDWaTOuu~Wk>Wb7#!$S4R9aq7!>z76Fz^TD)m|^Cu z3oo=eD$qBBvr9ich>({=ZlMQ=d8$pC^7H5Wh}NO_{{4)m>PHHpsbiSZMQg(e`adS1 zBI?50w} K#xioM!&0B!4z9tT0a)N!LH3v1#~z|Igvw|Ht9zG3@#RR!sL1)!ktW ze(A3mV%h+U^V`szyv5SHM?zL@Q;$tRL0)!({wf0lNW14tNxwcZjn%MEw-AC^(?}ytuN$&>o2+^$c6+>;g_j6dbiD#l6IRxbeVj`=_)y?yKbwH1a zU(<87J!5I6yvBtF7pLa(J*BUy)O-?Sl!)+_qn9wTq9#{%%$Y(&HE3<11Cwkw?)qC! zG%57-k?ui^pGbA%*o3eYQY6kL1~JUoJ1ux~E#nwq5a7m>lXu{XcSvcaYaL?5wfm_VL(b zFg2Badz0pfxVCBO29EEx&;BsMu8_c0>KjN_8^=YueNx0E$ASUAyhS~w2#+XZShSQ$t z#SAw_v2%Nmdhy)1A64T!6WVK|-cMWwuusM8b}TGBWQiJF8nHO6$Fe}05K)!m+UAb( zg)xS0OcO&P+A8YPns#YFT#6QaNj|VjhOZ`eowumM5-CDS)In3)o^H$bo_R-GIC1gT z&RP-mHboWJ4O|6Eh9Et1flsHi(zz+|t+j**G?P@js zo9>e8*2}^%m;M*}Q9VO*F@}~WtxM{@jwj2WX}$rXs0OgvFz3F}y$Qj4kiCnt$y?h& zy{q*(LC|uh>x>oQs;1a{p`oCde*ijtCHf&s;?@sdLMs*RKj9p7UXb>Q z3qYrENK<{A8cL$mWu=?I47fD~O@Xb?L*VXI4P}Y5J znXnEO*eLU~-lSf@%f})#4aQHy#){U)GoAA{&aR#*%`quj5;C~oy>vT}<;(>Z6zyW=$7s@>gR+u89^ZsLH>)oi(#TR?XA+nf> z?fy0{YyPbATzMhbj?4a=6-Inbq~^c`H^5|Bj4KT5$|~iYnT%}W7q}V!N-QD&eDIKK zDu>O@g3^(-o;Ou5z~4MrLkE~8Rm9EC8A4~SiZ4DTLTCvr zg@590E~T<%HRz~aE>S`OL1Rz-IYIvbGbgDyV2AV|)bLZ1AdEVM*o+7%N41z}mXLql zphPDd?fsg(BGYso*H`;iiuHF-0`UBYHc6uQ%>xHNRACi+hzNKk)~QGj6OKXxbtzyi zwEVxAb)Y##{*E4kWPKO8C98+XR+-g=LJ~m`s!KwBVey>t>3h5y@)zHb(77(qbtra& zgRx8W3cIJg8XkUvN_z<<_Og7X4#Pk5t<)MCi7=ekb6l1S%f{6Ok8O<@ZL+i@a@KyY z(IVl}YmJu#SsB?qv)i{;R#%71mr)RXIpXN51U;)8%Px-2fU;^cui+Cm>8Y(XWlO@^ zs&fcKlv?%PsD9N6D{oiCBN5Np|3qxu9;K84{C9g!iAOrlj_`=Geb- zcF6UdJ2G>gD@h%xv+>Y^AU;^!1=+&76l6pHT#KmGmzyb@f|KVR$N9I$D9o?qB?woj6mkI=KjH)>LFv}cnba_mk>%p3H`&auknd&VP@>n7pOg;t&$ z`y`F-29I`0?JE`(k>VF3tt~}i-=}QpXQF@cJt2^=G7Eh;>3DPzRiXJLNw!X*ves{| zFh%4SZz=1n%)GWNQJWlT%J1yJ2RO1Dar$YS=84vkS*uu|X`Gw>k>6??;F?e!6nA9H z^1&%46L=jbuwD5jtLT~9q)rvlqGd>PsBuwG5IM35IPT{h(L>%)IUZ&Lv}5m@;x&S5 z?4o>n>&kpiP`*8!^KWg&=lkqkW^#!eQnMlPAM@r;xV-u>$r)fHH%-i)6oa;&d!+rN zX~!r|*NTVP%vm{R$M3uJB+_y-u&dkmch^ShVWh>UTkZYvluO7HhH>RU1$V>VyRBo{ z!kEcI&1B=s3(2<4ZTGPACPQ+)xo#nc^4s@ibnekK?Ipiq@5Bzr3P8|m!p0;1rWJz{ zQ07%BhL5_>Y{R4WIJU)j&;~Wf!BXI&W=^J=O{z8DzESw$>yBI-i|z6H!-`t>mfbgQ z+()qv4o^xRuj;jrj@vy_445{0iMUB%zDMIWtro`vc=7Dy;fSNl{wy z_(31G!r;^W?GW<6j)zy%XhO`i5;G2E;v!|(=W-VI_KrcEZVJYQrArpg-J&igmavAz zCd*aHg(JTCLX5SV=wiB20hf0ls+)#BHee@fCDb%6mELxGUE*w9BE?Sb6~d5%wP`q; z2!8Dvc^l^j{w!i)Bn{ZS?8UsP;VWdkv}nb1{hn%Bx)*XkcMQ}Sn=Xs@O>!EW?j7!p z_V3|2H7`8G^W$BU&o8o!!MO}mJ3lPa^X7nwIZrw1=C}CjTTgBk`^U>qh#h316%v?X zB`{cAx=B@{^hZ;glJ;SlS(bdAbVthUvF^udM%P=DR}ewAU4jn&aFhChQw(LAh8^FF zOs~v-hqV7$LfgiF#k?UNmASuPy3c_8_f<;o-gN;n;wDRhhqZF6O}C``twtl-2h=#% z;=s=I>d`dvZ3Puz>p`~^HKS>T_m2uYPoB?`{!|2VC78}r7Zy6(8Dbw$#z)8o)2Z(% z%5Qtg|g2?IxeXp zce%f^MXTj1Y(=wg3G)$i`3lv^;|mji)O)#5KmEIqHhNuk>j4(xqJn8KKZYvak51&0 z0WccA@GPN2)}C|tf=vaLYsoL7$sOj#no7JW#IdIqpG40>wFX|PBoQ8}^_Cj$FDGa- zz7k`W=_bZD=1A!0_L?%0!2ODh<@dEc5`nvf)xox(&h8q5*%s^S1ZkFOv9{0lUDBMv zn|hwG#XXxVMzsk2N|6)|F`xR3k6Sq8TuFQ`GD^N+;JEbf<^n^DS)lvRofv`4E!;T2 z)4Ha`+bsbB_hXSOeoT8iq;lv0W&dX4^UBb}?^XW}RRPaf`VnWOw>mM*9GC@>0runv z6tb&{)`t~6P=D53PKu??m}yxuQ|PfQYpQBiA!mp@JDA5&DNGqx*XDR?wZobE2LtyS zk9c|#c>j+pZM$O6oILq9{BKU)2CH%AXtX30B8p#23j|1_TwquI5)M>&6-Ci`EBGq} z`pO3M(NdHAC|yu5a!pYmXlrJN--+OMTzou&x0{VV`t8`me<(UmCOE4uTIIJBOkf;N zAg+?N|8ebIZuK9E>E{>5GjmjPhA{RZTo4NsT71VOzQ^z<-gj?@Ip;KEwy`?KdBP z?10mUfPjT~Nn8vpG(u$E0<1VH{}{IWbV=yURVSNw?RLc^MvC~4U&d3X8Sg?Wwt#+g zz#toi_A+&$3g^^D8%$;b3@O)Y;tK1VP!EgnycvhE%vXvkj0yhgNZinZfKmdM5bZ=Q z<2*Mcw>@PK_h^#Hhmd@@Yz}iRvA&l0puGuH+H8%r6{C{WpV0C{>Kyl`_0X`ahMI(G z+{qB?km&vp5RLhf1#8lb{?@)JB(9o7j)C~d#VSiNTil#xtukppb;c7KYe~AjxT%pZ zv(UO;Gn$z; z#idUE1p&c;z1v*Ays@j3BoCi%Dc3XVx)C(>hOKIn@zP-1nKgKhVX|4}aju7$C#R<{im@YeGxZDSQSc>T^5$?kSf-k}S;5oO8-&XmEtkyTB3bBj{U^(Yo{n zzEnP~G*2g~OA>uXhXp4csjghJH|HGNYBj<>2wo^BCpOkqJznoU+Keg8_E-VGKW@kF^d)l?HDG%Q2#qz~JsQS!t zX>fV@zUdA!6)yD5P8;-S+#?0Cf1nKv>m}P;$}hz!D7>W!H@y3XzbAu4{JnwG&gB({ zHr5J;`namgtE$k-6$~%&v=d{52*GC0lQ;CVFC)CdG2%;Gy~G7`z0|1XU0$tVjGVr4 zD2PKmhy}d+jJ;bZQ_tpt$I;XJe=018JWe7%|JYk#f`dbO?*5c!oSp@g!=H;*>!R4* zhd*WJOg~ii12L%E)f;hs%&pCws+DlayeyD_E^_=Zr7#TZUhn8A_Yu%6hzvR6e_`Fm zbMkhvW9vg?9*rv4d(vB{blfT>?wX$w+gVd3 z?o=e+J=Gm=1iB=qK`^*|MXTIc7cAbv?pp9K7P46|3?fv-HgG4eaqhFQMjcZprEusv_z&L_iK@4JSZwr>dA=rh(QK zAT^2}p9CFIZFjb8-r7ZBCEA4+I8^&8w?=L~e(B@DajXtVgxRF=I)ZIh`Nj`8kH6La3lsD z>kOBwo3xe?Isa3QDUzFQ=Li&veOJdQ-m0I?_1XC`!J8Q}VM$|D+94hy_Bo%I4MljimPD)~JgV`OZX?HM90&1^$cFT% zowbl}i;L=`Tc5R6_!ro4|M&lG{zwscxQ~Bk%KyvXH~;qdKkK#sa`o=H!+iZWMEuX{ z?Y~3&L-_r#`t2W%{uP?^|L*9&sk#3S@n6dDf5okTdoF$^?*BkBd1-{_so>yVJs*JQ KT(lzlWAq<&!L$JY literal 0 HcmV?d00001 diff --git a/frontend/appflowy_flutter/assets/test/workspaces/empty_document.zip b/frontend/appflowy_flutter/assets/test/workspaces/empty_document.zip new file mode 100644 index 0000000000000000000000000000000000000000..1399d640ad8685e174663104cdf739243dff09e8 GIT binary patch literal 7906 zcma)>1z1~4xA%cUfnvoe+EOU)?u7!yLUDI1!QG{W;_eMv+#QM&C?!xFQY5$*O_AVw zIns09d){-u=Sz0>&OCeOKYRAGX3cNbQc-+>N`&;=rym%o_4}VcPjvTJOM53bZ(|Eb zb9Z}72R9CG3lBSKO%*{|pqh$+6|a`Mjh8Kl%AX1tzbm|Sf?Okr@0-3vLE`)WRIsvh z^z>%4Fm*FEGj+9Ow=mnwGPI+Bx%UYrORLo}&MwA92<&<(?aQjM&Rr)mmcrbaKoiWV z7N8e!KCJQ&%5a3}vUYtjkrP%}GwtNKdPy zg{{oV8E3}GJU?V4jT>T>ZTTTQAMX2(M~j6=6j zsuS5dQ?^1NhkC>V!G#^hI%`T0ZLev=VeX<7pNYYDo4~azeIvary+=|}!-m;rb%JRnnsSQ>HNm=6S@?-e@)SMoQL8k?9#L?z zLWyS^6u!Q){4O{PJTuUvPXJ>VY4-8k8D9us@I9nOG@GQB^G)U>M|qYXy%H3Vx1ew9 z-c=w4-D0Df@#M%`p~?UJ9+Fr6sD-^~lth(J{+mYw8?d+K%P?c4(g(ZzAFWSqKNJNo zZJ6Yf>J&wQZi0>y`zlT^R-UZ!M>iOlD_YLsl`5r zA%$CTFAHGdI8A+oPIN%%I)K>6bU51?nnQi|#x6U@_jUjgmJJw<-ki+6dve*93nmjL zyM&CbkLjKTj@kU_z>wacReSr$1|u6k-NHhJ#ArJWFd81BRioY*JQakWy}9zM#?frJ zmXy%M3e5nv4C)1db4gDHCdn(TFJAa{cddJ=M-@lvAqRE|$j@P+y~qIKBsXpil44&z zcyFb5L(jHUkP|yDK>dgh>Y~|DlD#A_*={^iH}xTR4S|+!BUGj*9@zgnYh0ufwwPX(O3+;iUTaJpa7(l`-j>Qt+N-B`2KNU8@8L{uoI@wIV%6O757) z_p-i^=a?m9lW>$nG;sGKVe^gXzV9MJE?Xp9H*VB*k%#jb+(7fNt zKa*ZE=M5N1Io?-x9#hBH^uXME>mz$rsgDA=34|aXP~4#Z>gwI-d%87p37%}{wgqHo z#m;OUP-c=D%gV`E*4&xrgkk}R7eoZ<`DSu7VBxh8NKf>Lp<3x;s;@def{E*iT6OKs@9=&#%Jg%(`>SKY3$nAjtQ(1% zmik~CoJ9&Z+-vJ)N;Z_=D&LPetSVrRwPz2|Z169GhVDkP5;Tq;j=ZW?aFZPHDZY6h zu}~Xk#8i&2d8X`}56U!Ju3{D>7Ig4js({ANSi3Hiaq5ih(6I{UO zlj4qINRDIfOnO1W0m!wLFLcpJP420Ecbj3aUkP-Z zml)^X8JF5>jW=T58`94we;(BTq_47v;NwB#BgI+;4l;uB{8IH!crC>PC;#G({H5Ac zuRr`EK97FcE4hPl1J>38B9tlQdA41FZ;H>-%54kTTUa3HxLN@h<7WXkhgb8WGG znMGJ-i*C$1NgV*x)@;v4d>b*i-|HL?sx{vNVAIrC?sL$Rm`mRJD>c08gsMmx4!@~bj*!({&yvg>92SnTfp@e-CwY$GSgSYs^0^JH-`Rq0+ z%K3WeL~>NXP#{z*jD4;Tv_BWn&pIbwl5KkpkevG)NiNP%1vKQ>lj;%`5NcXjXN)M z!f~vawMOP-bVXlq4Q1TOYjZ%@fDFN52G(FhW8s!dJFgSHcTRzu(QJ;$n#Jqapx_G| zfr_lMAwzG{a>p62}qV zvgkc*ytvfwyoO`)Yri3jA1rVVZoy$-g4<~+T(Aln=#KC8?^_j8l^26Lu#|3xoL2cC zJAjiqyb>-tmiWXz({)r5HcBlmyUxt2@6g=nAV`Ay&Zk2Br=rr2bb)yl?yX@1)iKIUrE?= zJW1Mh&b3mg#1@(vOau8Am3&W>rCyik*EBxXF)-E^G81%%&G>G7u+p+?x0TrmR2*b$~p<1Xq>-*%%6DXVwam6E_ex z8Kr|vLQ)I@IWIz{c>4BTYR0iD4cOOREW@;MuV@xr(jCp>Xg+Qz$ZT|3I(x|YVHj&u z9-yYdl4)6(tGCf+p(Fcxb)U9-VQN2D2s79EIw7&0D^4{{>`e;6Hi8P@R2ZCoBK(!j z*#!GDHd=RD^Li4g-BZHk64xGGza?dG&DzfFrs@H*&UL_3;X6T)tMWeoW3?Sy$d~i2 z0aX%+Z86o}-i6i+sJ>iFTUN=u&L&DJPCZTjy})64Y-)No(^H`Ih(AC3JJYM6e58Y9dD;uO`U zHI~oM=I&q*Z>^RmZ*y7$R{Yj6j>UJbw6Cgtzyr~9ch*}14Rs3eL!OcEXy|Rc^UPe) zqiKbhRRq|G_V z@m5h88k2f@k9&OFeQAzUpzR1Ucs;C~7UZ_bp6OX*yOO#B{2@$UR7Ab-rhT;nCa0@y zk-%=-$PAF)WXrY5Q+f1#eD%Bi$5zDkv!L(p(XAM&$5FVaMm3t@>CMq+0{8(y&YpXk8a!Xq zJ6jV^*&DVXQma4e=7vLsh#{rgt6g|^j_m;V<8LxNC45U^H3oGqE-*jH*?D4754%G? z^N#IK82wR*ICR_+$2n^|edGV_8!jGC9Dx-yl|@8xCGSLC(LM!6(W@2UK_tG#u9|YYw!uiv*Wrq7n;2BHRyJmXhHx)`F^0g@kK3gO3E0OK( zRqYS4JskjlL67D=2mIKu4McGVo_0sdKC5lH>_V9~!FG3ZEVq6(K!cxcBg_Y)m*niG;>1 zPuM-QsVF~W%>7x1&J3tpl~o-6y~36l%0(M)Py{=Oo>Tjg^h#qre`6v|UyUOdSy+ZgBpXsRlYsGFz!+^gbq+mid?88`2YP(rX= z{y6vSXe;yv(`@BNsYsZ!&rg=jv}L{+-5!89X)nRcl!HfS&-db%%!fSNz(!(`qqr@U zP5$UaZiXp|-V4?-vCKKFnvN5VAytnx^8KVO1NI%}WG=zt*FVGN4QY#$u~*zeqSjqp z>*@@ftw(BV-&l%_b)V`>(`UXkzI?&eSwvgd(4z~mPt*`D-TRnBrVs{&wX-%giLfY^ z@-kRp&1G2O)zNxNRB!hRpu~O#NIW+B^1t{3{5K6}`rY&Q>3hk!w~P?c@O77@wx=Ec4t>oHBx5B@ zG<5xPPu=iraD(@4!tF02Lh6Ec$-N2MZU^#F)#07dUAC!U-&X_WLisO$!F!kM*PK|+ zs`2S3MQ04bjRLvF4^oXqfPPG?#MjDQZ?8R3CY-=l^LKAWb7n-(EC1doV6G^QT7%v7 z(ZT=8{>x{7Zx}|=)jZaA2)!?t*?{KiMb(g^Bq`>OT;_`k!Sen{1$TcDLh&3&E02*) zJ`pY8S1+IUJeLBpankJ7#58%F)J$9faLZ5&1O!THG$@~L6fYmFDNky_w2?J6DO$>7 zCf4z3eG($hQa97vGFJwx4TWy&L@+DrPRLMX4DiEfV+`e(%n(pu*lv1!A#ckpnVOy) zp?^|qfO-A=1Y!S&a0oCmaRYUDuWVe$FtFNPLMNB(*j_%hB{OmDsHJ?~o;E3YBx2%H zSXEw20AQV2H&U2f;ee5N&vm53#i+A{s(#!_Pj5>htyTTpfQJc+Bs&!HYS4n(9<~g% z@0TQMF_>z;r^OzzFeTDa2HiGykp7Fg`N$f{g(>)QNsvQ9nvq|ZLT+I+zMna*>)p~~ zBQFESgB9=>FIo6iS8sMjR_$7DhllVdNhou-sLh=55`dQZ(F;bnp#3rm-CjVO1q}>@ z8v2^?QRy+k!KCRq-Af6yOE3@8Bg=+V?5+SOG^+VesPNK-e6dVMRRN0(tYw~?`FQ+K z`cc5-ex*F?7=vuPLOxf#XZ{okGG@U6!@~IW7~?;PcwmZ4d_f4DkslmWP{R&kLF2u* z^udwZa$ZypeqLO-y~&=KSs^w}o3E4_$d)z&{Ddu5IW&T}Y1HDvTsJn!S;eQ`Ng1Gd z`NNh_Bq7_g9LV)KS#{90cB|0kADpOhEo2VFE69&!M88JVp+=DoNo8h(w?g(YD3=VL zzL;k8w0qb?{>9*NEH-7NsCVCD(q=wkN(9$e&mF)RuVxDyAy9#l<8b^y$gfkDM@S_r%rOm-;3h)vKnrE zD_1H0jv}w$$DwU^KhvMwZ@QN$kdWB!9l}52(2`D0vcJcSU)cfg6FC05xynxYKh zn5VM7L1JI*Oe)?NIll^3!ID#56%^m}6TjWtr^ba5Yb@{Y8wVosVaK5ew@g}p;1k|S zU~$6JQF?y%NF5X3!g@)iSI$vkrhdEU-`l8HRqc8RmJRy^ znSJZ=i9exz0CT>LaZTRskHMsJu8EheMIld7C`7$X?nSB5E2q&q2Qx!<`kc2otK-6S z+6m+GyuVQMDu2Z3Za}?t(V-O}#Zk1+L|*H9w58Qeq_lFp9DtAKFKxE^a2+?88pn?k zd5@4f0^Lyj=JJ$~OwL|7jTBM})8exT;^t(VtP$@a!0yL*Rj7BR6C_4(pg%*{%{JOs zZ%^WV{iWxn=+G;n-0^oIRbloSh?wW(sDi@LWHj69XD;ERuS+i0KEZ$jvEk!YXN&H` z90Cs(O)uc>Y4Ty`F*qW)k8s?S9c}sjG60l~=^}D%sLsow*jFR*sK}-t^UtxFQ;5a- z`dz+zP?UzwPQ;tj4o>Lz?II3WZX(&cU2@CzW3Nqq>^?c^&42tHD>d9yoKd%X7IQ*5 zD>edqQ`(+yH2yIBV#k}TABlcA5$grO`h=_4hH5QGABr}u4YFt>iSw5AlDZ8DaeOJ# zJ8*GQaPjn6B?f6fdyhr3j20&puB$(cArvl#C4rwxJ7(FF*W|{+BBY71z`@Kc7neLH$7=J8x%~i+@IWUa)n#ePYfD3< zpr;sr9@o1DXBe-{;K?Dp1J+45cmQbtQRtWVPT&Urt9+@)sFJ@Q7c{lLO=Ir|iyT$dwIj@@Qd)~Ll2xFS?ts!V zt41r($WMsW>xlBn%GOOUYSo=o?Q*pwW|C6df-0ZvI(>t!9d|&m9lNt_k!gDBPn~7@ zSlbKg@#~#WDuN&1sho`TFa(<;fMX*3emA>G(~hAyIU&?BZ@FEK)CC$Jym9Dn!q}*z zoRD)U`QdjqV&>f&(nvYU!#iDFS|+QZ?a3zN%4=rbx+ZUCy8jI0RpJCH?kD7qca|d* zKRo?|#azR(27>)^PlXugxV0JrL%m?lCO zQ#lCc$?c){)={aHK>OP0C_~#KN)uUl#hbKQIgZ z0vBAB?(hx%&3v!ENdfrDuwDRaCBTMZkUFr6_!fZ`0?y=^Pht5F~;A zP4s8ZMsw{&-G>Y+ipVHLzt7Hp&%OS^!H@sA{Bs8XADP%+ivOOA{Y?rP>FNDh>i+i+ zpYX4W|CO2j`=K$A{%xVY*Zs4LaFYM(;{UyD|5N&(KJ0Jl{wMz>{kum~QAB(ATP@W4 OuiAYYz=!I$(*FPoSld_t literal 0 HcmV?d00001 diff --git a/frontend/appflowy_flutter/assets/translations/en.json b/frontend/appflowy_flutter/assets/translations/en.json index a00a49ceb8..dd3435c19a 100644 --- a/frontend/appflowy_flutter/assets/translations/en.json +++ b/frontend/appflowy_flutter/assets/translations/en.json @@ -326,7 +326,8 @@ "checklist": { "panelTitle": "Add an item" }, - "menuName": "Grid" + "menuName": "Grid", + "referencedGridPrefix": "View of" }, "document": { "menuName": "Document", @@ -390,7 +391,8 @@ "column": { "create_new_card": "New" }, - "menuName": "Board" + "menuName": "Board", + "referencedBoardPrefix": "View of" }, "calendar": { "menuName": "Calendar", diff --git a/frontend/appflowy_flutter/integration_test/board_test.dart b/frontend/appflowy_flutter/integration_test/board_test.dart new file mode 100644 index 0000000000..3900843207 --- /dev/null +++ b/frontend/appflowy_flutter/integration_test/board_test.dart @@ -0,0 +1,43 @@ +import 'package:appflowy_board/appflowy_board.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'util/util.dart'; + +/// Integration tests for an empty board. The [TestWorkspaceService] will load +/// a workspace from an empty board `assets/test/workspaces/board.zip` for all +/// tests. +/// +/// To create another integration test with a preconfigured workspace. +/// Use the following steps. +/// 1. Create a new workspace from the AppFlowy launch screen. +/// 2. Modify the workspace until it is suitable as the starting point for +/// the integration test you need to land. +/// 3. Use a zip utility program to zip the workspace folder that you created. +/// 4. Add the zip file under `assets/test/workspaces/` +/// 5. Add a new enumeration to [TestWorkspace] in `integration_test/utils/data.dart`. +/// For example, if you added a workspace called `empty_calendar.zip`, +/// then [TestWorkspace] should have the following value: +/// ```dart +/// enum TestWorkspace { +/// board('board'), +/// empty_calendar('empty_calendar'); +/// +/// /* code */ +/// } +/// ``` +/// 6. Double check that the .zip file that you added is included as an asset in +/// the pubspec.yaml file under appflowy_flutter. +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + const service = TestWorkspaceService(TestWorkspace.board); + + group('board', () { + setUpAll(() async => await service.setUpAll()); + setUp(() async => await service.setUp()); + + testWidgets('integration test unzips the proper workspace and loads it correctly.', (tester) async { + await tester.initializeAppFlowy(); + expect(find.byType(AppFlowyBoard), findsOneWidget); + }); + }); +} diff --git a/frontend/appflowy_flutter/integration_test/empty_document_test.dart b/frontend/appflowy_flutter/integration_test/empty_document_test.dart new file mode 100644 index 0000000000..51f92c4c35 --- /dev/null +++ b/frontend/appflowy_flutter/integration_test/empty_document_test.dart @@ -0,0 +1,120 @@ +import 'package:appflowy/plugins/document/presentation/plugins/base/built_in_page_widget.dart'; +import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'util/keyboard.dart'; +import 'util/util.dart'; + +/// Integration tests for an empty document. The [TestWorkspaceService] will load a workspace from an empty document `assets/test/workspaces/empty_document.zip` for all tests. +/// +/// To create another integration test with a preconfigured workspace. Use the following steps: +/// 1. Create a new workspace from the AppFlowy launch screen. +/// 2. Modify the workspace until it is suitable as the starting point for the integration test you need to land. +/// 3. Use a zip utility program to zip the workspace folder that you created. +/// 4. Add the zip file under `assets/test/workspaces/` +/// 5. Add a new enumeration to [TestWorkspace] in `integration_test/utils/data.dart`. For example, if you added a workspace called `empty_calendar.zip`, then [TestWorkspace] should have the following value: +/// ```dart +/// enum TestWorkspace { +/// board('board'), +/// empty_calendar('empty_calendar'); +/// +/// /* code */ +/// } +/// ``` +/// 6. Double check that the .zip file that you added is included as an asset in the pubspec.yaml file under appflowy_flutter. +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + const service = TestWorkspaceService(TestWorkspace.emptyDocument); + + group('Tests on a workspace with only an empty document', () { + setUpAll(() async => await service.setUpAll()); + setUp(() async => await service.setUp()); + + testWidgets('/board shortcut creates a new board and view of the board', (tester) async { + await tester.initializeAppFlowy(); + + // Needs tab to obtain focus for the app flowy editor. + // by default the tap appears at the center of the widget. + final Finder editor = find.byType(AppFlowyEditor); + await tester.tap(editor); + await tester.pumpAndSettle(); + + // tester.sendText() cannot be used since the editor + // does not contain any EditableText widgets. + // to interact with the app during an integration test, + // simulate physical keyboard events. + await FlowyTestKeyboard.simulateKeyDownEvent([ + LogicalKeyboardKey.slash, + LogicalKeyboardKey.keyB, + LogicalKeyboardKey.keyO, + LogicalKeyboardKey.keyA, + LogicalKeyboardKey.keyR, + LogicalKeyboardKey.keyD, + LogicalKeyboardKey.arrowDown, + ], tester: tester); + + // Checks whether the options in the selection menu + // for /board exist. + expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2)); + + // Finalizes the slash command that creates the board. + await FlowyTestKeyboard.simulateKeyDownEvent([ + LogicalKeyboardKey.enter, + ], tester: tester); + + // Checks whether new board is referenced and properly on the page. + expect(find.byType(BuiltInPageWidget), findsOneWidget); + + // Checks whether the new database was created + const newBoardLabel = "Untitled"; + expect(find.text(newBoardLabel), findsOneWidget); + + // Checks whether a view of the database was created + const viewOfBoardLabel = "View of Untitled"; + expect(find.text(viewOfBoardLabel), findsNWidgets(2)); + }); + + testWidgets('/grid shortcut creates a new grid and view of the grid', (tester) async { + await tester.initializeAppFlowy(); + + // Needs tab to obtain focus for the app flowy editor. + // by default the tap appears at the center of the widget. + final Finder editor = find.byType(AppFlowyEditor); + await tester.tap(editor); + await tester.pumpAndSettle(); + + // tester.sendText() cannot be used since the editor + // does not contain any EditableText widgets. + // to interact with the app during an integration test, + // simulate physical keyboard events. + await FlowyTestKeyboard.simulateKeyDownEvent([ + LogicalKeyboardKey.slash, + LogicalKeyboardKey.keyG, + LogicalKeyboardKey.keyR, + LogicalKeyboardKey.keyI, + LogicalKeyboardKey.keyD, + LogicalKeyboardKey.arrowDown, + ], tester: tester); + + // Checks whether the options in the selection menu + // for /grid exist. + expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2)); + + // Finalizes the slash command that creates the board. + await simulateKeyDownEvent(LogicalKeyboardKey.enter); + await tester.pumpAndSettle(); + + // Checks whether new board is referenced and properly on the page. + expect(find.byType(BuiltInPageWidget), findsOneWidget); + + // Checks whether the new database was created + const newTableLabel = "Untitled"; + expect(find.text(newTableLabel), findsOneWidget); + + // Checks whether a view of the database was created + const viewOfTableLabel = "View of Untitled"; + expect(find.text(viewOfTableLabel), findsNWidgets(2)); + }); + }); +} diff --git a/frontend/appflowy_flutter/integration_test/runner.dart b/frontend/appflowy_flutter/integration_test/runner.dart new file mode 100644 index 0000000000..1592cccb93 --- /dev/null +++ b/frontend/appflowy_flutter/integration_test/runner.dart @@ -0,0 +1,19 @@ +import 'package:integration_test/integration_test.dart'; + +import 'board_test.dart' as board_test; +import 'switch_folder_test.dart' as switch_folder_test; +import 'empty_document_test.dart' as empty_document_test; + +/// The main task runner for all integration tests in AppFlowy. +/// +/// Having a single entrypoint for integration tests is necessary due to an +/// [issue caused by switching files with integration testing](https://github.com/flutter/flutter/issues/101031). +/// If flutter/flutter#101031 is resolved, this file can be removed completely. +/// Once removed, the integration_test.yaml must be updated to exclude this as +/// as the test target. +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + switch_folder_test.main(); + board_test.main(); + empty_document_test.main(); +} diff --git a/frontend/appflowy_flutter/integration_test/switch_folder_test.dart b/frontend/appflowy_flutter/integration_test/switch_folder_test.dart index 555a5e41b1..6dcd41b081 100644 --- a/frontend/appflowy_flutter/integration_test/switch_folder_test.dart +++ b/frontend/appflowy_flutter/integration_test/switch_folder_test.dart @@ -1,10 +1,5 @@ -import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:appflowy/plugins/document/presentation/plugins/base/built_in_page_widget.dart'; import 'package:appflowy/user/presentation/folder/folder_widget.dart'; -import 'package:appflowy_editor/appflowy_editor.dart'; -import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text_field.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; @@ -162,135 +157,5 @@ void main() { await TestFolder.currentLocation(), ); }); - - testWidgets('/board shortcut creates a new board', (tester) async { - const folderName = 'appflowy'; - await TestFolder.cleanTestLocation(folderName); - await TestFolder.setTestLocation(folderName); - - await tester.initializeAppFlowy(); - - // tap open button - await mockGetDirectoryPath(folderName); - await tester.tapOpenFolderButton(); - - await tester.wait(1000); - await tester.expectToSeeWelcomePage(); - - final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - // Necessary for being able to enterText when not in debug mode - binding.testTextInput.register(); - - // Needs tab to obtain focus for the app flowy editor. - // by default the tap appears at the center of the widget. - final Finder editor = find.byType(AppFlowyEditor); - await tester.tap(editor); - await tester.pumpAndSettle(); - - // tester.sendText() cannot be used since the editor - // does not contain any EditableText widgets. - // to interact with the app during an integration test, - // simulate physical keyboard events. - await simulateKeyDownEvent(LogicalKeyboardKey.enter); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.enter); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.slash); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyB); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyO); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyA); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyR); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyD); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); - await tester.pumpAndSettle(); - - // Checks whether the options in the selection menu - // for /board exist. - expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2)); - - // Finalizes the slash command that creates the board. - await simulateKeyDownEvent(LogicalKeyboardKey.enter); - await tester.pumpAndSettle(); - - // Checks whether new board is referenced and properly on the page. - expect(find.byType(BuiltInPageWidget), findsOneWidget); - - // Checks whether the new board is in the side bar. - final sidebarLabel = LocaleKeys.newPageText.tr(); - expect(find.text(sidebarLabel), findsOneWidget); - }); - - testWidgets('/grid shortcut creates a new grid', (tester) async { - const folderName = 'appflowy'; - await TestFolder.cleanTestLocation(folderName); - await TestFolder.setTestLocation(folderName); - - await tester.initializeAppFlowy(); - - // tap open button - await mockGetDirectoryPath(folderName); - await tester.tapOpenFolderButton(); - - await tester.wait(1000); - await tester.expectToSeeWelcomePage(); - - final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - // Necessary for being able to enterText when not in debug mode - binding.testTextInput.register(); - - // Needs tab to obtain focus for the app flowy editor. - // by default the tap appears at the center of the widget. - final Finder editor = find.byType(AppFlowyEditor); - await tester.tap(editor); - await tester.pumpAndSettle(); - - // tester.sendText() cannot be used since the editor - // does not contain any EditableText widgets. - // to interact with the app during an integration test, - // simulate physical keyboard events. - await simulateKeyDownEvent(LogicalKeyboardKey.enter); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.enter); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.slash); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyG); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyR); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyI); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.keyD); - await tester.pumpAndSettle(); - await simulateKeyDownEvent(LogicalKeyboardKey.arrowDown); - await tester.pumpAndSettle(); - - // Checks whether the options in the selection menu - // for /grid exist. - expect(find.byType(SelectionMenuItemWidget), findsAtLeastNWidgets(2)); - - // Finalizes the slash command that creates the board. - await simulateKeyDownEvent(LogicalKeyboardKey.enter); - await tester.pumpAndSettle(); - - // Checks whether new board is referenced and properly on the page. - expect(find.byType(BuiltInPageWidget), findsOneWidget); - - // Checks whether the new board is in the side bar. - final sidebarLabel = LocaleKeys.newPageText.tr(); - expect(find.text(sidebarLabel), findsOneWidget); - }); }); } diff --git a/frontend/appflowy_flutter/integration_test/util/data.dart b/frontend/appflowy_flutter/integration_test/util/data.dart new file mode 100644 index 0000000000..a527950489 --- /dev/null +++ b/frontend/appflowy_flutter/integration_test/util/data.dart @@ -0,0 +1,66 @@ +import 'dart:io'; + +import 'package:appflowy/workspace/application/settings/settings_location_cubit.dart'; +import 'package:archive/archive_io.dart'; +import 'package:flutter/services.dart'; +import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +enum TestWorkspace { + board("board"), + emptyDocument("empty_document"); + + const TestWorkspace(this._name); + + final String _name; + + Future get zip async { + final Directory parent = await TestWorkspace._parent; + final File out = File(p.join(parent.path, '$_name.zip')); + if (await out.exists()) return out; + await out.create(); + final ByteData data = await rootBundle.load(_asset); + await out.writeAsBytes(data.buffer.asUint8List()); + return out; + } + + Future get root async { + final Directory parent = await TestWorkspace._parent; + return Directory(p.join(parent.path, _name)); + } + + static Future get _parent async { + final Directory root = await getTemporaryDirectory(); + if (await root.exists()) return root; + await root.create(); + return root; + } + + String get _asset => 'assets/test/workspaces/$_name.zip'; +} + +class TestWorkspaceService { + const TestWorkspaceService(this.workspace); + + final TestWorkspace workspace; + + /// Instructs the application to read workspace data from the workspace found under this [TestWorkspace]'s path. + Future setUpAll() async { + SharedPreferences.setMockInitialValues( + { + kSettingsLocationDefaultLocation: + await workspace.root.then((value) => value.path), + }, + ); + } + + /// Workspaces that are checked into source are compressed. [TestWorkspaceService.setUp()] decompresses the file into an ephemeral directory that will be ignored by source control. + Future setUp() async { + final inputStream = + InputFileStream(await workspace.zip.then((value) => value.path)); + final archive = ZipDecoder().decodeBuffer(inputStream); + extractArchiveToDisk( + archive, await TestWorkspace._parent.then((value) => value.path)); + } +} diff --git a/frontend/appflowy_flutter/integration_test/util/keyboard.dart b/frontend/appflowy_flutter/integration_test/util/keyboard.dart new file mode 100644 index 0000000000..02bbdb79f1 --- /dev/null +++ b/frontend/appflowy_flutter/integration_test/util/keyboard.dart @@ -0,0 +1,12 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart' as flutter_test; + +class FlowyTestKeyboard { + static Future simulateKeyDownEvent(List keys, + {required flutter_test.WidgetTester tester}) async { + for (final LogicalKeyboardKey key in keys) { + await flutter_test.simulateKeyDownEvent(key); + await tester.pumpAndSettle(); + } + } +} diff --git a/frontend/appflowy_flutter/integration_test/util/util.dart b/frontend/appflowy_flutter/integration_test/util/util.dart index 1b4b7c3272..20606483d3 100644 --- a/frontend/appflowy_flutter/integration_test/util/util.dart +++ b/frontend/appflowy_flutter/integration_test/util/util.dart @@ -1,3 +1,4 @@ export 'base.dart'; export 'launch.dart'; export 'settings.dart'; +export 'data.dart'; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart index 4d12cae839..b6ca40b630 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_service.dart @@ -5,7 +5,7 @@ import 'package:dartz/dartz.dart'; class DatabaseBackendService { static Future, FlowyError>> - getAllDatabase() { + getAllDatabases() { return DatabaseEventGetDatabases().send().then((result) { return result.fold((l) => left(l.items), (r) => right(r)); }); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart index 8d4afd917e..ff12cc9afd 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart @@ -1,20 +1,55 @@ +import 'package:appflowy/generated/locale_keys.g.dart'; +import 'package:appflowy/plugins/database_view/application/database_view_service.dart'; import 'package:appflowy/plugins/document/presentation/plugins/board/board_node_widget.dart'; import 'package:appflowy/plugins/document/presentation/plugins/grid/grid_node_widget.dart'; +import 'package:appflowy/workspace/application/app/app_service.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/app.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; +import 'package:easy_localization/easy_localization.dart'; const String kAppID = 'app_id'; const String kViewID = 'view_id'; extension InsertPage on EditorState { - void insertPage(AppPB appPB, ViewPB viewPB) { + Future insertPage(AppPB appPB, ViewPB viewPB) async { final selection = service.selectionService.currentSelection.value; final textNodes = service.selectionService.currentSelectedNodes.whereType(); if (selection == null || textNodes.isEmpty) { return; } + + // get the database that the view is associated with + final database = + await DatabaseViewBackendService(viewId: viewPB.id).openGrid().then( + (value) => value.getLeftOrNull(), + ); + + if (database == null) { + throw StateError( + 'The database associated with ${viewPB.id} could not be found while attempting to create a referenced ${viewPB.layout.name}.'); + } + + final prefix = referencedBoardPrefix(viewPB.layout); + + final ref = await AppBackendService().createView( + appId: appPB.id, + name: "$prefix ${viewPB.name}", + desc: appPB.desc, + layoutType: viewPB.layout, + ext: { + 'database_id': database.id, + }, + ).then( + (value) => value.getLeftOrNull(), + ); + + // TODO(a-wallen): Show error dialog here. + if (ref == null) { + return; + } + final transaction = this.transaction; transaction.insertNode( selection.end.path, @@ -22,13 +57,24 @@ extension InsertPage on EditorState { type: _convertPageType(viewPB), attributes: { kAppID: appPB.id, - kViewID: viewPB.id, + kViewID: ref.id, }, ), ); apply(transaction); } + String referencedBoardPrefix(ViewLayoutTypePB layout) { + switch (layout) { + case ViewLayoutTypePB.Grid: + return LocaleKeys.grid_referencedGridPrefix.tr(); + case ViewLayoutTypePB.Board: + return LocaleKeys.board_referencedBoardPrefix.tr(); + default: + throw UnimplementedError(); + } + } + String _convertPageType(ViewPB viewPB) { switch (viewPB.layout) { case ViewLayoutTypePB.Grid: diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 801a062534..613b205df1 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -95,6 +95,7 @@ dependencies: http: ^0.13.5 json_annotation: ^4.7.0 path: ^1.8.2 + archive: ^3.3.0 dev_dependencies: flutter_lints: ^2.0.1 @@ -163,30 +164,8 @@ flutter: - assets/images/common/ - assets/images/grid/setting/ - assets/translations/ - # - images/a_dot_ham.jpeg - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages + # The following assets will be excluded in release. + # BEGIN: EXCLUDE_IN_RELEASE + - assets/test/workspaces/ + # END: EXCLUDE_IN_RELEASE diff --git a/frontend/scripts/flutter_release_build/build_flowy.dart b/frontend/scripts/flutter_release_build/build_flowy.dart new file mode 100644 index 0000000000..a7c2a9ada4 --- /dev/null +++ b/frontend/scripts/flutter_release_build/build_flowy.dart @@ -0,0 +1,28 @@ +import 'dart:io'; + +part 'tool.dart'; + +const excludeTagBegin = 'BEGIN: EXCLUDE_IN_RELEASE'; +const excludeTagEnd = 'END: EXCLUDE_IN_RELEASE'; + +Future main(List args) async { + const help = ''' +A build script that modifies build assets before building the release version of AppFlowy. + +args[0]: The directory that contains the AppFlowy git repository. Should be the parent to appflowy_flutter. (absolute path) +args[1]: The appflowy version to be built (github ref_name). +'''; + const numArgs = 2; + assert(args.length == numArgs, + 'Expected ${numArgs}, got ${args.length}. Read the following for instructions about how to use this script.\n\n$help'); + if (args[0] == '-h' || args[0] == '--help') { + stdout.write(help); + stdout.flush(); + } + final repositoryRoot = Directory(args[0]); + assert(await repositoryRoot.exists(), + '$repositoryRoot is an invalid directory. Please try again with a valid directory.\n\n$help'); + final appVersion = args[1]; + await _BuildTool(repositoryRoot: repositoryRoot.path, appVersion: appVersion) + .run(); +} diff --git a/frontend/scripts/flutter_release_build/tool.dart b/frontend/scripts/flutter_release_build/tool.dart new file mode 100644 index 0000000000..36a0a2f177 --- /dev/null +++ b/frontend/scripts/flutter_release_build/tool.dart @@ -0,0 +1,115 @@ +part of 'build_flowy.dart'; + +enum _ScanMode { + ignore, + target, +} + +enum _ModifyMode { + include, + exclude, +} + +class _BuildTool { + const _BuildTool({ + required this.repositoryRoot, + required this.appVersion, + }); + + final String repositoryRoot; + final String appVersion; + + String get projectRoot => + [repositoryRoot, 'appflowy_flutter'].join(Platform.pathSeparator); + + File get pubspec => + File([projectRoot, 'pubspec.yaml'].join(Platform.pathSeparator)); + + Future get _architecture async => + await Process.run('uname', ['-m']).then((value) => value.stdout.trim()); + + Future get _commandForOS async { + // Check the operating system and CPU architecture + var os = Platform.operatingSystem; + var arch = Platform.isMacOS ? await _architecture : Platform.localHostname; + + // Determine the appropriate command based on the OS and architecture + if (os == 'windows') { + return 'cargo make --env APP_VERSION=$appVersion --profile production-windows-x86 appflowy'; + } + + if (os == 'linux') { + return 'cargo make --env APP_VERSION=$appVersion --profile production-linux-x86_64 appflowy'; + } + + if (os == 'macos') { + if (arch == 'x86_64') { + return 'cargo make --env APP_VERSION=$appVersion --profile production-mac-x86_64 appflowy'; + } + if (arch == 'arm64') { + return 'cargo make --env APP_VERSION=$appVersion --profile production-mac-arm64 appflowy'; + } + throw 'Unsupported CPU architecture: $arch'; + } + + throw 'Unsupported operating system: $os'; + } + + /// Scans a file for lines between # BEGIN: EXCLUDE_IN_RELEASE and + /// END: EXCLUDE_IN_RELEASE. Will add a comment to remove those assets + /// from the build. + Future _process_directives( + File file, { + required _ModifyMode mode, + }) async { + // Read the contents of the file into a list + var lines = await file.readAsLines(); + + // Find the lines between BEGIN: EXCLUDE_IN_RELEASE and END: EXCLUDE_IN_RELEASE + var scanMode = _ScanMode.ignore; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (line.contains(excludeTagBegin)) { + scanMode = _ScanMode.target; + } else if (line.contains(excludeTagEnd)) { + scanMode = _ScanMode.ignore; + } else if (scanMode == _ScanMode.target) { + lines[i] = _modify(line, mode: mode); + } + } + + // Write the modified contents back to the file + await file.writeAsString(lines.join('\n')); + } + + String _modify(String line, {required _ModifyMode mode}) { + switch (mode) { + case _ModifyMode.include: + return line.split('#').where((element) => element != '#').join(); + case _ModifyMode.exclude: + return '#$line'; + } + } + + Future _build() async { + final cwd = Directory.current; + Directory.current = repositoryRoot; + + final cmd = await _commandForOS; + // Run the command using the Process.run() function + // final build = await Process.run('echo', ['hello'], runInShell: true); + final build = + await Process.start(cmd.split(' ')[0], cmd.split(' ').sublist(1)); + await stdout.addStream(build.stdout); + await stderr.addStream(build.stderr); + Directory.current = cwd; + } + + Future run() async { + final pubspec = this.pubspec; + + await _process_directives(pubspec, mode: _ModifyMode.exclude); + await _build(); + await _process_directives(pubspec, mode: _ModifyMode.include); + } +} From 994332218e31507739ee66c6737b00fdecf4268b Mon Sep 17 00:00:00 2001 From: Yijing Huang Date: Mon, 3 Apr 2023 23:51:26 -0500 Subject: [PATCH 5/7] feat: Improve dark mode in grid page (#2160) * chore: Update the hover effect in FieldCellButton and CreateFieldButton * chore(grid): improve grid page UI 1. Update lightGreyHover in AFThemeExtension 2. Comment out dandelion and lavender temporary 3. Add text color in AFThemeExtension 4. Update NavigatorAlertDialog title color * chore: update the background color of auth page * chore: update UI in Select option cell * chore: update date cell UI * chore: update checklist UI * chore: comment out temporary * chore: update multi select and URL UI * chore: update scroll bar color * chore: update sort and filter UI * chore: rename default theme and put dandelion&lavender theme back * chore: update new app svg file --- .../assets/images/home/new_app.svg | 20 ++++++++++--- .../assets/images/home/new_app_dark.svg | 5 ---- .../widgets/filter/choicechip/choicechip.dart | 8 ++++-- .../widgets/filter/condition_button.dart | 9 ++++-- .../widgets/filter/create_filter_list.dart | 28 ++++++++++--------- .../widgets/filter/disclosure_button.dart | 2 ++ .../widgets/filter/filter_menu.dart | 5 +++- .../widgets/footer/grid_footer.dart | 7 +++-- .../widgets/header/field_cell.dart | 7 ++--- .../header/field_cell_action_sheet.dart | 10 +++++-- .../widgets/header/field_type_list.dart | 7 ++++- .../header/field_type_option_editor.dart | 3 ++ .../widgets/header/grid_header.dart | 7 ++--- .../widgets/header/type_option/date.dart | 10 ++----- .../header/type_option/select_option.dart | 7 ++++- .../type_option/select_option_editor.dart | 7 ++++- .../grid/presentation/widgets/row/action.dart | 6 +++- .../grid/presentation/widgets/row/row.dart | 13 +++++++-- .../widgets/sort/create_sort_list.dart | 28 ++++++++++--------- .../widgets/sort/sort_choice_button.dart | 5 +++- .../widgets/sort/sort_editor.dart | 11 ++------ .../presentation/widgets/sort/sort_menu.dart | 5 +++- .../widgets/toolbar/filter_button.dart | 2 +- .../widgets/toolbar/grid_property.dart | 7 ++++- .../widgets/toolbar/grid_setting.dart | 6 +++- .../widgets/toolbar/setting_button.dart | 1 + .../widgets/toolbar/sort_button.dart | 2 +- .../checklist_cell/checklist_cell_editor.dart | 8 +++++- .../checklist_progress_bar.dart | 2 +- .../row/cells/date_cell/date_editor.dart | 5 +--- .../cells/select_option_cell/extension.dart | 11 ++++++-- .../select_option_editor.dart | 2 +- .../widgets/row/cells/url_cell/url_cell.dart | 7 ++--- .../lib/workspace/application/appearance.dart | 7 +++-- .../home/menu/app/create_button.dart | 15 ++++++---- .../widgets/settings_appearance_view.dart | 2 +- .../presentation/widgets/dialogs.dart | 2 +- .../lib/src/extensions/theme_extension.dart | 2 +- .../lib/colorscheme/colorscheme.dart | 8 ++++-- .../lib/colorscheme/dandelion.dart | 25 ++++++++++------- .../lib/colorscheme/default_colorscheme.dart | 7 ++++- .../flowy_infra/lib/colorscheme/lavender.dart | 25 ++++++++++------- .../packages/flowy_infra/lib/theme.dart | 6 ++-- .../flowy_infra/lib/theme_extension.dart | 11 ++++++++ .../scrolling/styled_scroll_bar.dart | 2 +- 45 files changed, 243 insertions(+), 132 deletions(-) delete mode 100644 frontend/appflowy_flutter/assets/images/home/new_app_dark.svg diff --git a/frontend/appflowy_flutter/assets/images/home/new_app.svg b/frontend/appflowy_flutter/assets/images/home/new_app.svg index ac6c002d3d..c74ac3b349 100644 --- a/frontend/appflowy_flutter/assets/images/home/new_app.svg +++ b/frontend/appflowy_flutter/assets/images/home/new_app.svg @@ -1,5 +1,17 @@ - - - - + + + diff --git a/frontend/appflowy_flutter/assets/images/home/new_app_dark.svg b/frontend/appflowy_flutter/assets/images/home/new_app_dark.svg deleted file mode 100644 index f1ab9c8cd3..0000000000 --- a/frontend/appflowy_flutter/assets/images/home/new_app_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/choicechip/choicechip.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/choicechip/choicechip.dart index 6900f472e0..46fb701441 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/choicechip/choicechip.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/choicechip/choicechip.dart @@ -38,7 +38,10 @@ class ChoiceChipButton extends StatelessWidget { child: FlowyButton( decoration: decoration, useIntrinsicWidth: true, - text: FlowyText(filterInfo.fieldInfo.name), + text: FlowyText( + filterInfo.fieldInfo.name, + color: AFThemeExtension.of(context).textColor, + ), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), radius: const BorderRadius.all(Radius.circular(14)), leftIcon: svgWidget( @@ -62,7 +65,8 @@ class _ChoicechipFilterDesc extends StatelessWidget { Widget build(BuildContext context) { final arrow = Transform.rotate( angle: -math.pi / 2, - child: svgWidget("home/arrow_left"), + child: svgWidget("home/arrow_left", + color: AFThemeExtension.of(context).textColor), ); return Padding( padding: const EdgeInsets.symmetric(horizontal: 2), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/condition_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/condition_button.dart index ef4d58f447..660c0b0316 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/condition_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/condition_button.dart @@ -18,14 +18,19 @@ class ConditionButton extends StatelessWidget { Widget build(BuildContext context) { final arrow = Transform.rotate( angle: -math.pi / 2, - child: svgWidget("home/arrow_left"), + child: svgWidget("home/arrow_left", + color: AFThemeExtension.of(context).textColor), ); return SizedBox( height: 20, child: FlowyButton( useIntrinsicWidth: true, - text: FlowyText(conditionName, fontSize: 10), + text: FlowyText( + conditionName, + fontSize: 10, + color: AFThemeExtension.of(context).textColor, + ), margin: const EdgeInsets.symmetric(horizontal: 4), radius: const BorderRadius.all(Radius.circular(2)), rightIcon: arrow, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/create_filter_list.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/create_filter_list.dart index 3c8c6b4ba9..42ba35640e 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/create_filter_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/create_filter_list.dart @@ -3,6 +3,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.da import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -117,19 +118,16 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate { @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { - return Padding( + return Container( padding: const EdgeInsets.only(top: 4), - child: Container( - color: Theme.of(context).colorScheme.background, - height: fixHeight, - child: FlowyTextField( - hintText: LocaleKeys.grid_settings_filterBy.tr(), - onChanged: (text) { - context - .read() - .add(GridCreateFilterEvent.didReceiveFilterText(text)); - }, - ), + height: fixHeight, + child: FlowyTextField( + hintText: LocaleKeys.grid_settings_filterBy.tr(), + onChanged: (text) { + context + .read() + .add(GridCreateFilterEvent.didReceiveFilterText(text)); + }, ), ); } @@ -158,7 +156,11 @@ class _FilterPropertyCell extends StatelessWidget { @override Widget build(BuildContext context) { return FlowyButton( - text: FlowyText.medium(fieldInfo.name), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText.medium( + fieldInfo.name, + color: AFThemeExtension.of(context).textColor, + ), onTap: () => onTap(fieldInfo), leftIcon: svgWidget( fieldInfo.fieldType.iconName(), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart index 0f70d7be9d..fd296a73e0 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart @@ -3,6 +3,7 @@ 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:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/material.dart'; @@ -31,6 +32,7 @@ class _DisclosureButtonState extends State { .toList(), buildChild: (controller) { return FlowyIconButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, width: 20, icon: svgWidget( "editor/details", diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_menu.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_menu.dart index ec8c47dc6f..91cbcbe54b 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/filter/filter_menu.dart @@ -71,7 +71,10 @@ class _AddFilterButtonState extends State { SizedBox( height: 28, child: FlowyButton( - text: FlowyText(LocaleKeys.grid_settings_addFilter.tr()), + text: FlowyText( + LocaleKeys.grid_settings_addFilter.tr(), + color: AFThemeExtension.of(context).textColor, + ), useIntrinsicWidth: true, hoverColor: AFThemeExtension.of(context).lightGreyHover, leftIcon: svgWidget( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart index 44f1d3fb7d..b985f59430 100755 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart @@ -14,12 +14,15 @@ class GridAddRowButton extends StatelessWidget { @override Widget build(BuildContext context) { return FlowyButton( - text: FlowyText.medium(LocaleKeys.grid_row_newRow.tr()), + text: FlowyText.medium( + LocaleKeys.grid_row_newRow.tr(), + color: Theme.of(context).colorScheme.tertiary, + ), hoverColor: AFThemeExtension.of(context).lightGreyHover, onTap: () => context.read().add(const GridEvent.createRow()), leftIcon: svgWidget( "home/add", - color: Theme.of(context).iconTheme.color, + color: Theme.of(context).colorScheme.tertiary, ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell.dart index 3af13c93a2..526276e0f2 100755 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell.dart @@ -164,11 +164,10 @@ class FieldCellButton extends StatelessWidget { .replaceAll(Characters(''), Characters('\u{200B}')) .toString(); return FlowyButton( - hoverColor: AFThemeExtension.of(context).lightGreyHover, + hoverColor: AFThemeExtension.of(context).greyHover, onTap: onTap, - leftIcon: svgWidget( - field.fieldType.iconName(), - color: Theme.of(context).iconTheme.color, + leftIcon: FlowySvg( + name: field.fieldType.iconName(), ), radius: BorderRadius.zero, text: FlowyText.medium( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart index 4cd23e3b84..cf44799a88 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart @@ -5,6 +5,7 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/presentation/widgets/dialogs.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; @@ -81,8 +82,10 @@ class _EditFieldButton extends StatelessWidget { return SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, text: FlowyText.medium( LocaleKeys.grid_field_editProperty.tr(), + color: AFThemeExtension.of(context).textColor, ), onTap: onTap, ), @@ -148,9 +151,12 @@ class FieldActionCell extends StatelessWidget { @override Widget build(BuildContext context) { return FlowyButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, text: FlowyText.medium( action.title(), - color: enable ? null : Theme.of(context).disabledColor, + color: enable + ? AFThemeExtension.of(context).textColor + : Theme.of(context).disabledColor, ), onTap: () { if (enable) { @@ -160,7 +166,7 @@ class FieldActionCell extends StatelessWidget { leftIcon: svgWidget( action.iconName(), color: enable - ? Theme.of(context).colorScheme.onSurface + ? AFThemeExtension.of(context).textColor : Theme.of(context).disabledColor, ), ); diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart index f94b46cbee..b05d9391c3 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart @@ -1,5 +1,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; import 'package:flutter/material.dart'; @@ -57,7 +58,11 @@ class FieldTypeCell extends StatelessWidget { return SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( - text: FlowyText.medium(fieldType.title()), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText.medium( + fieldType.title(), + color: AFThemeExtension.of(context).textColor, + ), onTap: () => onSelectField(fieldType), leftIcon: svgWidget( fieldType.iconName(), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart index 5f2364571c..b8d1e9a26a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart @@ -4,6 +4,7 @@ import 'package:appflowy/plugins/database_view/application/field/type_option/typ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:dartz/dartz.dart' show Either; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart'; @@ -110,8 +111,10 @@ class _SwitchFieldButton extends StatelessWidget { Widget _buildMoreButton(BuildContext context) { final bloc = context.read(); return FlowyButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, text: FlowyText.medium( bloc.state.field.fieldType.title(), + color: AFThemeExtension.of(context).textColor, ), margin: GridSize.typeOptionContentInsets, leftIcon: svgWidget( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/grid_header.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/grid_header.dart index 986a91daa2..6a77ac83ee 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/grid_header.dart @@ -178,12 +178,9 @@ class CreateFieldButton extends StatelessWidget { child: FlowyButton( radius: BorderRadius.zero, text: FlowyText.medium(LocaleKeys.grid_field_newColumn.tr()), - hoverColor: AFThemeExtension.of(context).lightGreyHover, + hoverColor: AFThemeExtension.of(context).greyHover, onTap: () {}, - leftIcon: svgWidget( - "home/add", - color: Theme.of(context).iconTheme.color, - ), + leftIcon: const FlowySvg(name: 'home/add'), ), popupBuilder: (BuildContext popover) { return FieldEditor( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart index 3da0aadd93..12237b8350 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/date.dart @@ -151,10 +151,7 @@ class DateFormatButton extends StatelessWidget { margin: buttonMargins, onTap: onTap, onHover: onHover, - rightIcon: svgWidget( - "grid/more", - color: Theme.of(context).iconTheme.color, - ), + rightIcon: const FlowySvg(name: 'grid/more'), ), ); } @@ -182,10 +179,7 @@ class TimeFormatButton extends StatelessWidget { margin: buttonMargins, onTap: onTap, onHover: onHover, - rightIcon: svgWidget( - "grid/more", - color: Theme.of(context).iconTheme.color, - ), + rightIcon: const FlowySvg(name: 'grid/more'), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option.dart index cac4f1f0f0..56a0ad0736 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option.dart @@ -1,6 +1,7 @@ import 'package:appflowy/plugins/database_view/application/field/type_option/select_option_type_option_bloc.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:appflowy_backend/protobuf/flowy-database/select_type_option.pb.dart'; import 'package:flutter/material.dart'; @@ -243,7 +244,11 @@ class _AddOptionButton extends StatelessWidget { child: SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( - text: FlowyText.medium(LocaleKeys.grid_field_addSelectOption.tr()), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText.medium( + LocaleKeys.grid_field_addSelectOption.tr(), + color: AFThemeExtension.of(context).textColor, + ), onTap: () { context .read() diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart index b0d6338ae3..36ebffa692 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart @@ -1,6 +1,7 @@ import 'package:appflowy/plugins/database_view/application/field/type_option/edit_select_option_bloc.dart'; import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -103,7 +104,11 @@ class _DeleteTag extends StatelessWidget { return SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( - text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr()), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText.medium( + LocaleKeys.grid_selectOption_deleteTag.tr(), + color: AFThemeExtension.of(context).textColor, + ), leftIcon: svgWidget( "grid/delete", color: Theme.of(context).iconTheme.color, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/action.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/action.dart index 9ecaaf055b..33e1a69c7a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/action.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/action.dart @@ -3,6 +3,7 @@ import 'package:appflowy/plugins/database_view/grid/application/row/row_action_s import 'package:easy_localization/easy_localization.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -56,9 +57,12 @@ class _ActionCell extends StatelessWidget { return SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, text: FlowyText.medium( action.title(), - color: action.enable() ? null : Theme.of(context).disabledColor, + color: action.enable() + ? AFThemeExtension.of(context).textColor + : Theme.of(context).disabledColor, ), onTap: () { if (action.enable()) { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/row.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/row.dart index 09aff68112..425dec6317 100755 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/row.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/row/row.dart @@ -5,6 +5,7 @@ import 'package:appflowy/plugins/database_view/grid/application/row/row_bloc.dar import 'package:appflowy/plugins/database_view/widgets/row/cell_builder.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -152,11 +153,15 @@ class _InsertButton extends StatelessWidget { Widget build(BuildContext context) { return FlowyIconButton( tooltipText: LocaleKeys.tooltip_addNewRow.tr(), + hoverColor: AFThemeExtension.of(context).lightGreyHover, width: 20, height: 30, onPressed: () => context.read().add(const RowEvent.createRow()), iconPadding: const EdgeInsets.all(3), - icon: svgWidget("home/add"), + icon: svgWidget( + 'home/add', + color: Theme.of(context).colorScheme.tertiary, + ), ); } } @@ -182,11 +187,15 @@ class _MenuButtonState extends State<_MenuButton> { Widget build(BuildContext context) { return FlowyIconButton( tooltipText: LocaleKeys.tooltip_openMenu.tr(), + hoverColor: AFThemeExtension.of(context).lightGreyHover, width: 20, height: 30, onPressed: () => widget.openMenu(), iconPadding: const EdgeInsets.all(3), - icon: svgWidget("editor/details"), + icon: svgWidget( + 'editor/details', + color: Theme.of(context).colorScheme.tertiary, + ), ); } } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/create_sort_list.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/create_sort_list.dart index 531d781aee..6dea5acb43 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/create_sort_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/create_sort_list.dart @@ -5,6 +5,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/layout/sizes.da import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -116,19 +117,16 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate { @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { - return Padding( + return Container( padding: const EdgeInsets.only(top: 4), - child: Container( - color: Theme.of(context).colorScheme.background, - height: fixHeight, - child: FlowyTextField( - hintText: LocaleKeys.grid_settings_sortBy.tr(), - onChanged: (text) { - context - .read() - .add(CreateSortEvent.didReceiveFilterText(text)); - }, - ), + height: fixHeight, + child: FlowyTextField( + hintText: LocaleKeys.grid_settings_sortBy.tr(), + onChanged: (text) { + context + .read() + .add(CreateSortEvent.didReceiveFilterText(text)); + }, ), ); } @@ -157,7 +155,11 @@ class _SortPropertyCell extends StatelessWidget { @override Widget build(BuildContext context) { return FlowyButton( - text: FlowyText.medium(fieldInfo.name), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText.medium( + fieldInfo.name, + color: AFThemeExtension.of(context).textColor, + ), onTap: () => onTap(fieldInfo), leftIcon: svgWidget( fieldInfo.fieldType.iconName(), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_choice_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_choice_button.dart index 29e705f9d0..40afc7019f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_choice_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_choice_button.dart @@ -37,7 +37,10 @@ class SortChoiceButton extends StatelessWidget { return FlowyButton( decoration: decoration, useIntrinsicWidth: true, - text: FlowyText(text), + text: FlowyText( + text, + color: AFThemeExtension.of(context).textColor, + ), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), radius: BorderRadius.all(radius), leftIcon: leftIcon, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart index 8789a6829a..9895c08c43 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_editor.dart @@ -182,13 +182,11 @@ class _AddSortButtonState extends State<_AddSortButton> { child: SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( + hoverColor: AFThemeExtension.of(context).greyHover, disable: getCreatableSorts(widget.fieldController.fieldInfos).isEmpty, text: FlowyText.medium(LocaleKeys.grid_sort_addSort.tr()), onTap: () => _popoverController.show(), - leftIcon: svgWidget( - "home/add", - color: Theme.of(context).iconTheme.color, - ), + leftIcon: const FlowySvg(name: 'home/add'), ), ), popupBuilder: (BuildContext context) { @@ -220,10 +218,7 @@ class _DeleteSortButton extends StatelessWidget { .read() .add(const SortEditorEvent.deleteAllSorts()); }, - leftIcon: svgWidget( - "editor/delete", - color: Theme.of(context).iconTheme.color, - ), + leftIcon: const FlowySvg(name: 'editor/delete'), ), ); }, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart index 81a07844cf..c255e36525 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/sort/sort_menu.dart @@ -55,7 +55,10 @@ class SortChoiceChip extends StatelessWidget { Widget build(BuildContext context) { final arrow = Transform.rotate( angle: -math.pi / 2, - child: svgWidget("home/arrow_left"), + child: svgWidget( + "home/arrow_left", + color: Theme.of(context).iconTheme.color, + ), ); final text = LocaleKeys.grid_settings_sort.tr(); diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart index 38dfc83818..8d32ff981f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart @@ -25,7 +25,7 @@ class _FilterButtonState extends State { return BlocBuilder( builder: (context, state) { final textColor = state.filters.isEmpty - ? null + ? AFThemeExtension.of(context).textColor : Theme.of(context).colorScheme.primary; return _wrapPopover( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart index 0b6f67a6f3..0dc81d26b6 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_property.dart @@ -5,6 +5,7 @@ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -115,7 +116,11 @@ class _GridPropertyCellState extends State<_GridPropertyCell> { triggerActions: PopoverTriggerFlags.none, margin: EdgeInsets.zero, child: FlowyButton( - text: FlowyText.medium(widget.fieldInfo.name), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText.medium( + widget.fieldInfo.name, + color: AFThemeExtension.of(context).textColor, + ), leftIcon: svgWidget( widget.fieldInfo.fieldType.iconName(), color: Theme.of(context).iconTheme.color, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting.dart index e41d75ce69..875f752106 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/grid_setting.dart @@ -2,6 +2,7 @@ import 'package:appflowy/plugins/database_view/application/field/field_controlle import 'package:appflowy/plugins/database_view/application/setting/setting_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; @@ -71,9 +72,12 @@ class _SettingItem extends StatelessWidget { return SizedBox( height: GridSize.popoverItemHeight, child: FlowyButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, text: FlowyText.medium( action.title(), - color: action.enable() ? null : Theme.of(context).disabledColor, + color: action.enable() + ? AFThemeExtension.of(context).textColor + : Theme.of(context).disabledColor, ), onTap: () => onAction(action), leftIcon: svgWidget( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/setting_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/setting_button.dart index 93baeed518..b9b63eb5fb 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/setting_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/setting_button.dart @@ -52,6 +52,7 @@ class _SettingButtonState extends State { triggerActions: PopoverTriggerFlags.none, child: FlowyTextButton( LocaleKeys.settings_title.tr(), + fontColor: AFThemeExtension.of(context).textColor, fillColor: Colors.transparent, hoverColor: AFThemeExtension.of(context).lightGreyHover, padding: GridSize.typeOptionContentInsets, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart index 7a38b73d08..debb83493a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/widgets/toolbar/sort_button.dart @@ -24,7 +24,7 @@ class _SortButtonState extends State { return BlocBuilder( builder: (context, state) { final textColor = state.sortInfos.isEmpty - ? null + ? AFThemeExtension.of(context).textColor : Theme.of(context).colorScheme.primary; return wrapPopover( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_cell_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_cell_editor.dart index 891e3e7c05..e8ee95c406 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_cell_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_cell_editor.dart @@ -1,6 +1,7 @@ import 'package:appflowy/plugins/database_view/application/cell/cell_controller_builder.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -116,7 +117,11 @@ class _ChecklistOptionCellState extends State<_ChecklistOptionCell> { children: [ Expanded( child: FlowyButton( - text: FlowyText(widget.option.data.name), + hoverColor: AFThemeExtension.of(context).lightGreyHover, + text: FlowyText( + widget.option.data.name, + color: AFThemeExtension.of(context).textColor, + ), leftIcon: icon, onTap: () => context .read() @@ -132,6 +137,7 @@ class _ChecklistOptionCellState extends State<_ChecklistOptionCell> { Widget _disclosureButton() { return FlowyIconButton( + hoverColor: AFThemeExtension.of(context).lightGreyHover, width: 20, onPressed: () => _popoverController.show(), iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart index b8599f60c4..f997eb7768 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart @@ -20,7 +20,7 @@ class ChecklistProgressBar extends StatelessWidget { percent: percent, padding: EdgeInsets.zero, progressColor: Theme.of(context).colorScheme.primary, - backgroundColor: AFThemeExtension.of(context).tint9, + backgroundColor: AFThemeExtension.of(context).progressBarBGcolor, barRadius: const Radius.circular(5), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart index 3b338d5355..ae4de41db5 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart @@ -385,10 +385,7 @@ class _DateTypeOptionButton extends StatelessWidget { child: FlowyButton( text: FlowyText.medium(title), margin: GridSize.typeOptionContentInsets, - rightIcon: svgWidget( - "grid/more", - color: Theme.of(context).iconTheme.color, - ), + rightIcon: const FlowySvg(name: 'grid/more'), ), ), ), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart index 29b0d9b96e..7b8041cb3d 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart @@ -106,7 +106,11 @@ class SelectOptionTag extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Flexible( - child: FlowyText.medium(name, overflow: TextOverflow.ellipsis), + child: FlowyText.medium( + name, + overflow: TextOverflow.ellipsis, + color: Theme.of(context).colorScheme.onSurface, + ), ), if (onRemove != null) FlowyIconButton( @@ -116,7 +120,7 @@ class SelectOptionTag extends StatelessWidget { hoverColor: Colors.transparent, icon: svgWidget( 'home/close', - color: Theme.of(context).iconTheme.color, + color: Theme.of(context).colorScheme.onSurface, ), ), ], @@ -139,6 +143,9 @@ class SelectOptionTagCell extends StatelessWidget { @override Widget build(BuildContext context) { return FlowyHover( + style: HoverStyle( + hoverColor: AFThemeExtension.of(context).lightGreyHover, + ), child: InkWell( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart index e3ba894373..1d8ca404d8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart @@ -210,7 +210,7 @@ class _CreateOptionCell extends StatelessWidget { alignment: Alignment.centerLeft, child: SelectOptionTag( name: name, - color: AFThemeExtension.of(context).lightGreyHover, + color: AFThemeExtension.of(context).greyHover, onSelected: () => context .read() .add(SelectOptionEditorEvent.newOption(name)), diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart index 30cd9ae807..470fd31b26 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/widgets/row/cells/url_cell/url_cell.dart @@ -5,6 +5,7 @@ import 'package:appflowy/workspace/presentation/home/toast.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -211,10 +212,8 @@ class _EditURLAccessoryState extends State<_EditURLAccessory> controller: _popoverController, direction: PopoverDirection.bottomWithLeftAligned, offset: const Offset(0, 8), - child: svgWidget( - "editor/edit", - color: Theme.of(context).iconTheme.color, - ), + child: svgWidget("editor/edit", + color: AFThemeExtension.of(context).textColor), popupBuilder: (BuildContext popoverContext) { return URLEditorPopover( cellController: diff --git a/frontend/appflowy_flutter/lib/workspace/application/appearance.dart b/frontend/appflowy_flutter/lib/workspace/application/appearance.dart index b340b8612e..d7dbc10377 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/appearance.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/appearance.dart @@ -226,6 +226,7 @@ class AppearanceSettingsState with _$AppearanceSettingsState { fontColor: theme.surface, ), ), + scaffoldBackgroundColor: theme.surface, scrollbarTheme: ScrollbarThemeData( thumbColor: MaterialStateProperty.all(theme.shader3), thickness: MaterialStateProperty.resolveWith((states) { @@ -292,10 +293,12 @@ class AppearanceSettingsState with _$AppearanceSettingsState { tint7: theme.tint7, tint8: theme.tint8, tint9: theme.tint9, + textColor: theme.text, greyHover: theme.hoverBG1, greySelect: theme.bg3, - lightGreyHover: theme.shader6, + lightGreyHover: theme.hoverBG3, toggleOffFill: theme.shader5, + progressBarBGcolor: theme.progressBarBGcolor, code: _getFontStyle( fontFamily: monospaceFontFamily, fontColor: theme.shader3, @@ -309,7 +312,7 @@ class AppearanceSettingsState with _$AppearanceSettingsState { fontFamily: fontFamily, fontSize: FontSizes.s11, fontWeight: FontWeight.w400, - fontColor: theme.shader3, + fontColor: theme.hint, ), ) ], diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/create_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/create_button.dart index be6fddf37a..96e00499ee 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/create_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/app/create_button.dart @@ -20,12 +20,15 @@ class NewAppButton extends StatelessWidget { hoverColor: Colors.transparent, fontColor: Theme.of(context).colorScheme.tertiary, onPressed: () async => await _showCreateAppDialog(context), - heading: Theme.of(context).brightness == Brightness.light - ? svgWidget("home/new_app", size: const Size(16, 16)) - : svgWidget( - "home/new_app_dark", - size: const Size(16, 16), - ), + heading: Container( + width: 16, + height: 16, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context).colorScheme.surface, + ), + child: svgWidget("home/new_app"), + ), padding: EdgeInsets.symmetric(horizontal: Insets.l, vertical: 20), ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart index 81149f9f34..acbec83aa2 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart @@ -59,7 +59,7 @@ class ThemeSetting extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - _themeItemButton(context, BuiltInTheme.light), + _themeItemButton(context, BuiltInTheme.defaultTheme), _themeItemButton(context, BuiltInTheme.dandelion), _themeItemButton(context, BuiltInTheme.lavender), ], diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart index 681bd58cf3..88b3395e57 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart @@ -119,7 +119,7 @@ class _CreateFlowyAlertDialog extends State { FlowyText.medium( widget.title, fontSize: FontSizes.s16, - color: Theme.of(context).disabledColor, + color: Theme.of(context).colorScheme.tertiary, ), ], if (widget.confirm != null) ...[ diff --git a/frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/extensions/theme_extension.dart b/frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/extensions/theme_extension.dart index 11b5f23786..a41bac6a26 100644 --- a/frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/extensions/theme_extension.dart +++ b/frontend/appflowy_flutter/packages/appflowy_editor_plugins/lib/src/extensions/theme_extension.dart @@ -9,7 +9,7 @@ extension FlowyTintExtension on FlowyTint { ThemeMode? themeMode, String? theme, }) { - if (themeMode == ThemeMode.light && theme == BuiltInTheme.light) { + if (themeMode == ThemeMode.light && theme == BuiltInTheme.defaultTheme) { switch (this) { case FlowyTint.tint1: return l10n.lightLightTint1; diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart index b109dbad8d..704bd9337d 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/colorscheme.dart @@ -1,9 +1,9 @@ -import 'package:flowy_infra/colorscheme/lavender.dart'; import 'package:flutter/material.dart'; import 'package:flowy_infra/theme.dart'; import 'default_colorscheme.dart'; import 'dandelion.dart'; +import 'lavender.dart'; /// A map of all the built-in themes. /// @@ -11,7 +11,7 @@ import 'dandelion.dart'; /// the first is for light mode, and the second is for dark mode. const Map> themeMap = { - BuiltInTheme.light: [ + BuiltInTheme.defaultTheme: [ DefaultColorScheme.light(), DefaultColorScheme.dark(), ], @@ -69,9 +69,11 @@ abstract class FlowyColorScheme { final Color hoverBG1; //action item hover effect final Color hoverBG2; + final Color hoverBG3; //the text color when it is hovered final Color hoverFG; final Color questionBubbleBG; + final Color progressBarBGcolor; const FlowyColorScheme({ required this.surface, @@ -114,8 +116,10 @@ abstract class FlowyColorScheme { required this.onPrimary, required this.hoverBG1, required this.hoverBG2, + required this.hoverBG3, required this.hoverFG, required this.questionBubbleBG, + required this.progressBarBGcolor, }); factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) { diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart index 00655eef21..c5ec13a48f 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/dandelion.dart @@ -12,6 +12,7 @@ const _lightShader1 = Color(0xff333333); const _lightShader3 = Color(0xff828282); const _lightShader6 = Color(0xfff2f2f2); const _lightMain1 = Color(0xffe21f74); +const _lightTint9 = Color(0xffe1fbff); const _darkShader1 = Color(0xff131720); const _darkShader2 = Color(0xff1A202C); @@ -48,7 +49,7 @@ class DandelionColorScheme extends FlowyColorScheme { tint6: const Color(0xfff5ffdc), tint7: const Color(0xffddffd6), tint8: const Color(0xffdefff1), - tint9: const Color(0xffe1fbff), + tint9: _lightTint9, main1: _lightMain1, main2: const Color.fromARGB(255, 224, 25, 111), shadow: _black, @@ -63,8 +64,10 @@ class DandelionColorScheme extends FlowyColorScheme { onPrimary: _white, hoverBG1: _lightBg2, hoverBG2: _lightHover, + hoverBG3: _lightShader6, hoverFG: _lightShader1, questionBubbleBG: _lightSelector, + progressBarBGcolor: _lightTint9, ); const DandelionColorScheme.dark() @@ -86,15 +89,15 @@ class DandelionColorScheme extends FlowyColorScheme { bg2: _black, bg3: const Color(0xff4f4f4f), bg4: const Color(0xff2c144b), - tint1: const Color(0xffc3adff), - tint2: const Color(0xffffadf9), - tint3: const Color(0xffffadad), - tint4: const Color(0xffffcfad), - tint5: const Color(0xfffffead), - tint6: const Color(0xffe6ffa3), - tint7: const Color(0xffbcffad), - tint8: const Color(0xffadffe2), - tint9: const Color(0xffade4ff), + tint1: const Color(0xff8738F5), + tint2: const Color(0xffE6336E), + tint3: const Color(0xffFF2D9E), + tint4: const Color(0xffE9973E), + tint5: const Color(0xffFBF000), + tint6: const Color(0xffC0F000), + tint7: const Color(0xff15F74E), + tint8: const Color(0xff00F0E2), + tint9: const Color(0xff00BCF0), main1: _darkMain1, main2: const Color.fromARGB(255, 224, 25, 111), shadow: _black, @@ -109,7 +112,9 @@ class DandelionColorScheme extends FlowyColorScheme { onPrimary: _darkShader1, hoverBG1: _darkMain1, hoverBG2: _darkMain1, + hoverBG3: _darkShader3, hoverFG: _darkShader1, questionBubbleBG: _darkShader3, + progressBarBGcolor: _darkShader3, ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart index 590b5c7bc6..a11c453865 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart @@ -12,6 +12,7 @@ const _lightShader1 = Color(0xff333333); const _lightShader3 = Color(0xff828282); const _lightShader6 = Color(0xfff2f2f2); const _lightMain1 = Color(0xff00bcf0); +const _lightTint9 = Color(0xffe1fbff); const _darkShader1 = Color(0xff131720); const _darkShader2 = Color(0xff1A202C); const _darkShader3 = Color(0xff363D49); @@ -47,7 +48,7 @@ class DefaultColorScheme extends FlowyColorScheme { tint6: const Color(0xfff5ffdc), tint7: const Color(0xffddffd6), tint8: const Color(0xffdefff1), - tint9: const Color(0xffe1fbff), + tint9: _lightTint9, main1: _lightMain1, main2: const Color(0xff00b7ea), shadow: _black, @@ -64,6 +65,8 @@ class DefaultColorScheme extends FlowyColorScheme { hoverBG2: _lightHover, hoverFG: _lightShader1, questionBubbleBG: _lightSelector, + hoverBG3: _lightShader6, + progressBarBGcolor: _lightTint9, ); const DefaultColorScheme.dark() @@ -108,7 +111,9 @@ class DefaultColorScheme extends FlowyColorScheme { onPrimary: _darkShader1, hoverBG1: _darkMain1, hoverBG2: _darkMain1, + hoverBG3: _darkShader3, hoverFG: _darkShader1, questionBubbleBG: _darkShader3, + progressBarBGcolor: _darkShader3, ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart index 83f0557349..19f00ae4d4 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/colorscheme/lavender.dart @@ -13,6 +13,7 @@ const _lightShader1 = Color(0xff333333); const _lightShader3 = Color(0xff828282); const _lightShader6 = Color(0xfff2f2f2); const _lightMain1 = Color(0xffA652FB); +const _lightTint9 = Color(0xffe1fbff); const _darkShader1 = Color(0xff131720); const _darkShader2 = Color(0xff1A202C); @@ -49,7 +50,7 @@ class LavenderColorScheme extends FlowyColorScheme { tint6: const Color(0xfff5ffdc), tint7: const Color(0xffddffd6), tint8: const Color(0xffdefff1), - tint9: const Color(0xffe1fbff), + tint9: _lightTint9, main1: _lightMain1, main2: const Color(0xff9327FF), shadow: _black, @@ -64,8 +65,10 @@ class LavenderColorScheme extends FlowyColorScheme { onPrimary: _white, hoverBG1: _lightBg2, hoverBG2: _lightHover, + hoverBG3: _lightShader6, hoverFG: _lightShader1, questionBubbleBG: _lightSelector, + progressBarBGcolor: _lightTint9, ); const LavenderColorScheme.dark() @@ -87,15 +90,15 @@ class LavenderColorScheme extends FlowyColorScheme { bg2: _black, bg3: const Color(0xff4f4f4f), bg4: const Color(0xff2c144b), - tint1: const Color(0xffc3adff), - tint2: const Color(0xffffadf9), - tint3: const Color(0xffffadad), - tint4: const Color(0xffffcfad), - tint5: const Color(0xfffffead), - tint6: const Color(0xffe6ffa3), - tint7: const Color(0xffbcffad), - tint8: const Color(0xffadffe2), - tint9: const Color(0xffade4ff), + tint1: const Color(0xff8738F5), + tint2: const Color(0xffE6336E), + tint3: const Color(0xffFF2D9E), + tint4: const Color(0xffE9973E), + tint5: const Color(0xffFBF000), + tint6: const Color(0xffC0F000), + tint7: const Color(0xff15F74E), + tint8: const Color(0xff00F0E2), + tint9: const Color(0xff00BCF0), main1: _darkMain1, main2: const Color(0xff9327FF), shadow: _black, @@ -110,7 +113,9 @@ class LavenderColorScheme extends FlowyColorScheme { onPrimary: _darkShader1, hoverBG1: _darkMain1, hoverBG2: _darkMain1, + hoverBG3: _darkShader3, hoverFG: _darkShader1, questionBubbleBG: _darkShader3, + progressBarBGcolor: _darkShader3, ); } diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/theme.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/theme.dart index 9b07ccb7c4..1f4f3584e1 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/theme.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/theme.dart @@ -2,9 +2,9 @@ import 'package:flowy_infra/colorscheme/colorscheme.dart'; import 'package:flutter/material.dart'; class BuiltInTheme { - static const String light = 'light'; - static const String dandelion = 'dandelion'; - static const String lavender = 'lavender'; + static const String defaultTheme = 'Default'; + static const String dandelion = 'Dandelion'; + static const String lavender = 'Lavender'; } class AppTheme { diff --git a/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart b/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart index bc72732fef..77d8549fe1 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra/lib/theme_extension.dart @@ -15,10 +15,12 @@ class AFThemeExtension extends ThemeExtension { final Color tint8; final Color tint9; + final Color textColor; final Color greyHover; final Color greySelect; final Color lightGreyHover; final Color toggleOffFill; + final Color progressBarBGcolor; final TextStyle code; final TextStyle callout; @@ -40,9 +42,11 @@ class AFThemeExtension extends ThemeExtension { required this.greySelect, required this.lightGreyHover, required this.toggleOffFill, + required this.textColor, required this.code, required this.callout, required this.caption, + required this.progressBarBGcolor, }); static AFThemeExtension of(BuildContext context) { @@ -62,10 +66,12 @@ class AFThemeExtension extends ThemeExtension { Color? tint7, Color? tint8, Color? tint9, + Color? textColor, Color? greyHover, Color? greySelect, Color? lightGreyHover, Color? toggleOffFill, + Color? progressBarBGcolor, TextStyle? code, TextStyle? callout, TextStyle? caption, @@ -82,10 +88,12 @@ class AFThemeExtension extends ThemeExtension { tint7: tint7 ?? this.tint7, tint8: tint8 ?? this.tint8, tint9: tint9 ?? this.tint9, + textColor: textColor ?? this.textColor, greyHover: greyHover ?? this.greyHover, greySelect: greySelect ?? this.greySelect, lightGreyHover: lightGreyHover ?? this.lightGreyHover, toggleOffFill: toggleOffFill ?? this.toggleOffFill, + progressBarBGcolor: progressBarBGcolor ?? this.progressBarBGcolor, code: code ?? this.code, callout: callout ?? this.callout, caption: caption ?? this.caption, @@ -110,10 +118,13 @@ class AFThemeExtension extends ThemeExtension { tint7: Color.lerp(tint7, other.tint7, t)!, tint8: Color.lerp(tint8, other.tint8, t)!, tint9: Color.lerp(tint9, other.tint9, t)!, + textColor: Color.lerp(textColor, other.textColor, t)!, greyHover: Color.lerp(greyHover, other.greyHover, t)!, greySelect: Color.lerp(greySelect, other.greySelect, t)!, lightGreyHover: Color.lerp(lightGreyHover, other.lightGreyHover, t)!, toggleOffFill: Color.lerp(toggleOffFill, other.toggleOffFill, t)!, + progressBarBGcolor: + Color.lerp(progressBarBGcolor, other.progressBarBGcolor, t)!, code: other.code, callout: other.callout, caption: other.caption, diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart index 2eb27f12a7..61cc750478 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart @@ -138,7 +138,7 @@ class ScrollbarState extends State { // Handle color var handleColor = widget.handleColor ?? (Theme.of(context).brightness == Brightness.dark - ? AFThemeExtension.of(context).greyHover.withOpacity(.2) + ? AFThemeExtension.of(context).lightGreyHover : AFThemeExtension.of(context).greyHover); // Track color var trackColor = widget.trackColor ?? From fcd85889afd377221bdb966d4c20f14b183a7c2e Mon Sep 17 00:00:00 2001 From: Alex Wallen Date: Mon, 3 Apr 2023 18:51:47 -1000 Subject: [PATCH 6/7] feat: add PR template (#2151) --- .../pull_request_template.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_template.md diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000000..57ebf4205f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,27 @@ + + + + +### Feature Preview + + + +--- + + + +#### PR Checklist + +- [ ] My code adheres to the [AppFlowy Style Guide](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/software-contributions/submitting-code/style-guides) +- [ ] I've listed at least one issue that this PR fixes in the description above. +- [ ] I've added a test(s) to validate changes in this PR, or this PR only contains semantic changes. +- [ ] All existing tests are passing. From ddd3fbb17855847004cf2ecde963ef0094af6693 Mon Sep 17 00:00:00 2001 From: "Nathan.fooo" <86001920+appflowy@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:08:50 +0800 Subject: [PATCH 7/7] fix: tauri folder display (#2176) * fix: tauri folder display * refactor: rename layout type --- .gitignore | 2 + .../application/database_controller.dart | 4 +- .../application/database_view_service.dart | 2 +- .../board/application/board_bloc.dart | 2 +- .../plugins/database_view/board/board.dart | 2 +- .../calendar/application/calendar_bloc.dart | 2 +- .../database_view/calendar/calendar.dart | 2 +- .../lib/plugins/database_view/grid/grid.dart | 2 +- .../grid/presentation/grid_page.dart | 2 +- .../lib/plugins/document/document.dart | 2 +- .../plugins/base/insert_page_command.dart | 4 +- .../plugins/base/link_to_page_widget.dart | 12 +- .../plugins/board/board_menu_item.dart | 2 +- .../plugins/board/board_view_menu_item.dart | 6 +- .../plugins/grid/grid_menu_item.dart | 2 +- .../plugins/grid/grid_view_menu_item.dart | 6 +- .../lib/startup/plugin/plugin.dart | 2 +- .../application/app/app_service.dart | 4 +- .../workspace/application/view/view_ext.dart | 8 +- .../workspace/workspace_service.dart | 4 +- .../presentation/home/home_screen.dart | 2 +- .../test/bloc_test/board_test/util.dart | 2 +- .../grid_test/filter/create_filter_test.dart | 8 +- .../grid_test/filter/filter_util.dart | 2 +- .../bloc_test/grid_test/grid_bloc_test.dart | 4 +- .../test/bloc_test/grid_test/util.dart | 2 +- .../bloc_test/home_test/create_page_test.dart | 8 +- frontend/appflowy_tauri/src-tauri/Cargo.lock | 8 +- frontend/appflowy_tauri/src-tauri/Cargo.toml | 11 +- .../_shared/database-hooks/useDatabase.ts | 6 +- .../appflowy_app/components/board/Board.tsx | 7 +- .../NavigationPanel/FolderItem.hooks.ts | 16 +- .../NavigationPanel/NavigationPanel.hooks.ts | 8 +- .../layout/NavigationPanel/PageItem.tsx | 8 +- .../components/tests/DatabaseTestHelper.ts | 4 +- .../components/tests/DocumentTestHelper.ts | 4 +- .../components/tests/TestGrid.tsx | 40 ++-- .../components/tests/TestGroup.tsx | 12 +- .../stores/effects/folder/app/app_bd_svc.ts | 4 +- .../stores/effects/folder/app/app_observer.ts | 2 +- .../folder/workspace/workspace_bd_svc.ts | 4 +- .../folder/workspace/workspace_observer.ts | 10 +- .../stores/reducers/pages/slice.ts | 4 +- frontend/rust-lib/.gitignore | 3 +- frontend/rust-lib/Cargo.lock | 8 +- frontend/rust-lib/Cargo.toml | 12 +- frontend/rust-lib/flowy-core/Cargo.toml | 4 +- .../src/deps_resolve/folder2_deps.rs | 23 +-- frontend/rust-lib/flowy-core/src/lib.rs | 4 +- .../src/entities/database_entities.rs | 4 +- .../src/entities/setting_entities.rs | 28 +-- .../rust-lib/flowy-database/src/manager.rs | 8 +- .../src/services/persistence/migration/mod.rs | 4 +- .../src/services/setting/setting_builder.rs | 4 +- .../tests/database/database_editor.rs | 14 +- .../tests/database/filter_test/script.rs | 2 +- .../flowy-folder2/src/entities/app.rs | 183 ------------------ .../flowy-folder2/src/entities/mod.rs | 2 - .../entities/parser/app/app_color_style.rs | 13 -- .../src/entities/parser/app/app_desc.rs | 20 -- .../src/entities/parser/app/app_id.rs | 20 -- .../src/entities/parser/app/app_name.rs | 20 -- .../src/entities/parser/app/mod.rs | 9 - .../flowy-folder2/src/entities/parser/mod.rs | 2 +- .../flowy-folder2/src/entities/view.rs | 50 ++--- .../flowy-folder2/src/entities/workspace.rs | 12 ++ .../flowy-folder2/src/event_handler.rs | 7 +- .../rust-lib/flowy-folder2/src/manager.rs | 77 +++++--- .../rust-lib/flowy-folder2/src/test_helper.rs | 8 +- .../rust-lib/flowy-folder2/src/view_ext.rs | 14 +- frontend/rust-lib/flowy-test/src/helper.rs | 17 +- 71 files changed, 288 insertions(+), 532 deletions(-) delete mode 100644 frontend/rust-lib/flowy-folder2/src/entities/app.rs delete mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs delete mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs delete mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs delete mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs delete mode 100644 frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs diff --git a/.gitignore b/.gitignore index 5eeae980bc..bce47974c4 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,5 @@ pubspec.lock .githooks/gitlint .githooks/gitlint.exe .fvm/ + +**/AppFlowy-Collab/ diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart index dfff5279a2..86e6da42be 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_controller.dart @@ -79,7 +79,7 @@ class DatabaseController { final DatabaseViewBackendService _databaseViewBackendSvc; final FieldController fieldController; late DatabaseViewCache _viewCache; - final LayoutTypePB layoutType; + final DatabaseLayoutPB layoutType; // Callbacks DatabaseCallbacks? _databaseCallbacks; @@ -110,7 +110,7 @@ class DatabaseController { _listenOnFieldsChanged(); _listenOnGroupChanged(); _listenOnLayoutChanged(); - if (layoutType == LayoutTypePB.Calendar) { + if (layoutType == DatabaseLayoutPB.Calendar) { _listenOnCalendarLayoutChanged(); } } diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart index 44896c0883..bc6dd6e699 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/application/database_view_service.dart @@ -86,7 +86,7 @@ class DatabaseViewBackendService { } Future> getLayoutSetting( - LayoutTypePB layoutType) { + DatabaseLayoutPB layoutType) { final payload = DatabaseLayoutIdPB.create() ..viewId = viewId ..layout = layoutType; diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart index d91cd68558..6acfbfc650 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/application/board_bloc.dart @@ -30,7 +30,7 @@ class BoardBloc extends Bloc { BoardBloc({required ViewPB view}) : _databaseController = DatabaseController( view: view, - layoutType: LayoutTypePB.Board, + layoutType: DatabaseLayoutPB.Board, ), super(BoardState.initial(view.id)) { boardController = AppFlowyBoardController( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart b/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart index c6d2922cb2..15adee1187 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/board/board.dart @@ -29,7 +29,7 @@ class BoardPluginBuilder implements PluginBuilder { PluginType get pluginType => PluginType.board; @override - ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Board; + ViewLayoutPB? get layoutType => ViewLayoutPB.Board; } class BoardPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart index 147e7531cc..db5150d8d4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/application/calendar_bloc.dart @@ -28,7 +28,7 @@ class CalendarBloc extends Bloc { CalendarBloc({required ViewPB view}) : _databaseController = DatabaseController( view: view, - layoutType: LayoutTypePB.Calendar, + layoutType: DatabaseLayoutPB.Calendar, ), super(CalendarState.initial()) { on( diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart index 9e29fc8d06..558db1419a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/calendar/calendar.dart @@ -29,7 +29,7 @@ class CalendarPluginBuilder extends PluginBuilder { PluginType get pluginType => PluginType.calendar; @override - ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Calendar; + ViewLayoutPB? get layoutType => ViewLayoutPB.Calendar; } class CalendarPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart index 213e74ebe2..283eca5701 100644 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/grid.dart @@ -29,7 +29,7 @@ class GridPluginBuilder implements PluginBuilder { PluginType get pluginType => PluginType.grid; @override - ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Grid; + ViewLayoutPB? get layoutType => ViewLayoutPB.Grid; } class GridPluginConfig implements PluginConfig { diff --git a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart index 2971542529..2db3051642 100755 --- a/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database_view/grid/presentation/grid_page.dart @@ -38,7 +38,7 @@ class GridPage extends StatefulWidget { Key? key, }) : databaseController = DatabaseController( view: view, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, ), super(key: key); diff --git a/frontend/appflowy_flutter/lib/plugins/document/document.dart b/frontend/appflowy_flutter/lib/plugins/document/document.dart index 1a61742870..904dfd527f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/document.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/document.dart @@ -34,7 +34,7 @@ class DocumentPluginBuilder extends PluginBuilder { PluginType get pluginType => PluginType.editor; @override - ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Document; + ViewLayoutPB? get layoutType => ViewLayoutPB.Document; } class DocumentPlugin extends Plugin { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart index cb286d69ae..fae8652fad 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/insert_page_command.dart @@ -30,9 +30,9 @@ extension InsertPage on EditorState { String _convertPageType(ViewPB viewPB) { switch (viewPB.layout) { - case ViewLayoutTypePB.Grid: + case ViewLayoutPB.Grid: return kGridType; - case ViewLayoutTypePB.Board: + case ViewLayoutPB.Board: return kBoardType; default: throw Exception('Unknown layout type'); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart index 4a5c879fbf..bf7670dd1f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/base/link_to_page_widget.dart @@ -17,7 +17,7 @@ void showLinkToPageMenu( EditorState editorState, SelectionMenuService menuService, BuildContext context, - ViewLayoutTypePB pageType, + ViewLayoutPB pageType, ) { final alignment = menuService.alignment; final offset = menuService.offset; @@ -27,10 +27,10 @@ void showLinkToPageMenu( String hintText = ''; switch (pageType) { - case ViewLayoutTypePB.Grid: + case ViewLayoutPB.Grid: hintText = LocaleKeys.document_slashMenu_grid_selectAGridToLinkTo.tr(); break; - case ViewLayoutTypePB.Board: + case ViewLayoutPB.Board: hintText = LocaleKeys.document_slashMenu_board_selectABoardToLinkTo.tr(); break; default: @@ -82,7 +82,7 @@ class LinkToPageMenu extends StatefulWidget { }); final EditorState editorState; - final ViewLayoutTypePB layoutType; + final ViewLayoutPB layoutType; final String hintText; final void Function(ViewPB view, ViewPB childView) onSelected; @@ -174,9 +174,9 @@ class _LinkToPageMenuState extends State { String _iconName(ViewPB viewPB) { switch (viewPB.layout) { - case ViewLayoutTypePB.Grid: + case ViewLayoutPB.Grid: return 'editor/grid'; - case ViewLayoutTypePB.Board: + case ViewLayoutPB.Board: return 'editor/board'; default: throw Exception('Unknown layout type'); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart index 90bd0d68ec..8390f9201f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_menu_item.dart @@ -24,7 +24,7 @@ SelectionMenuItem boardMenuItem = SelectionMenuItem( editorState, menuService, context, - ViewLayoutTypePB.Board, + ViewLayoutPB.Board, ); }, ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart index 40f3c9ce86..56c55ba1bd 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/board/board_view_menu_item.dart @@ -23,17 +23,17 @@ SelectionMenuItem boardViewMenuItem(DocumentBloc documentBloc) => // TODO(a-wallen): Translate keywords. keywords: ['board', 'kanban'], handler: (editorState, menuService, context) async { - if (!documentBloc.view.hasAppId()) { + if (!documentBloc.view.hasParentViewId()) { return; } - final appId = documentBloc.view.appId; + final appId = documentBloc.view.parentViewId; final service = AppBackendService(); final result = (await service.createView( appId: appId, name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), - layoutType: ViewLayoutTypePB.Board, + layoutType: ViewLayoutPB.Board, )) .getLeftOrNull(); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart index aaf976274e..09806b4eb0 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_menu_item.dart @@ -23,7 +23,7 @@ SelectionMenuItem gridMenuItem = SelectionMenuItem( editorState, menuService, context, - ViewLayoutTypePB.Grid, + ViewLayoutPB.Grid, ); }, ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart index a3fa5fd8af..96cc8861cb 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/plugins/grid/grid_view_menu_item.dart @@ -22,17 +22,17 @@ SelectionMenuItem gridViewMenuItem(DocumentBloc documentBloc) => }, keywords: ['grid'], handler: (editorState, menuService, context) async { - if (!documentBloc.view.hasAppId()) { + if (!documentBloc.view.hasParentViewId()) { return; } - final appId = documentBloc.view.appId; + final appId = documentBloc.view.parentViewId; final service = AppBackendService(); final result = (await service.createView( appId: appId, name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), - layoutType: ViewLayoutTypePB.Grid, + layoutType: ViewLayoutPB.Grid, )) .getLeftOrNull(); diff --git a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart index 87b0ef7c4b..f6d6cad9fa 100644 --- a/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart +++ b/frontend/appflowy_flutter/lib/startup/plugin/plugin.dart @@ -52,7 +52,7 @@ abstract class PluginBuilder { PluginType get pluginType; - ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Document; + ViewLayoutPB? get layoutType => ViewLayoutPB.Document; } abstract class PluginConfig { diff --git a/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart b/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart index 110c906afb..5cc0e0439c 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/app/app_service.dart @@ -12,7 +12,7 @@ class AppBackendService { required String appId, required String name, String? desc, - required ViewLayoutTypePB layoutType, + required ViewLayoutPB layoutType, /// The initial data should be the JSON of the document. /// Currently, only support create document with initial data. @@ -90,7 +90,7 @@ class AppBackendService { } Future>>> fetchViews( - ViewLayoutTypePB layoutType) async { + ViewLayoutPB layoutType) async { final result = >>[]; return FolderEventReadCurrentWorkspace().send().then((value) async { final workspaces = value.getLeftOrNull(); 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 29173d7f0f..069cc8e07f 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -42,13 +42,13 @@ extension ViewExtension on ViewPB { PluginType get pluginType { switch (layout) { - case ViewLayoutTypePB.Board: + case ViewLayoutPB.Board: return PluginType.board; - case ViewLayoutTypePB.Calendar: + case ViewLayoutPB.Calendar: return PluginType.calendar; - case ViewLayoutTypePB.Document: + case ViewLayoutPB.Document: return PluginType.editor; - case ViewLayoutTypePB.Grid: + case ViewLayoutPB.Grid: return PluginType.grid; } diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart index 533b839fc6..a3e075f84e 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart @@ -9,7 +9,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart' CreateViewPayloadPB, MoveFolderItemPayloadPB, MoveFolderItemType, - ViewLayoutTypePB, + ViewLayoutPB, ViewPB; import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; @@ -26,7 +26,7 @@ class WorkspaceService { ..belongToId = workspaceId ..name = name ..desc = desc ?? "" - ..layout = ViewLayoutTypePB.Document; + ..layout = ViewLayoutPB.Document; return FolderEventCreateView(payload).send(); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart index 02dce780a9..b35da5cf9a 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_screen.dart @@ -261,7 +261,7 @@ class HomeScreenStackAdaptor extends HomeStackDelegate { @override void didDeleteStackWidget(ViewPB view, int? index) { final homeService = HomeService(); - homeService.readApp(appId: view.appId).then((result) { + homeService.readApp(appId: view.parentViewId).then((result) { result.fold( (parentView) { final List views = parentView.belongings; 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 3ffe8cbf5b..da0722bb04 100644 --- a/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/board_test/util.dart @@ -43,7 +43,7 @@ class AppFlowyBoardTest { view, DatabaseController( view: view, - layoutType: LayoutTypePB.Board, + layoutType: DatabaseLayoutPB.Board, ), ); final result = await context._boardDataController.open(); diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/create_filter_test.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/create_filter_test.dart index f6342904c2..cff1390ef2 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/create_filter_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/create_filter_test.dart @@ -53,7 +53,7 @@ void main() { final service = FilterBackendService(viewId: context.gridView.id); final gridController = DatabaseController( view: context.gridView, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, ); final gridBloc = GridBloc( view: context.gridView, @@ -77,7 +77,7 @@ void main() { final service = FilterBackendService(viewId: context.gridView.id); final gridController = DatabaseController( view: context.gridView, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, ); final gridBloc = GridBloc( view: context.gridView, @@ -121,7 +121,7 @@ void main() { final service = FilterBackendService(viewId: context.gridView.id); final gridController = DatabaseController( view: context.gridView, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, ); final gridBloc = GridBloc( view: context.gridView, @@ -143,7 +143,7 @@ void main() { final service = FilterBackendService(viewId: context.gridView.id); final gridController = DatabaseController( view: context.gridView, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, ); final gridBloc = GridBloc( view: context.gridView, diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart index b7b409f0e5..2d7d9babef 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/filter/filter_util.dart @@ -21,7 +21,7 @@ Future createTestFilterGrid(AppFlowyGridTest gridTest) async { view, DatabaseController( view: view, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, )); final result = await context.gridController.open(); diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/grid_bloc_test.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/grid_bloc_test.dart index a2ccbbd164..0129955344 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/grid_bloc_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/grid_bloc_test.dart @@ -23,7 +23,7 @@ void main() { view: context.gridView, databaseController: DatabaseController( view: context.gridView, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, )) ..add(const GridEvent.initial()), act: (bloc) => bloc.add(const GridEvent.createRow()), @@ -39,7 +39,7 @@ void main() { view: context.gridView, databaseController: DatabaseController( view: context.gridView, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, )) ..add(const GridEvent.initial()), act: (bloc) async { diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart index 32a1c4f1ce..79d0736ffd 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/util.dart @@ -178,7 +178,7 @@ class AppFlowyGridTest { view, DatabaseController( view: view, - layoutType: LayoutTypePB.Grid, + layoutType: DatabaseLayoutPB.Grid, )); final result = await context.gridController.open(); result.fold((l) => null, (r) => throw Exception(r)); diff --git a/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart b/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart index f0862643ce..98a640b6e5 100644 --- a/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/home_test/create_page_test.dart @@ -23,7 +23,7 @@ void main() { assert(bloc.state.views.length == 1); assert(bloc.state.views.last.name == "Test document"); - assert(bloc.state.views.last.layout == ViewLayoutTypePB.Document); + assert(bloc.state.views.last.layout == ViewLayoutPB.Document); }); test('create a grid', () async { @@ -36,7 +36,7 @@ void main() { assert(bloc.state.views.length == 1); assert(bloc.state.views.last.name == "Test grid"); - assert(bloc.state.views.last.layout == ViewLayoutTypePB.Grid); + assert(bloc.state.views.last.layout == ViewLayoutPB.Grid); }); test('create a kanban', () async { @@ -49,7 +49,7 @@ void main() { assert(bloc.state.views.length == 1); assert(bloc.state.views.last.name == "Test board"); - assert(bloc.state.views.last.layout == ViewLayoutTypePB.Board); + assert(bloc.state.views.last.layout == ViewLayoutPB.Board); }); test('create a calendar', () async { @@ -62,6 +62,6 @@ void main() { assert(bloc.state.views.length == 1); assert(bloc.state.views.last.name == "Test calendar"); - assert(bloc.state.views.last.layout == ViewLayoutTypePB.Calendar); + assert(bloc.state.views.last.layout == ViewLayoutPB.Calendar); }); } diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 4d56fe6426..93a06be85a 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -564,7 +564,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#9b3f895bb6f8e92830acd90cfb68b69aece83095" dependencies = [ "anyhow", "bytes", @@ -582,7 +582,7 @@ dependencies = [ [[package]] name = "collab-derive" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#9b3f895bb6f8e92830acd90cfb68b69aece83095" dependencies = [ "proc-macro2", "quote", @@ -594,7 +594,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#9b3f895bb6f8e92830acd90cfb68b69aece83095" dependencies = [ "anyhow", "collab", @@ -612,7 +612,7 @@ dependencies = [ [[package]] name = "collab-persistence" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#9b3f895bb6f8e92830acd90cfb68b69aece83095" dependencies = [ "bincode", "chrono", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index b99aa67948..085164b8fc 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -33,8 +33,13 @@ default = ["custom-protocol"] custom-protocol = ["tauri/custom-protocol"] [patch.crates-io] -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } -collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab" } +collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab" } +#collab = { path = "../../AppFlowy-Collab/collab" } +#collab-folder = { path = "../../AppFlowy-Collab/collab-folder" } +#collab-persistence = { path = "../../AppFlowy-Collab/collab-persistence" } + + diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts index e7187384fa..e39dc29ec0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts @@ -5,11 +5,11 @@ import { useAppDispatch } from '$app/stores/store'; import loadField from './loadField'; import { FieldInfo } from '$app/stores/effects/database/field/field_controller'; import { RowInfo } from '$app/stores/effects/database/row/row_cache'; -import { ViewLayoutTypePB } from '@/services/backend'; +import { ViewLayoutPB } from '@/services/backend'; import { DatabaseGroupController } from '$app/stores/effects/database/group/group_controller'; import { OnDragEndResponder } from 'react-beautiful-dnd'; -export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { +export const useDatabase = (viewId: string, type?: ViewLayoutPB) => { const dispatch = useAppDispatch(); const [controller, setController] = useState(); const [rows, setRows] = useState([]); @@ -58,7 +58,7 @@ export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { }); await controller.open(); - if (type === ViewLayoutTypePB.Board) { + if (type === ViewLayoutPB.Board) { const fieldId = await controller.getGroupByFieldId(); setGroupByFieldId(fieldId.unwrap()); setGroups(controller.groups.value); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index 7df79ede9a..b4b00d1796 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -3,17 +3,14 @@ import { SearchInput } from '../_shared/SearchInput'; import { BoardBlock } from './BoardBlock'; import { NewBoardBlock } from './NewBoardBlock'; import { useDatabase } from '../_shared/database-hooks/useDatabase'; -import { ViewLayoutTypePB } from '@/services/backend'; +import { ViewLayoutPB } from '@/services/backend'; import { DragDropContext } from 'react-beautiful-dnd'; import { useState } from 'react'; import { RowInfo } from '$app/stores/effects/database/row/row_cache'; import { EditRow } from '$app/components/_shared/EditRow/EditRow'; export const Board = ({ viewId }: { viewId: string }) => { - const { controller, rows, groups, groupByFieldId, onNewRowClick, onDragEnd } = useDatabase( - viewId, - ViewLayoutTypePB.Board - ); + const { controller, rows, groups, groupByFieldId, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutPB.Board); const [showBoardRow, setShowBoardRow] = useState(false); const [boardRowInfo, setBoardRowInfo] = useState(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts index 1d94beaf92..34850a89c3 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts @@ -2,7 +2,7 @@ import { foldersActions, IFolder } from '../../../stores/reducers/folders/slice' import { useEffect, useState } from 'react'; import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { IPage, pagesActions } from '../../../stores/reducers/pages/slice'; -import { AppPB, ViewLayoutTypePB } from '@/services/backend'; +import { ViewLayoutPB } from '@/services/backend'; import { AppBackendService } from '../../../stores/effects/folder/app/app_bd_svc'; import { WorkspaceBackendService } from '../../../stores/effects/folder/workspace/workspace_bd_svc'; import { useError } from '../../error/Error.hooks'; @@ -42,7 +42,7 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { const views = change.val; const updatedPages: IPage[] = views.items.map((view) => ({ id: view.id, - folderId: view.app_id, + folderId: view.parent_view_id, pageType: view.layout, title: view.name, })); @@ -129,13 +129,13 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { try { const newView = await appBackendService.createView({ name: 'New Document 1', - layoutType: ViewLayoutTypePB.Document, + layoutType: ViewLayoutPB.Document, }); appDispatch( pagesActions.addPage({ folderId: folder.id, - pageType: ViewLayoutTypePB.Document, + pageType: ViewLayoutPB.Document, title: newView.name, id: newView.id, }) @@ -154,7 +154,7 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { try { const newView = await appBackendService.createView({ name: 'New Board 1', - layoutType: ViewLayoutTypePB.Board, + layoutType: ViewLayoutPB.Board, }); setShowPages(true); @@ -162,7 +162,7 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { appDispatch( pagesActions.addPage({ folderId: folder.id, - pageType: ViewLayoutTypePB.Board, + pageType: ViewLayoutPB.Board, title: newView.name, id: newView.id, }) @@ -179,7 +179,7 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { try { const newView = await appBackendService.createView({ name: 'New Grid 1', - layoutType: ViewLayoutTypePB.Grid, + layoutType: ViewLayoutPB.Grid, }); setShowPages(true); @@ -187,7 +187,7 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { appDispatch( pagesActions.addPage({ folderId: folder.id, - pageType: ViewLayoutTypePB.Grid, + pageType: ViewLayoutPB.Grid, title: newView.name, id: newView.id, }) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts index d728c1e838..a3ef4c1752 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts @@ -1,7 +1,7 @@ import { useAppSelector } from '../../../stores/store'; import { useNavigate } from 'react-router-dom'; import { IPage } from '../../../stores/reducers/pages/slice'; -import { ViewLayoutTypePB } from '@/services/backend'; +import { ViewLayoutPB } from '@/services/backend'; import { useState } from 'react'; export const useNavigationPanelHooks = function () { @@ -23,12 +23,12 @@ export const useNavigationPanelHooks = function () { const onPageClick = (page: IPage) => { let pageTypeRoute = (() => { switch (page.pageType) { - case ViewLayoutTypePB.Document: + case ViewLayoutPB.Document: return 'document'; break; - case ViewLayoutTypePB.Grid: + case ViewLayoutPB.Grid: return 'grid'; - case ViewLayoutTypePB.Board: + case ViewLayoutPB.Board: return 'board'; default: return 'document'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx index b1736c1435..e00f37d0f9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx @@ -7,7 +7,7 @@ import { IPage } from '../../../stores/reducers/pages/slice'; import { Button } from '../../_shared/Button'; import { usePageEvents } from './PageItem.hooks'; import { RenamePopup } from './RenamePopup'; -import { ViewLayoutTypePB } from '@/services/backend'; +import { ViewLayoutPB } from '@/services/backend'; import { useEffect, useRef, useState } from 'react'; import { PAGE_ITEM_HEIGHT } from '../../_shared/constants'; @@ -47,9 +47,9 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = > - {page.pageType === ViewLayoutTypePB.Document && } - {page.pageType === ViewLayoutTypePB.Board && } - {page.pageType === ViewLayoutTypePB.Grid && } + {page.pageType === ViewLayoutPB.Document && } + {page.pageType === ViewLayoutPB.Board && } + {page.pageType === ViewLayoutPB.Grid && } {page.title} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts index 548ff6816b..6930e7c0e1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DatabaseTestHelper.ts @@ -1,7 +1,7 @@ import { FieldType, SingleSelectTypeOptionPB, - ViewLayoutTypePB, + ViewLayoutPB, ViewPB, WorkspaceSettingPB, } from '../../../services/backend'; @@ -29,7 +29,7 @@ import { SelectOptionBackendService } from '../../stores/effects/database/cell/s // Create a database view for specific layout type // Do not use it production code. Just for testing -export async function createTestDatabaseView(layout: ViewLayoutTypePB): Promise { +export async function createTestDatabaseView(layout: ViewLayoutPB): Promise { const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap()); const app = workspaceSetting.workspace.views[0]; const appService = new AppBackendService(app.id); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts index 67ababa3b5..4656d06577 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/tests/DocumentTestHelper.ts @@ -1,4 +1,4 @@ -import { ViewLayoutTypePB, WorkspaceSettingPB } from '@/services/backend'; +import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend'; import { FolderEventReadCurrentWorkspace } from '@/services/backend/events/flowy-folder2'; import { AppBackendService } from '$app/stores/effects/folder/app/app_bd_svc'; @@ -6,5 +6,5 @@ export async function createTestDocument() { const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap()); const app = workspaceSetting.workspace.views[0]; const appService = new AppBackendService(app.id); - return await appService.createView({ name: 'New Document', layoutType: ViewLayoutTypePB.Document }); + return await appService.createView({ name: 'New Document', layoutType: ViewLayoutPB.Document }); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx index 1a3925c82c..e44d334861 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGrid.tsx @@ -1,11 +1,5 @@ import React from 'react'; -import { - FieldType, - NumberFormat, - NumberTypeOptionPB, - SelectOptionCellDataPB, - ViewLayoutTypePB, -} from '@/services/backend'; +import { FieldType, NumberFormat, NumberTypeOptionPB, SelectOptionCellDataPB, ViewLayoutPB } from '@/services/backend'; import { Log } from '$app/utils/log'; import { assert, @@ -60,7 +54,7 @@ export const RunAllGridTests = () => { }; async function createBuildInGrid() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); databaseController.subscribe({ onViewChanged: (databasePB) => { @@ -82,7 +76,7 @@ async function createBuildInGrid() { } async function testEditGridCell() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -95,7 +89,7 @@ async function testEditGridCell() { } async function testEditTextCell() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -117,7 +111,7 @@ async function testEditTextCell() { } async function testEditURLCell() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -144,7 +138,7 @@ async function testEditURLCell() { } async function testEditDateCell() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -169,7 +163,7 @@ async function testEditDateCell() { } async function testCheckboxCell() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -195,7 +189,7 @@ async function testCheckboxCell() { } async function testCreateRow() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); await assertNumberOfRows(view.id, 3); @@ -207,7 +201,7 @@ async function testCreateRow() { } async function testDeleteRow() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -226,7 +220,7 @@ async function testDeleteRow() { } async function testCreateOptionInCell() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) { @@ -253,7 +247,7 @@ async function testCreateOptionInCell() { } async function testMoveField() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -271,7 +265,7 @@ async function testMoveField() { } async function testGetSingleSelectFieldData() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -296,7 +290,7 @@ async function testGetSingleSelectFieldData() { } async function testSwitchFromSingleSelectToNumber() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -322,7 +316,7 @@ async function testSwitchFromSingleSelectToNumber() { } async function testSwitchFromMultiSelectToRichText() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -372,7 +366,7 @@ async function testSwitchFromMultiSelectToRichText() { } async function testEditField() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); const fieldInfos = databaseController.fieldController.fieldInfos; @@ -390,7 +384,7 @@ async function testEditField() { } async function testCreateNewField() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); await assertNumberOfFields(view.id, 3); @@ -403,7 +397,7 @@ async function testCreateNewField() { } async function testDeleteField() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const view = await createTestDatabaseView(ViewLayoutPB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx index bbcf7a860c..b612d9ab9c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/tests/TestGroup.tsx @@ -5,7 +5,7 @@ import { createTestDatabaseView, openTestDatabase, } from './DatabaseTestHelper'; -import { FieldType, ViewLayoutTypePB } from '../../../services/backend'; +import { FieldType, ViewLayoutPB } from '../../../services/backend'; import React from 'react'; export const TestAllKanbanTests = () => { @@ -29,7 +29,7 @@ export const TestAllKanbanTests = () => { }; async function createBuildInBoard() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Board); + const view = await createTestDatabaseView(ViewLayoutPB.Board); const databaseController = await openTestDatabase(view.id); databaseController.subscribe({ onGroupByField: (groups) => { @@ -49,7 +49,7 @@ async function createBuildInBoard() { } async function createKanbanBoardRow() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Board); + const view = await createTestDatabaseView(ViewLayoutPB.Board); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -62,7 +62,7 @@ async function createKanbanBoardRow() { } async function moveKanbanBoardRow() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Board); + const view = await createTestDatabaseView(ViewLayoutPB.Board); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -113,7 +113,7 @@ async function moveKanbanBoardRow() { } async function createKanbanBoardColumn() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Board); + const view = await createTestDatabaseView(ViewLayoutPB.Board); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -128,7 +128,7 @@ async function createKanbanBoardColumn() { } async function createColumnInBoard() { - const view = await createTestDatabaseView(ViewLayoutTypePB.Board); + const view = await createTestDatabaseView(ViewLayoutPB.Board); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts index 53cd18680b..57cabe7705 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_bd_svc.ts @@ -4,7 +4,7 @@ import { FolderEventMoveItem, FolderEventReadView, FolderEventUpdateView, - ViewLayoutTypePB, + ViewLayoutPB, } from '@/services/backend/events/flowy-folder2'; import { CreateViewPayloadPB, @@ -29,7 +29,7 @@ export class AppBackendService { createView = async (params: { name: string; desc?: string; - layoutType: ViewLayoutTypePB; + layoutType: ViewLayoutPB; /// The initial data should be the JSON of the document /// For example: {"document":{"type":"editor","children":[]}} initialData?: string; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts index d46ffdef6f..a2c430d92f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts @@ -1,5 +1,5 @@ import { Ok, Result } from 'ts-results'; -import { AppPB, FlowyError, FolderNotification, RepeatedViewPB } from '@/services/backend'; +import { FlowyError, FolderNotification, RepeatedViewPB } from '@/services/backend'; import { ChangeNotifier } from '$app/utils/change_notifier'; import { FolderNotificationObserver } from '../notifications/observer'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts index 8dcfce6930..c92169ade7 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_bd_svc.ts @@ -9,7 +9,7 @@ import { CreateViewPayloadPB, FlowyError, MoveFolderItemPayloadPB, - ViewLayoutTypePB, + ViewLayoutPB, WorkspaceIdPB, } from '@/services/backend'; import assert from 'assert'; @@ -22,7 +22,7 @@ export class WorkspaceBackendService { belong_to_id: this.workspaceId, name: params.name, desc: params.desc || '', - layout: ViewLayoutTypePB.Document, + layout: ViewLayoutPB.Document, }); const result = await FolderEventCreateView(payload); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts index e668fa06a1..7fd72c6622 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts @@ -1,13 +1,5 @@ import { Ok, Result } from 'ts-results'; -import { - AppPB, - FolderNotification, - RepeatedAppPB, - WorkspacePB, - FlowyError, - RepeatedViewPB, - ViewPB, -} from '@/services/backend'; +import { FolderNotification, WorkspacePB, FlowyError, RepeatedViewPB, ViewPB } from '@/services/backend'; import { ChangeNotifier } from '$app/utils/change_notifier'; import { FolderNotificationObserver } from '../notifications/observer'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts index 804038444f..7ad447601c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts @@ -1,10 +1,10 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { ViewLayoutTypePB } from '@/services/backend'; +import { ViewLayoutPB } from '@/services/backend'; export interface IPage { id: string; title: string; - pageType: ViewLayoutTypePB; + pageType: ViewLayoutPB; folderId: string; } diff --git a/frontend/rust-lib/.gitignore b/frontend/rust-lib/.gitignore index 264aad238c..740f8d77a7 100644 --- a/frontend/rust-lib/.gitignore +++ b/frontend/rust-lib/.gitignore @@ -12,4 +12,5 @@ bin/ **/src/protobuf **/resources/proto -.idea/ \ No newline at end of file +.idea/ +AppFlowy-Collab/ \ No newline at end of file diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index 3127146c89..a61256f6b9 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -491,7 +491,7 @@ dependencies = [ [[package]] name = "collab" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#306f27e56481eb2a998da4cb9f13763699dade76" dependencies = [ "anyhow", "bytes", @@ -509,7 +509,7 @@ dependencies = [ [[package]] name = "collab-derive" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#306f27e56481eb2a998da4cb9f13763699dade76" dependencies = [ "proc-macro2", "quote", @@ -521,7 +521,7 @@ dependencies = [ [[package]] name = "collab-folder" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#306f27e56481eb2a998da4cb9f13763699dade76" dependencies = [ "anyhow", "collab", @@ -539,7 +539,7 @@ dependencies = [ [[package]] name = "collab-persistence" version = "0.1.0" -source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=f25ce7f#f25ce7f71ef3f0a2a35260ebdf74d75534bfad45" +source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab#306f27e56481eb2a998da4cb9f13763699dade76" dependencies = [ "bincode", "chrono", diff --git a/frontend/rust-lib/Cargo.toml b/frontend/rust-lib/Cargo.toml index a941760c75..a7e271a950 100644 --- a/frontend/rust-lib/Cargo.toml +++ b/frontend/rust-lib/Cargo.toml @@ -8,7 +8,7 @@ members = [ "flowy-user", "flowy-test", "flowy-sqlite", -# "flowy-folder", +# "flowy-folder",r "flowy-folder2", "flowy-notification", "flowy-document", @@ -37,8 +37,10 @@ opt-level = 3 ## the amount of IO and the size of ./target, which make caching less effective. incremental = false - [patch.crates-io] -collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } -collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } -collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "f25ce7f" } +collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab" } +collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab" } +collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab" } +#collab = { path = "../AppFlowy-Collab/collab" } +#collab-folder = { path = "../AppFlowy-Collab/collab-folder" } +#collab-persistence = { path = "../AppFlowy-Collab/collab-persistence" } diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 608b145b2a..98903e60f6 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -46,7 +46,7 @@ use_bunyan = ["lib-log/use_bunyan"] dart = [ "flowy-user/dart", "flowy-net/dart", - "flowy-folder/dart", +# "flowy-folder/dart", "flowy-folder2/dart", "flowy-database/dart", "flowy-document/dart", @@ -54,7 +54,7 @@ dart = [ ts = [ "flowy-user/ts", "flowy-net/ts", - "flowy-folder/ts", +# "flowy-folder/ts", "flowy-folder2/ts", "flowy-database/ts", "flowy-document/ts", diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs index e8d61e932a..c33d990730 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs @@ -1,13 +1,14 @@ use bytes::Bytes; use collab_persistence::CollabKV; use database_model::BuildDatabaseContext; -use flowy_database::entities::LayoutTypePB; +use flowy_database::entities::DatabaseLayoutPB; use flowy_database::manager::{create_new_database, link_existing_database, DatabaseManager}; use flowy_database::util::{make_default_board, make_default_calendar, make_default_grid}; use flowy_document::editor::make_transaction_from_document_content; use flowy_document::DocumentManager; use flowy_error::FlowyError; +use flowy_folder2::entities::ViewLayoutPB; use flowy_folder2::manager::{Folder2Manager, FolderUser}; use flowy_folder2::view_ext::{ViewDataProcessor, ViewDataProcessorMap}; use flowy_folder2::ViewLayout; @@ -183,9 +184,9 @@ impl ViewDataProcessor for DatabaseViewDataProcessor { match DatabaseExtParams::from_map(ext).map(|params| params.database_id) { None => { let (build_context, layout) = match layout { - ViewLayout::Grid => (make_default_grid(), LayoutTypePB::Grid), - ViewLayout::Board => (make_default_board(), LayoutTypePB::Board), - ViewLayout::Calendar => (make_default_calendar(), LayoutTypePB::Calendar), + ViewLayout::Grid => (make_default_grid(), DatabaseLayoutPB::Grid), + ViewLayout::Board => (make_default_board(), DatabaseLayoutPB::Board), + ViewLayout::Calendar => (make_default_calendar(), DatabaseLayoutPB::Calendar), ViewLayout::Document => { return FutureResult::new(async move { Err(FlowyError::internal().context(format!("Can't handle {:?} layout type", layout))) @@ -197,7 +198,7 @@ impl ViewDataProcessor for DatabaseViewDataProcessor { }) }, Some(database_id) => { - let layout = layout_type_from_view_layout(layout); + let layout = layout_type_from_view_layout(layout.into()); FutureResult::new(async move { link_existing_database(&view_id, name, &database_id, layout, database_manager).await }) @@ -220,7 +221,7 @@ impl ViewDataProcessor for DatabaseViewDataProcessor { ) -> FutureResult<(), FlowyError> { let view_id = view_id.to_string(); let database_manager = self.0.clone(); - let layout = layout_type_from_view_layout(layout); + let layout = layout_type_from_view_layout(layout.into()); let name = name.to_string(); match DatabaseExtParams::from_map(ext).map(|params| params.database_id) { None => FutureResult::new(async move { @@ -248,11 +249,11 @@ impl DatabaseExtParams { } } -pub fn layout_type_from_view_layout(layout: ViewLayout) -> LayoutTypePB { +pub fn layout_type_from_view_layout(layout: ViewLayoutPB) -> DatabaseLayoutPB { match layout { - ViewLayout::Grid => LayoutTypePB::Grid, - ViewLayout::Board => LayoutTypePB::Board, - ViewLayout::Calendar => LayoutTypePB::Calendar, - ViewLayout::Document => LayoutTypePB::Grid, + 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/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index f614315b33..7539f87826 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -3,7 +3,7 @@ pub mod module; use crate::deps_resolve::*; use flowy_client_ws::{listen_on_websocket, FlowyWebSocketConnect, NetworkType}; -use flowy_database::entities::LayoutTypePB; +use flowy_database::entities::DatabaseLayoutPB; use flowy_database::manager::DatabaseManager; use flowy_document::entities::DocumentVersionPB; use flowy_document::{DocumentConfig, DocumentManager}; @@ -320,7 +320,7 @@ impl UserStatusListener { layout_type_from_view_layout(view.layout), ) }) - .collect::>() + .collect::>() }); self .database_manager diff --git a/frontend/rust-lib/flowy-database/src/entities/database_entities.rs b/frontend/rust-lib/flowy-database/src/entities/database_entities.rs index 998b1db9b0..59026ebaee 100644 --- a/frontend/rust-lib/flowy-database/src/entities/database_entities.rs +++ b/frontend/rust-lib/flowy-database/src/entities/database_entities.rs @@ -1,5 +1,5 @@ use crate::entities::parser::NotEmptyStr; -use crate::entities::{FieldIdPB, LayoutTypePB, RowPB}; +use crate::entities::{DatabaseLayoutPB, FieldIdPB, RowPB}; use flowy_derive::ProtoBuf; use flowy_error::ErrorCode; @@ -201,5 +201,5 @@ pub struct DatabaseLayoutIdPB { pub view_id: String, #[pb(index = 2)] - pub layout: LayoutTypePB, + pub layout: DatabaseLayoutPB, } diff --git a/frontend/rust-lib/flowy-database/src/entities/setting_entities.rs b/frontend/rust-lib/flowy-database/src/entities/setting_entities.rs index 49c4edbcbf..78ffd0e82f 100644 --- a/frontend/rust-lib/flowy-database/src/entities/setting_entities.rs +++ b/frontend/rust-lib/flowy-database/src/entities/setting_entities.rs @@ -15,7 +15,7 @@ use strum_macros::EnumIter; #[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] pub struct DatabaseViewSettingPB { #[pb(index = 1)] - pub current_layout: LayoutTypePB, + pub current_layout: DatabaseLayoutPB, #[pb(index = 2)] pub layout_setting: LayoutSettingPB, @@ -32,34 +32,34 @@ pub struct DatabaseViewSettingPB { #[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, EnumIter)] #[repr(u8)] -pub enum LayoutTypePB { +pub enum DatabaseLayoutPB { Grid = 0, Board = 1, Calendar = 2, } -impl std::default::Default for LayoutTypePB { +impl std::default::Default for DatabaseLayoutPB { fn default() -> Self { - LayoutTypePB::Grid + DatabaseLayoutPB::Grid } } -impl std::convert::From for LayoutTypePB { +impl std::convert::From for DatabaseLayoutPB { fn from(rev: LayoutRevision) -> Self { match rev { - LayoutRevision::Grid => LayoutTypePB::Grid, - LayoutRevision::Board => LayoutTypePB::Board, - LayoutRevision::Calendar => LayoutTypePB::Calendar, + LayoutRevision::Grid => DatabaseLayoutPB::Grid, + LayoutRevision::Board => DatabaseLayoutPB::Board, + LayoutRevision::Calendar => DatabaseLayoutPB::Calendar, } } } -impl std::convert::From for LayoutRevision { - fn from(layout: LayoutTypePB) -> Self { +impl std::convert::From for LayoutRevision { + fn from(layout: DatabaseLayoutPB) -> Self { match layout { - LayoutTypePB::Grid => LayoutRevision::Grid, - LayoutTypePB::Board => LayoutRevision::Board, - LayoutTypePB::Calendar => LayoutRevision::Calendar, + DatabaseLayoutPB::Grid => LayoutRevision::Grid, + DatabaseLayoutPB::Board => LayoutRevision::Board, + DatabaseLayoutPB::Calendar => LayoutRevision::Calendar, } } } @@ -70,7 +70,7 @@ pub struct DatabaseSettingChangesetPB { pub view_id: String, #[pb(index = 2)] - pub layout_type: LayoutTypePB, + pub layout_type: DatabaseLayoutPB, #[pb(index = 3, one_of)] pub alter_filter: Option, diff --git a/frontend/rust-lib/flowy-database/src/manager.rs b/frontend/rust-lib/flowy-database/src/manager.rs index 860f748fbb..c93e963fd5 100644 --- a/frontend/rust-lib/flowy-database/src/manager.rs +++ b/frontend/rust-lib/flowy-database/src/manager.rs @@ -1,4 +1,4 @@ -use crate::entities::LayoutTypePB; +use crate::entities::DatabaseLayoutPB; use crate::services::database::{ make_database_block_rev_manager, DatabaseEditor, DatabaseRefIndexerQuery, DatabaseRevisionCloudService, DatabaseRevisionMergeable, DatabaseRevisionSerde, @@ -83,7 +83,7 @@ impl DatabaseManager { &self, user_id: i64, _token: &str, - get_views_fn: Fut>, + get_views_fn: Fut>, ) -> FlowyResult<()> { self.migration.run(user_id, get_views_fn).await?; Ok(()) @@ -327,7 +327,7 @@ pub async fn link_existing_database( view_id: &str, name: String, database_id: &str, - layout: LayoutTypePB, + layout: DatabaseLayoutPB, database_manager: Arc, ) -> FlowyResult<()> { tracing::trace!( @@ -358,7 +358,7 @@ pub async fn link_existing_database( pub async fn create_new_database( view_id: &str, name: String, - layout: LayoutTypePB, + layout: DatabaseLayoutPB, database_manager: Arc, build_context: BuildDatabaseContext, ) -> FlowyResult<()> { diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs b/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs index b0719c928c..aba2449d83 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/migration/mod.rs @@ -1,6 +1,6 @@ mod database_migration; mod database_view_migration; -use crate::entities::LayoutTypePB; +use crate::entities::DatabaseLayoutPB; use crate::manager::DatabaseUser; use crate::services::persistence::database_ref::DatabaseRefs; use crate::services::persistence::migration::database_migration::{ @@ -31,7 +31,7 @@ impl DatabaseMigration { pub async fn run( &self, user_id: i64, - get_views_fn: Fut>, + get_views_fn: Fut>, ) -> FlowyResult<()> { let pool = self.user.db_pool()?; diff --git a/frontend/rust-lib/flowy-database/src/services/setting/setting_builder.rs b/frontend/rust-lib/flowy-database/src/services/setting/setting_builder.rs index bec5e44fc9..1b5ba1d4d1 100644 --- a/frontend/rust-lib/flowy-database/src/services/setting/setting_builder.rs +++ b/frontend/rust-lib/flowy-database/src/services/setting/setting_builder.rs @@ -1,5 +1,5 @@ use crate::entities::{ - AlterFilterParams, DatabaseSettingChangesetParams, DeleteFilterParams, LayoutTypePB, + AlterFilterParams, DatabaseLayoutPB, DatabaseSettingChangesetParams, DeleteFilterParams, }; pub struct GridSettingChangesetBuilder { @@ -7,7 +7,7 @@ pub struct GridSettingChangesetBuilder { } impl GridSettingChangesetBuilder { - pub fn new(grid_id: &str, layout_type: &LayoutTypePB) -> Self { + pub fn new(grid_id: &str, layout_type: &DatabaseLayoutPB) -> Self { let params = DatabaseSettingChangesetParams { view_id: grid_id.to_string(), layout_type: layout_type.clone().into(), diff --git a/frontend/rust-lib/flowy-database/tests/database/database_editor.rs b/frontend/rust-lib/flowy-database/tests/database/database_editor.rs index ff0ebf925e..90b0dcbf4d 100644 --- a/frontend/rust-lib/flowy-database/tests/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database/tests/database/database_editor.rs @@ -26,32 +26,32 @@ pub struct DatabaseEditorTest { impl DatabaseEditorTest { pub async fn new_grid() -> Self { - Self::new(LayoutTypePB::Grid).await + Self::new(DatabaseLayoutPB::Grid).await } pub async fn new_board() -> Self { - Self::new(LayoutTypePB::Board).await + Self::new(DatabaseLayoutPB::Board).await } pub async fn new_calendar() -> Self { - Self::new(LayoutTypePB::Calendar).await + Self::new(DatabaseLayoutPB::Calendar).await } - pub async fn new(layout: LayoutTypePB) -> Self { + pub async fn new(layout: DatabaseLayoutPB) -> Self { let sdk = FlowySDKTest::default(); let _ = sdk.init_user().await; let test = match layout { - LayoutTypePB::Grid => { + DatabaseLayoutPB::Grid => { let build_context = make_test_grid(); let view_data: Bytes = build_context.into(); ViewTest::new_grid_view(&sdk, view_data.to_vec()).await }, - LayoutTypePB::Board => { + DatabaseLayoutPB::Board => { let build_context = make_test_board(); let view_data: Bytes = build_context.into(); ViewTest::new_board_view(&sdk, view_data.to_vec()).await }, - LayoutTypePB::Calendar => { + DatabaseLayoutPB::Calendar => { let build_context = make_test_calendar(); let view_data: Bytes = build_context.into(); ViewTest::new_calendar_view(&sdk, view_data.to_vec()).await diff --git a/frontend/rust-lib/flowy-database/tests/database/filter_test/script.rs b/frontend/rust-lib/flowy-database/tests/database/filter_test/script.rs index e4a0e566e0..a66751c29f 100644 --- a/frontend/rust-lib/flowy-database/tests/database/filter_test/script.rs +++ b/frontend/rust-lib/flowy-database/tests/database/filter_test/script.rs @@ -7,7 +7,7 @@ use std::time::Duration; use bytes::Bytes; use futures::TryFutureExt; use tokio::sync::broadcast::Receiver; -use flowy_database::entities::{AlterFilterParams, AlterFilterPayloadPB, DeleteFilterParams, LayoutTypePB, DatabaseSettingChangesetParams, DatabaseViewSettingPB, RowPB, TextFilterConditionPB, FieldType, NumberFilterConditionPB, CheckboxFilterConditionPB, DateFilterConditionPB, DateFilterContentPB, SelectOptionConditionPB, TextFilterPB, NumberFilterPB, CheckboxFilterPB, DateFilterPB, SelectOptionFilterPB, CellChangesetPB, FilterPB, ChecklistFilterConditionPB, ChecklistFilterPB}; +use flowy_database::entities::{AlterFilterParams, AlterFilterPayloadPB, DeleteFilterParams, DatabaseLayoutPB, DatabaseSettingChangesetParams, DatabaseViewSettingPB, RowPB, TextFilterConditionPB, FieldType, NumberFilterConditionPB, CheckboxFilterConditionPB, DateFilterConditionPB, DateFilterContentPB, SelectOptionConditionPB, TextFilterPB, NumberFilterPB, CheckboxFilterPB, DateFilterPB, SelectOptionFilterPB, CellChangesetPB, FilterPB, ChecklistFilterConditionPB, ChecklistFilterPB}; use flowy_database::services::field::{SelectOptionCellChangeset, SelectOptionIds}; use flowy_database::services::setting::GridSettingChangesetBuilder; use database_model::{FieldRevision, FieldTypeRevision}; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/app.rs b/frontend/rust-lib/flowy-folder2/src/entities/app.rs deleted file mode 100644 index ffff29eab4..0000000000 --- a/frontend/rust-lib/flowy-folder2/src/entities/app.rs +++ /dev/null @@ -1,183 +0,0 @@ -use crate::entities::parser::app::{AppColorStyle, AppIdentify, AppName}; -use crate::entities::parser::workspace::WorkspaceIdentify; -use crate::entities::RepeatedViewPB; - -use flowy_derive::ProtoBuf; -use flowy_error::ErrorCode; -use std::convert::TryInto; - -#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)] -pub struct AppPB { - #[pb(index = 1)] - pub id: String, - - #[pb(index = 2)] - pub workspace_id: String, - - #[pb(index = 3)] - pub name: String, - - #[pb(index = 4)] - pub belongings: RepeatedViewPB, - - #[pb(index = 5)] - pub create_time: i64, -} - -#[derive(Eq, PartialEq, Debug, Default, ProtoBuf, Clone)] -pub struct RepeatedAppPB { - #[pb(index = 1)] - pub items: Vec, -} - -#[derive(ProtoBuf, Default)] -pub struct CreateAppPayloadPB { - #[pb(index = 1)] - pub workspace_id: String, - - #[pb(index = 2)] - pub name: String, - - #[pb(index = 3)] - pub desc: String, - - #[pb(index = 4)] - pub color_style: ColorStylePB, -} - -#[derive(ProtoBuf, Default, Debug, Clone)] -pub struct ColorStylePB { - #[pb(index = 1)] - pub theme_color: String, -} - -#[derive(Debug)] -pub struct CreateAppParams { - pub workspace_id: String, - pub name: String, - pub desc: String, - pub color_style: ColorStylePB, -} - -impl TryInto for CreateAppPayloadPB { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let name = AppName::parse(self.name)?; - let id = WorkspaceIdentify::parse(self.workspace_id)?; - let color_style = AppColorStyle::parse(self.color_style.theme_color.clone())?; - - Ok(CreateAppParams { - workspace_id: id.0, - name: name.0, - desc: self.desc, - color_style: color_style.into(), - }) - } -} - -impl std::convert::From for ColorStylePB { - fn from(data: AppColorStyle) -> Self { - ColorStylePB { - theme_color: data.theme_color, - } - } -} - -#[derive(ProtoBuf, Default, Clone, Debug)] -pub struct AppIdPB { - #[pb(index = 1)] - pub value: String, -} - -impl AppIdPB { - pub fn new(app_id: &str) -> Self { - Self { - value: app_id.to_string(), - } - } -} - -#[derive(ProtoBuf, Default)] -pub struct UpdateAppPayloadPB { - #[pb(index = 1)] - pub app_id: String, - - #[pb(index = 2, one_of)] - pub name: Option, - - #[pb(index = 3, one_of)] - pub desc: Option, - - #[pb(index = 4, one_of)] - pub color_style: Option, - - #[pb(index = 5, one_of)] - pub is_trash: Option, -} - -#[derive(Debug, Clone)] -pub struct UpdateAppParams { - pub app_id: String, - - pub name: Option, - - pub desc: Option, - - pub color_style: Option, - - pub is_trash: Option, -} - -impl UpdateAppParams { - pub fn new(app_id: &str) -> Self { - Self { - app_id: app_id.to_string(), - name: None, - desc: None, - color_style: None, - is_trash: None, - } - } - - pub fn name(mut self, name: &str) -> Self { - self.name = Some(name.to_string()); - self - } - - pub fn desc(mut self, desc: &str) -> Self { - self.desc = Some(desc.to_string()); - self - } - - pub fn trash(mut self) -> Self { - self.is_trash = Some(true); - self - } -} - -impl TryInto for UpdateAppPayloadPB { - type Error = ErrorCode; - - fn try_into(self) -> Result { - let app_id = AppIdentify::parse(self.app_id)?.0; - - let name = match self.name { - None => None, - Some(name) => Some(AppName::parse(name)?.0), - }; - - let color_style = match self.color_style { - None => None, - Some(color_style) => Some(AppColorStyle::parse(color_style.theme_color)?.into()), - }; - - Ok(UpdateAppParams { - app_id, - name, - desc: self.desc, - color_style, - is_trash: self.is_trash, - }) - } -} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/mod.rs index d5370f0786..a596bf648c 100644 --- a/frontend/rust-lib/flowy-folder2/src/entities/mod.rs +++ b/frontend/rust-lib/flowy-folder2/src/entities/mod.rs @@ -1,10 +1,8 @@ -pub mod app; mod parser; pub mod trash; pub mod view; pub mod workspace; -pub use app::*; pub use trash::*; pub use view::*; pub use workspace::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs deleted file mode 100644 index b98b809f3d..0000000000 --- a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_color_style.rs +++ /dev/null @@ -1,13 +0,0 @@ -use flowy_error::ErrorCode; - -#[derive(Debug)] -pub struct AppColorStyle { - pub theme_color: String, -} - -impl AppColorStyle { - pub fn parse(theme_color: String) -> Result { - // TODO: verify the color style format - Ok(AppColorStyle { theme_color }) - } -} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs deleted file mode 100644 index 24cc2dcab8..0000000000 --- a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_desc.rs +++ /dev/null @@ -1,20 +0,0 @@ -use unicode_segmentation::UnicodeSegmentation; -#[derive(Debug)] -pub struct AppDesc(pub String); - -impl AppDesc { - #[allow(dead_code)] - pub fn parse(s: String) -> Result { - if s.graphemes(true).count() > 1024 { - return Err("Workspace description too long".to_string()); - } - - Ok(Self(s)) - } -} - -impl AsRef for AppDesc { - fn as_ref(&self) -> &str { - &self.0 - } -} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs deleted file mode 100644 index 2311001089..0000000000 --- a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_id.rs +++ /dev/null @@ -1,20 +0,0 @@ -use flowy_error::ErrorCode; - -#[derive(Debug)] -pub struct AppIdentify(pub String); - -impl AppIdentify { - pub fn parse(s: String) -> Result { - if s.trim().is_empty() { - return Err(ErrorCode::AppIdInvalid); - } - - Ok(Self(s)) - } -} - -impl AsRef for AppIdentify { - fn as_ref(&self) -> &str { - &self.0 - } -} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs deleted file mode 100644 index f14670c650..0000000000 --- a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/app_name.rs +++ /dev/null @@ -1,20 +0,0 @@ -use flowy_error::ErrorCode; - -#[derive(Debug)] -pub struct AppName(pub String); - -impl AppName { - pub fn parse(s: String) -> Result { - if s.trim().is_empty() { - return Err(ErrorCode::AppNameInvalid); - } - - Ok(Self(s)) - } -} - -impl AsRef for AppName { - fn as_ref(&self) -> &str { - &self.0 - } -} diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs deleted file mode 100644 index fcf6f4bd3f..0000000000 --- a/frontend/rust-lib/flowy-folder2/src/entities/parser/app/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod app_color_style; -mod app_desc; -mod app_id; -mod app_name; - -pub use app_color_style::*; -pub use app_desc::*; -pub use app_id::*; -pub use app_name::*; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs b/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs index 3ee0f4b591..7b8d7cc9d5 100644 --- a/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs +++ b/frontend/rust-lib/flowy-folder2/src/entities/parser/mod.rs @@ -1,4 +1,4 @@ -pub mod app; +// pub mod app; pub mod trash; pub mod view; pub mod workspace; diff --git a/frontend/rust-lib/flowy-folder2/src/entities/view.rs b/frontend/rust-lib/flowy-folder2/src/entities/view.rs index f952fd65e5..e20827f7a1 100644 --- a/frontend/rust-lib/flowy-folder2/src/entities/view.rs +++ b/frontend/rust-lib/flowy-folder2/src/entities/view.rs @@ -1,7 +1,4 @@ -use crate::entities::parser::{ - app::AppIdentify, - view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail}, -}; +use crate::entities::parser::view::{ViewDesc, ViewIdentify, ViewName, ViewThumbnail}; use crate::view_ext::gen_view_id; use collab_folder::core::{View, ViewLayout}; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; @@ -16,7 +13,7 @@ pub struct ViewPB { pub id: String, #[pb(index = 2)] - pub app_id: String, + pub parent_view_id: String, #[pb(index = 3)] pub name: String, @@ -28,14 +25,14 @@ pub struct ViewPB { pub belongings: Vec, #[pb(index = 6)] - pub layout: ViewLayoutTypePB, + pub layout: ViewLayoutPB, } impl std::convert::From for ViewPB { fn from(view: View) -> Self { ViewPB { id: view.id, - app_id: view.bid, + parent_view_id: view.bid, name: view.name, create_time: view.created_at, belongings: Default::default(), @@ -45,26 +42,35 @@ impl std::convert::From for ViewPB { } #[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)] -pub enum ViewLayoutTypePB { +pub enum ViewLayoutPB { Document = 0, Grid = 3, Board = 4, Calendar = 5, } -impl std::default::Default for ViewLayoutTypePB { +impl std::default::Default for ViewLayoutPB { fn default() -> Self { - ViewLayoutTypePB::Grid + ViewLayoutPB::Grid } } -impl std::convert::From for ViewLayoutTypePB { +impl ViewLayoutPB { + pub fn is_database(&self) -> bool { + matches!( + self, + ViewLayoutPB::Grid | ViewLayoutPB::Board | ViewLayoutPB::Calendar + ) + } +} + +impl std::convert::From for ViewLayoutPB { fn from(rev: ViewLayout) -> Self { match rev { - ViewLayout::Grid => ViewLayoutTypePB::Grid, - ViewLayout::Board => ViewLayoutTypePB::Board, - ViewLayout::Document => ViewLayoutTypePB::Document, - ViewLayout::Calendar => ViewLayoutTypePB::Calendar, + ViewLayout::Grid => ViewLayoutPB::Grid, + ViewLayout::Board => ViewLayoutPB::Board, + ViewLayout::Document => ViewLayoutPB::Document, + ViewLayout::Calendar => ViewLayoutPB::Calendar, } } } @@ -75,12 +81,8 @@ pub struct RepeatedViewPB { pub items: Vec, } -impl std::convert::From> for RepeatedViewPB { - fn from(views: Vec) -> Self { - let items = views - .into_iter() - .map(|value| value.into()) - .collect::>(); +impl std::convert::From> for RepeatedViewPB { + fn from(items: Vec) -> Self { RepeatedViewPB { items } } } @@ -120,7 +122,7 @@ pub struct CreateViewPayloadPB { pub thumbnail: Option, #[pb(index = 5)] - pub layout: ViewLayoutTypePB, + pub layout: ViewLayoutPB, #[pb(index = 6)] pub initial_data: Vec, @@ -134,7 +136,7 @@ pub struct CreateViewParams { pub belong_to_id: String, pub name: String, pub desc: String, - pub layout: ViewLayoutTypePB, + pub layout: ViewLayoutPB, pub view_id: String, pub initial_data: Vec, pub ext: HashMap, @@ -145,7 +147,7 @@ impl TryInto for CreateViewPayloadPB { fn try_into(self) -> Result { let name = ViewName::parse(self.name)?.0; - let belong_to_id = AppIdentify::parse(self.belong_to_id)?.0; + let belong_to_id = ViewIdentify::parse(self.belong_to_id)?.0; let view_id = gen_view_id(); Ok(CreateViewParams { diff --git a/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs b/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs index f0c027377e..c0b1553fd7 100644 --- a/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs +++ b/frontend/rust-lib/flowy-folder2/src/entities/workspace.rs @@ -22,6 +22,18 @@ pub struct WorkspacePB { pub create_time: i64, } +impl std::convert::From<(Workspace, Vec)> for WorkspacePB { + fn from(params: (Workspace, Vec)) -> Self { + let (workspace, views) = params; + WorkspacePB { + id: workspace.id, + name: workspace.name, + views, + create_time: workspace.created_at, + } + } +} + impl std::convert::From for WorkspacePB { fn from(workspace: Workspace) -> Self { WorkspacePB { diff --git a/frontend/rust-lib/flowy-folder2/src/event_handler.rs b/frontend/rust-lib/flowy-folder2/src/event_handler.rs index 38bc761964..17b9fb9ecc 100644 --- a/frontend/rust-lib/flowy-folder2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-folder2/src/event_handler.rs @@ -39,7 +39,8 @@ pub(crate) async fn open_workspace_handler( None => Err(FlowyError::workspace_id().context("workspace id should not be empty")), Some(workspace_id) => { let workspace = folder.open_workspace(&workspace_id).await?; - let workspace_pb: WorkspacePB = workspace.into(); + let views = folder.get_workspace_views(&workspace_id).await?; + let workspace_pb: WorkspacePB = (workspace, views).into(); data_result_ok(workspace_pb) }, } @@ -67,7 +68,9 @@ pub(crate) async fn read_workspaces_handler( pub async fn read_cur_workspace_setting_handler( folder: AFPluginState>, ) -> DataResult { - let workspace: WorkspacePB = folder.get_current_workspace().await?.into(); + let workspace = folder.get_current_workspace().await?; + let views = folder.get_workspace_views(&workspace.id).await?; + let workspace: WorkspacePB = (workspace, views).into(); let latest_view: Option = folder.get_current_view().await; data_result_ok(WorkspaceSettingPB { workspace, diff --git a/frontend/rust-lib/flowy-folder2/src/manager.rs b/frontend/rust-lib/flowy-folder2/src/manager.rs index 396c74cca2..cd4d8a6acf 100644 --- a/frontend/rust-lib/flowy-folder2/src/manager.rs +++ b/frontend/rust-lib/flowy-folder2/src/manager.rs @@ -63,41 +63,28 @@ impl Folder2Manager { } } - pub async fn get_current_workspace_views(&self) -> FlowyResult> { - let views = self.with_folder(vec![], |folder| { - let trash_ids = folder - .trash - .get_all_trash() - .into_iter() - .map(|trash| trash.id) - .collect::>(); + pub async fn get_current_workspace_views(&self) -> FlowyResult> { + let workspace_id = self + .folder + .lock() + .as_ref() + .map(|folder| folder.get_current_workspace_id()); - let mut views = folder.get_views_belong_to_current_workspace(); - views.retain(|view| !trash_ids.contains(&view.id)); - views + if let Some(Some(workspace_id)) = workspace_id { + self.get_workspace_views(&workspace_id).await + } else { + Ok(vec![]) + } + } + + pub async fn get_workspace_views(&self, workspace_id: &str) -> FlowyResult> { + let views = self.with_folder(vec![], |folder| { + get_workspace_view_pbs(workspace_id, folder) }); Ok(views) } - pub async fn get_workspace_views( - &self, - workspace_id: &str, - filter: F, - ) -> FlowyResult> - where - F: Fn(&ViewLayout) -> bool, - { - Ok(self.with_folder(vec![], |folder| { - folder - .views - .get_views_belong_to(workspace_id) - .into_iter() - .filter(|view| filter(&view.layout)) - .collect::>() - })) - } - /// Called immediately after the application launched with the user sign in/sign up. #[tracing::instrument(level = "trace", skip(self), err)] pub async fn initialize(&self, user_id: i64) -> FlowyResult<()> { @@ -532,6 +519,34 @@ fn listen_on_trash_change(mut rx: TrashChangeReceiver, folder: Folder) { }); } +fn get_workspace_view_pbs(workspace_id: &str, folder: &InnerFolder) -> Vec { + let trash_ids = folder + .trash + .get_all_trash() + .into_iter() + .map(|trash| trash.id) + .collect::>(); + + let mut views = folder.get_workspace_views(workspace_id); + views.retain(|view| !trash_ids.contains(&view.id)); + + views + .into_iter() + .map(|view| { + let mut parent_view: ViewPB = view.into(); + + // Get child views + parent_view.belongings = folder + .views + .get_views_belong_to(&parent_view.id) + .into_iter() + .map(|view| view.into()) + .collect(); + parent_view + }) + .collect() +} + #[tracing::instrument(level = "debug", skip(folder, parent_view_ids))] fn notify_parent_view_did_change>( folder: Folder, @@ -553,9 +568,7 @@ fn notify_parent_view_did_change>( // if the view's bid is equal to workspace id. Then it will fetch the current // workspace views. Because the the workspace is not a view stored in the views map. if parent_view_id == workspace_id { - let mut child_views = folder.get_views_belong_to_current_workspace(); - child_views.retain(|view| !trash_ids.contains(&view.id)); - let repeated_view: RepeatedViewPB = child_views.into(); + let repeated_view: RepeatedViewPB = get_workspace_view_pbs(&workspace_id, folder).into(); send_notification(&workspace_id, FolderNotification::DidUpdateWorkspaceViews) .payload(repeated_view) .send(); diff --git a/frontend/rust-lib/flowy-folder2/src/test_helper.rs b/frontend/rust-lib/flowy-folder2/src/test_helper.rs index f6a243336a..b7fe61d22f 100644 --- a/frontend/rust-lib/flowy-folder2/src/test_helper.rs +++ b/frontend/rust-lib/flowy-folder2/src/test_helper.rs @@ -1,4 +1,4 @@ -use crate::entities::{CreateViewParams, ViewLayoutTypePB}; +use crate::entities::{CreateViewParams, ViewLayoutPB}; use crate::manager::Folder2Manager; use crate::view_ext::gen_view_id; use std::collections::HashMap; @@ -12,7 +12,7 @@ impl Folder2Manager { ext: HashMap, ) -> String { self - .create_test_view(app_id, name, ViewLayoutTypePB::Grid, ext) + .create_test_view(app_id, name, ViewLayoutPB::Grid, ext) .await } @@ -23,7 +23,7 @@ impl Folder2Manager { ext: HashMap, ) -> String { self - .create_test_view(app_id, name, ViewLayoutTypePB::Board, ext) + .create_test_view(app_id, name, ViewLayoutPB::Board, ext) .await } @@ -31,7 +31,7 @@ impl Folder2Manager { &self, app_id: &str, name: &str, - layout: ViewLayoutTypePB, + layout: ViewLayoutPB, ext: HashMap, ) -> String { let view_id = gen_view_id(); diff --git a/frontend/rust-lib/flowy-folder2/src/view_ext.rs b/frontend/rust-lib/flowy-folder2/src/view_ext.rs index fa371840d7..87d7b3b437 100644 --- a/frontend/rust-lib/flowy-folder2/src/view_ext.rs +++ b/frontend/rust-lib/flowy-folder2/src/view_ext.rs @@ -1,4 +1,4 @@ -use crate::entities::{CreateViewParams, ViewLayoutTypePB}; +use crate::entities::{CreateViewParams, ViewLayoutPB}; use bytes::Bytes; use collab_folder::core::{View, ViewLayout}; use flowy_error::FlowyError; @@ -43,13 +43,13 @@ pub trait ViewDataProcessor { pub type ViewDataProcessorMap = Arc>>; -impl From for ViewLayout { - fn from(pb: ViewLayoutTypePB) -> Self { +impl From for ViewLayout { + fn from(pb: ViewLayoutPB) -> Self { match pb { - ViewLayoutTypePB::Document => ViewLayout::Document, - ViewLayoutTypePB::Grid => ViewLayout::Grid, - ViewLayoutTypePB::Board => ViewLayout::Board, - ViewLayoutTypePB::Calendar => ViewLayout::Calendar, + ViewLayoutPB::Document => ViewLayout::Document, + ViewLayoutPB::Grid => ViewLayout::Grid, + ViewLayoutPB::Board => ViewLayout::Board, + ViewLayoutPB::Calendar => ViewLayout::Calendar, } } } diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index cd6a10f22c..01a8fcd721 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -1,7 +1,6 @@ use crate::prelude::*; use flowy_folder2::entities::{ - CreateViewPayloadPB, CreateWorkspacePayloadPB, ViewLayoutTypePB, ViewPB, WorkspaceIdPB, - WorkspacePB, + CreateViewPayloadPB, CreateWorkspacePayloadPB, ViewLayoutPB, ViewPB, WorkspaceIdPB, WorkspacePB, }; use flowy_folder2::event_map::FolderEvent::{CreateView, CreateWorkspace, OpenWorkspace}; use flowy_user::{ @@ -21,7 +20,7 @@ pub struct ViewTest { impl ViewTest { #[allow(dead_code)] - pub async fn new(sdk: &FlowySDKTest, layout: ViewLayoutTypePB, data: Vec) -> Self { + pub async fn new(sdk: &FlowySDKTest, layout: ViewLayoutPB, data: Vec) -> Self { let workspace = create_workspace(sdk, "Workspace", "").await; open_workspace(sdk, &workspace.id).await; let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; @@ -35,19 +34,19 @@ impl ViewTest { } pub async fn new_grid_view(sdk: &FlowySDKTest, data: Vec) -> Self { - Self::new(sdk, ViewLayoutTypePB::Grid, data).await + Self::new(sdk, ViewLayoutPB::Grid, data).await } pub async fn new_board_view(sdk: &FlowySDKTest, data: Vec) -> Self { - Self::new(sdk, ViewLayoutTypePB::Board, data).await + Self::new(sdk, ViewLayoutPB::Board, data).await } pub async fn new_calendar_view(sdk: &FlowySDKTest, data: Vec) -> Self { - Self::new(sdk, ViewLayoutTypePB::Calendar, data).await + Self::new(sdk, ViewLayoutPB::Calendar, data).await } pub async fn new_document_view(sdk: &FlowySDKTest) -> Self { - Self::new(sdk, ViewLayoutTypePB::Document, vec![]).await + Self::new(sdk, ViewLayoutPB::Document, vec![]).await } } @@ -82,7 +81,7 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s name: name.to_string(), desc: desc.to_string(), thumbnail: None, - layout: ViewLayoutTypePB::Document, + layout: ViewLayoutPB::Document, initial_data: vec![], ext: Default::default(), }; @@ -98,7 +97,7 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s async fn create_view( sdk: &FlowySDKTest, app_id: &str, - layout: ViewLayoutTypePB, + layout: ViewLayoutPB, data: Vec, ) -> ViewPB { let payload = CreateViewPayloadPB {