fix: search launch review (#5169)

* fix: support filtering results by workspace

* feat: add search button to sidebar

* fix: reduce view/recent view fetching across application

* feat: add channel to search listener

* feat: clean + localization

* chore: remove redundant code

* fix: disable search

* chore: trigger ci

* chore: disable search in backend

* test: disable search tests for now

* feat: temp disable reliance on folder search

* fix: add debounce to inline actions

* chore: complete future if disposed

* fix: clean code

* chore: disable unused bloc with feature flag

* fix: recent views lazy read

* chore: revert podilfe change

* chore: update logs

* chore: update client api and collab

* chore: fix tst

* chore: fix test & update collab commit

* chore: update collab commit

* test: fix unit tests

* chore: update rust toolchain 1.77

* chore: use opt-level 1

* fix: code review

* chore: clippy

---------

Co-authored-by: nathan <nathan@appflowy.io>
Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
This commit is contained in:
Mathias Mogensen 2024-04-23 15:46:57 +02:00 committed by GitHub
parent bf64b0d2fa
commit 275d0b2ac4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
91 changed files with 1057 additions and 848 deletions

View File

@ -20,7 +20,7 @@
# env:
# CARGO_TERM_COLOR: always
# FLUTTER_VERSION: "3.19.0"
# RUST_TOOLCHAIN: "1.75"
# RUST_TOOLCHAIN: "1.77.2"
# CARGO_MAKE_VERSION: "0.36.6"
# concurrency:

View File

@ -26,7 +26,7 @@ on:
env:
CARGO_TERM_COLOR: always
FLUTTER_VERSION: "3.19.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
CARGO_MAKE_VERSION: "0.36.6"
concurrency:
@ -39,7 +39,7 @@ jobs:
strategy:
fail-fast: true
matrix:
os: [ubuntu-latest]
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
flutter_profile: development-linux-x86_64
@ -73,7 +73,7 @@ jobs:
strategy:
fail-fast: true
matrix:
os: [windows-latest]
os: [ windows-latest ]
include:
- os: windows-latest
flutter_profile: development-windows-x86
@ -99,7 +99,7 @@ jobs:
strategy:
fail-fast: true
matrix:
os: [macos-latest]
os: [ macos-latest ]
include:
- os: macos-latest
flutter_profile: development-mac-x86_64
@ -121,12 +121,12 @@ jobs:
flutter_profile: ${{ matrix.flutter_profile }}
unit_test:
needs: [prepare-linux]
needs: [ prepare-linux ]
if: github.event.pull_request.draft != true
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
flutter_profile: development-linux-x86_64
@ -212,11 +212,11 @@ jobs:
shell: bash
cloud_integration_test:
needs: [prepare-linux]
needs: [ prepare-linux ]
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
flutter_profile: development-linux-x86_64
@ -301,12 +301,12 @@ jobs:
# split the integration tests into different machines to minimize the time
integration_test_1:
needs: [prepare-linux]
needs: [ prepare-linux ]
if: github.event.pull_request.draft != true
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
target: 'x86_64-unknown-linux-gnu'
@ -325,12 +325,12 @@ jobs:
rust_target: ${{ matrix.target }}
integration_test_2:
needs: [prepare-linux]
needs: [ prepare-linux ]
if: github.event.pull_request.draft != true
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
target: 'x86_64-unknown-linux-gnu'
@ -349,12 +349,12 @@ jobs:
rust_target: ${{ matrix.target }}
integration_test_3:
needs: [prepare-linux]
needs: [ prepare-linux ]
if: github.event.pull_request.draft != true
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
os: [ ubuntu-latest ]
include:
- os: ubuntu-latest
target: 'x86_64-unknown-linux-gnu'

View File

@ -19,7 +19,7 @@ on:
env:
FLUTTER_VERSION: "3.19.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@ -31,7 +31,7 @@ jobs:
strategy:
fail-fast: true
matrix:
os: [macos-14]
os: [ macos-14 ]
runs-on: ${{ matrix.os }}
steps:
@ -86,7 +86,7 @@ jobs:
model: 'iPhone 15'
shutdown_after_job: false
# enable it again if the 12 mins timeout is fixed
# - name: Run integration tests
# working-directory: frontend/appflowy_flutter
# enable it again if the 12 mins timeout is fixed
# - name: Run integration tests
# working-directory: frontend/appflowy_flutter
# run: flutter test integration_test/runner.dart -d ${{ steps.simulator-action.outputs.udid }}

View File

@ -7,7 +7,7 @@ on:
env:
FLUTTER_VERSION: "3.19.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
jobs:
create-release:
@ -232,10 +232,10 @@ jobs:
matrix:
job:
- {
targets: "aarch64-apple-darwin,x86_64-apple-darwin",
os: macos-11,
extra-build-args: "",
}
targets: "aarch64-apple-darwin,x86_64-apple-darwin",
os: macos-11,
extra-build-args: "",
}
steps:
- name: Checkout source code
uses: actions/checkout@v4
@ -336,12 +336,12 @@ jobs:
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,
}
steps:
- name: Checkout source code
uses: actions/checkout@v4

View File

@ -19,7 +19,7 @@ on:
env:
CARGO_TERM_COLOR: always
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
jobs:
test-on-ubuntu:

View File

@ -11,7 +11,7 @@ on:
env:
CARGO_TERM_COLOR: always
FLUTTER_VERSION: "3.19.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
jobs:
tests:

View File

@ -10,7 +10,7 @@ on:
env:
NODE_VERSION: "18.16.0"
PNPM_VERSION: "8.5.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}

View File

@ -10,7 +10,7 @@ on:
env:
NODE_VERSION: "18.16.0"
PNPM_VERSION: "8.5.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@ -22,7 +22,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [ubuntu-20.04]
platform: [ ubuntu-20.04 ]
runs-on: ${{ matrix.platform }}

View File

@ -14,7 +14,7 @@ on:
env:
NODE_VERSION: "18.16.0"
PNPM_VERSION: "8.5.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
jobs:

View File

@ -12,7 +12,7 @@ env:
CARGO_TERM_COLOR: always
NODE_VERSION: "18.16.0"
PNPM_VERSION: "8.5.0"
RUST_TOOLCHAIN: "1.75"
RUST_TOOLCHAIN: "1.77.2"
CARGO_MAKE_VERSION: "0.36.6"
jobs:

View File

@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-search/notification.pbenum.dart';
import 'package:appflowy_backend/rust_stream.dart';
import 'package:appflowy_result/appflowy_result.dart';
@ -23,9 +23,11 @@ class SearchNotificationParser
SearchNotificationParser({
super.id,
required super.callback,
String? channel,
}) : super(
tyParser: (ty, source) =>
source == _source ? SearchNotification.valueOf(ty) : null,
tyParser: (ty, source) => source == "$_source$channel"
? SearchNotification.valueOf(ty)
: null,
errorParser: (bytes) => FlowyError.fromBuffer(bytes),
);
}
@ -39,7 +41,12 @@ class SearchNotificationListener {
SearchNotificationListener({
required String objectId,
required SearchNotificationHandler handler,
}) : _parser = SearchNotificationParser(id: objectId, callback: handler) {
String? channel,
}) : _parser = SearchNotificationParser(
id: objectId,
callback: handler,
channel: channel,
) {
_subscription =
RustStreamReceiver.listen((observable) => _parser?.parse(observable));
}

View File

@ -1,12 +1,14 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:appflowy/mobile/presentation/database/board/mobile_board_screen.dart';
import 'package:appflowy/mobile/presentation/database/mobile_calendar_screen.dart';
import 'package:appflowy/mobile/presentation/database/mobile_grid_screen.dart';
import 'package:appflowy/mobile/presentation/presentation.dart';
import 'package:appflowy/workspace/application/recent/recent_service.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
extension MobileRouter on BuildContext {
@ -17,7 +19,7 @@ extension MobileRouter on BuildContext {
queryParameters: view.queryParameters(arguments),
).toString(),
).then((value) {
RecentService().updateRecentViews([view.id], true);
getIt<CachedRecentService>().updateRecentViews([view.id], true);
});
}
}

View File

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
@ -8,7 +10,6 @@ import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';

View File

@ -102,10 +102,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
late final InlineActionsService inlineActionsService = InlineActionsService(
context: context,
handlers: [
InlinePageReferenceService(
currentViewId: documentBloc.view.id,
limitResults: 5,
),
InlinePageReferenceService(currentViewId: documentBloc.view.id),
DateReferenceService(context),
ReminderReferenceService(context),
],

View File

@ -11,28 +11,27 @@ import 'package:appflowy/plugins/inline_actions/inline_actions_menu.dart';
import 'package:appflowy/plugins/inline_actions/inline_actions_result.dart';
import 'package:appflowy/plugins/inline_actions/service_handler.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy/workspace/application/workspace/workspace_listener.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-folder/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
// const _channel = "InlinePageReference";
// TODO(Mathias): Clean up and use folder search instead
class InlinePageReferenceService extends InlineActionsDelegate {
InlinePageReferenceService({
required this.currentViewId,
this.viewLayout,
this.customTitle,
this.insertPage = false,
this.limitResults = 0,
}) {
this.limitResults = 5,
}) : assert(limitResults > 0, 'limitResults must be greater than 0') {
init();
}
@ -48,147 +47,102 @@ class InlinePageReferenceService extends InlineActionsDelegate {
///
final bool insertPage;
/// Defaults to 0 where there are no limits
/// Anything above 0 will limit the page reference results
/// Defaults to 5
/// Will limit the page reference results
/// to [limitResults].
///
final int limitResults;
final ViewBackendService service = ViewBackendService();
List<InlineActionsMenuItem> _items = [];
List<InlineActionsMenuItem> _filtered = [];
late final CachedRecentService _recentService;
UserProfilePB? _user;
String? _workspaceId;
WorkspaceListener? _listener;
bool _recentViewsInitialized = false;
late final List<InlineActionsMenuItem> _recentViews;
Future<void> init() async {
_items = await _generatePageItems(currentViewId, viewLayout);
_filtered = limitResults > 0 ? _items.take(limitResults).toList() : _items;
Future<List<InlineActionsMenuItem>> _getRecentViews() async {
if (_recentViewsInitialized) {
return _recentViews;
}
await _initWorkspaceListener();
_recentViewsInitialized = true;
_initCompleter.complete();
}
final views =
(await _recentService.recentViews()).reversed.toSet().toList();
Future<void> _initWorkspaceListener() async {
final snapshot = await Future.wait([
FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(),
]);
final (workspaceSettings, userProfile) = (snapshot.first, snapshot.last);
_workspaceId = workspaceSettings.fold(
(s) => (s as WorkspaceSettingPB).workspaceId,
(e) => null,
// Filter by viewLayout
views.retainWhere(
(i) =>
currentViewId != i.id &&
(viewLayout == null || i.layout == viewLayout),
);
_user = userProfile.fold((s) => s as UserProfilePB, (e) => null);
// Map to InlineActionsMenuItem, then take 5 items
return _recentViews = views.map(_fromView).take(5).toList();
}
if (_user != null && _workspaceId != null) {
_listener = WorkspaceListener(
user: _user!,
workspaceId: _workspaceId!,
);
_listener!.start(
appsChanged: (_) async {
_items = await _generatePageItems(currentViewId, viewLayout);
_filtered =
limitResults > 0 ? _items.take(limitResults).toList() : _items;
},
);
bool _viewsInitialized = false;
late final List<ViewPB> _allViews;
Future<List<ViewPB>> _getViews() async {
if (_viewsInitialized) {
return _allViews;
}
_viewsInitialized = true;
final viewResult = await ViewBackendService.getAllViews();
return _allViews = viewResult
.toNullable()
?.items
.where((v) => viewLayout == null || v.layout == viewLayout)
.toList() ??
const [];
}
Future<void> init() async {
_recentService = getIt<CachedRecentService>();
// _searchListener.start(onResultsClosed: _onResults);
}
@override
Future<void> dispose() async {
if (!_initCompleter.isCompleted) {
_initCompleter.complete();
}
await super.dispose();
}
@override
Future<InlineActionsResult> search([
String? search,
]) async {
_filtered = await _filterItems(search);
final isSearching = search != null && search.isNotEmpty;
late List<InlineActionsMenuItem> items;
if (isSearching) {
final allViews = await _getViews();
items = allViews
.where(
(view) => view.name.toLowerCase().contains(search.toLowerCase()),
)
.take(limitResults)
.map((view) => _fromView(view))
.toList();
} else {
items = await _getRecentViews();
}
return InlineActionsResult(
title: customTitle?.isNotEmpty == true
? customTitle!
: LocaleKeys.inlineActions_pageReference.tr(),
results: _filtered,
: isSearching
? LocaleKeys.inlineActions_pageReference.tr()
: LocaleKeys.inlineActions_recentPages.tr(),
results: items,
);
}
@override
Future<void> dispose() async {
await _listener?.stop();
}
Future<List<InlineActionsMenuItem>> _filterItems(String? search) async {
await _initCompleter.future;
final items = (search == null || search.isEmpty)
? _items
: _items.where(
(item) =>
item.keywords != null &&
item.keywords!.isNotEmpty &&
item.keywords!.any(
(keyword) => keyword.contains(search.toLowerCase()),
),
);
return limitResults > 0
? items.take(limitResults).toList()
: items.toList();
}
Future<List<InlineActionsMenuItem>> _generatePageItems(
String currentViewId,
ViewLayoutPB? viewLayout,
) async {
late List<ViewPB> views;
if (viewLayout != null) {
views = await service.fetchViewsWithLayoutType(viewLayout);
} else {
views = await service.fetchViews();
}
if (views.isEmpty) {
return [];
}
final List<InlineActionsMenuItem> pages = [];
views.sort((a, b) => b.createTime.compareTo(a.createTime));
for (final view in views) {
if (view.id == currentViewId) {
continue;
}
final pageSelectionMenuItem = InlineActionsMenuItem(
keywords: [view.name.toLowerCase()],
label: view.name,
icon: (onSelected) => view.icon.value.isNotEmpty
? EmojiText(
emoji: view.icon.value,
fontSize: 12,
textAlign: TextAlign.center,
lineHeight: 1.3,
)
: view.defaultIcon(),
onSelected: (context, editorState, menuService, replace) => insertPage
? _onInsertPageRef(view, context, editorState, replace)
: _onInsertLinkRef(
view,
context,
editorState,
menuService,
replace,
),
);
pages.add(pageSelectionMenuItem);
}
return pages;
}
Future<void> _onInsertPageRef(
ViewPB view,
BuildContext context,
@ -268,4 +222,32 @@ class InlinePageReferenceService extends InlineActionsDelegate {
await editorState.apply(transaction);
}
InlineActionsMenuItem _fromView(ViewPB view) => InlineActionsMenuItem(
keywords: [view.name.toLowerCase()],
label: view.name,
icon: (onSelected) => view.icon.value.isNotEmpty
? EmojiText(
emoji: view.icon.value,
fontSize: 12,
textAlign: TextAlign.center,
lineHeight: 1.3,
)
: view.defaultIcon(),
onSelected: (context, editorState, menu, replace) => insertPage
? _onInsertPageRef(view, context, editorState, replace)
: _onInsertLinkRef(view, context, editorState, menu, replace),
);
// Future<InlineActionsMenuItem?> _fromSearchResult(
// SearchResultPB result,
// ) async {
// final viewRes = await ViewBackendService.getView(result.viewId);
// final view = viewRes.toNullable();
// if (view == null) {
// return null;
// }
// return _fromView(view);
// }
}

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@ -79,6 +81,8 @@ class _InlineActionsHandlerState extends State<InlineActionsHandler> {
final _focusNode = FocusNode(debugLabel: 'inline_actions_menu_handler');
final _scrollController = ScrollController();
Timer? _debounce;
late List<InlineActionsResult> results = widget.results;
int invalidCounter = 0;
late int startOffset;
@ -86,7 +90,8 @@ class _InlineActionsHandlerState extends State<InlineActionsHandler> {
String _search = '';
set search(String search) {
_search = search;
_doSearch();
_debounce?.cancel();
_debounce = Timer(const Duration(milliseconds: 200), _doSearch);
}
Future<void> _doSearch() async {
@ -138,6 +143,7 @@ class _InlineActionsHandlerState extends State<InlineActionsHandler> {
void dispose() {
_scrollController.dispose();
_focusNode.dispose();
_debounce?.cancel();
super.dispose();
}

View File

@ -29,6 +29,9 @@ enum FeatureFlag {
// if it's on, the collaborators will show in the database
syncDatabase,
// used for the search feature
search,
// used for ignore the conflicted feature flag
unknown;
@ -98,15 +101,13 @@ enum FeatureFlag {
switch (this) {
case FeatureFlag.collaborativeWorkspace:
return false;
case FeatureFlag.membersSettings:
return false;
case FeatureFlag.syncDocument:
return true;
case FeatureFlag.syncDatabase:
return true;
case FeatureFlag.search:
case FeatureFlag.unknown:
return false;
case FeatureFlag.syncDocument:
case FeatureFlag.syncDatabase:
return true;
}
}
@ -120,6 +121,8 @@ enum FeatureFlag {
return 'if it\'s on, the document will be synced in real-time';
case FeatureFlag.syncDatabase:
return 'if it\'s on, the collaborators will show in the database';
case FeatureFlag.search:
return 'if it\'s on, the command palette and search button will be available';
case FeatureFlag.unknown:
return '';
}

View File

@ -21,6 +21,7 @@ import 'package:appflowy/user/presentation/router.dart';
import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart';
import 'package:appflowy/workspace/application/edit_panel/edit_panel_bloc.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
import 'package:appflowy/workspace/application/settings/appearance/desktop_appearance.dart';
import 'package:appflowy/workspace/application/settings/appearance/mobile_appearance.dart';
@ -171,6 +172,7 @@ void _resolveUserDeps(GetIt getIt, IntegrationMode mode) {
getIt.registerFactory<EditPanelBloc>(() => EditPanelBloc());
getIt.registerFactory<SplashBloc>(() => SplashBloc());
getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
getIt.registerLazySingleton<CachedRecentService>(() => CachedRecentService());
}
void _resolveHomeDeps(GetIt getIt) {
@ -203,12 +205,10 @@ void _resolveHomeDeps(GetIt getIt) {
}
void _resolveFolderDeps(GetIt getIt) {
//workspace
// Workspace
getIt.registerFactoryParam<WorkspaceListener, UserProfilePB, String>(
(user, workspaceId) => WorkspaceListener(
user: user,
workspaceId: workspaceId,
),
(user, workspaceId) =>
WorkspaceListener(user: user, workspaceId: workspaceId),
);
getIt.registerFactoryParam<ViewBloc, ViewPB, void>(
@ -217,21 +217,23 @@ void _resolveFolderDeps(GetIt getIt) {
),
);
//Settings
// Settings
getIt.registerFactoryParam<SettingsDialogBloc, UserProfilePB, void>(
(user, _) => SettingsDialogBloc(user),
);
//User
// User
getIt.registerFactoryParam<SettingsUserViewBloc, UserProfilePB, void>(
(user, _) => SettingsUserViewBloc(user),
);
// trash
// Trash
getIt.registerLazySingleton<TrashService>(() => TrashService());
getIt.registerLazySingleton<TrashListener>(() => TrashListener());
getIt.registerFactory<TrashBloc>(
() => TrashBloc(),
);
// Favorite
getIt.registerFactory<FavoriteBloc>(() => FavoriteBloc());
}

View File

@ -1,12 +1,13 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/startup/tasks/feature_flag_task.dart';
import 'package:appflowy/workspace/application/settings/prelude.dart';
import 'package:appflowy_backend/appflowy_backend.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:package_info_plus/package_info_plus.dart';
@ -136,6 +137,7 @@ class FlowyRunner {
if (isAppFlowyCloudEnabled) InitAppFlowyCloudTask(),
const InitAppWidgetTask(),
const InitPlatformServiceTask(),
const RecentServiceTask(),
],
],
);

View File

@ -5,11 +5,13 @@ import 'package:flutter/services.dart';
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/plugins/document/application/document_appearance_cubit.dart';
import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
import 'package:appflowy/user/application/user_settings_service.dart';
import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart';
import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart';
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
import 'package:appflowy/workspace/application/notification/notification_service.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy/workspace/application/settings/notifications/notification_settings_cubit.dart';
@ -126,18 +128,27 @@ class ApplicationWidget extends StatefulWidget {
class _ApplicationWidgetState extends State<ApplicationWidget> {
late final GoRouter routerConfig;
final _commandPaletteNotifier = ValueNotifier<bool>(false);
@override
void initState() {
super.initState();
// avoid rebuild routerConfig when the appTheme is changed.
// Avoid rebuild routerConfig when the appTheme is changed.
routerConfig = generateRouter(widget.child);
}
@override
void dispose() {
_commandPaletteNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
if (FeatureFlag.search.isOn)
BlocProvider<CommandPaletteBloc>(create: (_) => CommandPaletteBloc()),
BlocProvider<AppearanceSettingsCubit>(
create: (_) => AppearanceSettingsCubit(
widget.appearanceSetting,
@ -152,10 +163,7 @@ class _ApplicationWidgetState extends State<ApplicationWidget> {
create: (_) => DocumentAppearanceCubit()..fetch(),
),
BlocProvider.value(value: getIt<RenameViewBloc>()),
BlocProvider.value(
value: getIt<ActionNavigationBloc>()
..add(const ActionNavigationEvent.initialize()),
),
BlocProvider.value(value: getIt<ActionNavigationBloc>()),
BlocProvider.value(
value: getIt<ReminderBloc>()..add(const ReminderEvent.started()),
),
@ -196,10 +204,12 @@ class _ApplicationWidgetState extends State<ApplicationWidget> {
),
child: overlayManagerBuilder(
context,
CommandPalette(
toggleNotifier: ValueNotifier<bool>(false),
child: child,
),
FeatureFlag.search.isOn
? CommandPalette(
toggleNotifier: _commandPaletteNotifier,
child: child,
)
: child,
),
),
debugShowCheckedModeBanner: false,

View File

@ -12,3 +12,4 @@ export 'platform_service.dart';
export 'rust_sdk.dart';
export 'supabase_task.dart';
export 'windows.dart';
export 'recent_service_task.dart';

View File

@ -0,0 +1,14 @@
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/recent/prelude.dart';
import 'package:appflowy_backend/log.dart';
class RecentServiceTask extends LaunchTask {
const RecentServiceTask();
@override
Future<void> initialize(LaunchContext context) async =>
Log.info('[CachedRecentService] Initialized');
@override
Future<void> dispose() async => getIt<CachedRecentService>().dispose();
}

View File

@ -1,10 +1,5 @@
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy/workspace/application/workspace/workspace_listener.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -15,15 +10,21 @@ class ActionNavigationBloc
ActionNavigationBloc() : super(const ActionNavigationState.initial()) {
on<ActionNavigationEvent>((event, emit) async {
await event.when(
initialize: () async {
final views = await ViewBackendService().fetchViews();
emit(state.copyWith(views: views));
await initializeListeners();
},
viewsChanged: (views) {
emit(state.copyWith(views: views));
},
performAction: (action, nextActions) {
performAction: (action, nextActions) async {
NavigationAction currentAction = action;
if (currentAction.arguments?[ActionArgumentKeys.view] == null &&
action.type == ActionType.openView) {
final result = await ViewBackendService.getView(action.objectId);
final view = result.toNullable();
if (view != null) {
if (currentAction.arguments == null) {
currentAction = currentAction.copyWith(arguments: {});
}
action.arguments?.addAll({ActionArgumentKeys.view: view});
}
}
emit(state.copyWith(action: action, nextActions: nextActions));
if (nextActions.isNotEmpty) {
@ -43,92 +44,38 @@ class ActionNavigationBloc
);
});
}
WorkspaceListener? _workspaceListener;
@override
Future<void> close() async {
await _workspaceListener?.stop();
return super.close();
}
Future<void> initializeListeners() async {
if (_workspaceListener != null) {
return;
}
final userOrFailure = await getIt<AuthService>().getUser();
final user = userOrFailure.fold((s) => s, (f) => null);
if (user == null) {
_workspaceListener = null;
return;
}
final workspaceSettingsOrFailure =
await FolderEventGetCurrentWorkspaceSetting().send();
final workspaceId = workspaceSettingsOrFailure.fold(
(s) => s.workspaceId,
(f) => null,
);
if (workspaceId == null) {
_workspaceListener = null;
return;
}
_workspaceListener = WorkspaceListener(
user: user,
workspaceId: workspaceId,
);
_workspaceListener?.start(
appsChanged: (_) async {
final views = await ViewBackendService().fetchViews();
add(ActionNavigationEvent.viewsChanged(views));
},
);
}
}
@freezed
class ActionNavigationEvent with _$ActionNavigationEvent {
const factory ActionNavigationEvent.initialize() = _Initialize;
const factory ActionNavigationEvent.performAction({
required NavigationAction action,
@Default([]) List<NavigationAction> nextActions,
}) = _PerformAction;
const factory ActionNavigationEvent.viewsChanged(List<ViewPB> views) =
_ViewsChanged;
}
class ActionNavigationState {
const ActionNavigationState.initial()
: action = null,
nextActions = const [],
views = const [];
nextActions = const [];
const ActionNavigationState({
required this.action,
this.nextActions = const [],
this.views = const [],
});
final NavigationAction? action;
final List<NavigationAction> nextActions;
final List<ViewPB> views;
ActionNavigationState copyWith({
NavigationAction? action,
List<NavigationAction>? nextActions,
List<ViewPB>? views,
}) =>
ActionNavigationState(
action: action ?? this.action,
nextActions: nextActions ?? this.nextActions,
views: views ?? this.views,
);
ActionNavigationState setNoAction() =>
ActionNavigationState(action: null, nextActions: [], views: views);
const ActionNavigationState(action: null);
}

View File

@ -7,12 +7,14 @@ import 'package:appflowy/plugins/trash/application/trash_service.dart';
import 'package:appflowy/workspace/application/command_palette/search_listener.dart';
import 'package:appflowy/workspace/application/command_palette/search_service.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'command_palette_bloc.freezed.dart';
const _searchChannel = 'CommandPalette';
class CommandPaletteBloc
extends Bloc<CommandPaletteEvent, CommandPaletteState> {
CommandPaletteBloc() : super(CommandPaletteState.initial()) {
@ -27,9 +29,12 @@ class CommandPaletteBloc
Timer? _debounceOnChanged;
final TrashService _trashService = TrashService();
final SearchListener _searchListener = SearchListener();
final SearchListener _searchListener = SearchListener(
channel: _searchChannel,
);
final TrashListener _trashListener = TrashListener();
String? _oldQuery;
String? _workspaceId;
@override
Future<void> close() {
@ -44,8 +49,7 @@ class CommandPaletteBloc
searchChanged: _debounceOnSearchChanged,
trashChanged: (trash) async {
if (trash != null) {
emit(state.copyWith(trash: trash));
return;
return emit(state.copyWith(trash: trash));
}
final trashOrFailure = await _trashService.readTrash();
@ -59,10 +63,14 @@ class CommandPaletteBloc
}
},
performSearch: (search) async {
if (search.isNotEmpty) {
if (search.isNotEmpty && search != state.query) {
_oldQuery = state.query;
emit(state.copyWith(query: search, isLoading: true));
await SearchBackendService.performSearch(search);
await SearchBackendService.performSearch(
search,
workspaceId: _workspaceId,
channel: _searchChannel,
);
} else {
emit(state.copyWith(query: null, isLoading: false, results: []));
}
@ -82,6 +90,10 @@ class CommandPaletteBloc
),
);
},
workspaceChanged: (workspaceId) {
_workspaceId = workspaceId;
emit(state.copyWith(results: [], query: '', isLoading: false));
},
);
});
}
@ -162,6 +174,10 @@ class CommandPaletteEvent with _$CommandPaletteEvent {
const factory CommandPaletteEvent.trashChanged({
@Default(null) List<TrashPB>? trash,
}) = _TrashChanged;
const factory CommandPaletteEvent.workspaceChanged({
@Default(null) String? workspaceId,
}) = _WorkspaceChanged;
}
@freezed

View File

@ -4,7 +4,8 @@ import 'dart:typed_data';
import 'package:appflowy/core/notification/search_notification.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/notification.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
import 'package:appflowy_result/appflowy_result.dart';
import 'package:flowy_infra/notifier.dart';
@ -12,7 +13,15 @@ import 'package:flowy_infra/notifier.dart';
const _searchObjectId = "SEARCH_IDENTIFIER";
class SearchListener {
SearchListener();
SearchListener({this.channel});
/// Use this to filter out search results from other channels.
///
/// If null, it will receive search results from all
/// channels, otherwise it will only receive search results from the specified
/// channel.
///
final String? channel;
PublishNotifier<RepeatedSearchResultPB>? _updateNotifier = PublishNotifier();
PublishNotifier<RepeatedSearchResultPB>? _updateDidCloseNotifier =
@ -20,14 +29,21 @@ class SearchListener {
SearchNotificationListener? _listener;
void start({
required void Function(RepeatedSearchResultPB) onResultsChanged,
required void Function(RepeatedSearchResultPB) onResultsClosed,
void Function(RepeatedSearchResultPB)? onResultsChanged,
void Function(RepeatedSearchResultPB)? onResultsClosed,
}) {
_updateNotifier?.addPublishListener(onResultsChanged);
_updateDidCloseNotifier?.addPublishListener(onResultsClosed);
if (onResultsChanged != null) {
_updateNotifier?.addPublishListener(onResultsChanged);
}
if (onResultsClosed != null) {
_updateDidCloseNotifier?.addPublishListener(onResultsClosed);
}
_listener = SearchNotificationListener(
objectId: _searchObjectId,
handler: _handler,
channel: channel,
);
}

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
extension GetIcon on SearchResultPB {
Widget? getIcon() {

View File

@ -1,13 +1,21 @@
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/query.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/search_filter.pb.dart';
import 'package:appflowy_result/appflowy_result.dart';
class SearchBackendService {
static Future<FlowyResult<void, FlowyError>> performSearch(
String keyword,
) async {
final request = SearchQueryPB(search: keyword);
String keyword, {
String? workspaceId,
String? channel,
}) async {
final filter = SearchFilterPB(workspaceId: workspaceId);
final request = SearchQueryPB(
search: keyword,
filter: filter,
channel: channel,
);
return SearchEventSearch(request).send();
}

View File

@ -1,15 +0,0 @@
import 'dart:async';
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_result/appflowy_result.dart';
class HomeService {
static Future<FlowyResult<ViewPB, FlowyError>> readApp({
required String appId,
}) {
final payload = ViewIdPB.create()..value = appId;
return FolderEventGetView(payload).send();
}
}

View File

@ -0,0 +1,87 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/recent/recent_listener.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_result/appflowy_result.dart';
/// This is a lazy-singleton to share recent views across the application.
///
/// Use-cases:
/// - Desktop: Command Palette recent view history
/// - Desktop: (Documents) Inline-page reference recent view history
/// - Mobile: Recent view history on home screen
///
/// See the related [LaunchTask] in [RecentServiceTask].
///
class CachedRecentService {
CachedRecentService();
Completer<void> _completer = Completer();
ValueNotifier<List<ViewPB>> notifier = ValueNotifier(const []);
List<ViewPB> _recentViews = const [];
final _listener = RecentViewsListener();
Future<List<ViewPB>> recentViews() async {
if (_isInitialized) return _recentViews;
_isInitialized = true;
_listener.start(recentViewsUpdated: _recentViewsUpdated);
final result = await _readRecentViews();
_recentViews = result.toNullable()?.items ?? const [];
notifier.value = _recentViews;
_completer.complete();
return _recentViews;
}
/// Updates the recent views history
Future<FlowyResult<void, FlowyError>> updateRecentViews(
List<String> viewIds,
bool addInRecent,
) async {
return FolderEventUpdateRecentViews(
UpdateRecentViewPayloadPB(viewIds: viewIds, addInRecent: addInRecent),
).send();
}
Future<FlowyResult<RepeatedViewPB, FlowyError>> _readRecentViews() =>
FolderEventReadRecentViews().send();
bool _isInitialized = false;
Future<void> reset() async {
await _listener.stop();
_resetCompleter();
_isInitialized = false;
_recentViews = const [];
}
Future<void> dispose() async {
await _listener.stop();
}
void _recentViewsUpdated(
FlowyResult<RepeatedViewIdPB, FlowyError> result,
) {
final viewIds = result.toNullable();
if (viewIds != null) {
_readRecentViews().then(
(views) => _recentViews = views.toNullable()?.items ?? const [],
);
}
}
void _resetCompleter() {
if (!_completer.isCompleted) {
_completer.complete();
}
_completer = Completer<void>();
}
}

View File

@ -1,2 +1,2 @@
export 'recent_service.dart';
export 'cached_recent_service.dart';
export 'recent_views_bloc.dart';

View File

@ -1,19 +0,0 @@
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart';
import 'package:appflowy_result/appflowy_result.dart';
class RecentService {
Future<FlowyResult<void, FlowyError>> updateRecentViews(
List<String> viewIds,
bool addInRecent,
) async {
return FolderEventUpdateRecentViews(
UpdateRecentViewPayloadPB(viewIds: viewIds, addInRecent: addInRecent),
).send();
}
Future<FlowyResult<RepeatedViewPB, FlowyError>> readRecentViews() {
return FolderEventReadRecentViews().send();
}
}

View File

@ -1,9 +1,6 @@
import 'package:appflowy/workspace/application/recent/recent_listener.dart';
import 'package:appflowy/workspace/application/recent/recent_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_result/appflowy_result.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
@ -11,15 +8,15 @@ part 'recent_views_bloc.freezed.dart';
class RecentViewsBloc extends Bloc<RecentViewsEvent, RecentViewsState> {
RecentViewsBloc() : super(RecentViewsState.initial()) {
_service = getIt<CachedRecentService>();
_dispatch();
}
final _service = RecentService();
final _listener = RecentViewsListener();
late final CachedRecentService _service;
@override
Future<void> close() async {
await _listener.stop();
_service.notifier.removeListener(_onRecentViewsUpdated);
return super.close();
}
@ -28,9 +25,7 @@ class RecentViewsBloc extends Bloc<RecentViewsEvent, RecentViewsState> {
(event, emit) async {
await event.map(
initial: (e) async {
_listener.start(
recentViewsUpdated: (result) => _onRecentViewsUpdated(result),
);
_service.notifier.addListener(_onRecentViewsUpdated);
add(const RecentViewsEvent.fetchRecentViews());
},
addRecentViews: (e) async {
@ -40,22 +35,15 @@ class RecentViewsBloc extends Bloc<RecentViewsEvent, RecentViewsState> {
await _service.updateRecentViews(e.viewIds, false);
},
fetchRecentViews: (e) async {
final result = await _service.readRecentViews();
result.fold(
(views) => emit(state.copyWith(views: views.items)),
(error) => Log.error(error),
);
emit(state.copyWith(views: await _service.recentViews()));
},
);
},
);
}
void _onRecentViewsUpdated(
FlowyResult<RepeatedViewIdPB, FlowyError> result,
) {
add(const RecentViewsEvent.fetchRecentViews());
}
void _onRecentViewsUpdated() =>
add(const RecentViewsEvent.fetchRecentViews());
}
@freezed
@ -74,7 +62,5 @@ class RecentViewsState with _$RecentViewsState {
required List<ViewPB> views,
}) = _RecentViewsState;
factory RecentViewsState.initial() => const RecentViewsState(
views: [],
);
factory RecentViewsState.initial() => const RecentViewsState(views: []);
}

View File

@ -1,12 +1,14 @@
import 'package:flutter/foundation.dart';
import 'package:appflowy/plugins/util.dart';
import 'package:appflowy/startup/plugin/plugin.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
import 'package:appflowy/workspace/presentation/home/menu/menu_shared_state.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:bloc/bloc.dart';
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'tabs_bloc.freezed.dart';
@ -81,11 +83,15 @@ class TabsBloc extends Bloc<TabsEvent, TabsState> {
void openPlugin(
ViewPB view, {
Map<String, dynamic> arguments = const {},
}) =>
add(
TabsEvent.openPlugin(
plugin: view.plugin(arguments: arguments),
view: view,
),
);
}) {
add(
TabsEvent.openPlugin(
plugin: view.plugin(arguments: arguments),
view: view,
),
);
// Update recent views
getIt<CachedRecentService>().updateRecentViews([view.id], true);
}
}

View File

@ -4,7 +4,7 @@ import 'package:appflowy/core/config/kv.dart';
import 'package:appflowy/core/config/kv_keys.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/favorite/favorite_listener.dart';
import 'package:appflowy/workspace/application/recent/recent_service.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy/workspace/application/view/view_listener.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
@ -88,9 +88,7 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
await _setViewIsExpanded(view, e.isExpanded);
},
viewDidUpdate: (e) async {
final result = await ViewBackendService.getView(
view.id,
);
final result = await ViewBackendService.getView(view.id);
final view_ = result.fold((l) => l, (r) => null);
e.result.fold(
(view) async {
@ -146,7 +144,10 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
),
),
);
await RecentService().updateRecentViews([view.id], false);
await getIt<CachedRecentService>().updateRecentViews(
[view.id],
false,
);
},
duplicate: (e) async {
final result = await ViewBackendService.duplicate(view: view);
@ -313,9 +314,7 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
}
if (update.updateChildViews.isNotEmpty) {
final view = await ViewBackendService.getView(
update.parentViewId,
);
final view = await ViewBackendService.getView(update.parentViewId);
final childViews = view.fold((l) => l.childViews, (r) => []);
bool isSameOrder = true;
if (childViews.length == update.updateChildViews.length) {

View File

@ -99,9 +99,7 @@ class ViewBackendService {
layoutType: layoutType,
parentViewId: parentViewId,
name: name,
ext: {
'database_id': databaseId,
},
ext: {'database_id': databaseId},
);
}
@ -215,49 +213,13 @@ class ViewBackendService {
return FolderEventMoveNestedView(payload).send();
}
Future<List<ViewPB>> fetchViewsWithLayoutType(
ViewLayoutPB? layoutType,
) async {
final views = await fetchViews();
if (layoutType == null) {
return views;
}
return views
.where(
(element) => layoutType == element.layout,
)
.toList();
}
Future<List<ViewPB>> fetchViews() async {
final result = <ViewPB>[];
return FolderEventReadCurrentWorkspace().send().then((value) async {
final workspace = value.toNullable();
if (workspace != null) {
final views = workspace.views;
for (final view in views) {
result.add(view);
final childViews = await getAllViews(view);
result.addAll(childViews);
}
}
return result;
});
}
Future<List<ViewPB>> getAllViews(ViewPB view) async {
final result = <ViewPB>[];
final childViews = await getChildViews(viewId: view.id).then(
(value) => value.toNullable(),
);
if (childViews != null && childViews.isNotEmpty) {
result.addAll(childViews);
final views = await Future.wait(
childViews.map((e) async => getAllViews(e)),
);
result.addAll(views.expand((element) => element));
}
return result;
/// Fetches a flattened list of all Views.
///
/// Views do not contain their children in this list, as they all exist
/// in the same level in this version.
///
static Future<FlowyResult<RepeatedViewPB, FlowyError>> getAllViews() async {
return FolderEventGetAllViews().send();
}
static Future<FlowyResult<ViewPB, FlowyError>> getView(

View File

@ -61,7 +61,6 @@ class _CommandPaletteController extends StatefulWidget {
}
class _CommandPaletteControllerState extends State<_CommandPaletteController> {
late final CommandPaletteBloc _commandPaletteBloc;
late ValueNotifier<bool> _toggleNotifier = widget.toggleNotifier;
bool _isOpen = false;
@ -86,31 +85,28 @@ class _CommandPaletteControllerState extends State<_CommandPaletteController> {
void initState() {
super.initState();
_toggleNotifier.addListener(_onToggle);
_commandPaletteBloc = CommandPaletteBloc();
}
@override
void dispose() {
_toggleNotifier.removeListener(_onToggle);
_toggleNotifier.dispose();
_commandPaletteBloc.close();
super.dispose();
}
void _onToggle() {
if (widget.toggleNotifier.value && !_isOpen) {
if (_toggleNotifier.value && !_isOpen) {
_isOpen = true;
FlowyOverlay.show(
context: context,
builder: (_) => BlocProvider.value(
value: _commandPaletteBloc,
value: context.read<CommandPaletteBloc>(),
child: CommandPaletteModal(shortcutBuilder: _buildShortcut),
),
).then((_) {
_isOpen = false;
widget.toggleNotifier.value = false;
_toggleNotifier.value = false;
});
} else if (!widget.toggleNotifier.value && _isOpen) {
} else if (!_toggleNotifier.value && _isOpen) {
FlowyOverlay.pop(context);
_isOpen = false;
}
@ -148,52 +144,48 @@ class CommandPaletteModal extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<CommandPaletteBloc, CommandPaletteState>(
builder: (context, state) {
return FlowyDialog(
alignment: Alignment.topCenter,
insetPadding: const EdgeInsets.only(top: 100),
constraints: const BoxConstraints(maxHeight: 420, maxWidth: 510),
expandHeight: false,
child: shortcutBuilder(
Column(
mainAxisSize: MainAxisSize.min,
children: [
SearchField(query: state.query, isLoading: state.isLoading),
if ((state.query?.isEmpty ?? true) ||
state.isLoading && state.results.isEmpty) ...[
const Divider(height: 0),
Flexible(
child: RecentViewsList(
onSelected: () => FlowyOverlay.pop(context),
),
builder: (context, state) => FlowyDialog(
alignment: Alignment.topCenter,
insetPadding: const EdgeInsets.only(top: 100),
constraints: const BoxConstraints(maxHeight: 420, maxWidth: 510),
expandHeight: false,
child: shortcutBuilder(
Column(
mainAxisSize: MainAxisSize.min,
children: [
SearchField(query: state.query, isLoading: state.isLoading),
if ((state.query?.isEmpty ?? true) ||
state.isLoading && state.results.isEmpty) ...[
const Divider(height: 0),
Flexible(
child: RecentViewsList(
onSelected: () => FlowyOverlay.pop(context),
),
],
if (state.results.isNotEmpty) ...[
const Divider(height: 0),
Flexible(
child: SearchResultsList(
trash: state.trash,
results: state.results,
),
),
],
_CommandPaletteFooter(
shouldShow: state.results.isNotEmpty &&
(state.query?.isNotEmpty ?? false),
),
],
),
if (state.results.isNotEmpty) ...[
const Divider(height: 0),
Flexible(
child: SearchResultsList(
trash: state.trash,
results: state.results,
),
),
],
_CommandPaletteFooter(
shouldShow: state.results.isNotEmpty &&
(state.query?.isNotEmpty ?? false),
),
],
),
);
},
),
),
);
}
}
class _CommandPaletteFooter extends StatelessWidget {
const _CommandPaletteFooter({
required this.shouldShow,
});
const _CommandPaletteFooter({required this.shouldShow});
final bool shouldShow;
@ -204,38 +196,22 @@ class _CommandPaletteFooter extends StatelessWidget {
}
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: Theme.of(context).dividerColor,
),
),
border: Border(top: BorderSide(color: Theme.of(context).dividerColor)),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 5,
vertical: 1,
),
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 1),
decoration: BoxDecoration(
color: AFThemeExtension.of(context).lightGreyHover,
borderRadius: BorderRadius.circular(4),
),
child: const FlowyText.semibold(
'TAB',
fontSize: 10,
),
child: const FlowyText.semibold('TAB', fontSize: 10),
),
const HSpace(4),
FlowyText(
LocaleKeys.commandPalette_navigateHint.tr(),
fontSize: 11,
),
FlowyText(LocaleKeys.commandPalette_navigateHint.tr(), fontSize: 11),
],
),
);

View File

@ -5,7 +5,7 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart';
import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart';
import 'package:appflowy/workspace/application/command_palette/search_result_ext.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/workspace/presentation/command_palette/widgets/search_result_tile.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-search/result.pb.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -6,12 +6,12 @@ import 'package:appflowy/user/application/auth/auth_service.dart';
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/home/home_bloc.dart';
import 'package:appflowy/workspace/application/home/home_service.dart';
import 'package:appflowy/workspace/application/home/home_setting_bloc.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/application/view/view_service.dart';
import 'package:appflowy/workspace/presentation/home/errors/workspace_failed_screen.dart';
import 'package:appflowy/workspace/presentation/home/hotkeys.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar.dart';
@ -298,8 +298,8 @@ class DesktopHomeScreenStackAdaptor extends HomeStackDelegate {
@override
void didDeleteStackWidget(ViewPB view, int? index) {
HomeService.readApp(appId: view.parentViewId).then((result) {
result.fold(
ViewBackendService.getView(view.parentViewId).then(
(result) => result.fold(
(parentView) {
final List<ViewPB> views = parentView.childViews;
if (views.isNotEmpty) {
@ -316,7 +316,7 @@ class DesktopHomeScreenStackAdaptor extends HomeStackDelegate {
.add(TabsEvent.openPlugin(plugin: BlankPagePlugin()));
},
(err) => Log.error(err),
);
});
),
);
}
}

View File

@ -1,14 +1,22 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/shared/feature_flags.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/workspace/application/action_navigation/action_navigation_bloc.dart';
import 'package:appflowy/workspace/application/action_navigation/navigation_action.dart';
import 'package:appflowy/workspace/application/command_palette/command_palette_bloc.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/favorite/prelude.dart';
import 'package:appflowy/workspace/application/menu/sidebar_sections_bloc.dart';
import 'package:appflowy/workspace/application/recent/cached_recent_service.dart';
import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart';
import 'package:appflowy/workspace/application/user/user_workspace_bloc.dart';
import 'package:appflowy/workspace/application/view/view_ext.dart';
import 'package:appflowy/workspace/presentation/command_palette/command_palette.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_folder.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_new_page_button.dart';
import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar_top_menu.dart';
@ -19,8 +27,10 @@ import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'
show UserProfilePB;
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:easy_localization/easy_localization.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';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
/// Home Sidebar is the left side bar of the home page.
@ -58,7 +68,23 @@ class HomeSideBar extends StatelessWidget {
// +-- Public Or Private Section: control the sections of the workspace
// |
// +-- Trash Section
return BlocBuilder<UserWorkspaceBloc, UserWorkspaceState>(
return BlocConsumer<UserWorkspaceBloc, UserWorkspaceState>(
listenWhen: (previous, current) =>
previous.currentWorkspace?.workspaceId !=
current.currentWorkspace?.workspaceId,
listener: (context, state) {
if (FeatureFlag.search.isOn) {
// Notify command palette that workspace has changed
context.read<CommandPaletteBloc>().add(
CommandPaletteEvent.workspaceChanged(
workspaceId: state.currentWorkspace?.workspaceId,
),
);
}
// Re-initialize workspace-specific services
getIt<CachedRecentService>().reset();
},
// Rebuild the whole sidebar when the current workspace changes
buildWhen: (previous, current) =>
previous.currentWorkspace?.workspaceId !=
@ -130,11 +156,9 @@ class HomeSideBar extends StatelessWidget {
) {
final action = state.action;
if (action?.type == ActionType.openView) {
final view = state.views.findView(action!.objectId);
final view = action!.arguments?[ActionArgumentKeys.view];
if (view != null) {
final Map<String, dynamic> arguments = {};
final nodePath = action.arguments?[ActionArgumentKeys.nodePath];
if (nodePath != null) {
arguments[PluginArgumentKeys.selection] = Selection.collapsed(
@ -186,6 +210,7 @@ class _SidebarState extends State<_Sidebar> {
@override
Widget build(BuildContext context) {
const menuHorizontalInset = EdgeInsets.symmetric(horizontal: 12);
final userState = context.read<UserWorkspaceBloc>().state;
return DecoratedBox(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceVariant,
@ -206,21 +231,17 @@ class _SidebarState extends State<_Sidebar> {
padding: menuHorizontalInset,
child:
// if the workspaces are empty, show the user profile instead
context.read<UserWorkspaceBloc>().state.isCollabWorkspaceOn &&
context
.read<UserWorkspaceBloc>()
.state
.workspaces
.isNotEmpty
? SidebarWorkspace(
userProfile: widget.userProfile,
)
: SidebarUser(
userProfile: widget.userProfile,
),
userState.isCollabWorkspaceOn && userState.workspaces.isNotEmpty
? SidebarWorkspace(userProfile: widget.userProfile)
: SidebarUser(userProfile: widget.userProfile),
),
const VSpace(20),
if (FeatureFlag.search.isOn) ...[
const VSpace(8),
const Padding(
padding: menuHorizontalInset,
child: _SidebarSearchButton(),
),
],
// scrollable document list
Expanded(
child: Padding(
@ -263,3 +284,16 @@ class _SidebarState extends State<_Sidebar> {
}
}
}
class _SidebarSearchButton extends StatelessWidget {
const _SidebarSearchButton();
@override
Widget build(BuildContext context) {
return FlowyButton(
onTap: () => CommandPalette.of(context).toggle(),
leftIcon: const FlowySvg(FlowySvgs.search_s),
text: FlowyText(LocaleKeys.search_label.tr()),
);
}
}

View File

@ -1,3 +1,5 @@
import 'package:flutter/material.dart';
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/widgets/loading.dart';
@ -14,7 +16,6 @@ import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class SidebarWorkspace extends StatefulWidget {
@ -147,7 +148,7 @@ class _SidebarWorkspaceState extends State<SidebarWorkspace> {
}
}
class SidebarSwitchWorkspaceButton extends StatefulWidget {
class SidebarSwitchWorkspaceButton extends StatelessWidget {
const SidebarSwitchWorkspaceButton({
super.key,
required this.userProfile,
@ -157,26 +158,15 @@ class SidebarSwitchWorkspaceButton extends StatefulWidget {
final UserWorkspacePB currentWorkspace;
final UserProfilePB userProfile;
@override
State<SidebarSwitchWorkspaceButton> createState() =>
_SidebarSwitchWorkspaceButtonState();
}
class _SidebarSwitchWorkspaceButtonState
extends State<SidebarSwitchWorkspaceButton> {
final controller = PopoverController();
@override
Widget build(BuildContext context) {
return AppFlowyPopover(
direction: PopoverDirection.bottomWithCenterAligned,
offset: const Offset(0, 10),
constraints: const BoxConstraints(maxWidth: 260, maxHeight: 600),
onOpen: () {
context.read<UserWorkspaceBloc>().add(
const UserWorkspaceEvent.fetchWorkspaces(),
);
},
onOpen: () => context
.read<UserWorkspaceBloc>()
.add(const UserWorkspaceEvent.fetchWorkspaces()),
popupBuilder: (_) {
return BlocProvider<UserWorkspaceBloc>.value(
value: context.read<UserWorkspaceBloc>(),
@ -188,7 +178,7 @@ class _SidebarSwitchWorkspaceButtonState
return const SizedBox.shrink();
}
return WorkspacesMenu(
userProfile: widget.userProfile,
userProfile: userProfile,
currentWorkspace: currentWorkspace,
workspaces: workspaces,
);
@ -197,8 +187,6 @@ class _SidebarSwitchWorkspaceButtonState
);
},
child: FlowyButton(
onTap: () => controller.show(),
useIntrinsicWidth: true,
margin: const EdgeInsets.symmetric(vertical: 8),
text: Row(
children: [
@ -206,7 +194,7 @@ class _SidebarSwitchWorkspaceButtonState
SizedBox.square(
dimension: 30.0,
child: WorkspaceIcon(
workspace: widget.currentWorkspace,
workspace: currentWorkspace,
iconSize: 20,
enableEdit: false,
),
@ -214,7 +202,7 @@ class _SidebarSwitchWorkspaceButtonState
const HSpace(6),
Expanded(
child: FlowyText.medium(
widget.currentWorkspace.name,
currentWorkspace.name,
overflow: TextOverflow.ellipsis,
withTooltip: true,
),

View File

@ -14,6 +14,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.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-search/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:appflowy_result/appflowy_result.dart';
import 'package:ffi/ffi.dart';
@ -25,8 +26,6 @@ import '../protobuf/flowy-config/entities.pb.dart';
import '../protobuf/flowy-config/event_map.pb.dart';
import '../protobuf/flowy-date/entities.pb.dart';
import '../protobuf/flowy-date/event_map.pb.dart';
import '../protobuf/flowy-search/entities.pb.dart';
import '../protobuf/flowy-search/event_map.pb.dart';
import 'error.dart';

View File

@ -75,14 +75,14 @@ void main() {
..add(const ViewEvent.initial());
await blocResponseFuture();
deleteViewBloc.add(const ViewEvent.delete());
await blocResponseFuture();
await blocResponseFuture(millisecond: 1000);
assert(context.viewBloc.state.view.childViews.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();
await blocResponseFuture(millisecond: 1000);
assert(context.viewBloc.state.view.childViews.length == 3);
assert(trashBloc.state.objects.isEmpty);
@ -92,8 +92,7 @@ void main() {
..add(const ViewEvent.initial());
await blocResponseFuture();
deleteViewBloc.add(const ViewEvent.delete());
await blocResponseFuture();
await blocResponseFuture();
await blocResponseFuture(millisecond: 1000);
}
expect(trashBloc.state.objects[0].id, context.allViews[0].id);
expect(trashBloc.state.objects[1].id, context.allViews[1].id);
@ -101,12 +100,12 @@ void main() {
// delete a view permanently
trashBloc.add(TrashEvent.delete(trashBloc.state.objects[0]));
await blocResponseFuture();
await blocResponseFuture(millisecond: 1000);
expect(trashBloc.state.objects.length, 2);
// delete all view permanently
trashBloc.add(const TrashEvent.deleteAll());
await blocResponseFuture();
await blocResponseFuture(millisecond: 1000);
assert(
trashBloc.state.objects.isEmpty,
"but receive ${trashBloc.state.objects.length}",

View File

@ -49,7 +49,7 @@ void main() {
const ViewEvent.initial(),
);
childViewBloc.add(const ViewEvent.duplicate());
await blocResponseFuture();
await blocResponseFuture(millisecond: 1000);
expect(viewBloc.state.view.childViews.length, 2);
});
@ -220,7 +220,7 @@ void main() {
section: ViewSectionPB.Public,
),
);
await blocResponseFuture();
await blocResponseFuture(millisecond: 1000);
expect(viewBloc.state.view.childViews.length, i + 1);
expect(viewBloc.state.view.childViews.last.name, 'Test $layout');
expect(viewBloc.state.view.childViews.last.layout, layout);

View File

@ -134,9 +134,9 @@ dependencies = [
[[package]]
name = "allocator-api2"
version = "0.2.18"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "android-tzdata"
@ -162,7 +162,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -191,6 +191,7 @@ dependencies = [
"flowy-document",
"flowy-error",
"flowy-notification",
"flowy-search",
"flowy-user",
"lib-dispatch",
"serde",
@ -205,9 +206,9 @@ dependencies = [
[[package]]
name = "arc-swap"
version = "1.7.1"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "arrayvec"
@ -739,7 +740,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"again",
"anyhow",
@ -785,7 +786,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"futures-channel",
"futures-util",
@ -859,7 +860,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -883,7 +884,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -913,7 +914,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -932,7 +933,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"bytes",
@ -947,7 +948,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"chrono",
@ -985,7 +986,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-stream",
@ -1024,7 +1025,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -1049,7 +1050,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -1063,7 +1064,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -1403,7 +1404,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -1583,9 +1584,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "downcast-rs"
version = "1.2.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dtoa"
@ -1721,9 +1722,9 @@ dependencies = [
[[package]]
name = "fastdivide"
version = "0.4.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59668941c55e5c186b8b58c391629af56774ec768f73c08bbcd56f09348eb00b"
checksum = "25c7df09945d65ea8d70b3321547ed414bbc540aad5bac6883d021b970f35b04"
[[package]]
name = "fastrand"
@ -2134,8 +2135,8 @@ dependencies = [
"protobuf",
"serde",
"serde_json",
"strsim 0.11.1",
"strum_macros 0.26.2",
"strsim 0.11.0",
"strum_macros 0.26.1",
"tantivy",
"tempfile",
"tokio",
@ -2769,7 +2770,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"futures-util",
@ -2786,7 +2787,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -3218,7 +3219,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"reqwest",
@ -3493,9 +3494,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "libloading"
@ -3608,9 +3609,9 @@ dependencies = [
[[package]]
name = "lz4_flex"
version = "0.11.3"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15"
[[package]]
name = "mac"
@ -3838,9 +3839,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]]
name = "murmurhash32"
version = "0.3.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2195bf6aa996a481483b29d62a7663eed3fe39600c460e323f8ff41e90bdd89b"
checksum = "d9380db4c04d219ac5c51d14996bbf2c2e9a15229771b53f8671eb6c83cf44df"
[[package]]
name = "nanoid"
@ -4721,7 +4722,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2"
dependencies = [
"bytes",
"heck 0.4.1",
"itertools 0.10.5",
"itertools 0.11.0",
"log",
"multimap",
"once_cell",
@ -4742,7 +4743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
dependencies = [
"anyhow",
"itertools 0.10.5",
"itertools 0.11.0",
"proc-macro2",
"quote",
"syn 2.0.47",
@ -5046,6 +5047,15 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_users"
version = "0.4.3"
@ -5285,9 +5295,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.33"
version = "0.38.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad"
checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
dependencies = [
"bitflags 2.4.0",
"errno",
@ -5697,7 +5707,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -5915,9 +5925,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
name = "strum"
@ -5952,9 +5962,9 @@ dependencies = [
[[package]]
name = "strum_macros"
version = "0.26.2"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@ -6486,12 +6496,13 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.10.1"
version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall 0.4.1",
"rustix",
"windows-sys 0.52.0",
]

View File

@ -60,6 +60,7 @@ flowy-error = { path = "../../rust-lib/flowy-error", features = [
"impl_from_serde",
"tauri_ts",
] }
flowy-search = { path = "../../rust-lib/flowy-search", features = ["tauri_ts"] }
flowy-document = { path = "../../rust-lib/flowy-document", features = [
"tauri_ts",
] }
@ -87,7 +88,7 @@ yrs = { git = "https://github.com/appflowy/y-crdt", rev = "3f25bb510ca5274e7657d
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca70c426311fc6fb87ecccfa66e3927b36e96795" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "1019b8c5b6ffb548253dc2c7819afb84d242ab7b" }
# Please use the following script to update collab.
# Working directory: frontend
#
@ -97,10 +98,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca7
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }

View File

@ -1,2 +1,2 @@
[toolchain]
channel = "1.75"
channel = "1.77.2"

View File

@ -215,7 +215,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -541,7 +541,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"again",
"anyhow",
@ -587,7 +587,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"futures-channel",
"futures-util",
@ -631,7 +631,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -655,7 +655,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -674,7 +674,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"bytes",
@ -689,7 +689,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"chrono",
@ -727,7 +727,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-stream",
@ -765,7 +765,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -790,7 +790,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -804,7 +804,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -1001,7 +1001,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -1774,7 +1774,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"futures-util",
@ -1791,7 +1791,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -2092,7 +2092,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"reqwest",
@ -3732,7 +3732,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -4994,4 +4994,4 @@ dependencies = [
[[patch.unused]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"

View File

@ -55,7 +55,7 @@ codegen-units = 1
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca70c426311fc6fb87ecccfa66e3927b36e96795" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "1019b8c5b6ffb548253dc2c7819afb84d242ab7b" }
# Please use the following script to update collab.
# Working directory: frontend
#
@ -65,10 +65,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca7
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }

View File

@ -1,2 +1,2 @@
[toolchain]
channel = "1.75"
channel = "1.77.2"

View File

@ -153,7 +153,7 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -714,7 +714,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"again",
"anyhow",
@ -760,7 +760,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"futures-channel",
"futures-util",
@ -843,7 +843,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -867,7 +867,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -897,7 +897,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -916,7 +916,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"bytes",
@ -931,7 +931,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"chrono",
@ -969,7 +969,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-stream",
@ -1008,7 +1008,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -1033,7 +1033,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -1047,7 +1047,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -1280,7 +1280,7 @@ dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa 1.0.10",
"phf 0.8.0",
"phf 0.11.2",
"smallvec",
]
@ -1391,7 +1391,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -2844,7 +2844,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"futures-util",
@ -2861,7 +2861,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -3298,7 +3298,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"reqwest",
@ -4803,7 +4803,7 @@ checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2"
dependencies = [
"bytes",
"heck 0.4.1",
"itertools 0.11.0",
"itertools 0.10.5",
"log",
"multimap",
"once_cell",
@ -4824,7 +4824,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e"
dependencies = [
"anyhow",
"itertools 0.11.0",
"itertools 0.10.5",
"proc-macro2",
"quote",
"syn 2.0.55",
@ -5802,7 +5802,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",

View File

@ -87,7 +87,7 @@ yrs = { git = "https://github.com/appflowy/y-crdt", rev = "3f25bb510ca5274e7657d
# Run the script:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca70c426311fc6fb87ecccfa66e3927b36e96795" }
client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "1019b8c5b6ffb548253dc2c7819afb84d242ab7b" }
# Please use the following script to update collab.
# Working directory: frontend
#
@ -97,10 +97,10 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca7
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }

View File

@ -1,2 +1,2 @@
[toolchain]
channel = "1.75"
channel = "1.77.2"

View File

@ -1193,6 +1193,7 @@
},
"inlineActions": {
"noResults": "No results",
"recentPages": "Recent pages",
"pageReference": "Page reference",
"docReference": "Document reference",
"boardReference": "Board reference",

View File

@ -135,9 +135,9 @@ dependencies = [
[[package]]
name = "allocator-api2"
version = "0.2.18"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "android-tzdata"
@ -163,7 +163,7 @@ checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "app-error"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -182,9 +182,9 @@ dependencies = [
[[package]]
name = "arc-swap"
version = "1.7.1"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]]
name = "arrayvec"
@ -696,7 +696,7 @@ dependencies = [
[[package]]
name = "client-api"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"again",
"anyhow",
@ -742,7 +742,7 @@ dependencies = [
[[package]]
name = "client-websocket"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"futures-channel",
"futures-util",
@ -785,7 +785,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -809,7 +809,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-trait",
@ -839,7 +839,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -858,7 +858,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"bytes",
@ -873,7 +873,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"chrono",
@ -911,7 +911,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"async-stream",
@ -950,7 +950,7 @@ dependencies = [
[[package]]
name = "collab-rt-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -975,7 +975,7 @@ dependencies = [
[[package]]
name = "collab-rt-protocol"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"bincode",
@ -989,7 +989,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=5e32057ac8e6939368a8e75df91bcbce2ac143e7#5e32057ac8e6939368a8e75df91bcbce2ac143e7"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=66bc02f87ba73b3f1095424a2ec053c1fac72c36#66bc02f87ba73b3f1095424a2ec053c1fac72c36"
dependencies = [
"anyhow",
"collab",
@ -1326,7 +1326,7 @@ checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
[[package]]
name = "database-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -1432,6 +1432,12 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d95203a6a50906215a502507c0f879a0ce7ff205a6111e2db2a5ef8e4bb92e43"
[[package]]
name = "deunicode"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94"
[[package]]
name = "diesel"
version = "2.1.4"
@ -1496,9 +1502,9 @@ checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "downcast-rs"
version = "1.2.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dtoa"
@ -1647,12 +1653,12 @@ dependencies = [
[[package]]
name = "fake"
version = "2.8.0"
version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9af7b0c58ac9d03169e27f080616ce9f64004edca3d2ef4147a811c21b23b319"
checksum = "1c25829bde82205da46e1823b2259db6273379f626fc211f126f65654a2669be"
dependencies = [
"deunicode 1.4.3",
"rand 0.8.5",
"unidecode",
]
[[package]]
@ -1695,15 +1701,15 @@ dependencies = [
[[package]]
name = "fastdivide"
version = "0.4.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59668941c55e5c186b8b58c391629af56774ec768f73c08bbcd56f09348eb00b"
checksum = "25c7df09945d65ea8d70b3321547ed414bbc540aad5bac6883d021b970f35b04"
[[package]]
name = "fastrand"
version = "2.0.2"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "finl_unicode"
@ -2102,8 +2108,8 @@ dependencies = [
"protobuf",
"serde",
"serde_json",
"strsim 0.11.1",
"strum_macros 0.26.2",
"strsim 0.11.0",
"strum_macros 0.26.1",
"tantivy",
"tempfile",
"tokio",
@ -2589,7 +2595,7 @@ dependencies = [
[[package]]
name = "gotrue"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"futures-util",
@ -2606,7 +2612,7 @@ dependencies = [
[[package]]
name = "gotrue-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -2977,7 +2983,7 @@ dependencies = [
[[package]]
name = "infra"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"reqwest",
@ -3156,9 +3162,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.153"
version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "libloading"
@ -3259,9 +3265,9 @@ dependencies = [
[[package]]
name = "lz4_flex"
version = "0.11.3"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15"
[[package]]
name = "mac"
@ -3465,9 +3471,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
[[package]]
name = "murmurhash32"
version = "0.3.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2195bf6aa996a481483b29d62a7663eed3fe39600c460e323f8ff41e90bdd89b"
checksum = "d9380db4c04d219ac5c51d14996bbf2c2e9a15229771b53f8671eb6c83cf44df"
[[package]]
name = "nanoid"
@ -4741,9 +4747,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.33"
version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad"
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
"bitflags 2.4.0",
"errno",
@ -5089,7 +5095,7 @@ dependencies = [
[[package]]
name = "shared-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=ca70c426311fc6fb87ecccfa66e3927b36e96795#ca70c426311fc6fb87ecccfa66e3927b36e96795"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Cloud?rev=1019b8c5b6ffb548253dc2c7819afb84d242ab7b#1019b8c5b6ffb548253dc2c7819afb84d242ab7b"
dependencies = [
"anyhow",
"app-error",
@ -5180,7 +5186,7 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373"
dependencies = [
"deunicode",
"deunicode 0.4.4",
]
[[package]]
@ -5275,9 +5281,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strsim"
version = "0.11.1"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
[[package]]
name = "strum"
@ -5312,9 +5318,9 @@ dependencies = [
[[package]]
name = "strum_macros"
version = "0.26.2"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18"
dependencies = [
"heck 0.4.1",
"proc-macro2",
@ -5551,9 +5557,9 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.10.1"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
dependencies = [
"cfg-if",
"fastrand",
@ -6210,12 +6216,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unidecode"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc"
[[package]]
name = "universal-hash"
version = "0.5.1"

View File

@ -81,7 +81,7 @@ chrono = { version = "0.4.31", default-features = false, features = ["clock"] }
yrs = { version = "0.17.2" }
[profile.dev]
opt-level = 0
opt-level = 1
lto = false
codegen-units = 16
@ -115,7 +115,7 @@ rocksdb = { git = "https://github.com/LucasXu0/rust-rocksdb", rev = "21cf4a23ec1
# Run the script.add_workspace_members:
# scripts/tool/update_client_api_rev.sh new_rev_id
# ⚠️⚠️⚠️️
client-api = { git = " https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca70c426311fc6fb87ecccfa66e3927b36e96795" }
client-api = { git = " https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "1019b8c5b6ffb548253dc2c7819afb84d242ab7b" }
# Please use the following script to update collab.
# Working directory: frontend
#
@ -125,10 +125,10 @@ client-api = { git = " https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "ca
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "5e32057ac8e6939368a8e75df91bcbce2ac143e7" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "66bc02f87ba73b3f1095424a2ec053c1fac72c36" }

View File

@ -197,7 +197,7 @@ fn generate_ts_protobuf_files(
.write(true)
.append(false)
.truncate(true)
.open(&ts_index)
.open(ts_index)
{
Ok(ref mut file) => {
let mut export = String::new();

View File

@ -77,7 +77,7 @@ pub fn gen(dest_folder_name: &str, project: Project) {
.write(true)
.append(false)
.truncate(true)
.open(&ts_index)
.open(ts_index)
{
Ok(ref mut file) => {
let mut export = String::new();

View File

@ -46,6 +46,7 @@ pub fn save_content_to_file_with_diff_prompt(content: &str, output_file: &str) {
} else {
match OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(output_file)
{

View File

@ -8,7 +8,7 @@ edition = "2021"
crate-type = ["cdylib", "rlib"]
[dependencies]
collab = { version = "0.1.0" }
collab = { version = "0.1.0", features = ["trace_transact"] }
collab-plugins = { version = "0.1.0" }
collab-entity = { version = "0.1.0" }
serde.workspace = true

View File

@ -177,6 +177,7 @@ pub extern "C" fn link_me_please() {}
#[inline(always)]
async fn post_to_flutter(response: AFPluginEventResponse, port: i64) {
let isolate = allo_isolate::Isolate::new(port);
#[allow(clippy::blocks_in_conditions)]
match isolate
.catch_unwind(async {
let ffi_resp = FFIResponse::from(response);

View File

@ -141,7 +141,7 @@ impl EventIntegrationTest {
pub fn get_folder_data(&self) -> FolderData {
let mutex_folder = self.appflowy_core.folder_manager.get_mutex_folder().clone();
let folder_lock_guard = mutex_folder.lock();
let folder_lock_guard = mutex_folder.read();
let folder = folder_lock_guard.as_ref().unwrap();
folder.get_folder_data().clone().unwrap()
}

View File

@ -1,6 +1,8 @@
mod database;
mod document;
mod folder;
mod search;
// TODO(Mathias): Enable tests for search
// mod search;
mod user;
pub mod util;

View File

@ -79,7 +79,7 @@ async fn test_folder_index_create_view() {
// Wait for the index to be updated
sleep(Duration::from_millis(500)).await;
let results = folder_search_manager.perform_search(view.name.clone());
let results = folder_search_manager.perform_search(view.name.clone(), None);
if let Err(e) = results {
panic!("Error performing search: {:?}", e);
}
@ -114,12 +114,12 @@ async fn test_folder_index_rename_view() {
// Wait for the index to be updated
sleep(Duration::from_millis(500)).await;
let first = folder_search_manager.perform_search(view.name);
let first = folder_search_manager.perform_search(view.name, None);
if let Err(e) = first {
panic!("Error performing search: {:?}", e);
}
let second = folder_search_manager.perform_search(new_view_name.clone());
let second = folder_search_manager.perform_search(new_view_name.clone(), None);
if let Err(e) = second {
panic!("Error performing search: {:?}", e);
}

View File

@ -162,9 +162,7 @@ impl AppFlowyCore {
Arc::downgrade(&(server_provider.clone() as Arc<dyn ObjectStorageService>)),
);
let folder_indexer = Arc::new(FolderIndexManagerImpl::new(Arc::downgrade(
&authenticate_user,
)));
let folder_indexer = Arc::new(FolderIndexManagerImpl::new(None));
let folder_manager = FolderDepsResolver::resolve(
Arc::downgrade(&authenticate_user),
&document_manager,

View File

@ -293,7 +293,7 @@ async fn according_to_select_option_is_filter_test() {
let multi_select_field = test.get_first_field(FieldType::MultiSelect);
let options = test.get_multi_select_type_option(&multi_select_field.id);
let filtering_options = vec![options[1].clone(), options[2].clone()];
let filtering_options = [options[1].clone(), options[2].clone()];
let ids = filtering_options
.iter()
.map(|option| option.id.clone())
@ -346,7 +346,7 @@ async fn according_to_select_option_contains_filter_test() {
let multi_select_field = test.get_first_field(FieldType::MultiSelect);
let options = test.get_multi_select_type_option(&multi_select_field.id);
let filtering_options = vec![options[1].clone(), options[2].clone()];
let filtering_options = [options[1].clone(), options[2].clone()];
let ids = filtering_options
.iter()
.map(|option| option.id.clone())

View File

@ -344,6 +344,7 @@ impl DocumentManager {
// create file if not exist
let mut file = tokio::fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&local_file_path)
.await?;

View File

@ -72,6 +72,19 @@ pub fn view_pb_without_child_views(view: View) -> ViewPB {
}
}
pub fn view_pb_without_child_views_from_arc(view: Arc<View>) -> ViewPB {
ViewPB {
id: view.id.clone(),
parent_view_id: view.parent_view_id.clone(),
name: view.name.clone(),
create_time: view.created_at,
child_views: Default::default(),
layout: view.layout.clone().into(),
icon: view.icon.clone().map(|icon| icon.into()),
is_favorite: view.is_favorite,
}
}
/// Returns a ViewPB with child views. Only the first level of child views are included.
pub fn view_pb_with_child_views(view: Arc<View>, child_views: Vec<Arc<View>>) -> ViewPB {
ViewPB {

View File

@ -138,6 +138,16 @@ pub(crate) async fn get_view_handler(
data_result_ok(view_pb)
}
#[tracing::instrument(level = "debug", skip(folder), err)]
pub(crate) async fn get_all_views_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<RepeatedViewPB, FlowyError> {
let folder = upgrade_folder(folder)?;
let view_pbs = folder.get_all_views_pb().await?;
data_result_ok(RepeatedViewPB::from(view_pbs))
}
#[tracing::instrument(level = "debug", skip(data, folder), err)]
pub(crate) async fn get_view_ancestors_handler(
data: AFPluginData<ViewIdPB>,

View File

@ -18,6 +18,7 @@ pub fn init(folder: Weak<FolderManager>) -> AFPlugin {
.event(FolderEvent::CreateView, create_view_handler)
.event(FolderEvent::CreateOrphanView, create_orphan_view_handler)
.event(FolderEvent::GetView, get_view_handler)
.event(FolderEvent::GetAllViews, get_all_views_handler)
.event(FolderEvent::UpdateView, update_view_handler)
.event(FolderEvent::DeleteView, delete_view_handler)
.event(FolderEvent::DuplicateView, duplicate_view_handler)
@ -97,6 +98,10 @@ pub enum FolderEvent {
#[event(input = "CreateOrphanViewPayloadPB", output = "ViewPB")]
CreateOrphanView = 16,
/// Return the view info
#[event(output = "RepeatedViewPB")]
GetAllViews = 17,
#[event()]
CopyLink = 20,

View File

@ -1,8 +1,9 @@
use crate::entities::icon::UpdateViewIconParams;
use crate::entities::{
view_pb_with_child_views, view_pb_without_child_views, CreateViewParams, CreateWorkspaceParams,
DeletedViewPB, FolderSnapshotPB, MoveNestedViewParams, RepeatedTrashPB, RepeatedViewIdPB,
RepeatedViewPB, UpdateViewParams, ViewPB, ViewSectionPB, WorkspacePB, WorkspaceSettingPB,
view_pb_with_child_views, view_pb_without_child_views, view_pb_without_child_views_from_arc,
CreateViewParams, CreateWorkspaceParams, DeletedViewPB, FolderSnapshotPB, MoveNestedViewParams,
RepeatedTrashPB, RepeatedViewIdPB, RepeatedViewPB, UpdateViewParams, ViewPB, ViewSectionPB,
WorkspacePB, WorkspaceSettingPB,
};
use crate::manager_observer::{
notify_child_views_changed, notify_did_update_workspace, notify_parent_view_did_change,
@ -30,11 +31,11 @@ use flowy_folder_pub::cloud::{gen_view_id, FolderCloudService};
use flowy_folder_pub::folder_builder::ParentChildViews;
use flowy_search_pub::entities::FolderIndexManager;
use lib_infra::conditional_send_sync_trait;
use parking_lot::{Mutex, RwLock};
use parking_lot::RwLock;
use std::fmt::{Display, Formatter};
use std::ops::Deref;
use std::sync::{Arc, Weak};
use tracing::{error, info, instrument};
use tracing::{error, info, instrument, trace};
conditional_send_sync_trait! {
"[crate::manager::FolderUser] represents the user for folder.";
@ -134,7 +135,7 @@ impl FolderManager {
pub async fn get_current_workspace_public_views(&self) -> FlowyResult<Vec<ViewPB>> {
let workspace_id = self
.mutex_folder
.lock()
.read()
.as_ref()
.map(|folder| folder.get_workspace_id());
@ -367,7 +368,7 @@ impl FolderManager {
pub async fn get_workspace_pb(&self) -> FlowyResult<WorkspacePB> {
let workspace_pb = {
let guard = self.mutex_folder.lock();
let guard = self.mutex_folder.read();
let folder = guard
.as_ref()
.ok_or(FlowyError::internal().with_context("folder is not initialized"))?;
@ -396,7 +397,7 @@ impl FolderManager {
async fn get_current_workspace_id(&self) -> FlowyResult<String> {
self
.mutex_folder
.lock()
.read()
.as_ref()
.map(|folder| folder.get_workspace_id())
.ok_or(FlowyError::internal().with_context("Unexpected empty workspace id"))
@ -409,12 +410,13 @@ impl FolderManager {
///
/// * `none_callback`: A callback function that is invoked when `mutex_folder` contains `None`.
/// * `f2`: A callback function that is invoked when `mutex_folder` contains a `Some` value. The contained folder is passed as an argument to this callback.
#[instrument(level = "debug", skip_all)]
fn with_folder<F1, F2, Output>(&self, none_callback: F1, f2: F2) -> Output
where
F1: FnOnce() -> Output,
F2: FnOnce(&Folder) -> Output,
{
let folder = self.mutex_folder.lock();
let folder = self.mutex_folder.read();
match &*folder {
None => none_callback(),
Some(folder) => f2(folder),
@ -471,7 +473,7 @@ impl FolderManager {
);
if let Ok(workspace_id) = self.get_current_workspace_id().await {
let folder = &self.mutex_folder.lock();
let folder = &self.mutex_folder.read();
if let Some(folder) = folder.as_ref() {
notify_did_update_workspace(&workspace_id, folder);
}
@ -523,8 +525,10 @@ impl FolderManager {
/// again using the ID of the child view you wish to access.
#[tracing::instrument(level = "debug", skip(self))]
pub async fn get_view_pb(&self, view_id: &str) -> FlowyResult<ViewPB> {
trace!("Get view pb with id: {}", view_id);
let view_id = view_id.to_string();
let folder = self.mutex_folder.lock();
let folder = self.mutex_folder.read();
let folder = folder.as_ref().ok_or_else(folder_not_init_error)?;
// trash views and other private views should not be accessed
@ -555,6 +559,30 @@ impl FolderManager {
}
}
/// Retrieves all views.
///
/// It is important to note that this will return a flat map of all views,
/// excluding all child views themselves, as they are all at the same level in this
/// map.
///
#[tracing::instrument(level = "debug", skip(self))]
pub async fn get_all_views_pb(&self) -> FlowyResult<Vec<ViewPB>> {
let folder = self.mutex_folder.read();
let folder = folder.as_ref().ok_or_else(folder_not_init_error)?;
// trash views and other private views should not be accessed
let view_ids_should_be_filtered = self.get_view_ids_should_be_filtered(folder);
let all_views = folder.views.get_all_views();
let views = all_views
.into_iter()
.filter(|view| !view_ids_should_be_filtered.contains(&view.id))
.map(view_pb_without_child_views_from_arc)
.collect::<Vec<_>>();
Ok(views)
}
/// Retrieves the ancestors of the view corresponding to the specified view ID, including the view itself.
///
/// For example, if the view hierarchy is as follows:
@ -1063,7 +1091,7 @@ impl FolderManager {
.send();
if let Ok(workspace_id) = self.get_current_workspace_id().await {
let folder = &self.mutex_folder.lock();
let folder = &self.mutex_folder.read();
if let Some(folder) = folder.as_ref() {
notify_did_update_workspace(&workspace_id, folder);
}
@ -1318,9 +1346,9 @@ pub(crate) fn get_workspace_private_view_pbs(_workspace_id: &str, folder: &Folde
/// The MutexFolder is a wrapper of the [Folder] that is used to share the folder between different
/// threads.
#[derive(Clone, Default)]
pub struct MutexFolder(Arc<Mutex<Option<Folder>>>);
pub struct MutexFolder(Arc<RwLock<Option<Folder>>>);
impl Deref for MutexFolder {
type Target = Arc<Mutex<Option<Folder>>>;
type Target = Arc<RwLock<Option<Folder>>>;
fn deref(&self) -> &Self::Target {
&self.0
}

View File

@ -133,7 +133,7 @@ impl FolderManager {
let index_content_rx = folder.subscribe_index_content();
self
.folder_indexer
.set_index_content_receiver(index_content_rx);
.set_index_content_receiver(index_content_rx, workspace_id.clone());
// Index all views in the folder if needed
if !self.folder_indexer.is_indexed() {
@ -141,12 +141,13 @@ impl FolderManager {
let folder_indexer = self.folder_indexer.clone();
// We spawn a blocking task to index all views in the folder
let wid = workspace_id.clone();
spawn_blocking(move || {
folder_indexer.index_all_views(views);
folder_indexer.index_all_views(views, wid);
});
}
*self.mutex_folder.lock() = Some(folder);
*self.mutex_folder.write() = Some(folder);
let weak_mutex_folder = Arc::downgrade(&self.mutex_folder);
subscribe_folder_sync_state_changed(workspace_id.clone(), folder_state_rx, &weak_mutex_folder);

View File

@ -67,7 +67,7 @@ pub(crate) fn subscribe_folder_snapshot_state_changed(
af_spawn(async move {
if let Some(mutex_folder) = weak_mutex_folder.upgrade() {
let stream = mutex_folder
.lock()
.read()
.as_ref()
.map(|folder| folder.subscribe_snapshot_state());
if let Some(mut state_stream) = stream {
@ -119,7 +119,7 @@ pub(crate) fn subscribe_folder_trash_changed(
TrashSectionChange::TrashItemAdded { ids } => ids,
TrashSectionChange::TrashItemRemoved { ids } => ids,
};
if let Some(folder) = folder.lock().as_ref() {
if let Some(folder) = folder.read().as_ref() {
let views = folder.views.get_views(&ids);
for view in views {
unique_ids.insert(view.parent_view_id.clone());
@ -146,7 +146,7 @@ pub(crate) fn notify_parent_view_did_change<T: AsRef<str>>(
folder: Arc<MutexFolder>,
parent_view_ids: Vec<T>,
) -> Option<()> {
let folder = folder.lock();
let folder = folder.read();
let folder = folder.as_ref()?;
let workspace_id = folder.get_workspace_id();
let trash_ids = folder

View File

@ -9,10 +9,11 @@ pub struct IndexableData {
pub data: String,
pub icon: Option<ViewIcon>,
pub layout: ViewLayout,
pub workspace_id: String,
}
pub trait IndexManager: Send + Sync {
fn set_index_content_receiver(&self, rx: IndexContentReceiver);
fn set_index_content_receiver(&self, rx: IndexContentReceiver, workspace_id: String);
fn add_index(&self, data: IndexableData) -> Result<(), FlowyError>;
fn update_index(&self, data: IndexableData) -> Result<(), FlowyError>;
fn remove_indices(&self, ids: Vec<String>) -> Result<(), FlowyError>;
@ -22,5 +23,5 @@ pub trait IndexManager: Send + Sync {
}
pub trait FolderIndexManager: IndexManager {
fn index_all_views(&self, views: Vec<View>);
fn index_all_views(&self, views: Vec<View>, workspace_id: String);
}

View File

@ -1,2 +1,2 @@
proto_input = ["src/event_map.rs", "src/entities.rs"]
proto_input = ["src/event_map.rs", "src/entities"]
event_files = ["src/event_map.rs"]

View File

@ -0,0 +1,30 @@
use flowy_derive::ProtoBuf_Enum;
#[derive(ProtoBuf_Enum, Eq, PartialEq, Debug, Clone)]
pub enum IndexTypePB {
View = 0,
DocumentBlock = 1,
DatabaseRow = 2,
}
impl Default for IndexTypePB {
fn default() -> Self {
Self::View
}
}
impl std::convert::From<IndexTypePB> for i32 {
fn from(notification: IndexTypePB) -> Self {
notification as i32
}
}
impl std::convert::From<i32> for IndexTypePB {
fn from(notification: i32) -> Self {
match notification {
1 => IndexTypePB::View,
2 => IndexTypePB::DocumentBlock,
_ => IndexTypePB::DatabaseRow,
}
}
}

View File

@ -0,0 +1,11 @@
mod index_type;
mod notification;
mod query;
mod result;
mod search_filter;
pub use index_type::*;
pub use notification::*;
pub use query::*;
pub use result::*;
pub use search_filter::*;

View File

@ -0,0 +1,39 @@
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use super::SearchResultPB;
#[derive(ProtoBuf, Default, Debug, Clone)]
pub struct SearchResultNotificationPB {
#[pb(index = 1)]
pub items: Vec<SearchResultPB>,
#[pb(index = 2)]
pub closed: bool,
#[pb(index = 3, one_of)]
pub channel: Option<String>,
}
#[derive(ProtoBuf_Enum, Debug, Default)]
pub enum SearchNotification {
#[default]
Unknown = 0,
DidUpdateResults = 1,
DidCloseResults = 2,
}
impl std::convert::From<SearchNotification> for i32 {
fn from(notification: SearchNotification) -> Self {
notification as i32
}
}
impl std::convert::From<i32> for SearchNotification {
fn from(notification: i32) -> Self {
match notification {
1 => SearchNotification::DidUpdateResults,
2 => SearchNotification::DidCloseResults,
_ => SearchNotification::Unknown,
}
}
}

View File

@ -0,0 +1,25 @@
use flowy_derive::ProtoBuf;
use super::SearchFilterPB;
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]
pub struct SearchQueryPB {
#[pb(index = 1)]
pub search: String,
#[pb(index = 2, one_of)]
pub limit: Option<i64>,
#[pb(index = 3, one_of)]
pub filter: Option<SearchFilterPB>,
/// Used to identify the channel of the search
///
/// This can be used to have multiple search notification listeners in place.
/// It is up to the client to decide how to handle this.
///
/// If not set, then no channel is used.
///
#[pb(index = 4, one_of)]
pub channel: Option<String>,
}

View File

@ -1,14 +1,7 @@
use collab_folder::{IconType, ViewIcon};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]
pub struct SearchQueryPB {
#[pb(index = 1)]
pub search: String,
#[pb(index = 2, one_of)]
pub limit: Option<i64>,
}
use super::IndexTypePB;
#[derive(Debug, Default, ProtoBuf, Clone)]
pub struct RepeatedSearchResultPB {
@ -35,6 +28,9 @@ pub struct SearchResultPB {
#[pb(index = 6)]
pub score: f64,
#[pb(index = 7)]
pub workspace_id: String,
}
impl SearchResultPB {
@ -46,6 +42,7 @@ impl SearchResultPB {
data: self.data.clone(),
icon: self.icon.clone(),
score,
workspace_id: self.workspace_id.clone(),
}
}
}
@ -125,65 +122,3 @@ impl From<ViewIcon> for ResultIconPB {
}
}
}
#[derive(ProtoBuf_Enum, Eq, PartialEq, Debug, Clone)]
pub enum IndexTypePB {
View = 0,
DocumentBlock = 1,
DatabaseRow = 2,
}
impl Default for IndexTypePB {
fn default() -> Self {
Self::View
}
}
impl std::convert::From<IndexTypePB> for i32 {
fn from(notification: IndexTypePB) -> Self {
notification as i32
}
}
impl std::convert::From<i32> for IndexTypePB {
fn from(notification: i32) -> Self {
match notification {
1 => IndexTypePB::View,
2 => IndexTypePB::DocumentBlock,
_ => IndexTypePB::DatabaseRow,
}
}
}
#[derive(ProtoBuf, Default, Debug, Clone)]
pub struct SearchResultNotificationPB {
#[pb(index = 1)]
pub items: Vec<SearchResultPB>,
#[pb(index = 2)]
pub closed: bool,
}
#[derive(ProtoBuf_Enum, Debug, Default)]
pub enum SearchNotification {
#[default]
Unknown = 0,
DidUpdateResults = 1,
DidCloseResults = 2,
}
impl std::convert::From<SearchNotification> for i32 {
fn from(notification: SearchNotification) -> Self {
notification as i32
}
}
impl std::convert::From<i32> for SearchNotification {
fn from(notification: i32) -> Self {
match notification {
1 => SearchNotification::DidUpdateResults,
2 => SearchNotification::DidCloseResults,
_ => SearchNotification::Unknown,
}
}
}

View File

@ -0,0 +1,7 @@
use flowy_derive::ProtoBuf;
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]
pub struct SearchFilterPB {
#[pb(index = 1, one_of)]
pub workspace_id: Option<String>,
}

View File

@ -21,7 +21,7 @@ pub(crate) async fn search_handler(
) -> Result<(), FlowyError> {
let query = data.into_inner();
let manager = upgrade_manager(manager)?;
manager.perform_search(query.search);
manager.perform_search(query.search, query.filter, query.channel);
Ok(())
}

View File

@ -8,6 +8,7 @@ pub struct FolderIndexData {
pub title: String,
pub icon: String,
pub icon_ty: i64,
pub workspace_id: String,
}
impl From<FolderIndexData> for SearchResultPB {
@ -28,6 +29,7 @@ impl From<FolderIndexData> for SearchResultPB {
data: data.title,
score: 0.0,
icon,
workspace_id: data.workspace_id,
}
}
}

View File

@ -1,5 +1,7 @@
use crate::entities::SearchResultPB;
use crate::services::manager::{SearchHandler, SearchType};
use crate::{
entities::{SearchFilterPB, SearchResultPB},
services::manager::{SearchHandler, SearchType},
};
use flowy_error::FlowyResult;
use std::sync::Arc;
@ -20,8 +22,20 @@ impl SearchHandler for FolderSearchHandler {
SearchType::Folder
}
fn perform_search(&self, query: String) -> FlowyResult<Vec<SearchResultPB>> {
self.index_manager.search(query)
fn perform_search(
&self,
query: String,
filter: Option<SearchFilterPB>,
) -> FlowyResult<Vec<SearchResultPB>> {
let mut results = self.index_manager.search(query, filter.clone())?;
if let Some(filter) = filter {
if let Some(workspace_id) = filter.workspace_id {
// Filter results by workspace ID
results.retain(|result| result.workspace_id == workspace_id);
}
}
Ok(results)
}
fn index_count(&self) -> u64 {

View File

@ -8,8 +8,11 @@ use std::{
};
use crate::{
entities::ResultIconTypePB,
folder::schema::{FolderSchema, FOLDER_ICON_FIELD_NAME, FOLDER_TITLE_FIELD_NAME},
entities::{ResultIconTypePB, SearchFilterPB, SearchResultPB},
folder::schema::{
FolderSchema, FOLDER_ICON_FIELD_NAME, FOLDER_ICON_TY_FIELD_NAME, FOLDER_ID_FIELD_NAME,
FOLDER_TITLE_FIELD_NAME, FOLDER_WORKSPACE_ID_FIELD_NAME,
},
};
use collab::core::collab::{IndexContent, IndexContentReceiver};
use collab_folder::{View, ViewIcon, ViewIndexContent, ViewLayout};
@ -23,12 +26,7 @@ use tantivy::{
IndexWriter, Term,
};
use crate::entities::SearchResultPB;
use super::{
entities::FolderIndexData,
schema::{FOLDER_ICON_TY_FIELD_NAME, FOLDER_ID_FIELD_NAME},
};
use super::entities::FolderIndexData;
#[derive(Clone)]
pub struct FolderIndexManagerImpl {
@ -41,7 +39,15 @@ pub struct FolderIndexManagerImpl {
const FOLDER_INDEX_DIR: &str = "folder_index";
impl FolderIndexManagerImpl {
pub fn new(auth_user: Weak<AuthenticateUser>) -> Self {
pub fn new(auth_user: Option<Weak<AuthenticateUser>>) -> Self {
// TODO(Mathias): Temporarily disable seaerch
let auth_user = match auth_user {
Some(auth_user) => auth_user,
None => {
return FolderIndexManagerImpl::empty();
},
};
// AuthenticateUser is required to get the index path
let authenticate_user = auth_user.upgrade();
@ -130,15 +136,19 @@ impl FolderIndexManagerImpl {
let title_field = folder_schema.schema.get_field(FOLDER_TITLE_FIELD_NAME)?;
let icon_field = folder_schema.schema.get_field(FOLDER_ICON_FIELD_NAME)?;
let icon_ty_field = folder_schema.schema.get_field(FOLDER_ICON_TY_FIELD_NAME)?;
let workspace_id_field = folder_schema
.schema
.get_field(FOLDER_WORKSPACE_ID_FIELD_NAME)?;
for data in indexes {
let (icon, icon_ty) = self.extract_icon(data.icon, data.layout);
let _ = index_writer.add_document(doc![
id_field => data.id.clone(),
title_field => data.data.clone(),
icon_field => icon.unwrap_or_default(),
icon_ty_field => icon_ty,
id_field => data.id.clone(),
title_field => data.data.clone(),
icon_field => icon.unwrap_or_default(),
icon_ty_field => icon_ty,
workspace_id_field => data.workspace_id.clone(),
]);
}
@ -206,7 +216,11 @@ impl FolderIndexManagerImpl {
(icon, icon_ty)
}
pub fn search(&self, query: String) -> Result<Vec<SearchResultPB>, FlowyError> {
pub fn search(
&self,
query: String,
_filter: Option<SearchFilterPB>,
) -> Result<Vec<SearchResultPB>, FlowyError> {
let folder_schema = self.get_folder_schema()?;
let index = match &self.index {
@ -222,11 +236,7 @@ impl FolderIndexManagerImpl {
let title_field = folder_schema.schema.get_field(FOLDER_TITLE_FIELD_NAME)?;
let length = query.len();
let distance: u8 = match length {
_ if length > 4 => 2,
_ if length > 2 => 1,
_ => 0,
};
let distance: u8 = if length >= 2 { 2 } else { 1 };
let mut query_parser = QueryParser::for_index(&index.clone(), vec![title_field]);
query_parser.set_field_fuzzy(title_field, true, distance, true);
@ -273,8 +283,9 @@ impl IndexManager for FolderIndexManagerImpl {
.unwrap_or(false)
}
fn set_index_content_receiver(&self, mut rx: IndexContentReceiver) {
fn set_index_content_receiver(&self, mut rx: IndexContentReceiver, workspace_id: String) {
let indexer = self.clone();
let wid = workspace_id.clone();
af_spawn(async move {
while let Ok(msg) = rx.recv().await {
match msg {
@ -285,6 +296,7 @@ impl IndexManager for FolderIndexManagerImpl {
data: view.name,
icon: view.icon,
layout: view.layout,
workspace_id: wid.clone(),
});
},
Err(err) => tracing::error!("FolderIndexManager error deserialize: {:?}", err),
@ -296,6 +308,7 @@ impl IndexManager for FolderIndexManagerImpl {
data: view.name,
icon: view.icon,
layout: view.layout,
workspace_id: wid.clone(),
});
},
Err(err) => tracing::error!("FolderIndexManager error deserialize: {:?}", err),
@ -317,7 +330,11 @@ impl IndexManager for FolderIndexManagerImpl {
let id_field = folder_schema.schema.get_field(FOLDER_ID_FIELD_NAME)?;
let title_field = folder_schema.schema.get_field(FOLDER_TITLE_FIELD_NAME)?;
let icon_field = folder_schema.schema.get_field(FOLDER_ICON_FIELD_NAME)?;
let icon_ty_field = folder_schema.schema.get_field(FOLDER_ICON_TY_FIELD_NAME)?;
let icon_ty_field: tantivy::schema::Field =
folder_schema.schema.get_field(FOLDER_ICON_TY_FIELD_NAME)?;
let workspace_id_field = folder_schema
.schema
.get_field(FOLDER_WORKSPACE_ID_FIELD_NAME)?;
let delete_term = Term::from_field_text(id_field, &data.id.clone());
@ -332,6 +349,7 @@ impl IndexManager for FolderIndexManagerImpl {
title_field => data.data,
icon_field => icon.unwrap_or_default(),
icon_ty_field => icon_ty,
workspace_id_field => data.workspace_id.clone(),
]);
index_writer.commit()?;
@ -364,6 +382,9 @@ impl IndexManager for FolderIndexManagerImpl {
let title_field = folder_schema.schema.get_field(FOLDER_TITLE_FIELD_NAME)?;
let icon_field = folder_schema.schema.get_field(FOLDER_ICON_FIELD_NAME)?;
let icon_ty_field = folder_schema.schema.get_field(FOLDER_ICON_TY_FIELD_NAME)?;
let workspace_id_field = folder_schema
.schema
.get_field(FOLDER_WORKSPACE_ID_FIELD_NAME)?;
let (icon, icon_ty) = self.extract_icon(data.icon, data.layout);
@ -373,6 +394,7 @@ impl IndexManager for FolderIndexManagerImpl {
title_field => data.data,
icon_field => icon.unwrap_or_default(),
icon_ty_field => icon_ty,
workspace_id_field => data.workspace_id,
]);
index_writer.commit()?;
@ -386,7 +408,7 @@ impl IndexManager for FolderIndexManagerImpl {
}
impl FolderIndexManager for FolderIndexManagerImpl {
fn index_all_views(&self, views: Vec<View>) {
fn index_all_views(&self, views: Vec<View>, workspace_id: String) {
let indexable_data = views
.into_iter()
.map(|view| IndexableData {
@ -394,6 +416,7 @@ impl FolderIndexManager for FolderIndexManagerImpl {
data: view.name,
icon: view.icon,
layout: view.layout,
workspace_id: workspace_id.clone(),
})
.collect();

View File

@ -4,6 +4,7 @@ pub const FOLDER_ID_FIELD_NAME: &str = "id";
pub const FOLDER_TITLE_FIELD_NAME: &str = "title";
pub const FOLDER_ICON_FIELD_NAME: &str = "icon";
pub const FOLDER_ICON_TY_FIELD_NAME: &str = "icon_ty";
pub const FOLDER_WORKSPACE_ID_FIELD_NAME: &str = "workspace_id";
#[derive(Clone)]
pub struct FolderSchema {
@ -33,6 +34,10 @@ impl FolderSchema {
tantivy::schema::TEXT | tantivy::schema::STORED,
);
schema_builder.add_i64_field(FOLDER_ICON_TY_FIELD_NAME, tantivy::schema::STORED);
schema_builder.add_text_field(
FOLDER_WORKSPACE_ID_FIELD_NAME,
tantivy::schema::TEXT | tantivy::schema::STORED,
);
let schema = schema_builder.build();

View File

@ -5,7 +5,7 @@ use flowy_error::FlowyResult;
use lib_dispatch::prelude::af_spawn;
use tokio::{sync::broadcast, task::spawn_blocking};
use crate::entities::{SearchResultNotificationPB, SearchResultPB};
use crate::entities::{SearchFilterPB, SearchResultNotificationPB, SearchResultPB};
use super::notifier::{SearchNotifier, SearchResultChanged, SearchResultReceiverRunner};
@ -18,7 +18,11 @@ pub trait SearchHandler: Send + Sync + 'static {
/// returns the type of search this handler is responsible for
fn search_type(&self) -> SearchType;
/// performs a search and returns the results
fn perform_search(&self, query: String) -> FlowyResult<Vec<SearchResultPB>>;
fn perform_search(
&self,
query: String,
filter: Option<SearchFilterPB>,
) -> FlowyResult<Vec<SearchResultPB>>;
/// returns the number of indexed objects
fn index_count(&self) -> u64;
}
@ -50,17 +54,24 @@ impl SearchManager {
self.handlers.get(&search_type)
}
pub fn perform_search(&self, query: String) {
pub fn perform_search(
&self,
query: String,
filter: Option<SearchFilterPB>,
channel: Option<String>,
) {
let mut sends: usize = 0;
let max: usize = self.handlers.len();
let handlers = self.handlers.clone();
for (_, handler) in handlers {
let q = query.clone();
let f = filter.clone();
let ch = channel.clone();
let notifier = self.notifier.clone();
spawn_blocking(move || {
let res = handler.perform_search(q);
let res = handler.perform_search(q, f);
sends += 1;
let close = sends == max;
@ -68,6 +79,7 @@ impl SearchManager {
let notification = SearchResultNotificationPB {
items,
closed: close,
channel: ch,
};
let _ = notifier.send(SearchResultChanged::SearchResultUpdate(notification));

View File

@ -37,7 +37,7 @@ impl SearchResultReceiverRunner {
SearchNotification::DidUpdateResults
};
send_notification(SEARCH_ID, ty)
send_notification(SEARCH_ID, ty, notification.channel.clone())
.payload(notification)
.send();
},
@ -48,6 +48,16 @@ impl SearchResultReceiverRunner {
}
#[tracing::instrument(level = "trace")]
pub fn send_notification(id: &str, ty: SearchNotification) -> NotificationBuilder {
NotificationBuilder::new(id, ty, SEARCH_OBSERVABLE_SOURCE)
pub fn send_notification(
id: &str,
ty: SearchNotification,
channel: Option<String>,
) -> NotificationBuilder {
let observable_source = &format!(
"{}{}",
SEARCH_OBSERVABLE_SOURCE,
channel.unwrap_or_default()
);
NotificationBuilder::new(id, ty, observable_source)
}

View File

@ -32,9 +32,6 @@ pub(crate) struct UserProfileResponse {
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Deserialize)]
pub(crate) struct UserProfileResponseList(pub Vec<UserProfileResponse>);
#[derive(Deserialize, Clone)]
pub(crate) struct UidResponse {
#[allow(dead_code)]

View File

@ -1,3 +1,5 @@
use std::io;
use std::io::Write;
use std::sync::{Arc, RwLock};
use chrono::Local;
@ -88,8 +90,8 @@ impl Builder {
.pretty()
.with_env_filter(env_filter)
.finish()
.with(FlowyFormattingLayer::new(StdoutWriter))
.with(JsonStorageLayer)
.with(FlowyFormattingLayer::new(DebugStdoutWriter))
.with(file_layer);
set_global_default(subscriber).map_err(|e| format!("{:?}", e))?;
};
@ -106,12 +108,19 @@ impl tracing_subscriber::fmt::time::FormatTime for CustomTime {
}
}
pub struct StdoutWriter;
pub struct DebugStdoutWriter;
impl<'a> MakeWriter<'a> for StdoutWriter {
type Writer = std::io::Stdout;
impl<'a> MakeWriter<'a> for DebugStdoutWriter {
type Writer = Box<dyn Write>;
fn make_writer(&'a self) -> Self::Writer {
std::io::stdout()
#[cfg(not(debug_assertions))]
{
Box::new(io::sink())
}
#[cfg(debug_assertions)]
{
Box::new(io::stdout())
}
}
}

View File

@ -1,2 +1,2 @@
[toolchain]
channel = "1.75"
channel = "1.77.2"